ADHD IMAP Sync is a lightweight Alpine-based container that combines goimapnotify and fetchmail to instantly process incoming mail and deliver it to your local MDA (LMTP/SMTP, etc.).
The idea is simple: IMAP IDLE via goimapnotify
detects new mail and immediately wakes up fetchmail
to retrieve and deliver it locally. π¬β‘
- π¨ Instant trigger on new messages (IMAP IDLE)
- π οΈ Support for unlimited mail accounts
- π Configuration via environment variables or Docker secrets
- π Auto-regenerated configs on container restart
- π Passwords via
_FILE
support - ποΈ Flexible delivery: LMTP (TCP/UNIX), SMTP, or custom commands
Example compose.yml
:
services:
adhd-imap-sync:
image: ghcr.io/kriakiku/adhd-imap-sync:latest
container_name: adhd-imap-sync
restart: unless-stopped
secrets:
- imap_work_pass
volumes:
- ./data:/config
environment:
TZ: UTC
PUID: "1000"
PGID: "1000"
# Default settings
ADHD_IMAP_HOST: "imap.example.com"
ADHD_DELIVERY_TARGET: |
mda "/usr/bin/maildrop -d %T"
# Default account (no suffix)
ADHD_IMAP_USER: "user@example.com"
ADHD_IMAP_PASS: "SECRET1"
# Extra account with "WORK" suffix
ADHD_IMAP_USER_WORK: "work@example.com"
ADHD_IMAP_PASS_FILE_WORK: "/run/secrets/imap_work_pass"
ADHD_DELIVERY_TARGET_WORK: |
lmtp
smtpname "work@target.com"
smtphost /var/run/dovecot/lmtp
# smtphost dovecot/24
secrets:
imap_work_pass:
file: ./imap_work_pass.txt
Variable | Default | Description | Example |
---|---|---|---|
ADHD_IMAP_HOST |
(none) | IMAP server hostname | imap.example.com |
ADHD_IMAP_PORT |
993 |
IMAP port | 143 |
ADHD_IMAP_TLS |
true |
Use SSL/TLS for IMAP (true or false ) |
false |
ADHD_IMAP_USER |
(none) | IMAP username | user@example.com |
ADHD_IMAP_PASS |
(none) | IMAP password (or use _FILE ) |
secret |
ADHD_IMAP_PASS_FILE |
(none) | Path to file containing IMAP password | /run/secrets/imap_work_pass |
ADHD_DELIVERY_TARGET |
(none) | Fetch mail config part (LMTP/SMTP/MDA) | mda "/usr/bin/maildrop -d %T" |
ADHD_POLL_INTERVAL |
300 |
Fetchmail polling interval in seconds | 60 |
ADHD_WAKE_MIN |
3 |
Minimum delay in seconds between wake-up signals | 5 |
ADHD_KEEP |
keep |
Whether to leave messages on the server (keep or no keep ) |
no keep |
You can define multiple mail accounts by appending a suffix (e.g., _WORK
, _ME
, _GMAIL
) to the variable names.
Each suffix will be treated as a separate account, with its own configuration.
If a variable is not set for a suffix, it will fall back to the default account values (without a suffix).
Account Name Generation:
- If suffix is empty β account name is
"default"
. - If suffix exists β account name is the suffix in lowercase (e.g.,
_WORK_UA
β"work_ua"
).
Example with multiple accounts:
# Default account
ADHD_IMAP_HOST=imap.example.com
ADHD_IMAP_USER=user@example.com
ADHD_IMAP_PASS=secret
# Work account
ADHD_IMAP_HOST_WORK=imap.work.com
ADHD_IMAP_USER_WORK=me@work.com
ADHD_IMAP_PASS_FILE_WORK=/run/secrets/imap_work_pass
Fetchmail stores the identifiers of processed messages in the file /config/.fetchids
(used via the --idfile /config/.fetchids
option).
This file ensures that already retrieved emails are not processed again after container restarts.
You can mount a persistent volume to /config
to preserve this state:
volumes:
- ./data:/config
You can provide a .netrc
file for authentication either by mounting it as /config/.netrc
.
- goimapnotify connects to IMAP and listens for new mail using IDLE.
- When a new message arrives, it calls /usr/local/bin/fetchmail-wakeup.
- fetchmail retrieves messages and delivers them to the configured ADHD_DELIVERY_TARGET.
I run a self-hosted mail server (Stalwart) on my home server. But home servers arenβt exactly the most stable environment β in the last 3 years I had to move 5 times (thanks to one deranged dictator), and sometimes there are internet outages.
To keep my email reliable, I use MXroute for both sending and receiving. Stalwart lets me use external SMTP servers to send mail, but I couldnβt find a way to pull mail from external inboxes (would be hilarious if it actually exists π ).
So, I turned to Fetchmail β but hereβs the catch: it doesnβt support IMAP IDLE (push notifications for new mail). Instead, it just polls every few minutes. Not good enough β I want my OTP codes instantly β‘π².
Thatβs when I found GoIMAPNotify, which does support IMAP IDLE and can trigger commands when new mail arrives. Perfect match! So I built a Docker image that automatically generates configs for both tools and makes them work together.
Maybe someone else finds this handy too. π
- Add
tlsOptions
support forgoimapnotify
:unauthorized
flag (allow self-signed certs)starttls
support
- Add per-account mailbox selection support (currently all mailboxes are monitored)