Files
032-birthday-wisher/docs/milestones/mil-002-birthday-wisher-core.md
2026-10-17 15:11:26 +08:00

3.8 KiB

MIL-002 Birthday Wisher Core

Metadata

Key Value
ID MIL-002
CrossReference BC-001, SA-001, MIL-001
Language en
Domain it

Version History

Date Status Author Reviewer Change Commit
2026-10-17 Accepted Jens Tirsvad Nielsen S01 Initial version; reviewed in RC-004 (Go) 052008f

Purpose

Decide whether the birthday wisher works: it finds today's birthdays, builds a letter and sends it, with tests that need no network and no credentials.

Deliverable

The birthday_wisher package: loading birthdays.csv, matching today's month and day, choosing a random template and replacing [NAME], sending by SMTP with STARTTLS, a main entry point, and a pytest suite. All public items carry Doxygen comments.

Go / No-Go Criteria

# Criterion (objectively checkable) Go No-Go
1 python -m pytest passes with no network access and without a .env file Go No-Go
2 A test proves that a person whose month and day equal today receives exactly one letter and nobody else does Go No-Go
3 A test proves that [NAME] is replaced and every one of the three templates can be chosen Go No-Go
4 A test with a fake SMTP object proves STARTTLS is called before login and that the subject is "Happy Birthday" Go No-Go
5 No source or test file imports or reads .env; the token is read from the GMAIL_TOKEN environment variable only Go No-Go
6 The code is reviewed against qc-programming-python and the review record says Go Go No-Go

Dependencies

Depends on Reason
MIL-001 Needs the skeleton, constants and data files

Traceability

Business Case objective / KPI / user story Reference
Objectives 1, 2 and 3 BC-001
S01, S02 concerns SA-001

Ownership

Role Stakeholder ID (SA)
Owner S01
Approving reviewer S01

Target Date

2026-10-19 - within the schedule of the Business Case constraints.

Tasks

# Task Summary Needs its own Use Case/User Story? Reference
1 Load and match birthdays Read birthdays.csv with the standard csv module into a dictionary keyed by (month, day) as the course hint describes, and return the people whose key equals today's (month, day). Today is a parameter so tests can fix the date. No
2 Build the letter Choose one of the letter templates at random (the chooser is injectable for tests), and replace [NAME] with the person's name. Fail with a clear message when a template is missing. No
3 Send the letter by SMTP Send the letter with smtplib: connect to the host in constants.py, call starttls(), log in with the sender address and the GMAIL_TOKEN environment variable, and send with the subject "Happy Birthday". The SMTP class is injected; the token is never logged. No
4 Add main entry point Wire the pieces together in main.py (composition root): load, match, build, send. Add a --dry-run option that prints instead of sending, used for screenshots and by learners without credentials. Exit with a non-zero status on error. No
5 Write pytest tests Cover matching, letters, sending with a fake SMTP and the entry point with a fixed date. Tests use temporary files and never touch the network or .env. No
6 Review code against the Python checklist Review src/ and tests/ against qc-programming-python, write the RC-* record and fix findings before the pull request. No