-
-
Save loleg/f006b4f6dc7c0a5a79f91c8ca320b93d to your computer and use it in GitHub Desktop.
Secret Santa script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
""" | |
Ye olde Secret Santa script based on https://gist.github.com/will-bainbridge/a4666a196fb5833cf37035647b74c064 | |
You will need to prepare a "people file", which is in CSV format (UTF-8, comma delimited) and has the following columns (without a header row) | |
Name, E-mail, Extra content 1, Extra content 2 | |
We used the postal address as extra content 1 and a link to Google Street View as extra content 2. Then you can specify a plain text message file which includes %s for the buyer name, recipient name, recipient extra 1, and recipient extra 2 (in that order!). For example: | |
Ho ho ho! Merry Christmas dear %s | |
You are the secret santa of %s | |
Please send joyful greetings to %s | |
To make a virtual visit go to %s | |
Example test run command (remove --no-send to actually send it): | |
python3 santa.py --people-file=family.csv \ | |
[email protected] \ | |
--message-subject="A global family x-mas" \ | |
--message-body-file=message.txt \ | |
--server-address=mail.northpole.ch \ | |
--server-port=25 \ | |
[email protected] \ | |
--no-send | |
Note: the script requires Python 3 and numpy installed on your system. | |
""" | |
import csv | |
import getpass | |
import numpy as np | |
import optparse | |
import smtplib | |
import sys | |
from email.mime.multipart import MIMEMultipart | |
from email.mime.text import MIMEText | |
parser = optparse.OptionParser() | |
parser.add_option( | |
'--people-file', | |
help='the CSV file (see details in script) of each person included in the secret santa', | |
metavar='FILE' | |
) | |
parser.add_option( | |
'--no-message', | |
action='store_true', | |
help='don\'t construct or send the messages, just print the matches', | |
) | |
parser.add_option( | |
'--no-send', | |
action='store_true', | |
help='don\'t send the messages, just print the messages', | |
) | |
parser.add_option( | |
'--message-from', | |
help='the email address the message is from', | |
metavar='EMAIL' | |
) | |
parser.add_option( | |
'--message-subject', | |
help='the message subject line', | |
metavar='SUBJECT' | |
) | |
parser.add_option( | |
'--message-body-file', | |
help='the file containing the message body (see instructions in script)', | |
metavar='FILE' | |
) | |
parser.add_option( | |
'--server-address', | |
help='the SMTP server address', | |
metavar='ADDRESS' | |
) | |
parser.add_option( | |
'--server-port', | |
help='the SMTP server port', | |
metavar='PORT' | |
) | |
parser.add_option( | |
'--server-user', | |
help='the SMTP server user', | |
metavar='USER' | |
) | |
options, dummy = parser.parse_args() | |
# Check options | |
if options.people_file is None: | |
parser.error('people-file not given') | |
if not options.no_message: | |
if options.message_from is None: | |
parser.error('message-from not given') | |
if options.message_subject is None: | |
parser.error('message-subject not given') | |
if options.message_body_file is None: | |
parser.error('message-body-file not given') | |
if not (options.no_send or options.no_message): | |
if options.server_address is None: | |
parser.error('server-address not given') | |
if options.server_port is None: | |
parser.error('server-port not given') | |
if options.server_user is None: | |
parser.error('server-user not given') | |
with open(options.people_file) as peopleFile: | |
people = [ tuple(row) for row in csv.reader(peopleFile, delimiter=',', quotechar='"') ] | |
if not options.no_message: | |
with open(options.message_body_file) as messageBodyFile: | |
messageBody = ''.join(messageBodyFile.readlines()) | |
if not (options.no_send or options.no_message): | |
passwordPrompt = 'Password for %s@%s: ' % (options.server_user, options.server_address) | |
server = smtplib.SMTP(options.server_address, options.server_port) | |
server.ehlo() | |
server.starttls() | |
server.ehlo() | |
server.login(options.server_user, getpass.getpass(passwordPrompt)) | |
while True: | |
permutation = np.random.permutation(len(people)) | |
if not any([ | |
people[b][2] == people[r][2] for b, r in | |
zip(permutation, np.roll(permutation, 1)) | |
]): | |
break | |
for b, r in zip(permutation, np.roll(permutation, 1)): | |
buyer, recipient = people[b], people[r] | |
if not options.no_message: | |
msg = MIMEMultipart() | |
msg['From'] = options.message_from | |
msg['To'] = buyer[1] | |
msg['Subject'] = options.message_subject | |
body = messageBody % (buyer[0], recipient[0], recipient[2], recipient[3]) | |
msg.attach(MIMEText(body, 'plain')) | |
if options.no_message: | |
print(buyer[0], "buys for", recipient[0]) | |
elif options.no_send: | |
print(msg) | |
else: | |
server.sendmail(msg['from'], msg['to'], msg.as_string()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment