| notifier | ||
| .gitignore | ||
| config.py | ||
| config.toml.example | ||
| imap_client.py | ||
| install.sh | ||
| LICENSE | ||
| main.py | ||
| models.py | ||
| README.MD | ||
| rules.py | ||
mailalertd
A lightweight email monitoring daemon that watches your IMAP mailbox and fires alerts the moment a message matches your rules — via Telegram, XMPP, or both.
No polling web interfaces. No bloated dependencies. Just a tight Python daemon that does one thing well.
New email arrives → matches rule → alert sent in seconds
↘ no match → left as unread in your mailbox
Features
- Real IMAP support — IMAPS and STARTTLS, with automatic reconnection on failure
- Flexible rules — filter by sender, subject (substring or regex), or body (regex), with AND/OR logic
- Modular notifications — Telegram works out of the box; XMPP ready to enable; new channels trivial to add
- Respects your inbox — emails that don't match any rule are reverted to unread, so your mail client still sees them
- HTML email handling — extracts readable text from HTML emails, strips scripts and styles
- Credentials via env vars — no plaintext secrets in config files
- First-class daemon support — systemd (Linux) and rc.d with daemon(8) (FreeBSD), with a one-command installer
Requirements
- Python 3.11+
requests(installed automatically by the installer)slixmpp— only if you use XMPP (installed automatically)
Installation
git clone https://github.com/youruser/mailalertd
cd mailalertd
sudo sh install.sh
The installer will:
- Detect your OS (Linux/systemd or FreeBSD/rc.d)
- Ask for an installation path (default:
/opt/mailalertdor/usr/local/mailalertd) - Create a dedicated
mailalertdsystem user - Copy program files and install config under
/etc/mailalertd/(or/usr/local/etc/mailalertd/) - Create a
secrets.envfile for your credentials (mode600) - Install and register the service unit
- Install
pip,requests, andslixmppautomatically
After installation:
# 1. Edit config
$EDITOR /etc/mailalertd/config.toml
# 2. Fill in credentials
$EDITOR /etc/mailalertd/secrets.env
# 3. Start
systemctl enable --now mailalertd # Linux
# or
echo 'mailalertd_enable="YES"' >> /etc/rc.conf && service mailalertd start # FreeBSD
Configuration
Copy config.toml.example to config.toml to get started. Every option is documented inline.
IMAP
[imap]
hostname = "mail.example.com"
connection = "imaps" # or "starttls"
username = "you@example.com"
password_env = "IMAP_PASSWORD" # reads from environment variable
check_interval = 30 # seconds between polls
Notifications
Enable one or more channels:
[notifications]
enabled = ["telegram"] # or ["telegram", "xmpp"]
Telegram — get a token from @BotFather, your chat ID from @userinfobot:
[telegram]
bot_token_env = "TELEGRAM_TOKEN"
chat_id = "123456789"
XMPP — any standard Jabber account works:
[xmpp]
jid_env = "XMPP_JID"
password_env = "XMPP_PASSWORD"
recipient = "you@jabber.org"
Credentials
Every sensitive value supports two forms — pick one:
# Recommended: read from environment variable
password_env = "IMAP_PASSWORD"
# Alternative: plaintext (never commit this to git)
# password = "hunter2"
Set your variables in /etc/mailalertd/secrets.env:
IMAP_PASSWORD=your_imap_password
TELEGRAM_TOKEN=123456789:ABCdef...
Filtering rules
Rules are evaluated top-to-bottom. The first match wins.
# Notify on any email with "ALERT" in the subject
[[rule]]
name = "Monitoring alerts"
subject_contains = "ALERT"
# Notify on urgent emails from your boss
[[rule]]
name = "Boss emails"
from = "boss@company.com"
subject_regex = "(?i)(urgent|important)"
# OR logic — match if subject OR body mentions "critical"
[[rule]]
name = "Any critical mention"
match = "any"
subject_regex = "(?i)critical"
body_regex = "(?i)critical"
Available matchers:
| Field | Description |
|---|---|
from |
Exact sender address |
subject_contains |
Subject contains this string |
subject_regex |
Subject matches this regex |
body_regex |
Body matches this regex |
match = "all" (default) requires every field to match. match = "any" fires on the first field that matches.
Logs
Logs go to stdout and are captured by the init system:
journalctl -u mailalertd -f # Linux
tail -f /var/log/mailalertd/mailalertd.log # FreeBSD
Log level is configurable in config.toml:
[logging]
level = "info" # debug | info | warning | error
Running manually
export IMAP_PASSWORD="..."
export TELEGRAM_TOKEN="..."
python3 main.py
# Custom config path
MAILALERTD_CONFIG=/path/to/config.toml python3 main.py
Adding a new notification channel
- Create
notifier/yourchannel.pyextendingBaseNotifier - Implement
send(self, message: str) -> None - Add an entry to
_REGISTRYinnotifier/loader.py - Add a
[yourchannel]section toconfig.toml - Add
"yourchannel"to[notifications] enabled
That's it. The loader picks it up automatically.
Project structure
mailalertd/
├── main.py # Main loop, signal handling, logging
├── config.py # Config loader (TOML)
├── imap_client.py # IMAP client — fetch, flag management, HTML extraction
├── models.py # Mail dataclass
├── rules.py # Rule engine (AND / OR)
├── config.toml.example # Documented config template
├── install.sh # Installer (Linux + FreeBSD)
└── notifier/
├── base.py # BaseNotifier interface
├── loader.py # Dynamic notifier registry
├── telegram.py # Telegram Bot API
└── xmpp.py # XMPP via slixmpp
License
This is free and unencumbered software released into the public domain. See The Unlicense for details.