SMTP でメールを受け取り Maildir / JSON に保存するだけの開発用メール受信ツール
Project description
maildirsink
A tiny tool that receives mail over SMTP and just saves it to a file. Like a development mail sink such as mailpit, but with no UI and no forwarding — it sticks to one job: receive and store.
日本語版は README-ja.md を参照してください。
Why
In the find-job project, notification mail was written directly into a Maildir by a shell script. maildirsink extracts just that "store mail locally" part into a general-purpose tool.
It commits to standard Maildir as the storage target, so it slots straight into Maildir-native MUAs (mutt / neomutt) and existing Maildir tooling (procmail, mbsync, and friends).
What it does
- On startup, listens as an SMTP server on the given port.
- On receiving a message, stores it in the given directory in the given format.
- Nothing else — no forwarding, no web UI.
Storage formats
-
maildir — standard Maildir. Incoming mail is written to
tmp/and then moved intonew/(the unread-mail spool). Filenames follow the standard uniqueness-guaranteeing scheme (time.Ppid.hostname). mutt / neomutt scannew/directly, so no extra setup is needed. -
json — one JSON file per message:
{ "subject": "...", "from": "...", "to": "...", "date": "...", "message_id": "...", "body": "..." }
Note: Direct delivery to Thunderbird is intentionally out of scope. Thunderbird keeps a
.msfsummary cache and won't notice mail written into a Maildir from outside until you "Repair Folder". Maildir-native MUAs like mutt don't have this problem and pick up mail dropped intonew/immediately.
Install
pip install .
# or, for development:
pip install -e ".[dev]"
Usage
maildirsink [--port PORT] [--host HOST] [--format maildir|json] [--dir DIR]
| Option | Meaning | Default |
|---|---|---|
--port |
SMTP listen port | 1025 |
--host |
Listen host | localhost |
--format |
Storage format (maildir / json) | maildir |
--dir |
Storage directory | ./mail |
Exposing on a LAN
The default localhost only accepts mail sent from the same host. To receive
from another host (a container, a find-job instance on the LAN, etc.), listen on
all interfaces:
maildirsink --host 0.0.0.0 --port 1025
Warning: There is no authentication and no TLS. Use it only within a trusted LAN. Do not expose it directly to the internet.
Reading mail (mutt / neomutt)
Just point your MUA at the Maildir that maildirsink writes to. Because there is
no index cache like .msf, no repair step is ever needed.
set mbox_type = Maildir
set folder = "/path/to/maildir"
set spoolfile = "+."
mailboxes = "/path/to/maildir"
# Pick up mail that arrives while mutt is running
set mail_check = 5 # seconds
set timeout = 10
Once mail lands in new/, mutt reflects it automatically.
Implementation notes
- Written in Python.
- SMTP server:
aiosmtpd(the stdlibsmtpdwas removed in Python 3.12). - Maildir writing: the stdlib
mailbox.Maildir.Maildir.add()handles thetmp/→new/sequence and filename uniqueness for you (reference/maildir-delivery.shis a hand-written example of the same).
- SMTP server:
- Character sets: MIME-encoded headers (
=?UTF-8?B?...?=) are decoded.
Tests
pytest
License
MIT — see LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file maildirsink-0.1.0.tar.gz.
File metadata
- Download URL: maildirsink-0.1.0.tar.gz
- Upload date:
- Size: 10.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0f827eac2fc29a6a4043e2e0b94f5ab2e4b5667bf4ae3974f8ba5eee7093a057
|
|
| MD5 |
299ac1c67d0cf56f695ef0a2c72cc38b
|
|
| BLAKE2b-256 |
542ae68bb2298833ee8d28c14e17e0415c272bf120fea4ae624b4a6827b8512b
|
File details
Details for the file maildirsink-0.1.0-py3-none-any.whl.
File metadata
- Download URL: maildirsink-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5cec864e49398ea50908e4b6247857189247d33b42af11c6463d88095f1f3ddf
|
|
| MD5 |
ffa1cb0bcb7aa1e42a033a421f42772a
|
|
| BLAKE2b-256 |
05b8acff2218afd6cfb59b74bb7e6578d828d7cf7db8baa72e4f4b31c2c3c65f
|