Compare commits

...

5 Commits

Author SHA1 Message Date
Stefan Sterz 7732db81d9
fix: refactor script to be more modular and add price to config 2022-10-26 14:32:23 +02:00
Stefan Sterz fb0f8e1777
chore: minor style improvements 2022-10-26 14:09:42 +02:00
Stefan Sterz 1bea9f70c3
chore: add proper code formatting 2022-10-26 14:08:21 +02:00
Stefan Sterz b61d1dd8e2
fix: add a message id and html body to reduce spam score
these changes should lower the spam score for systems that use e.g.
spamassassin and increase the likelihood of the email being delivered.
2022-10-26 14:05:29 +02:00
Stefan Sterz fd0e30bca2
feat: make script properly executable 2022-10-26 14:04:04 +02:00
3 changed files with 115 additions and 69 deletions

View File

@ -1,7 +1,8 @@
{ {
"server":"your.email.server", "server":"your.email.server",
"port":587, "port":587,
"user":"you@yourmail.com", "user":"you@yourmail.com",
"pass":"yourPassword", "pass":"yourPassword",
"sender":"santa@yourmail.com" "sender":"santa@yourmail.com",
"price": "75€"
} }

View File

@ -1,3 +1,5 @@
[ [
{"name":"Alice","mail":"alice@mail.com","gender":"e"},{"name":"Bob","mail":"bob@mail.com","gender":"er"},{"name":"Chris","mail":"chris@mail.com","gender":"er"} {"name":"Alice","mail":"alice@stefansterz.com","gender":"e"},
{"name":"Bob","mail":"bob@stefansterz.com","gender":"er"},
{"name":"Chris","mail":"chris@stefansterz.com","gender":"er"}
] ]

169
wichteln.py Normal file → Executable file
View File

@ -1,3 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
''' '''
This script creates randoms pairs from a list of participants in a secret santa This script creates randoms pairs from a list of participants in a secret santa
game and sends them an email to notify them who the person is that they should game and sends them an email to notify them who the person is that they should
@ -8,80 +11,120 @@ buy presents for.
from argparse import ArgumentParser from argparse import ArgumentParser
from email.mime.multipart import MIMEMultipart from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText from email.mime.text import MIMEText
from email.utils import formatdate from email.utils import formatdate, make_msgid
import json import json
import random import random
import smtplib import smtplib
from typing import Literal
import types
parser = ArgumentParser()
parser.add_argument('-p', '--participants',
dest='pFileLocation',
default='participants.json',
help='read a list of participants from PARTICIPANTFILE',
metavar='PARTICIPANTFILE')
parser.add_argument('-c', '--config',
dest='cFileLocation',
default='config.json',
help='read the configuration from CONFIGFILE',
metavar='CONFIGFILE')
args = parser.parse_args()
# load and prepare a list containing all participants def secret_santa_matching(participants: list) -> list:
with open(args.pFileLocation, 'r') as pFile: # create a copy of the list to make choosing a partner easier
participants = json.load(pFile) copy = list(enumerate(participants[:]))
# create a copy of the list to make choosing a partner easier # choose a partner for each participant
copy = list(enumerate(participants[:])) for i in range(len(participants)):
# choose a partner for each participant # if the last participant has only themselves left to choose, make them
for i in range(len(participants)): # switch partners with another random participant
if len(copy) == 1 and participants[i] == copy[0][1]:
# if the last participant has only themselves left to choose, make them current = participants[i]
# switch partners with another random participant participants.remove(current)
if len(copy) == 1 and participants[i] == copy[0][1]: partner = random.choice(participants)
current = participants[i] current['partner'] = partner['partner']
participants.remove(current) partner['partner'] = current['name'] + ' (' + current['mail']+')'
partner = random.choice(participants) participants.append(current)
break
current['partner'] = partner['partner'] # otherwise choose a random partner for each participant
partner['partner'] = current['name'] + ' (' + current['mail']+')' else:
participants.append(current) partner = random.choice(copy)
break while partner[0] == i:
partner = random.choice(copy)
# otherwise choose a random partner for each participant participants[i]['partner'] = partner[1]['name'] + \
else: ' ('+partner[1]['mail']+')'
partner = random.choice(copy) copy.remove(partner)
while partner[0] == i:
partner = random.choice(copy)
participants[i]['partner'] = partner[1]['name']+' ('+partner[1]['mail']+')' return participants
copy.remove(partner)
# load mail server configuration and open smtp server connection
with open(args.cFileLocation, 'r') as cFile:
config = json.load(cFile)
server = smtplib.SMTP(config['server'], config['port'])
server.ehlo()
server.starttls()
server.ehlo()
server.login(config['user'], config['pass'])
# create emails for all participants and send them def send_secret_santa_mails(participants: list, config: dict):
# change the text for the mail here if you want to open smtp connection
for r in participants: server = smtplib.SMTP(config['server'], config['port'])
server.ehlo()
msg = MIMEMultipart('alternative') server.starttls()
msg['From'] = config['sender'] server.ehlo()
msg['To'] = r['mail'] server.login(config['user'], config['pass'])
msg['Subject'] = 'Wichteln 🎄'
msg['Date'] = formatdate(localtime=True) # create emails for all participants and send them
# change the text for the mail here if you want to
body = 'Lieb'+r['gender']+' '+r['name']+'!\n\n' for r in participants:
body += 'Du bist heuer Wichtel für '+r['partner']+'.\n' msg = MIMEMultipart('alternative')
body += 'Das Geschenk sollte nicht mehr als 50€ kosten.\n\n' msg['From'] = config['sender']
body += 'Frohe Weihnachten!\n— Dein Christkind 👼' msg['To'] = r['mail']
msg['Subject'] = 'Wichteln 🎄'
msg.attach(MIMEText(body, 'plain', 'utf-8')) msg['Message-ID'] = make_msgid(domain=config['sender']
server.sendmail(config['sender'], r['mail'], msg.as_string()) .split('@')[1]
.strip('>'))
msg['Date'] = formatdate(localtime=True)
plain = f'''Lieb{r['gender']} {r['name']}!
Du bist heuer Wichtel für {r['partner']}.
Das Geschenk sollte nicht mehr als {config['price']} kosten.
Frohe Weihnachten!
Dein Christkind 👼'''
html = f'''
<html>
<head></head>
<body>
<p>Lieb{r['gender']} {r['name']}!<br><br>
Du bist heuer Wichtel für {r['partner']}.<br>
Das Geschenk sollte nicht mehr als {config['price']} kosten.<br><br>
Frohe Weihnachten!<br>
Dein Christkind 👼
</p>
</body>
</html>
'''
msg.attach(MIMEText(plain, 'plain', 'utf-8'))
msg.attach(MIMEText(html, 'html', 'utf-8'))
print('Sending email to', r['name'], '...')
server.sendmail(config['sender'], r['mail'], msg.as_string())
def main():
parser = ArgumentParser()
parser.add_argument('-p', '--participants',
dest='pFileLocation',
default='participants.json',
help='read list of participants from PARTICIPANTFILE',
metavar='PARTICIPANTFILE')
parser.add_argument('-c', '--config',
dest='cFileLocation',
default='config.json',
help='read the configuration from CONFIGFILE',
metavar='CONFIGFILE')
args = parser.parse_args()
matches = []
# load and prepare a list containing all participants
with open(args.pFileLocation, 'r') as pFile:
matches = secret_santa_matching(json.load(pFile))
# load mail server configuration
with open(args.cFileLocation, 'r') as cFile:
config = json.load(cFile)
send_secret_santa_mails(matches, config)
if __name__ == '__main__':
main()