Skunk Christmas

A collection of Christmas dinners and Secret Santas

Narakura
Unexpert Bosun

Every December

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:

Automating Santa 🎅

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:

  1. Create a dictionary with the participants and their email addresses
  2. Create a list of tuples containing the restrictions (i.e. people that must not be matched)
  3. Pass the dictionary and the list of restrictions to the trigger function

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)
    

Back to Top
Free icons from flaticon.com
Poorly built by J.G. in 2024