Is there an example available of a working [ARC] section for Mailman3? The documentation is awfully vague and I've not been able to make it work: https://docs.mailman3.org/projects/mailman/en/latest/src/mailman/config/docs/config.html#arc
I'm on a Debian 12 Bookworm server and use postfix and opendkim. My server has mailing lists for about a hundred domains.
Mailman3 works currently: I can send from a mailing list and the emails reach their destination. The source email are properly DKIM-signed. The issue is that since Mailman3 modifies the emails in transit, this DKIM fails when it reaches its destination.
I tried to define the /etc/mailman3/mailman.cfg [ARC] section but I don't understand what to put in each field. Does Mailman3 requires its own DKIM key-pair? Or does it uses one of OpenDKIM key-pair? How can it access that key-pair since Mailman3 runs with a user and OpenDKIM runs with another?
I tried something:
[ARC]
enabled: yes
authserv_id: myserver.com
trusted_authserv_ids: $domain
privkey: /etc/opendkim/keys/$domain/myprivatekeyfile
selector: myselector
domain: $domain
But the $domain variable does not exist in this context. I think it only exists for the [mta] context.
Maybe, since I have about a hundred domains lists in Mailman3, I would be better to use the old approach to just strip the original DKIM headers and put back my own?
ARC is the right tool for what you're describing, so it's worth getting working. Set expectations first, though: ARC only helps at receivers that actually evaluate it (Gmail, Microsoft, and a handful of others). Plenty of receivers still ignore it, and for those, a message the list has modified will still fail DMARC. That matters at a hundred domains, so I'll come back to it at the end.
On your specific questions:
Does Mailman need its own key, or can it use an OpenDKIM one?
Give it its own. Mailman signs ARC through dkimpy using the privkey you point it at, and sharing an OpenDKIM key is painful for two reasons:
- Permissions. OpenDKIM keys are normally mode 600 owned by the opendkim user, and Mailman runs as a different user, so it simply cannot read them. Generate a dedicated key, put it under something like
/etc/mailman3/arc/, and chown it to the Mailman user with chmod 640.
- Key format. dkimpy is picky about the PEM encoding. If ARC signing silently does nothing, regenerate the key with OpenSSL's -traditional flag. The Mailman docs call this out, because newer OpenSSL defaults to a format dkimpy cannot read.
The public half goes into DNS exactly like a DKIM key, at selector._domainkey.yourdomain, as v=DKIM1; k=rsa; p=... . That is what a receiver uses to verify your seal.
Why $domain does nothing, and what to do with a hundred domains
$domain is only interpolated in the [mta] context, so in [ARC] the fields are read literally, which is what you ran into. That looks like a problem for a hundred domains, but it isn't, because ARC does not sign as the author's domain. Unlike DKIM under DMARC, the ARC seal is never checked for alignment with the From header. It only attests "when this list received the message, here is how it authenticated," signed by a domain you control. So you use one identity for the whole installation, all literal:
[ARC]
enabled: yes
authserv_id: lists.example.com
trusted_authserv_ids: lists.example.com, <the AuthservID your OpenDKIM stamps>
privkey: /etc/mailman3/arc/arc.key
selector: arc
domain: lists.example.com
One key, one selector, one arc._domainkey.lists.example.com TXT record, covering every list no matter which of the hundred domains authored the message.
The field people get wrong is trusted_authserv_ids. For the seal to carry a real result, Mailman has to trust the Authentication-Results header your incoming OpenDKIM/OpenDMARC already stamped, so this must contain the exact authserv-id string OpenDKIM writes (its AuthservID), literally. If it doesn't match, Mailman seals an empty result and the whole exercise is pointless.
Your fallback question: strip and re-sign instead?
Re-signing with your own DKIM does not fix DMARC by itself. The visible From is still the author's domain, and a signature with d=yourlists.com does not align with it, so DMARC still fails. The thing that reliably rescues list mail for a From you do not control is From-munging: set the list's dmarc_mitigate_action to munge_from, which rewrites the header to "Author via List [email protected]" and moves the original address into Reply-To. That new From aligns with the list's own domain, so DMARC passes. The cost is the visible change to the From and to reply behavior.
So for a hundred domains where some authors are on p=reject, I would run both. Enable ARC as the clean fix for the big mailboxes that honor it, and keep munge_from as the safety net. Leave dmarc_mitigate_unconditionally off so Mailman only munges mail from authors whose domain actually publishes p=quarantine or p=reject, and leaves everyone else's From untouched. ARC on its own will keep failing at every receiver that doesn't check it, and across a hundred domains you will have some.