Commit Graph
2 Commits
Author SHA1 Message Date
mixandClaude Opus 5.5 14de9a05c8 panel-dkim-signing stage 1: the panel's DKIM signer, beside OpenDKIM
internal/milter/sign.go: a milter on two sockets (cmd/panel/signer.go):
sign.sock for 465/587, the key of the domain the SASL login belongs to
(Bindings.DomainOf, the sender_login_maps Postfix reads), and
sign-local.sock for the panel's own sendmail(1) mail, the server's name.
go-msgauth/dkim v0.7.0, relaxed/simple, OpenDKIM's dkim_should_signhdrs[]
(libopendkim/dkim.c:223-246) in message order plus From once more; keys
and selectors from the KeyTable the panel writes, a key path outside the
key directory refused; strict - whatever cannot be signed is deferred.

From the sources: Postfix 3.10.13 milter8.c:2329-2400 hands a folded
header \n-separated, so the signer joins its lines with CRLF; inserts are
1-based in cleanup_ins_header() (cleanup_milter.c:1193), so index 0 is the
top, where OpenDKIM puts its own (opendkim.c:3673). go-milter v0.4.1 calls
no Abort when a connection ends, so a watchdog closes go-msgauth's
streaming signer after an hour and a late end of message is deferred.

Postfix: smtpd_milters = sender check, signer, OpenDKIM, journal;
non_smtpd_milters = the signer's local socket, OpenDKIM - both sign every
message until stage 2. disable_mime_output_conversion=yes (default off,
mail_params.h:3088): an 8-bit message is no longer re-encoded after it is
signed.

Tests: unit tests sign and verify folded, tab-led and space-free headers,
an added From:, a changed body, two messages on a connection, odd bodies,
and five cases deferred. e2e: the sink image has python3-dkim (dkimpy
1.1.8-2) and the stand's DNS; on an application's message and on a
notification the two signatures must agree on h=, bh=, c=, s=, a= and each
must pass dkimverify. On the server: make e2e exit 0 (714 s), go vet + go
test 27 packages ok.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 23:49:14 +03:00
mixandClaude Opus 5.5 b905f3e560 panel-notifications: Account, Server > Settings, Server > Health, help; e2e
test / test (push) Canceled after 0s
The pages of the mockups accepted in 87fa0a4, built from the kit's partials
(written by a Sonnet agent into the working tree, reviewed here):

- Account: "Send me notifications" in the Profile form, saved with the
  profile; an unticked box is off.
- Server > Settings: the instance switch (box 03), and box 04 Notification
  mail with the DKIM and SPF records of the server's own name, drawn with the
  record partial of a domain's DNS page and checked in DNS. Sending rate
  limits are box 02 in the left column. A record that is not in place is
  tagged as a warning, not a failure: notifications are sent without it.
- Server > Health: card 06 Notification mail with the state of each record
  and a link to Settings, beside Configuration (07); part of the polled
  fragment; Re-check DNS forces it too. Overview does not run this check.
- help.go: the Notifications topic and the clauses in Settings and Your
  account, word for word with help.html.

If the server's key cannot be read the pages still render: the DKIM record
is left out and SPF is shown unchecked.

e2e: the administrator gets a mailbox behind the sink and the server's DKIM
record from Settings is published; the level-2 refusal of the next step must
then arrive as a notification from postmaster@mail.e2e.test, signed as that
name with the key Settings shows, and must not be a row of the Outbound log.
The rotation step now waits for Postfix to be running: it follows a step that
restarts the container, and logrotate's `postfix reload` failed in between.

On the test server, for this tree: go vet clean, go test ./... 23 packages
ok, make e2e ok (147 s); the notification reached the sink 28 s after the
refusal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 16:21:48 +03:00