Narakura
Unexpert Bosun
Every Skunk Christmas deserves a festive feast. It’s time to celebrate the season with our cherished tradition: Secret Santa, spreading holiday cheer among old friends. We've been doing this for years, and with each one, we get a little better at it :D
Here's the page contents:
The usual way of organizing Secret Santa is to get everyone together and draw names from a hat, which is a nice tradition. However, we’re always running late and rarely find time to gather everyone for the draw. So, we decided to automate the process this year. This is the code we used in 2024. It’s not great, but it worked well enough. God bless GPT algorithms :D
Here’s a function to generate participant matching for Secret Santa. It supports restrictions, so you can avoid situations like gifting something to your significant other or any other pairing you want to prevent.
import random
def Match_Participants(participants_dictionary, restriction_tuple):
givers = list(participants_dictionary.keys())
receivers = list(participants_dictionary.keys())
for _ in range(1000):
random.shuffle(receivers)
match = []
used_receivers = set()
for giver in givers:
for receiver in receivers:
if (
giver != receiver and
(giver, receiver) not in restriction_tuple and
(receiver, giver) not in restriction_tuple and
receiver not in used_receivers
):
match.append((giver, receiver))
used_receivers.add(receiver)
break
if len(match) == len(givers):
return match
raise ValueError("Error :(")
Here's the function to send the emails to participants based on the generated matching.
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
def Send_Secret_Santa_Email(participants, giver_receiver_tuple):
sender_email = "skunktroopers@gmail.com"
app_password = "ABCD ABCD ABCD ABCD" # Password of "Google App Passwords"
subject = "🎅 Secret Santa 2024! 🎁" # Substitute with correct year
giver = giver_receiver_tuple[0]
receiver = giver_receiver_tuple[1]
giver_email = participants[giver]
# Substitute body with whatever
body = f"""Hey {giver},
Anche quest’anno è tornato il momento del Secret Santa :D
Il tuo compito sarà trovare un regalo per {receiver}. Non dirlo a nessuno! (che altrimenti va tutto in merda).
Ti ricordiamo che non esistono requisiti di spesa per il regalo, basta che sia fatto con tanto amore ❤️
Alla data del ritrovo, porta il regalo incartato e – se possibile – all’interno di un sacchetto anonimo.
Ti ringraziamo per la partecipazione e ti auguriamo un felice natale.
Distinti saluti,
The SkunkTroopers Staff
P.S. Se non ha funzionato mi uccido.
"""
msg = MIMEMultipart()
msg['From'] = sender_email
msg['To'] = giver_email
msg['Subject'] = subject
msg.attach(MIMEText(body, 'plain'))
try:
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(sender_email, app_password)
server.sendmail(sender_email, giver_email, msg.as_string())
print("Sending email to ",giver_email+"... Email sent successfully!")
except Exception as e:
print(f"Error: {e}")
finally:
server.quit()
Here's a function that sends the generated matching to someone external and not participating in the secret santa, so that they can validate manually that the matching is correct (e.g. to make sure no one will receive more than one gift).
def Send_Match_For_Validation(match):
sender_email = "skunktroopers@gmail.com"
app_password = "ABCD ABCD ABCD ABCD"
receiver_email = "XYZ@gmail.com" # <-- Email of external third party that will validate the matching
subject = "Match validation"
body = f"""
{match}
Le tuple sono (Giver, Receiver).
Verificare che:
- Ciascuno è giver solo una volta e receiver solo una volta
- Nessuno faccia un regalo a sè stesso
- Pane e Marta non si facciano regali
"""
msg = MIMEMultipart()
msg['From'] = sender_email
msg['To'] = receiver_email
msg['Subject'] = subject
msg.attach(MIMEText(body, 'plain'))
try:
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(sender_email, app_password)
server.sendmail(sender_email, receiver_email, msg.as_string())
print("Sending match validation to",receiver_email+"... Email sent successfully!")
except Exception as e:
print(f"Error: {e}")
finally:
server.quit()
The trigger function executes the sequence.
def Trigger(participants_dictionary, restriction_tuple):
match = Match_Participants(participants_dictionary, restriction_tuple)
Send_Match_For_Validation(match)
for couple in match:
Send_Secret_Santa_Email(participants=participants_dictionary, giver_receiver_tuple=couple)
print("Done! :D")
To use the code it is enough to:
The following is an example:
# Participants dictionary:
participants = {
"Jack":"jack@email.com",
"Marta":"marta@email.com",
"Pane":"pane@email.com",
"Bob":"bob@email.com",
"Jonah":"jonah@email.com",
"Masi":"masi@email.com",
"Patrick":"patrick@email.com",
"Teo":"teo@email.com"
}
# List of restriction tuples
restrictions = [("Marta","Pane")]
# Launch automation
Trigger(participants_dictionary=participants, restriction_tuple=restrictions)