secret-santa/app.py

79 lines
3.0 KiB
Python

import json, os, random, smtplib, ssl
from email.message import EmailMessage
from string import Template
from config import Config as Config
from secret import USERNAME, PASSWORD
context = ssl.create_default_context()
# Load data file
data_path = os.path.normpath(Config.DATA)
with open(data_path, 'r') as data_file:
data = json.loads(data_file.read())
print('Parsed data file.')
if not data: raise Exception('Error: data file is empty.')
# Randomise participants.
participants = list(data.keys())
random.shuffle(participants)
# Create a derangement in the permutation by moving the first participant to the bottom
derangement = list(participants)
derangement.append(derangement.pop(0))
# Create a dictionary pairing participants and gift recipients
buying = {}
for index, participant in enumerate(participants):
buying[participant] = derangement[index]
buying = {key: value for key, value in sorted(buying.items())}
# Create output file
output_path = os.path.normpath(Config.OUTPUT)
with open(output_path, 'w') as output:
output.write(json.dumps(buying, indent=4))
# Parse Templates
plain_path = os.path.normpath('./templates/plain.txt')
with open(plain_path, 'r') as plain_file:
plain_template = Template(plain_file.read())
rich_path = os.path.normpath('./templates/rich.html')
with open(rich_path, 'r') as rich_file:
rich_template = Template(rich_file.read())
def construct_message(participant, gift_recipient):
message = EmailMessage()
message['From'] = USERNAME
if '@' in data[participant]['email']:
participant_email = data[participant]['email']
elif hasattr(Config,'EMAIL_DOMAIN') and Config.EMAIL_DOMAIN:
participant_email = f'{data[participant]["email"]}@{Config.EMAIL_DOMAIN}'
else:
raise Exception(f'Error: Invalid email address for participant {participant}.')
if hasattr(Config,'OVERRIDE_RECIPIENT') and Config.OVERRIDE_RECIPIENT and hasattr(Config,'RECIPIENT_EMAIL') and Config.RECIPIENT_EMAIL:
message['To'] = Config.RECIPIENT_EMAIL
else: message['To'] = participant_email
message['Subject'] = Config.SUBJECT
preference = 'None' if not data[gift_recipient].get('preference') else data[gift_recipient].get('preference')
template_substitutions = {
'subject': Config.SUBJECT,
'greeting': Config.GREETING,
'participant': participant.title(),
'gift_recipient': gift_recipient.title(),
'preference': preference,
'sender': Config.SENDER
}
body_html = rich_template.substitute(template_substitutions)
body_plain = plain_template.substitute(template_substitutions)
message.set_content(body_plain)
message.add_alternative(body_html, subtype='html')
return message
messages = [construct_message(participant=participant, gift_recipient=gift_recipient) for participant, gift_recipient in buying.items()]
with smtplib.SMTP_SSL(Config.SERVER, Config.PORT, context=context) as smtp:
smtp.login(user=USERNAME, password=PASSWORD)
for message in messages: smtp.send_message(message)
smtp.quit()