Lightweight IMAP email monitoring daemon. Watches your mailbox, fires alerts via Telegram or XMPP when emails match your rules, and leaves everything else unread. Runs as a systemd or FreeBSD rc.d service.
Find a file
2026-06-01 11:29:03 +02:00
notifier first commit 2026-05-31 21:45:05 +02:00
.gitignore first commit 2026-05-31 21:45:05 +02:00
config.py first commit 2026-05-31 21:45:05 +02:00
config.toml.example first commit 2026-05-31 21:45:05 +02:00
imap_client.py first commit 2026-05-31 21:45:05 +02:00
install.sh first commit 2026-05-31 21:45:05 +02:00
LICENSE first commit 2026-05-31 21:45:05 +02:00
main.py first commit 2026-05-31 21:45:05 +02:00
models.py first commit 2026-05-31 21:45:05 +02:00
README.MD first commit 2026-05-31 21:45:05 +02:00
rules.py Update rules.py 2026-06-01 11:29:03 +02:00

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:

  1. Detect your OS (Linux/systemd or FreeBSD/rc.d)
  2. Ask for an installation path (default: /opt/mailalertd or /usr/local/mailalertd)
  3. Create a dedicated mailalertd system user
  4. Copy program files and install config under /etc/mailalertd/ (or /usr/local/etc/mailalertd/)
  5. Create a secrets.env file for your credentials (mode 600)
  6. Install and register the service unit
  7. Install pip, requests, and slixmpp automatically

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

  1. Create notifier/yourchannel.py extending BaseNotifier
  2. Implement send(self, message: str) -> None
  3. Add an entry to _REGISTRY in notifier/loader.py
  4. Add a [yourchannel] section to config.toml
  5. 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.