4.6 KiB
Birthday Manager
Self-hosted birthday reminder application that automatically e-mails people on their birthday.
© 2026 Martinhal IT - Joao Vaz - Version 1.2
Features
Page 1 — Dashboard
- Three panels at the top: Yesterday's Birthdays, Today's Birthdays (with the Force Send button to resend the e-mail) and Tomorrow's Birthdays
- Add / remove birthday entries: First Name, Last Name, Date of Birth, Gender, E-mail address
- Yearly calendar overview of all entries (hover a marked day to see the names; browse other years)
Page 2 — Administration
- Add / remove application users
- Every user can enable/disable MFA (TOTP — Google Authenticator, Authy, etc.) and change their own password
- Full e-mail log: who received mail, at what date & time, and whether it succeeded
- Setting for the time of day the automatic birthday e-mails are sent (applies immediately, no restart needed)
- Two template zones: E-mail Template Male and E-Mail Template Female, with placeholders
{first_name},{last_name},{age} - Image upload — select multiple files at once (15 MB total per upload); each image shows its ready-to-copy
<img src="/uploads/…">command, and images are embedded inline in the outgoing e-mail
Automatic sending: a scheduler runs every day at SEND_HOUR (default 08:00) and e-mails everyone whose birthday it is, using the template matching their gender. Duplicates are avoided (one automatic mail per person per day); Force Send always resends. February 29 birthdays are celebrated on February 28 in non-leap years.
Every successfully sent e-mail is also copied to the mailbox's Sent folder via IMAP, so it shows up in your normal mail client.
Mail provider
The app comes pre-configured for Purelymail:
| Server | Port | Security | |
|---|---|---|---|
| Outgoing (SMTP) | smtp.purelymail.com |
465 |
SSL/TLS |
| Incoming (IMAP, Sent-folder copy) | imap.purelymail.com |
993 |
SSL/TLS |
You only need to fill in SMTP_USER, SMTP_PASS and SMTP_FROM with your Purelymail mailbox credentials. If your network only supports STARTTLS for SMTP, set SMTP_PORT=587 and SMTP_SECURITY=starttls instead. Any other provider works too — just override the host/port variables.
Quick start (Docker — recommended)
- Edit
docker-compose.ymland fill in your Purelymail credentials (SMTP_USER,SMTP_PASS,SMTP_FROM) plus a randomSECRET_KEYand your timezone. - Run:
docker compose up -d --build
- Open http://localhost:8080 and log in with admin / admin — then change the password on the Administration page immediately.
All data (SQLite database + uploaded images) lives in ./data, so back up that folder.
Quick start (plain Python)
pip install -r requirements.txt
# Purelymail servers are the built-in defaults - only credentials are needed
export SMTP_USER=you@yourdomain.com
export SMTP_PASS=your-purelymail-password
export SMTP_FROM=you@yourdomain.com
export SEND_HOUR=8
export SECRET_KEY=$(python -c "import secrets;print(secrets.token_hex(32))")
python app.py
The app listens on port 8080 (PORT env var to change). Data is stored in ./data (DATA_DIR env var to change).
Environment variables
| Variable | Default | Purpose |
|---|---|---|
SMTP_HOST |
smtp.purelymail.com |
SMTP server |
SMTP_PORT |
465 |
SMTP port |
SMTP_USER |
– | SMTP username / mailbox |
SMTP_PASS |
– | SMTP password |
SMTP_FROM |
SMTP_USER |
From address |
SMTP_SECURITY |
ssl |
ssl, starttls or none |
IMAP_HOST |
imap.purelymail.com |
IMAP server for the Sent-folder copy |
IMAP_PORT |
993 |
IMAP port (SSL/TLS) |
IMAP_USER |
SMTP_USER |
IMAP username |
IMAP_PASS |
SMTP_PASS |
IMAP password |
IMAP_SENT_FOLDER |
Sent |
Mailbox folder sent mail is stored in |
SEND_HOUR |
8 |
Default hour for the daily send — the time picked on the Administration page overrides this |
SECRET_KEY |
random | Flask session key — set it so logins survive restarts |
PORT |
8080 |
HTTP port |
DATA_DIR |
./data |
Where the database and uploads are stored |
Notes
- The e-mail address field on entries is required because it is where the birthday greeting is sent.
- Failed sends (e.g. SMTP misconfigured) are also recorded in the e-mail log with the error as tooltip on the "Failed" status. If a mail is delivered but the IMAP copy to the Sent folder fails, the mail is still logged as Sent and the IMAP error appears as a tooltip.
- Run behind a reverse proxy (nginx / Caddy / Traefik) with HTTPS if you expose it beyond your LAN.