Decision: separate key publication from message signing
- Published selector
- A TXT or CNAME result proves that a verifier can retrieve a candidate public key. It does not prove the sending MTA used the matching private key.
- DKIM-Signature header
- This is the evidence that a signer acted on that message. If the header is absent, changing DNS alone cannot make the already-sent message pass.
- Receiver result
dkim=none,dkim=fail, anddkim=passare different boundaries. Use the topmost trusted receiver result from the same fresh message.
Do not post a private DKIM key, complete configuration, full message header, recipient address, message body, container environment, or raw mail log. The planner uses categorical states only. The optional scan form sends only a public domain.
Browser-local evidence planner
Find the first unsigned boundary
No domain, selector, address, message, configuration, key, container value, or log is requested or transmitted by this planner.
- Public key
- Message signature
- Receiver result
- Submission path
- Boundary
- Next action
- Exit condition
- Safety
Why Docker SMTP can stay unsigned
OpenDKIM documents InternalHosts as the set whose mail is signed instead of verified. Replacing the default list means every internal source that should be signed must be represented explicitly.
Postfix applies smtpd_milters to mail received by smtpd. It applies non_smtpd_milters to local sendmail or queue-injection paths. A message submitted by an application container over SMTP therefore needs the SMTP Milter path and a source identity that OpenDKIM treats as internal.
Trust only the exact application subnet or authenticated submission path you control. Adding all of 172.16.0.0/12 merely because Docker commonly uses that range widens the signing boundary unnecessarily.
One bounded verification
- Identify the selector from the intended signer configuration or a fresh
DKIM-Signature. Confirm the exact public key withopendkim-testkeyor the public selector checker. - Classify how the application handed the message to Postfix: SMTP through
smtpd, or local sendmail/cleanup. - For SMTP submission, compare the application's observed source address or exact subnet with OpenDKIM
InternalHosts. For local submission, verifynon_smtpd_milters. - Send one fresh message and inspect only the new message. First require a
DKIM-Signaturewith the intendedd=ands=; then require the trusted receiver to reportdkim=pass.
postconf smtpd_milters non_smtpd_milters milter_default_action opendkim-testkey -d example.com -s selector -vvv
Keep the command output private. A successful key lookup proves DNS and key matching; it does not prove that a particular message traversed the signer.
If dkim=pass but the message still lands in spam
Stop changing DKIM once the fresh message passes with the intended aligned signing domain. Continue with DMARC policy and alignment, forward-confirmed PTR and HELO identity, sending-IP reputation, content, complaint history, volume, and receiver-specific evidence. A monitoring policy such as p=none does not request quarantine or rejection, and dkim=pass does not guarantee inbox placement.
Run the public domain, SPF, DMARC, DKIM-selector, PTR and policy checks before changing multiple boundaries at once.
Public case that exposes the boundary
A public project reported receiver evidence with SPF and DMARC passing while DKIM was absent. Its later repository configuration publishes a selector and configures both Postfix Milter paths, but the generated OpenDKIM trusted-host list contains loopback and the sending domain while the application submits over a Docker private address. The public key can therefore exist while the application source still needs to be proven inside the signing boundary.
This is a source-based hypothesis, not proof of the current runtime. A fresh message and protected runtime evidence decide it.