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()