It’s that time of year again. Christmas. Buying presents is a chore and stressful, so a popular option is Secret Santa. Buying for one is better than buying for several! But there’s always the problem of who does the selection so it’s secret for everyone?
In this post I’ll share how I make Secret Santa allocations using Python. The program randomises the allocation and automatically sends the emails to each person informing them who they are buying for from your designated email account. It ensures nobody is allocated themselves and the master list is stored just in case it is needed. Sure, there are a plethora of apps that can do this but it’s fun to do it yourself. Plus, you’ll probably use the app once, forget about it for the following year, have to re-learn how to use it and need to input all the data again. With your own script in Python you’ll always know you have it and know how to use it. Each following year it will only take a minute or two and the allocations are done.
The full code template is on Github or at the bottom of this post.
Email list
Arguably the most amount of work needed is ensuring your email list is up to date. All those participating need to be listed in the dictionary. There are no checks to ensure the email addresses entered are valid so it’s important to double check them and ensure they are correct.
# EMAIL DICTIONARY
# replace the names and emails with those participating
# example emails only
fam = {
'Alice' : 'alice@gmail.com',
'Bob' : 'bob@gmail.com',
'Chris' : 'chris@gmail.com',
'Daniel' : 'daniel@hotmail.com',
'Evelyn' : 'evelyn@gmail.com',
'Fred' : 'fred@gmail.com'
}
The allocation
The allocation is made simply by first shuffling the names list then pairing the list with itself at lag 1. This way you can be sure no one will be allocated themselves. For example, assume the names list was shuffled [Evelyn, Chris, Fred, Bob, Alice, Daniel]. This list is labelled Santa. The Santa list is then shifted by 1 to create the receiver list, [Daniel, Evelyn, Chris, Fred, Bob, Alice]. Done.
# SELECT SECRET SANTAS
santa = list(np.random.choice(list(fam.keys()), len(list(fam.keys())), replace = False))
recvr = []
for k in range(-1, len(santa)-1):
recvr.append(santa[k])
The emails
Once the allocation is done the emails are sent to each Santa using the smtplib
package. This package allows you to send emails from your designated account directly from Python. It is best done using a Gmail account (pretty sure hotmail is fine but not sure about others).
The connection is first established, then python will ask for your email and account password. These can be hard coded for ease but that’s up to you if you want to take on that extra risk.
Once Python has logged in it will send an email to each Santa individually. This is where you can get creative with your message in the email. Write a poem or send a picture or gif, just make sure you input who they are buying for!
# STARTING EMAILS
smtpObj = smtplib.SMTP('smtp.gmail.com', 587)
smtpObj.ehlo()
smtpObj.starttls()
eml = raw_input('Enter your email: ')
pwd = raw_input('Enter login details: ')
smtpObj.login(eml, pwd)
# SENDING EMAILS
for k in range(len(fam)):
smtpObj.sendmail(eml, fam[santa[k]], \
'Subject: Secret Santa 2018 \
\nHo Ho Ho %s! \
\n\nChristmas is almost here, \
\nTime to find that Christmas cheer! \
\n\nThis year you are buying for....... %s! \
\n\nThis was sent on %s.' % (santa[k], recvr[k], date))
# QUIT SERVER
smtpObj.quit()
Before any emails can be sent from your account you’ll need allow less secure apps to access your account. To do this go to your Google account, select ‘Sign-in & Security’, scroll to the bottom and toggle ‘allow less secure apps’ to ON. You’ll get an email straight away from Google saying your account is not secure, which is fair enough, so it’s good to do this just before you send the emails and switch it back to off afterwards. This can be done with other emails but I’m only familiar with Googs.
Store the list
Finally, it is good practice to save the master list in case it is needed.
# STORE SELECTIONS FOR SAFE KEEPING
santadf = pd.DataFrame({'santa':santa, 'recvr':recvr})
santadf.to_csv('Secret Santa list ' + datem + '.csv')
Send, sit back and receive
And that’s it, Secret Santa allocations made. This is a simple template for sending a list but should be easy to add in constraints e.g. spouses don’t get each other, get someone different from last year, etc.
The only other thing to remember is you will have a number of sent emails from your account which will have the Santa and receiver so you could accidentally find out who your Santa is. Also, if a family member replies to the email it could also reveal your Santa. Maybe it would be wise to look into do-not-reply tags!
The code
# SECRET SANTA # LIBRARIES import numpy as np, import datetime import pandas as pd import smtplib # DATE AND TIME dt = datetime.datetime.now() date = dt.strftime('%Y-%m-%d at %I:%M%p') datem = dt.strftime('%Y-%m-%d') # EMAIL DICTIONARY # replace the names and emails with those participating # example emails only fam = { 'Alice' : 'alice@gmail.com', 'Bob' : 'bob@gmail.com', 'Chris' : 'chris@gmail.com', 'Daniel' : 'daniel@hotmail.com', 'Evelyn' : 'evelyn@gmail.com', 'Fred' : 'fred@gmail.com' } # SELECT SECRET SANTAS santa = list(np.random.choice(list(fam.keys()), len(list(fam.keys())), replace = False)) recvr = [] for k in range(-1, len(santa)-1): recvr.append(santa[k]) # STARTING EMAILS smtpObj = smtplib.SMTP('smtp.gmail.com', 587) smtpObj.ehlo() smtpObj.starttls() eml = raw_input('Enter your email: ') pwd = raw_input('Enter login details: ') smtpObj.login(eml, pwd) # SENDING EMAILS for k in range(len(fam)): smtpObj.sendmail(eml, fam[santa[k]], \ 'Subject: Secret Santa 2018 \ \nHo Ho Ho %s! \ \n\nChristmas is almost here, \ \nTime to find that Christmas cheer! \ \n\nThis year you are buying for....... %s! \ \n\nThis was sent on %s.' % (santa[k], recvr[k], date)) # QUIT SERVER smtpObj.quit() # STORE SELECTIONS FOR SAFE KEEPING santadf = pd.DataFrame({'santa':santa, 'recvr':recvr}) santadf.to_csv('Secret Santa list ' + datem + '.csv')Follow me on social media: