Commit 8dc1efd2 authored by H. Fischer's avatar H. Fischer
Browse files

Upload files

parent 1716fb99
Loading
Loading
Loading
Loading

.gitignore

0 → 100644
+3 −0
Original line number Diff line number Diff line
teilnehmer.json
pairs.dump
mails/
 No newline at end of file

mail.py

0 → 100644
+52 −0
Original line number Diff line number Diff line
"""This module manages sending and saving mails. Most of the code is adopted
from Jakob's implementation of a digital Kurswahl for the GT. Thank you for the
help!"""

import ssl
from email import charset
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import formatdate

from smtplib import SMTP
from typing import Optional

_connection: Optional[SMTP] = None
# Encode utf-8 strings using utf-8, and not base-64
# See https://bugs.python.org/issue12552
charset.add_charset('utf-8', charset.SHORTEST)

def open_connection():
    global _connection
    _connection = SMTP("mail.urz.uni-heidelberg.de", 587)
    _connection.starttls(context=ssl.create_default_context())

def send_mail(msg: MIMEMultipart, auto_close_connection: bool = True):
    if _connection is None:
        open_connection()
    try:
        print(f"Sending to {msg['To']}...")
        _connection.send_message(msg)
    finally:
        if auto_close_connection:
            close_connection()

def save_mail(file, msg):
    with open(file, "wb") as f:
        f.write(msg.as_bytes())

def generate_mail(recipient, content):
    msg = MIMEMultipart()
    msg["From"] = "knecht-robobert@cl.uni-heidelberg.de"
    msg["To"] = recipient
    msg["Date"] = formatdate(localtime=True)
    msg["Subject"] = "Wunderbares Winterwichteln"
    msg["Bcc"] = "knecht-robobert@cl.uni-heidelberg.de"
    text = MIMEText(content)
    msg.attach(text)
    return msg

def close_connection():
    global _connection
    _connection.quit()

main.py

0 → 100644
+67 −0
Original line number Diff line number Diff line
import argparse
import os
import json
from mail import generate_mail, save_mail, open_connection, close_connection, send_mail
from sampling import HamiltonSampler

SAMPLERS = {"hamilton": HamiltonSampler}
MAILDIR = "./mails"
os.makedirs(MAILDIR, exist_ok=True)
MAIL_TEMPLATE = "./src/assignment_mail.txt"

def prepare_mail_content(giver, presentee):
    with open(MAIL_TEMPLATE, "r") as f:
        text = f.read()
    text = text.replace("{giver_name}", giver["name"])
    for attribute in ["name", "fullname", "street", "city", "address_appendix"]:
        value = presentee[attribute] if attribute in presentee else ""
        text = text.replace(f"{{presentee_{attribute}}}", value)
    text = text.replace("{presentee_note}", f"Notiz der Person: {presentee['note']}" if "note" in presentee else "")
    return text


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("input", 
                        help="the input file containing the data of the participants")
    parser.add_argument("--sampling", 
                        choices=list(SAMPLERS.keys()),
                        default="hamilton",
                        help="The sampling strategy/algorithm for choosing pairs")
    args = parser.parse_args()


    # Load the people
    with open(args.input, "r") as f:
        people = json.load(f)
    print(f"Loaded {len(people)} participants")

    # Sample the pairs
    sampler = SAMPLERS[args.sampling](list(people.keys()))
    pairs = sampler.sample_pairs()
    with open("pairs.dump", "w") as f:
        json.dump(pairs, f, indent=4, ensure_ascii=False)

    # Generate mails
    mails = []
    for pair in pairs:
        giver, presentee = people[pair[0]], people[pair[1]]
        mail_content = prepare_mail_content(giver, presentee)
        mail = generate_mail(pair[0], mail_content)
        mails.append(mail)
        save_mail(f"{MAILDIR}/{pair[0]}.eml", mail)

    # Ask for confirmation
    print(f"Created {len(mails)} mails. Please check them in the folder {MAILDIR}.")
    command = input(f"Enter \"confirm\" to automatically send the mails. Please don't terminate the program, or the pairs will be lost.\n")

    if command != "confirm":
        print("Aborting...")
        exit()

    # Send the mails
    print("Sending mails...")
    open_connection()
    for msg in mails:
        send_mail(msg, auto_close_connection=False)
    close_connection()
 No newline at end of file

sampling.py

0 → 100644
+18 −0
Original line number Diff line number Diff line
import random

class Sampler():
    def __init__(self, elements):
        self.elements = elements

    def sample_pairs(self):
        raise NotImplementedError()

class HamiltonSampler(Sampler):
    def sample_pairs(self):
        pairs = []
        e = self.elements[:]
        random.shuffle(e)
        for i in range(len(e)):
            pairs.append((e[i], e[i+1 if i+1 < len(e) else 0]))
        return pairs
        
 No newline at end of file
+25 −0
Original line number Diff line number Diff line
Ho Ho Ho {giver_name}!

Ich freue mich sehr, dass du am diesjährigen Wichteln teilnimmst!

Du wichtelst für {presentee_name}.
Sende das Paket also bitte so bald wie möglich an folgende Adresse:

    {presentee_fullname}
    {presentee_street} {presentee_address_appendix}
    {presentee_city}

{presentee_note}

Denke an genügend Porto, damit das Geschenk auch rechtzeitig ankommt!
Damit das ganze schön anonym stattfinden kann, kannst du als Absendeadresse das Institut angeben, damit dein Paket im Notfall nicht verloren geht:

    Sekretariat, Raum 109a
    Im Neuenheimer Feld 325
    69120 Heidelberg

(Wenn das Paket allerdings nicht ausreichend frankiert ist, wird es natürlich trotzdem nicht angenommen werden können!)

Winterliche Grüße und eine tolle vorlesungsfreie Zeit

Knecht Robobert
 No newline at end of file