Features
difuzio covers the whole chain of a mailing list: receive, decide, transform, deliver, then handle what comes back. This page describes what is actually implemented and covered by the project's test suite.
Mail reception
Mail comes in over LMTP from a front mail server, or by polling an IMAP mailbox at a hosting provider.
An address classifier recognises the service-address grammar: post to the list,
subscribe, unsubscribe, contact the owners, VERP bounce, feedback-loop complaint.
It follows the reserved-suffix and longest-list-match rule, so a list named
announce-tech and a list named announce coexist without ambiguity.
List policies
Every list decides who may write to it: open to anyone, subscribers only, moderated, or owners only. On top of that come first-post moderation for new subscribers, temporary suspension of the list, and an attachment policy.
Items awaiting moderation are visible in the console, actionable there or from the command line, and every decision leaves a trace in the audit log.
Message transformation
Before delivery, the pipeline applies what the list asks for: subject tag, footer,
complete List-* headers, RFC 8058 one-click unsubscribe, and a feedback
identifier for the large mailbox providers.
Two behaviours are worth knowing about, because they change what subscribers receive:
- Byte-for-byte passthrough when possible. If no rewriting is required, the
message is relayed unchanged and its author's DKIM signature stays valid. Many
list managers re-serialise the message in every case, which breaks the signature
and shows up as
dkim=failfor the recipients. - Deliberate DMARC alignment. When the author's domain publishes a strict
policy, the From address is rewritten in the name of the list, with a
Reply-Tothat preserves the conversation. As soon as a signed field is touched, the author's signature is stripped rather than left invalid.
Subscriptions and consent
Subscribing happens by mail or from the list's public pages. Either way, confirmation is requested at the address concerned, with a single-use token of limited lifetime. An anonymous web form proves nothing, so double confirmation is enforced there even on an open list.
Also included: bulk CSV import, delivery modes (message by message or periodic digest), automatic disabling of an address that bounces, removal by a manager, and one-click unsubscribe from the mail client's own button.
The messages difuzio writes itself - confirmation, welcome, farewell, sign-in link
- are sent as both plain text and HTML, in the language of the domain, with a layout designed for real mail clients.
Deliverability and reputation
- VERP. Each copy leaves with a return path unique to one subscriber, signed and self-contained: a bounce is attributed to exactly one person, with no lookup table to maintain.
- Bounces. Delivery status notifications are parsed, classified as hard or soft, deduplicated and accumulated over a sliding window. At the threshold the address is disabled; re-activation resets the counter.
- Complaints. ARF feedback-loop reports from the large providers are ingested and counted as the strongest signal there is.
- Kill switch. Past a complaint or hard-bounce rate, the list is suspended automatically. Resuming is manual: a list burning your reputation must not restart on its own.
- Adaptive throughput. Sending slows down and speeds back up per pool according to what remote servers answer.
Web console and public pages
The administration console covers domains, lists, members, moderation, API keys and the audit log, with dashboards that adapt to the role of the person signed in.
A list's public pages - help, subscription form, archives - are served by the same service. Archives mask addresses, rate-limit per IP and declare themselves to crawlers according to the list's setting. Sessions, anti-CSRF tokens and content sanitising are part of the foundation, not of an option.
REST API and webhooks
The /api/v1 API is authenticated by key, described by an OpenAPI 3.1 document
served by the application itself and checked in continuous integration against a
versioned golden file. It exposes domains, lists, members, moderation and sends.
An idempotency header protects replayed creations. Outgoing webhooks are HMAC signed, delivered at least once with retries, and the HTTP client refuses internal addresses so it never becomes a relay into your private network.
Isolation and roles
One deployment hosts several domains without them seeing each other. Roles range from super administrator to moderator, by way of domain administrator and list owner. Every read is filtered by the scope of the person signed in, and anything out of scope answers "not found" rather than "forbidden": that is the only way not to reveal the existence of another tenant's list.
Compliance and personal data
Erasing a person walks every table, including indirect traces, and deletes the relevant message bodies from disk, not just their metadata. Proof of consent is recorded at subscription time. Archives have a per-list retention period, applied automatically.
Operations
Three processes share one configuration: the web interface and API, mail reception, and the worker that drains the queues and runs periodic tasks. Run several workers for throughput.
/healthzand/readyzprobes, Prometheus metrics on/metrics.- Hardened systemd units and Debian packages for both backends.
- A
doctorcommand that checks the database and the schema state,check-dnsfor SPF, DKIM and DMARC, andmta-config, which prints the Postfix lines to copy over. - Schema migrations applied at startup, an audit log of every sensitive decision, and the project's underlying rule: no silent failure.
What difuzio does not do
Better said here than discovered in production.
- DKIM signing for the list domain is done by the front mail server, not by difuzio. Without it, one-click unsubscribe is not honoured by the large mailbox providers.
- Inbound antivirus and antispam filtering is likewise the front server's job.
- In the external-mailbox profile, bounces are not processed automatically: the original SMTP envelope is lost, so a dead address is removed by hand.
Going further
The operator manual covers each of these points with the matching configuration: administration documentation (in French).