inbound-antispam-panel: refused inbound mail from mail.log; retention
Step 4/12 of docs/plans/inbound-antispam-panel.md. The log tailer writes an inbound_spam_log row for mail port 25 refused (internal/logtail/inbound.go): a "reject:" line of the port-25 smtpd is Postfix's own policy; a milter-reject / milter-hold / milter-discard line of cleanup is the filter's verdict. Only a recipient at an inbound domain is a row, so "Relay access denied" for a stranger's domain is not. The row is dated by its log line; the reply text is cut to 255 bytes of printable ASCII; a reply starting with 4 is a tempfail. To tell port 25 from 465 / 587 the listener now logs as postfix/inbound (syslog_name). cleanup logs under one name for every listener, so its verdict counts only for a queue id the port-25 smtpd was seen to open (4096 remembered). Lines are matched from the head, after timestamp and host: their tail is the sender's own text. Retention: PruneInboundSpam every six hours - older than the inbound_spam_log_retention_days setting (seeded from INBOUND_SPAM_LOG_RETENTION_DAYS, 90, range 7-365), then down to 10 000 rows. The setting has no field in the panel yet. Known limits, in architecture.md: a log line names one recipient, so a message refused at end-of-message is one row; a line re-read after an unclean stop would be a second row. Checked on the test server, uncommitted tree: go vet ./... ok, go test ./... ok (22 packages), make e2e ok - the unknown recipient at the inbound domain refused on port 25 has its row (reject by postfix), the stranger's domain has none. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+15
-2
@@ -5,6 +5,13 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Changed
|
||||
|
||||
- **Port 25 logs as `postfix/inbound`.** Its lines in the mail log (Server ›
|
||||
System log) now read `postfix/inbound/smtpd[…]` where they read
|
||||
`postfix/smtpd[…]`; the submission ports keep `postfix/smtpd`. This is how a
|
||||
refusal on port 25 is told from one on 465 / 587.
|
||||
|
||||
### Added
|
||||
|
||||
- Schema: migration `0002_inbound_spam_log.sql`, the first after the 2.0
|
||||
@@ -16,8 +23,14 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
|
||||
of a message that was accepted for an inbound domain: client address,
|
||||
envelope, subject and - with a spam filter attached - the filter's action,
|
||||
score and heaviest symbols. It only watches: it refuses nothing and Postfix
|
||||
accepts mail when it is down. Refused mail is not there yet (it comes from
|
||||
the mail log, next), and there is no page for the journal yet.
|
||||
accepts mail when it is down. There is no page for the journal yet.
|
||||
- **Refused inbound mail is recorded too**, from the mail log: a recipient
|
||||
Postfix refused at an inbound domain (unknown user, sender domain not
|
||||
found), and a message the spam filter rejected, deferred, held or
|
||||
discarded. The row is dated by its log line and carries the reply text. A
|
||||
refusal to relay for a domain that is not an inbound one is not recorded.
|
||||
- The inbound journal is pruned every six hours: rows older than 90 days
|
||||
(`INBOUND_SPAM_LOG_RETENTION_DAYS`, 7-365) and anything beyond 10 000 rows.
|
||||
- The antispam compose fragment mounts `antispam/rspamd/milter_headers.conf`
|
||||
into the rspamd sidecar, which makes it write its verdict into
|
||||
`X-Rspamd-Action` and `X-Spamd-Result`. **Copy `deploy/antispam/rspamd/`
|
||||
|
||||
Reference in New Issue
Block a user