I was asked to organise a Secret Santa, so I did it in Python!

Christmas is just around the corner. How is your Christmas preparation going?

I recently been asked to organise a Secret Santa for me and my friends. In case you don’t know what Secret Santa is, “Secret Santa is a Western Christmas tradition in which members of a group or community are randomly assigned a person to whom they give a gift. The identity of the gift giver is a secret not to be revealed.”

But the problem is, it might be too much hassle for everyone to meet up just to draw the names and assign secret Santa. I know there’s already a website you can use for organising Secret Santa, but I wanted to put my Python skills into test to see what I can come up with.

Even though I’ve been using Python as a tool for data science, I haven’t written a full Python software before, and the environment I’m familiar with is Jupyter Notebook. So, this is not about full program you can deploy as an app, but a rather simple Python code blocks you can run on your Jupyter notebook.

This was a fun small project for me, since I haven’t coded any general purpose Python code before, and the code I have been writing for my study is all about making data analysis and making predictive models.

First, let’s start by loading dependencies to use in the code.

import copy
import random
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.MIMEBase import MIMEBase
from email import encoders

Next step is to define the names and email addresses of the people, who will be in the Secret Santa.

names = ['Person A','Person B','Person C','Person D']
emails = ['Person A email address','Person B email address','Person C email address','Person D email address']

Now we have to define our Secret Santa function. Before I start coding, I thought this will be easily done, but when I started coding I realised this is more complicated than I thought. First thing need to be considered is one person should not draw his/her own name, and once one name has been drawn, this needs to be eliminated from the list, so that the next person will not draw the same name.

def secret_santa(names):
my_list = names
choose = copy.copy(my_list)
result = []
for i in my_list:
names = copy.copy(my_list)
names.pop(names.index(i))
chosen = random.choice(list(set(choose)&set(names)))
result.append((i,chosen))
choose.pop(choose.index(chosen))
return result

The above function will return a list of tuples, and each tuple contains the name of the person who will give the present as the first entry, and the person who should receive the present as the second entry.

And in my case, I am also participating in the secret Santa, and I didn’t want look at the result and ruin the fun. So I assigned the result to a variable without looking to use it to send as emails.

ss_result = secret_santa(names)
final = zip(ss_result,emails)

The next part is the actual email sending part. If your email address is gmail, you can easily run this code just by putting your password into the code. And I also attached an image to the email. You can attach any image you want, as long as you put it in the same directory as the notebook, and pass this name together with extension in “filename”, and “attachment” in below code block.

for x in final:
fromaddr = "your email address"
toaddr = x[1]
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = "SECRET EMAIL FOR SECRET SANTA!"

body1 = "Hello, "+str(x[0][0])
body2 = '''!\n This is an automated email from (your name)'s Secret Santa Python Program.\n\nYou drew\n.......\n........\n........\n'''+str(x[0][1])+"!!\n\nRule Number 1: Please do not tell anyone!\n"
body3 = "Rule Number 2: The budget is 10GBP! \nWhat are you waiting for? Go ahead and get something nice for "+str(x[0][1])+"!\n\n\n"
body = body1+body2+body3
msg.attach(MIMEText(body, 'plain'))

filename = "The image file you put in the same directory with this file"
attachment = open("The image file you put in the same directory with this file(ex: xxxx.jpg)", "rb")

part = MIMEBase('application', 'octet-stream')
part.set_payload((attachment).read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename= %s" % filename)

msg.attach(part)


server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(fromaddr, "your gmail password")
text = msg.as_string()
server.sendmail(fromaddr, toaddr, text)
server.quit()
print "mail sent to",x[1]

The only problem of this is, if you are also in the Secret Santa, you can find out who drew who by checking your gmail sent box. But why would you ruin the fun? As long as you don’t open the sent emails in your sent box, you can still have fun!

I guess there could be more elegant and pythonic way to do the same thing, but for now I am happy that I did automate something with Python, and can’t wait to find out who my secret Santa is. And no, I won’t check my gmail sent box until Christmas.

Merry Christmas!!

You can find the Jupyter Notebook with the code from below link.

https://github.com/tthustla/Secret_Santa/blob/master/Secret_Santa.ipynb