Skip to content

Instantly share code, notes, and snippets.

@will-bainbridge
Last active October 27, 2021 20:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save will-bainbridge/a4666a196fb5833cf37035647b74c064 to your computer and use it in GitHub Desktop.
Save will-bainbridge/a4666a196fb5833cf37035647b74c064 to your computer and use it in GitHub Desktop.
#!/usr/bin/python3
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 of the people 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',
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([
set(people[b][-1].split()) & set(people[r][-1].split()) 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])
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