79 lines
3.0 KiB
Python
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()
|