From 5348330d2b0d5b3ff4b75a7c7f716c2c4d2a103b Mon Sep 17 00:00:00 2001 From: Mix Date: Fri, 16 Oct 2026 14:10:23 +0300 Subject: [PATCH] design: inbound-upstream-result - an Upstream column in the Inbound log MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The owner, 2026-10-16: "Нам не хватает в журнале для Inbound ответа upstream. Не понятна судьба письма: принято, отклонено, хост не доступен и пр." and, asked whether a result in the row or a page per message: "Да, согласен. Пока только результат. Отдельная страница в план в случае появления потребности." Inbound › Log gets an Upstream column after Decision: what became of an accepted message - queued (a plain tag: not tried yet), sent, deferred, bounced - each but queued a tag that opens an "Upstream" sheet with the host that answered (left out when Postfix had no session: relay=none, src/smtp/smtp_trouble.c:273, 421 in Postfix 3.10.13), the last reply (the "(...)" of the delivery line, src/global/log_adhoc.c) and when it came, with what happens next for deferred and bounced. A refused message has "—". The lead and the box foot say so; the help's Inbound log topic replaces "Accept says what this server did, not what the upstream did" with what each result means, and notes that rows logged before 2.10.0 have none. A new first row shows queued. Outline unchanged (the box is still a table). check.py: 0 violations. Co-Authored-By: Claude Opus 5.5 --- docs/assets/panel-redesign/panel/help.html | 2 +- docs/assets/panel-redesign/panel/in-log.html | 19 ++++++++++--------- .../assets/panel-redesign/panel/src/help.html | 2 +- .../panel-redesign/panel/src/in-log.html | 19 ++++++++++--------- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/docs/assets/panel-redesign/panel/help.html b/docs/assets/panel-redesign/panel/help.html index 2cc1804..2d3d596 100644 --- a/docs/assets/panel-redesign/panel/help.html +++ b/docs/assets/panel-redesign/panel/help.html @@ -137,7 +137,7 @@

Upstream

The upstream is the server that actually holds the mailboxes. Give its host and port — used exactly as written, with no MX lookup — and choose the TLS for the hop to it: Opportunistic uses TLS when the upstream offers it and otherwise sends in the clear; Required sends only over TLS, and the mail waits in the queue while the upstream does not offer it or the TLS handshake fails - an upstream that answers STARTTLS with a permanent error bounces it; Off never uses TLS. While the upstream does not answer, Postfix keeps the mail and retries as for any other mail.

Valid recipients

Choose whom this domain accepts. Listed addresses only: the relay accepts exactly the addresses you list, one per line or comma-separated, and refuses any other while the sender is still connected, so it never has to send a bounce for them. Any recipient: everything at the domain is accepted and passed on, and an address the upstream then rejects comes back as a bounce from this server to a sender who is often forged — backscatter. Prefer a list, and keep it in step with the mailboxes upstream.

Spam filter

The spam filter belongs to the server, not to a domain. The server's administrator attaches it in the server's .env, and from then on every inbound domain is screened by it before mail is handed on; the box shows on or off and has nothing to switch. Off means mail goes to the upstream unfiltered. While the filter is down, mail is either accepted unfiltered (the default) or refused with a temporary error, so the sending server tries again later, as the server's setting says; the box states which.

-

Inbound log

One row per recipient of a message offered on port 25 for an inbound domain, with what was decided: accept — handed on to the upstream; reject — refused for good; tempfail — the sender was asked to come back later; quarantine — held by the filter. Why names who decided. rspamd is the spam filter, with its action, the score against the reject threshold and the heaviest symbols; postfix is the relay's own rule — an unknown recipient, a sender domain that does not exist — with its reply; selfpost means nobody judged the message: it was relayed with no filter attached. Accept says what this server did, not what the upstream did with the message afterwards.

Accepted mail is recorded as it passes; refused mail is read from mail.log, so its row has no subject, and a message refused after its text was sent is one row however many recipients it had. A refusal to relay for a domain that is not an inbound one is every scanner on the internet and is not recorded. Rows are kept for the number of days set in Settings, and never more than 10 000.

+

Inbound log

One row per recipient of a message offered on port 25 for an inbound domain, with what was decided: accept — taken for the upstream; reject — refused for good; tempfail — the sender was asked to come back later; quarantine — held by the filter. Why names who decided. rspamd is the spam filter, with its action, the score against the reject threshold and the heaviest symbols; postfix is the relay's own rule — an unknown recipient, a sender domain that does not exist — with its reply; selfpost means nobody judged the message: it was relayed with no filter attached. Upstream says what became of an accepted message: queued — not tried yet; sent — the upstream took it; deferred — the upstream put it off or could not be reached, and Postfix tries again; bounced — the upstream refused it, or it waited in the queue too long, and the sender was sent a bounce. It opens the last reply and the host that gave it. A refused message has no upstream result, and neither has a row logged before 2.10.0.

Accepted mail is recorded as it passes; refused mail is read from mail.log, so its row has no subject, and a message refused after its text was sent is one row however many recipients it had. A refusal to relay for a domain that is not an inbound one is every scanner on the internet and is not recorded. Rows are kept for the number of days set in Settings, and never more than 10 000.

Filter lists

Two lists for the whole server that correct the spam filter by hand. An entry is a sender address, a sender domain — that domain, not its subdomains — or a client address or network in CIDR form. A sender on the Deny list is refused outright. A sender on the Allow list is given a weight no spam score outweighs, so the filter lets it through. The sender's address is whatever the sending server says it is - anyone can claim to be a sender you allow - so allow a client address or network where you can, and a sender address only for mail you would rather receive forged than lose. When entries of both lists match one message, Deny wins.

SelfPost does not apply the lists itself: it writes them as files under /data/antispam/, and rspamd rereads a file within seconds of a change. With the spam filter off the lists are kept and can be edited, but nothing reads them. The sender matched is the envelope sender — the one in the log — not the From line a mail program shows. Matched counts the messages in the Inbound log that the entry decided, so it reaches back as far as the log does; never means not once in that time, and such an entry is one to consider removing.

diff --git a/docs/assets/panel-redesign/panel/in-log.html b/docs/assets/panel-redesign/panel/in-log.html index 2acc212..74c84c1 100644 --- a/docs/assets/panel-redesign/panel/in-log.html +++ b/docs/assets/panel-redesign/panel/in-log.html @@ -69,7 +69,7 @@

Inbound

Inbound log

-

What port 25 decided about each message, one row per recipient. Accepted mail is recorded as it passes, refused mail is read from mail.log; the filter's verdict appears when the spam filter is on. Rows older than 90 days are deleted — change that in Settings.

+

What port 25 decided about each message and what the upstream answered, one row per recipient. Accepted mail is recorded as it passes, refused mail is read from mail.log; the filter's verdict appears when the spam filter is on. Rows older than 90 days are deleted — change that in Settings.

@@ -86,17 +86,18 @@
- + - - - - - - + + + + + + +
Time, UTCFromToSubjectDecision
Time, UTCFromToSubjectDecisionUpstream
09-21 14:00:18t.berg@uni.example
192.0.2.77
dev@lists.example.orgRe: [dev] patch series v3
accept

Why

Decided byrspamd
Verdictno action, score 0.40 / 15.00
SubjectRe: [dev] patch series v3
Deny sender
09-21 13:59:02invoice@partner-billing.example
203.0.113.140
owner@lists.example.orgOutstanding invoice — action required
accept

Why

Decided byrspamd
Verdictadd header, score 9.80 / 15.00
SymbolsPHISHING(5.00)
FORGED_SENDER(3.00)
R_SPF_FAIL(1.00)
SubjectOutstanding invoice — action required
Deny sender
09-21 13:57:41promo@bulk.example
198.51.100.90
sales@lists.example.org—
reject

Why

Decided bypostfix
Reply550 5.1.1 <sales@lists.example.org>: Recipient address rejected: User unknown in relay recipient table
09-21 13:51:30billing@partner.example
198.51.100.12
owner@lists.example.org—
reject

Why

Decided byrspamd
Reply5.7.1 Spam message rejected
Allow sender
09-21 13:44:02hr@partner.example
192.0.2.31
jobs@acme.io—
tempfail

Why

Decided byrspamd
Reply4.7.1 Try again later
Allow sender
09-21 13:30:55noreply@github.example
192.0.2.200
security@lists.example.org[advisory] new report
accept

Why

Decided byrspamd
Verdictno action, score -98.10 / 15.00
SymbolsSELFPOST_ALLOW_FROM(-100.00)
R_DKIM_ALLOW(-0.20)
Subject[advisory] new report
Deny sender
09-21 14:00:31ci@builds.example
192.0.2.90
dev@lists.example.org[ci] nightly build passed
accept

Why

Decided byrspamd
Verdictno action, score 1.10 / 15.00
Subject[ci] nightly build passed
queuedDeny sender
09-21 14:00:18t.berg@uni.example
192.0.2.77
dev@lists.example.orgRe: [dev] patch series v3
accept

Why

Decided byrspamd
Verdictno action, score 0.40 / 15.00
SubjectRe: [dev] patch series v3
sent

Upstream

Hostmx.upstream.example[198.51.100.5]:25
Reply250 2.0.0 Ok: queued as CE05D10261D
At09-21 14:00:19
Deny sender
09-21 13:59:02invoice@partner-billing.example
203.0.113.140
owner@lists.example.orgOutstanding invoice — action required
accept

Why

Decided byrspamd
Verdictadd header, score 9.80 / 15.00
SymbolsPHISHING(5.00)
FORGED_SENDER(3.00)
R_SPF_FAIL(1.00)
SubjectOutstanding invoice — action required
bounced

Upstream

Hostmx.upstream.example[198.51.100.5]:25
Reply550 5.7.1 Message rejected as spam by the upstream filter
At09-21 13:59:04
ThenThe sender was sent a bounce
Deny sender
09-21 13:57:41promo@bulk.example
198.51.100.90
sales@lists.example.org—
reject

Why

Decided bypostfix
Reply550 5.1.1 <sales@lists.example.org>: Recipient address rejected: User unknown in relay recipient table
—
09-21 13:51:30billing@partner.example
198.51.100.12
owner@lists.example.org—
reject

Why

Decided byrspamd
Reply5.7.1 Spam message rejected
—Allow sender
09-21 13:44:02hr@partner.example
192.0.2.31
jobs@acme.io—
tempfail

Why

Decided byrspamd
Reply4.7.1 Try again later
—Allow sender
09-21 13:30:55noreply@github.example
192.0.2.200
security@lists.example.org[advisory] new report
accept

Why

Decided byrspamd
Verdictno action, score -98.10 / 15.00
SymbolsSELFPOST_ALLOW_FROM(-100.00)
R_DKIM_ALLOW(-0.20)
Subject[advisory] new report
deferred

Upstream

Replyconnect to mx.upstream.example[198.51.100.5]:25: Connection refused
At09-21 13:45:12
ThenPostfix tries again; the message is in the queue
Deny sender
-
Page 1 of 38Older →A decision opens its reason · Allow / Deny sender opens Filter lists with the entry filled in
+
Page 1 of 38Older →A decision opens its reason, an upstream result its last reply · Allow / Deny sender opens Filter lists with the entry filled in
diff --git a/docs/assets/panel-redesign/panel/src/help.html b/docs/assets/panel-redesign/panel/src/help.html index 7feb5d8..f0be335 100644 --- a/docs/assets/panel-redesign/panel/src/help.html +++ b/docs/assets/panel-redesign/panel/src/help.html @@ -71,7 +71,7 @@

Upstream

The upstream is the server that actually holds the mailboxes. Give its host and port — used exactly as written, with no MX lookup — and choose the TLS for the hop to it: Opportunistic uses TLS when the upstream offers it and otherwise sends in the clear; Required sends only over TLS, and the mail waits in the queue while the upstream does not offer it or the TLS handshake fails - an upstream that answers STARTTLS with a permanent error bounces it; Off never uses TLS. While the upstream does not answer, Postfix keeps the mail and retries as for any other mail.

Valid recipients

Choose whom this domain accepts. Listed addresses only: the relay accepts exactly the addresses you list, one per line or comma-separated, and refuses any other while the sender is still connected, so it never has to send a bounce for them. Any recipient: everything at the domain is accepted and passed on, and an address the upstream then rejects comes back as a bounce from this server to a sender who is often forged — backscatter. Prefer a list, and keep it in step with the mailboxes upstream.

Spam filter

The spam filter belongs to the server, not to a domain. The server's administrator attaches it in the server's .env, and from then on every inbound domain is screened by it before mail is handed on; the box shows on or off and has nothing to switch. Off means mail goes to the upstream unfiltered. While the filter is down, mail is either accepted unfiltered (the default) or refused with a temporary error, so the sending server tries again later, as the server's setting says; the box states which.

-

Inbound log

One row per recipient of a message offered on port 25 for an inbound domain, with what was decided: accept — handed on to the upstream; reject — refused for good; tempfail — the sender was asked to come back later; quarantine — held by the filter. Why names who decided. rspamd is the spam filter, with its action, the score against the reject threshold and the heaviest symbols; postfix is the relay's own rule — an unknown recipient, a sender domain that does not exist — with its reply; selfpost means nobody judged the message: it was relayed with no filter attached. Accept says what this server did, not what the upstream did with the message afterwards.

Accepted mail is recorded as it passes; refused mail is read from mail.log, so its row has no subject, and a message refused after its text was sent is one row however many recipients it had. A refusal to relay for a domain that is not an inbound one is every scanner on the internet and is not recorded. Rows are kept for the number of days set in Settings, and never more than 10 000.

+

Inbound log

One row per recipient of a message offered on port 25 for an inbound domain, with what was decided: accept — taken for the upstream; reject — refused for good; tempfail — the sender was asked to come back later; quarantine — held by the filter. Why names who decided. rspamd is the spam filter, with its action, the score against the reject threshold and the heaviest symbols; postfix is the relay's own rule — an unknown recipient, a sender domain that does not exist — with its reply; selfpost means nobody judged the message: it was relayed with no filter attached. Upstream says what became of an accepted message: queued — not tried yet; sent — the upstream took it; deferred — the upstream put it off or could not be reached, and Postfix tries again; bounced — the upstream refused it, or it waited in the queue too long, and the sender was sent a bounce. It opens the last reply and the host that gave it. A refused message has no upstream result, and neither has a row logged before 2.10.0.

Accepted mail is recorded as it passes; refused mail is read from mail.log, so its row has no subject, and a message refused after its text was sent is one row however many recipients it had. A refusal to relay for a domain that is not an inbound one is every scanner on the internet and is not recorded. Rows are kept for the number of days set in Settings, and never more than 10 000.

Filter lists

Two lists for the whole server that correct the spam filter by hand. An entry is a sender address, a sender domain — that domain, not its subdomains — or a client address or network in CIDR form. A sender on the Deny list is refused outright. A sender on the Allow list is given a weight no spam score outweighs, so the filter lets it through. The sender's address is whatever the sending server says it is - anyone can claim to be a sender you allow - so allow a client address or network where you can, and a sender address only for mail you would rather receive forged than lose. When entries of both lists match one message, Deny wins.

SelfPost does not apply the lists itself: it writes them as files under /data/antispam/, and rspamd rereads a file within seconds of a change. With the spam filter off the lists are kept and can be edited, but nothing reads them. The sender matched is the envelope sender — the one in the log — not the From line a mail program shows. Matched counts the messages in the Inbound log that the entry decided, so it reaches back as far as the log does; never means not once in that time, and such an entry is one to consider removing.

diff --git a/docs/assets/panel-redesign/panel/src/in-log.html b/docs/assets/panel-redesign/panel/src/in-log.html index f698dc9..4ddf50e 100644 --- a/docs/assets/panel-redesign/panel/src/in-log.html +++ b/docs/assets/panel-redesign/panel/src/in-log.html @@ -3,7 +3,7 @@

Inbound

Inbound log

-

What port 25 decided about each message, one row per recipient. Accepted mail is recorded as it passes, refused mail is read from mail.log; the filter's verdict appears when the spam filter is on. Rows older than 90 days are deleted — change that in Settings.

+

What port 25 decided about each message and what the upstream answered, one row per recipient. Accepted mail is recorded as it passes, refused mail is read from mail.log; the filter's verdict appears when the spam filter is on. Rows older than 90 days are deleted — change that in Settings.

@@ -20,15 +20,16 @@
- + - - - - - - + + + + + + +
Time, UTCFromToSubjectDecision
Time, UTCFromToSubjectDecisionUpstream
09-21 14:00:18t.berg@uni.example
192.0.2.77
dev@lists.example.orgRe: [dev] patch series v3
accept

Why

Decided byrspamd
Verdictno action, score 0.40 / 15.00
SubjectRe: [dev] patch series v3
Deny sender
09-21 13:59:02invoice@partner-billing.example
203.0.113.140
owner@lists.example.orgOutstanding invoice — action required
accept

Why

Decided byrspamd
Verdictadd header, score 9.80 / 15.00
SymbolsPHISHING(5.00)
FORGED_SENDER(3.00)
R_SPF_FAIL(1.00)
SubjectOutstanding invoice — action required
Deny sender
09-21 13:57:41promo@bulk.example
198.51.100.90
sales@lists.example.org—
reject

Why

Decided bypostfix
Reply550 5.1.1 <sales@lists.example.org>: Recipient address rejected: User unknown in relay recipient table
09-21 13:51:30billing@partner.example
198.51.100.12
owner@lists.example.org—
reject

Why

Decided byrspamd
Reply5.7.1 Spam message rejected
Allow sender
09-21 13:44:02hr@partner.example
192.0.2.31
jobs@acme.io—
tempfail

Why

Decided byrspamd
Reply4.7.1 Try again later
Allow sender
09-21 13:30:55noreply@github.example
192.0.2.200
security@lists.example.org[advisory] new report
accept

Why

Decided byrspamd
Verdictno action, score -98.10 / 15.00
SymbolsSELFPOST_ALLOW_FROM(-100.00)
R_DKIM_ALLOW(-0.20)
Subject[advisory] new report
Deny sender
09-21 14:00:31ci@builds.example
192.0.2.90
dev@lists.example.org[ci] nightly build passed
accept

Why

Decided byrspamd
Verdictno action, score 1.10 / 15.00
Subject[ci] nightly build passed
queuedDeny sender
09-21 14:00:18t.berg@uni.example
192.0.2.77
dev@lists.example.orgRe: [dev] patch series v3
accept

Why

Decided byrspamd
Verdictno action, score 0.40 / 15.00
SubjectRe: [dev] patch series v3
sent

Upstream

Hostmx.upstream.example[198.51.100.5]:25
Reply250 2.0.0 Ok: queued as CE05D10261D
At09-21 14:00:19
Deny sender
09-21 13:59:02invoice@partner-billing.example
203.0.113.140
owner@lists.example.orgOutstanding invoice — action required
accept

Why

Decided byrspamd
Verdictadd header, score 9.80 / 15.00
SymbolsPHISHING(5.00)
FORGED_SENDER(3.00)
R_SPF_FAIL(1.00)
SubjectOutstanding invoice — action required
bounced

Upstream

Hostmx.upstream.example[198.51.100.5]:25
Reply550 5.7.1 Message rejected as spam by the upstream filter
At09-21 13:59:04
ThenThe sender was sent a bounce
Deny sender
09-21 13:57:41promo@bulk.example
198.51.100.90
sales@lists.example.org—
reject

Why

Decided bypostfix
Reply550 5.1.1 <sales@lists.example.org>: Recipient address rejected: User unknown in relay recipient table
—
09-21 13:51:30billing@partner.example
198.51.100.12
owner@lists.example.org—
reject

Why

Decided byrspamd
Reply5.7.1 Spam message rejected
—Allow sender
09-21 13:44:02hr@partner.example
192.0.2.31
jobs@acme.io—
tempfail

Why

Decided byrspamd
Reply4.7.1 Try again later
—Allow sender
09-21 13:30:55noreply@github.example
192.0.2.200
security@lists.example.org[advisory] new report
accept

Why

Decided byrspamd
Verdictno action, score -98.10 / 15.00
SymbolsSELFPOST_ALLOW_FROM(-100.00)
R_DKIM_ALLOW(-0.20)
Subject[advisory] new report
deferred

Upstream

Replyconnect to mx.upstream.example[198.51.100.5]:25: Connection refused
At09-21 13:45:12
ThenPostfix tries again; the message is in the queue
Deny sender
-
Page 1 of 38Older →A decision opens its reason · Allow / Deny sender opens Filter lists with the entry filled in
+
Page 1 of 38Older →A decision opens its reason, an upstream result its last reply · Allow / Deny sender opens Filter lists with the entry filled in