Skip to Content
Course content

429: Building an Automatic Birthday Reminder Emailer

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Imagine you have a personal assistant who wakes up every single morning, opens a physical ledger of all your friends' birthdays, and checks if today's date matches any of the entries. If they find a match, they don't just shout "Happy Birthday!" into the void; they grab a pre-written greeting card, scribble the friend's name at the top, and drop it in the mailbox. Then, they close the ledger and go back to sleep until tomorrow.

That's exactly what we're building here. In Python terms: the ledger is a CSV file, the assistant is our script, the "checking" is a loop comparing dates using the datetime module, and the mailbox is an SMTP server provided by your email provider.

Managing the Birthday Ledger

I've always found that for small utility scripts like this, a CSV file is the sweet spot. It's easier to edit in Excel than a JSON file, but it's still easy for Python to parse. You'll want a file named birthdays.csv with three columns: name,email,birthday (where the date is formatted as YYYY-MM-DD).

import csv
from datetime import datetime

def check_birthdays():
    today = datetime.now().strftime("%m-%d")
    with open("birthdays.csv", mode="r") as file:
        reader = csv.DictReader(file)
        for row in reader:
            # We only care about month and day for the reminder
            birthday = datetime.strptime(row["birthday"], "%Y-%m-%d").strftime("%m-%d")
            if birthday == today:
                send_reminder(row["name"], row["email"])

Notice how I used strftime("%m-%d"). We don't care about the year the person was born—unless you're building a system to track their actual age—just whether today is their special day.

Drafting and Sending the Message

Sending emails in Python can feel clunky because you're dealing with protocols from the 80s, but the smtplib and email.message libraries make it manageable. The key is to use EmailMessage; it's much more intuitive than the older MIMEMultipart approach.

import smtplib
from email.message import EmailMessage

def send_reminder(name, email_address):
    msg = EmailMessage()
    msg.set_content(f"Hey {name}, hope you have a fantastic birthday today!")
    msg["Subject"] = "Happy Birthday!"
    msg["From"] = "your_email@gmail.com"
    msg["To"] = email_address

    # I recommend using an 'App Password' if you're using Gmail
    with smtplib.SMTP_SSL("smtp.gmail.com", 465) as server:
        server.login("your_email@gmail.com", "your_app_password")
        server.send_message(msg)

A quick pro-tip: Never hardcode your password directly in the script if you're planning to push this to GitHub. I usually use environment variables or a separate .env file. Also, if you're using Gmail, you'll need to generate an "App Password" because Google will block a standard login attempt from a script for security reasons.

Automating the Wake-up Call

Right now, the script only runs when you manually execute it. To make it truly "automatic," you need the operating system to handle the timing. On Linux or macOS, you'd use a cron job. On Windows, you'd use the Task Scheduler.

I usually set mine to run at 9:00 AM daily. It's a satisfying feeling knowing your code is working in the background, maintaining your social life while you're still drinking your first cup of coffee.




📋 Practical Task

Adding Age Calculation to the Birthday Bot

Right now, the script only sends a generic "Happy Birthday" message. Your task is to modify the send_reminder function and the logic in check_birthdays to calculate exactly how old the person is turning based on the year in the CSV file.

Requirements:

  • Modify the script to subtract the birth year from the current year.
  • Update the email body to say something like: "Happy 25th Birthday, [Name]!" (or a generic "Happy Birthday" if the age calculation fails).
  • Ensure that the script still only sends the email if the month and day match today's date.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.