-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
429: Building an Automatic Birthday Reminder Emailer
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.
There are no comments for now.