Files
SUST/sustApp/mail_payment_slips.py
T
2026-06-25 11:19:08 +02:00

127 lines
5.3 KiB
Python

from sqlalchemy import extract
from models.database import engine, SessionLocal
import models.models as models
import logging, sys
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from os.path import exists
import datetime
from create_payment_slip import create_payment_slip
import os
from config_loader import load_config
import argparse
from salutation_helpers import get_gender_salutation, get_pronouns
cfg = load_config()
year = cfg['year']
# Parse CLI arguments
parser = argparse.ArgumentParser(description='Send payment slip emails to members')
parser.add_argument('--resend', action='store_true', help='Send email again even if already mailed')
args = parser.parse_args()
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
def payment_slip_delivered(member: models.Members, year: int):
return db.query(models.Deliveries.delivery_date)\
.filter(models.Deliveries.member_id == member.id, extract('year', models.Deliveries.delivery_date) == year)\
.count()
def payment_slip_paid(member: models.Members, year: int):
return db.query(models.Payments.payment_year)\
.filter(models.Payments.member_id == member.id, extract('year', models.Payments.payment_year) == year)\
.count()
def send_mail(member: models.Members, force_resend: bool = False):
paid = payment_slip_paid(member, year)
if paid:
logging.debug(f'Member: {member.member_surname} already paid!')
return
delivered = payment_slip_delivered(member, year)
if delivered and not force_resend:
logging.debug(f'Member: {member.member_surname} already mailed or delivered!')
return
smtp_server = 'mail.gmx.com'
smtp_port = 587
smtp_username = 'zisco@gmx.at'
#TODO Secure
smtp_password = '[Jy010]Q&7te2qR&2x0d'
from_email = 'sv.stthomas@gmx.at'
to_email = member.member_email
subject = f'Mitgliedsbeitrag {year}'
is_plural = bool(member.member_count > 1)
pronouns = get_pronouns(is_plural=is_plural)
salutation = pronouns['possessive']
salutation2 = pronouns['neutral']
salutation3 = pronouns['accusative']
salutation4 = pronouns['conditional']
salutation5 = pronouns['verb']
# Get spouse's salutation based on their gender
if is_plural and member.spouse:
spouse_salutation = get_gender_salutation(str(member.spouse.member_gender), capitalize=False)
member_salutation = get_gender_salutation(str(member.member_gender), capitalize=False)
combined_salutation = f"{spouse_salutation.capitalize()} {member.spouse.member_firstname} und {member_salutation} {member.member_firstname}"
else:
combined_salutation = f"{get_gender_salutation(str(member.member_gender), capitalize=True)} {member.member_firstname}"
body = f"{combined_salutation},\n\n{salutation2} Zahlschein für {year} liegt bei.\n\nBitte mittels auf beiliegendem Zahlschein aufgedrucktem QR-Code überweisen.\nDanke sagt Dein Team vom Sportverein!"
msg = MIMEMultipart()
msg['From'] = from_email
msg['To'] = to_email
msg['Subject'] = subject
msg.attach(MIMEText(body))
path_to_file = os.path.join(os.path.expanduser("~"),"sust",f"payment_slips_{year}","mail",f"{member.member_zip}_payment_slip_member{member.id}.pdf")
if not exists(path_to_file):
create_payment_slip(member=member,
forMail=True)
with open(path_to_file, 'rb') as f:
attachment = MIMEApplication(f.read(), _subtype='pdf')
attachment.add_header('Content-Disposition', 'attachment', filename=f'{member.member_zip}_payment_slip_member{member.id}.pdf')
msg.attach(attachment)
with smtplib.SMTP(smtp_server, smtp_port) as smtp:
smtp.starttls()
smtp.login(smtp_username, smtp_password)
# smtp.send_message(msg)
# Send to recipient AND BCC to sender (so it appears in sent folder)
recipients = [to_email, from_email] # Add from_email as BCC
smtp.sendmail(from_email, recipients, msg.as_string())
newDelivery = models.Deliveries(delivery_date = datetime.datetime.now(),
member_id = member.id,
delivered_by_id = 186,
delivery_year = datetime.date.today())
db.add(newDelivery)
db.commit()
logging.debug(f'Sent mail to {member.member_email}')
db = SessionLocal()
models.Base.metadata.create_all(bind=engine)
members = db.query(models.Members).filter(
models.Members.member_active == True,
models.Members.member_email != None,
models.Members.member_primary == True
).all()
#members = db.query(models.Members).filter(models.Members.member_email != None, ~models.Members.id.in_([183,51,200,49])).all()
#members = db.query(models.Members).filter(models.Members.member_active == True).all()
#members = db.query(models.Members).filter(models.Members.id.in_([2,3,9,199]), models.Members.member_active == True, models.Members.member_printed == False).all()
members = db.query(models.Members).filter(models.Members.id.in_([77])).all()
for member in members:
if member.member_email:
send_mail(member=member, force_resend=args.resend)
else:
logging.debug(f'Member {member.member_surname} has no email associated!')