from-header-binding (docs/plans/from-header-binding.md, 9/9), at the owner's
word (2026-10-12, "Да").
- A message's From: line is held to what its envelope sender is held to:
any address of the application's domain, or the addresses of its list,
with or without a +extension. Anything else is refused with 550 5.7.1 -
another registered domain, the server's own name, a domain this server
does not sign for. Until now an application could have mail signed with
another domain's key by writing that domain into From:.
- The check is the panel's, first in the milter chain and strict: while
the panel does not answer, Postfix defers mail.
- Server > Health counts what that costs - the panel's downtime under a
running Postfix and the submissions turned away - and is laid out anew,
boxes numbered by importance.
- A refused row of the Outbound log says why in its tag.
- Migration 0006.
Upgrading: mail whose From: is not the application's own stops being
accepted - another of your domains, an address off an application's list, a
visitor's address a form puts there. The guide says what to do about each.
A stopped panel now stops submission.
Not done, written into the plan at the owner's word: the Delivery log box on
a refused message's page, the log's status filter, "messages" that are
connections, and what was reasoned about rather than run - OpenDKIM's own
parser above all.
Cut: CHANGELOG 2.4.0 written (nothing had been put under [Unreleased]
while building); image pin 2.4.0 in compose, README, guide; version table,
roadmap, plan status. security.md: a malformed packet on a milter socket,
as an accepted risk. No tag: the owner tags when he decides to, so there is
no image of this version until then.
On the test server, on c817f08: go vet ./... ok, go test ./... ok
(23 packages), make e2e ok. This commit changes documents and the pin only.
Full detail: CHANGELOG.md (2.4.0).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,65 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [2.4.0] - 2026-10-12
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- **An application signs only as itself.** OpenDKIM chooses the key by the
|
||||||
|
`From:` header, and Postfix held only the envelope sender against the
|
||||||
|
login: an application of one sending domain could write another registered
|
||||||
|
domain, or the server's own name, into `From:` and have the message signed
|
||||||
|
with that name's key (security review of `2.3.0`, where it was recorded as
|
||||||
|
an accepted risk). The panel now holds the header to what the envelope is
|
||||||
|
held to - any address of the application's domain, or the addresses of its
|
||||||
|
list, with or without a `+extension` - and refuses anything else with
|
||||||
|
`550 5.7.1`, a domain this server does not sign for included
|
||||||
|
([plans/from-header-binding.md](docs/plans/from-header-binding.md)).
|
||||||
|
- **The check is strict.** It is the first milter of the chain, on a socket
|
||||||
|
of its own (`SENDER_CHECK_SOCKET`), attached with
|
||||||
|
`default_action=tempfail`: while the panel does not answer, Postfix defers
|
||||||
|
mail and accepts nothing unchecked. The journal milter keeps its socket and
|
||||||
|
stays fail-open.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **Server › Health counts what the strict check costs** in a card of its
|
||||||
|
own, *Sender check*: for how long the panel did not answer while Postfix
|
||||||
|
was running, and how many submissions Postfix turned away because of it -
|
||||||
|
today, in the last 30 days and in the last 12 months (UTC days, kept a
|
||||||
|
year). The card warns when mail was deferred in the last 24 hours. The
|
||||||
|
numbers are there to decide whether the check needs a process of its own.
|
||||||
|
- **A refused row of the Outbound log says why**, in its tag: `wrong From`,
|
||||||
|
`wrong client` (the application's client IP list) or `rate-limited`; a row
|
||||||
|
refused before this version says `rejected`. A message refused for its
|
||||||
|
`From:` line shows on its page what the line said and what the application
|
||||||
|
may send as. Help has a *Sender check* topic.
|
||||||
|
- Migration `0006_sender_check.sql` (DDL only): `send_log.reason`,
|
||||||
|
`send_log.header_from`, `sender_check_days`.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Mail with a `From:` the application is not bound to is refused.** What
|
||||||
|
stops working on upgrade: an application sending with the `From:` of
|
||||||
|
another of your domains (give that domain an application); an application
|
||||||
|
with a list whose envelope and `From:` addresses differ (add the second to
|
||||||
|
the list); a form that puts its visitor's address into `From:` (use
|
||||||
|
`Reply-To:`). The line is read strictly: one `From:` field, one address,
|
||||||
|
one `@` outside a quoted display name; a name with a comma or brackets has
|
||||||
|
to be quoted. Guide § Who an application may send as.
|
||||||
|
- **With the panel down, mail is deferred, not accepted.** Until now a
|
||||||
|
stopped panel cost the send log and the level-2 limits and nothing else.
|
||||||
|
- **Server › Health is laid out as two stacks of boxes numbered by
|
||||||
|
importance**, read left to right and top to bottom, each stack closed up:
|
||||||
|
Processes, Milter sockets, Sender check, TLS certificate, Hostname and
|
||||||
|
reverse DNS, Notification mail, Machine, Configuration. On a phone they
|
||||||
|
come in that order.
|
||||||
|
- A refused message is one row of the log, naming its first recipient and
|
||||||
|
how many more there were.
|
||||||
|
- `recipient_delimiter` is set to `+` by the image instead of being left to
|
||||||
|
the distribution's default; the start removes milter sockets a killed
|
||||||
|
container left behind.
|
||||||
|
|
||||||
## [2.3.0] - 2026-10-12
|
## [2.3.0] - 2026-10-12
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ docker run --rm -d --name selfpost-try \
|
|||||||
-e SELFPOST_HOSTNAME=mail.local.test \
|
-e SELFPOST_HOSTNAME=mail.local.test \
|
||||||
-e PANEL_COOKIE_SECURE=false \
|
-e PANEL_COOKIE_SECURE=false \
|
||||||
-v selfpost-try-data:/data \
|
-v selfpost-try-data:/data \
|
||||||
ghcr.io/mixeme/selfpost:2.3.0
|
ghcr.io/mixeme/selfpost:2.4.0
|
||||||
```
|
```
|
||||||
|
|
||||||
**Get the setup URL** (pick one):
|
**Get the setup URL** (pick one):
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
selfpost:
|
selfpost:
|
||||||
image: ghcr.io/mixeme/selfpost:2.3.0
|
image: ghcr.io/mixeme/selfpost:2.4.0
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
SELFPOST_HOSTNAME: "${SELFPOST_HOSTNAME:?set the mail/panel hostname, e.g. mail.example.com}"
|
SELFPOST_HOSTNAME: "${SELFPOST_HOSTNAME:?set the mail/panel hostname, e.g. mail.example.com}"
|
||||||
|
|||||||
+2
-1
@@ -107,7 +107,7 @@ than the default «meaningful step» rule in [§ Commits and release build](#com
|
|||||||
2. Git tag `vX.Y.Z` and publish the GitHub Release only on explicit request (see
|
2. Git tag `vX.Y.Z` and publish the GitHub Release only on explicit request (see
|
||||||
[§ Release image](#release-image)).
|
[§ Release image](#release-image)).
|
||||||
|
|
||||||
**Planned version cuts** (from pin `2.3.0`; adjust if semver changes mid-track):
|
**Planned version cuts** (from pin `2.4.0`; adjust if semver changes mid-track):
|
||||||
|
|
||||||
| Stage | ID | Cut |
|
| Stage | ID | Cut |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@@ -128,6 +128,7 @@ than the default «meaningful step» rule in [§ Commits and release build](#com
|
|||||||
| 15 | inbound-antispam-panel | `2.1.0` (was `1.10.0`, reordered 2026-10-09) |
|
| 15 | inbound-antispam-panel | `2.1.0` (was `1.10.0`, reordered 2026-10-09) |
|
||||||
| 16 | delivery-log-storage | `2.2.0` |
|
| 16 | delivery-log-storage | `2.2.0` |
|
||||||
| 17 | panel-notifications | `2.3.0` |
|
| 17 | panel-notifications | `2.3.0` |
|
||||||
|
| 18 | from-header-binding | `2.4.0` |
|
||||||
|
|
||||||
Docs-only prep (checklists in plans, no product code) uses the same per-step
|
Docs-only prep (checklists in plans, no product code) uses the same per-step
|
||||||
commit rule but **no** version cut until the next product stage ships.
|
commit rule but **no** version cut until the next product stage ships.
|
||||||
|
|||||||
+1
-1
@@ -184,7 +184,7 @@ cat ./data/setup-token
|
|||||||
#### Fixed image tag
|
#### Fixed image tag
|
||||||
|
|
||||||
`deploy/docker-compose.yml` pins an explicit version (`ghcr.io/mixeme/selfpost:X.Y.Z`),
|
`deploy/docker-compose.yml` pins an explicit version (`ghcr.io/mixeme/selfpost:X.Y.Z`),
|
||||||
deliberately never `:latest`. The current pin is `2.3.0`. Intermediate
|
deliberately never `:latest`. The current pin is `2.4.0`. Intermediate
|
||||||
CHANGELOG sections (`0.2.0`…`0.6.0`) record development cuts from before that
|
CHANGELOG sections (`0.2.0`…`0.6.0`) record development cuts from before that
|
||||||
image was published. Pinning matters because of the backup version check (see
|
image was published. Pinning matters because of the backup version check (see
|
||||||
[Full backup and restore](#full-backup-and-restore)): the panel binary's
|
[Full backup and restore](#full-backup-and-restore)): the panel binary's
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Plan: from-header-binding
|
# Plan: from-header-binding
|
||||||
|
|
||||||
**Status:** agreed 2026-10-12 - the design questions were closed with the owner one at a time and he took it into work
|
**Status:** shipped in `2.4.0` (2026-10-12); agreed the same day - the design questions were closed with the owner one at a time and he took it into work ("Да")
|
||||||
**Date:** 2026-10-12
|
**Date:** 2026-10-12
|
||||||
**Version:** `2.4.0` MINOR (one migration; it refuses mail that was accepted before).
|
**Version:** `2.4.0` MINOR (one migration; it refuses mail that was accepted before).
|
||||||
|
|
||||||
@@ -148,3 +148,87 @@ the fourth was not.
|
|||||||
- [x] `go vet`, `go test`, e2e: refused for another domain's `From:`, for the hostname's and for an address off the list; accepted for its own (on the test server: vet ok, 23 packages ok, e2e ok - `sender_check_holds_the_from_line`, `panel_down_defers_mail`)
|
- [x] `go vet`, `go test`, e2e: refused for another domain's `From:`, for the hostname's and for an address off the list; accepted for its own (on the test server: vet ok, 23 packages ok, e2e ok - `sender_check_holds_the_from_line`, `panel_down_defers_mail`)
|
||||||
- [x] Technical review — **Opus** (2026-10-12; one Critical, fixed: a folded `From:` line - what a mail library makes of a long display name - was refused for good. Also fixed: a display name in a charset Go does not convert was refused; the statistics ran before the check served, and a hung `supervisorctl` would have kept it from serving; the count of deferred mail missed a check that stops answering in the middle of a message, and is now taken at Postfix's warning; a card whose figures could not be read said ok; a killed container's stale socket satisfied the wrapper's wait; outside quoted strings the line may now hold one `@` only. Three were first left as found and fixed the same evening at the owner's question: downtime is cut at the UTC midnights it crossed; the row of a message with the null envelope sender takes the domain the login is bound to; a log read again after an unclean stop does not count again what it counted before)
|
- [x] Technical review — **Opus** (2026-10-12; one Critical, fixed: a folded `From:` line - what a mail library makes of a long display name - was refused for good. Also fixed: a display name in a charset Go does not convert was refused; the statistics ran before the check served, and a hung `supervisorctl` would have kept it from serving; the count of deferred mail missed a check that stops answering in the middle of a message, and is now taken at Postfix's warning; a card whose figures could not be read said ok; a killed container's stale socket satisfied the wrapper's wait; outside quoted strings the line may now hold one `@` only. Three were first left as found and fixed the same evening at the owner's question: downtime is cut at the UTC midnights it crossed; the row of a message with the null envelope sender takes the domain the login is bound to; a log read again after an unclean stop does not count again what it counted before)
|
||||||
- [x] Security review — **Fable** (2026-10-12; no Critical or High. The same folded line, as its one Medium. Fixed: another sender's name in an encoded display name passed the second look; a client could arm the deferred counter by writing the socket's name where Postfix quotes it in a warning; a refused message wrote a row per recipient, a thousand at most - now one. Recorded: what a display name looks like to a person is not promised. The review also found the check stricter than Postfix for an address with an extension (`invoices+x@`, allowed in the envelope and refused in the header); the owner asked for it to work, and the check now makes Postfix's second try, with `recipient_delimiter` set explicitly. Confirmed from the code: no path to the signer around the check, and every failure of the check defers)
|
- [x] Security review — **Fable** (2026-10-12; no Critical or High. The same folded line, as its one Medium. Fixed: another sender's name in an encoded display name passed the second look; a client could arm the deferred counter by writing the socket's name where Postfix quotes it in a warning; a refused message wrote a row per recipient, a thousand at most - now one. Recorded: what a display name looks like to a person is not promised. The review also found the check stricter than Postfix for an address with an extension (`invoices+x@`, allowed in the envelope and refused in the header); the owner asked for it to work, and the check now makes Postfix's second try, with `recipient_delimiter` set explicitly. Confirmed from the code: no path to the signer around the check, and every failure of the check defers)
|
||||||
|
|
||||||
|
## Not done
|
||||||
|
|
||||||
|
Written at the owner's word when he had the version cut ("Запиши все
|
||||||
|
недоделки в план", 2026-10-12). Nothing here was promised and dropped in
|
||||||
|
silence; each line says what is missing and what it would take.
|
||||||
|
|
||||||
|
### Decided to wait
|
||||||
|
|
||||||
|
- **A process of its own for the check.** The owner: measure first. Server ›
|
||||||
|
Health now has the numbers; the decision is his when they have had time to
|
||||||
|
say something. Moving the role out is a change of where it is started -
|
||||||
|
a subcommand of the panel binary and a `[program:]` in supervisord - and
|
||||||
|
the downtime figure then needs a new meaning.
|
||||||
|
|
||||||
|
### Shown to the owner one way and built another
|
||||||
|
|
||||||
|
- **The Delivery log box is on a refused message's page.** The picture he
|
||||||
|
approved had left it out; the built page keeps it, with one sentence. And
|
||||||
|
the sentence is less than the truth for a `From:` refusal: cleanup did
|
||||||
|
write a line about it under a queue id (`milter-reject: END-OF-MESSAGE …
|
||||||
|
5.7.1 From: …`), but the check answers before the queue id reaches it, so
|
||||||
|
the row keeps none and the page cannot show that line. To do: either drop
|
||||||
|
the box for a refused row, or have the tailer attach the line to the row.
|
||||||
|
- **The Outbound log has no status filter.** The mockup draws one; the built
|
||||||
|
log filters by domain and application. With three kinds of refusal now
|
||||||
|
told apart by tag, a filter by status and reason would be worth having.
|
||||||
|
- **"Messages deferred" counts connections Postfix turned away.** Postfix
|
||||||
|
refuses from the connection on, before a message is offered, so a monitor
|
||||||
|
that only connects during an outage is counted. The guide says so; the
|
||||||
|
card's column head and the help topic still say "messages".
|
||||||
|
|
||||||
|
### Known and small
|
||||||
|
|
||||||
|
- **"Today" on the card is the UTC day**, and the card does not say so.
|
||||||
|
- **A deferral in the very second of the last one counted before an unclean
|
||||||
|
stop is passed over** at the restart: `mail.log` stamps whole seconds.
|
||||||
|
Chosen over counting a stretch of the log twice.
|
||||||
|
- **Deferrals are lost when `mail.log` is rotated while the panel is down**:
|
||||||
|
the tailer starts on the new file.
|
||||||
|
- **A start at which `supervisorctl` fails counts no downtime**; it is
|
||||||
|
logged.
|
||||||
|
- **Logins are compared as written**, Postfix compares them without regard
|
||||||
|
to case. The panel writes logins one way, so nothing differs today.
|
||||||
|
- **The phone order of the `cards` layout is written for four boxes to a
|
||||||
|
stack** and takes every child of a stack for a box (said at the partial).
|
||||||
|
The rule the technical review suggested instead - the order from the
|
||||||
|
box's own number - changes the component and would be drawn first.
|
||||||
|
- **Health's socket check looks at the file, not at who listens**: a socket
|
||||||
|
nobody answers on would read "ok". The start now removes stale sockets,
|
||||||
|
which was the one way to get such a file.
|
||||||
|
- **The kit page's table of status tags does not list the new ones**
|
||||||
|
(`wrong From`, `wrong client`, `rate-limited`), and `rate-limited` is grey
|
||||||
|
beside two red tags - as the mockup has it, not as a decision.
|
||||||
|
- **Refusal rows still in the buffer when the panel stops are not written**;
|
||||||
|
the refusals themselves were answered.
|
||||||
|
|
||||||
|
### Accepted, in security.md
|
||||||
|
|
||||||
|
- **The panel's downtime is mail's.** The price of the strict check.
|
||||||
|
- **What a display name looks like to a person is not promised.** A name of
|
||||||
|
another sender written without an `@` the scan can find passes, signed
|
||||||
|
with the application's own key.
|
||||||
|
- **A malformed packet on the check's socket ends the panel** (the milter
|
||||||
|
library panics on an empty one). The socket is reachable only inside the
|
||||||
|
container, by the group Postfix is in; the journal milter always had this,
|
||||||
|
and what is new is that the price is deferred mail.
|
||||||
|
|
||||||
|
### Not verified
|
||||||
|
|
||||||
|
- **OpenDKIM's reading of a `From:` line** was reasoned about, not run: its
|
||||||
|
parser is not in this repository. The two rules that do not depend on it -
|
||||||
|
no other signing name after any `@`, one `@` outside quotes - are what the
|
||||||
|
claim rests on. A test that feeds the stand's OpenDKIM the lines the check
|
||||||
|
passes and reads which key it signs with would settle it.
|
||||||
|
- **The pages were not looked at in a browser on the deployed panel**: I
|
||||||
|
cannot sign in there. They were rendered from the fixtures and
|
||||||
|
screenshotted, the polling and the phone order read from the code and
|
||||||
|
exercised by e2e only as far as the Health numbers.
|
||||||
|
- **No refusal has been seen on the test server itself**, only on the e2e
|
||||||
|
stand: there is no application there I can send as.
|
||||||
|
- **A check that stops answering in the middle of a message** is counted
|
||||||
|
from a warning composed from Postfix's source; the stand only produced the
|
||||||
|
case of nobody listening.
|
||||||
|
|||||||
+9
-6
@@ -39,7 +39,7 @@ in `git log` and [CHANGELOG.md](../CHANGELOG.md).
|
|||||||
| delivery-log-storage | Keep a message's `mail.log` lines with its send-log row | shipped `2.2.0` | 8/8 | [plans/delivery-log-storage.md](plans/delivery-log-storage.md) |
|
| delivery-log-storage | Keep a message's `mail.log` lines with its send-log row | shipped `2.2.0` | 8/8 | [plans/delivery-log-storage.md](plans/delivery-log-storage.md) |
|
||||||
| password-reset | Password reset by e-mail | candidate | — | — |
|
| password-reset | Password reset by e-mail | candidate | — | — |
|
||||||
| phone-desktop-mode | A phone browser in "desktop site" mode gets the phone navigation | candidate | — | — |
|
| phone-desktop-mode | A phone browser in "desktop site" mode gets the phone navigation | candidate | — | — |
|
||||||
| from-header-binding | Hold a message's `From:` header against the application that sends it | built and reviewed, for `2.4.0` | 9/9 | [plans/from-header-binding.md](plans/from-header-binding.md) |
|
| from-header-binding | Hold a message's `From:` header against the application that sends it | shipped `2.4.0` | 9/9 | [plans/from-header-binding.md](plans/from-header-binding.md) |
|
||||||
| panel-redesign | Panel redesign (accepted mockups, design contract) | shipped `2.0.0` | 27/27 | [plans/panel-redesign.md](plans/panel-redesign.md) |
|
| panel-redesign | Panel redesign (accepted mockups, design contract) | shipped `2.0.0` | 27/27 | [plans/panel-redesign.md](plans/panel-redesign.md) |
|
||||||
| schema-squash | Squash SQLite migrations into a 2.x baseline | built in panel-redesign (stage 1) | — | [plans/panel-redesign.md](plans/panel-redesign.md) |
|
| schema-squash | Squash SQLite migrations into a 2.x baseline | built in panel-redesign (stage 1) | — | [plans/panel-redesign.md](plans/panel-redesign.md) |
|
||||||
|
|
||||||
@@ -47,7 +47,8 @@ in `git log` and [CHANGELOG.md](../CHANGELOG.md).
|
|||||||
development convenience): **panel-redesign** shipped as `2.0.0` (2026-10-11) and
|
development convenience): **panel-redesign** shipped as `2.0.0` (2026-10-11) and
|
||||||
**inbound-antispam-panel** as `2.1.0` (2026-10-12), built in the new component
|
**inbound-antispam-panel** as `2.1.0` (2026-10-12), built in the new component
|
||||||
kit — styling its two screens once instead of twice. **delivery-log-storage**
|
kit — styling its two screens once instead of twice. **delivery-log-storage**
|
||||||
shipped as `2.2.0` the same day, and **panel-notifications** as `2.3.0`.
|
shipped as `2.2.0` the same day, **panel-notifications** as `2.3.0` and
|
||||||
|
**from-header-binding** as `2.4.0`.
|
||||||
Nothing is agreed after it: every remaining
|
Nothing is agreed after it: every remaining
|
||||||
item is a candidate. panel-docs shipped in
|
item is a candidate. panel-docs shipped in
|
||||||
[CHANGELOG.md](../CHANGELOG.md) `[1.8.0]`; dmarc-reports in `[1.7.0]`
|
[CHANGELOG.md](../CHANGELOG.md) `[1.8.0]`; dmarc-reports in `[1.7.0]`
|
||||||
@@ -440,8 +441,9 @@ since 2.3.0, the server's own name - into `From:` and have the message signed
|
|||||||
with that name's key: mail that passes DMARC as a domain the application has
|
with that name's key: mail that passes DMARC as a domain the application has
|
||||||
no right to, or that looks like a notification of the panel.
|
no right to, or that looks like a notification of the panel.
|
||||||
|
|
||||||
**Agreed with the owner on 2026-10-12** and taken into work
|
**Agreed with the owner on 2026-10-12**, built and reviewed the same day
|
||||||
([plans/from-header-binding.md](plans/from-header-binding.md)). The rule he
|
([plans/from-header-binding.md](plans/from-header-binding.md); what is not
|
||||||
|
done is listed there under *Not done*). The rule he
|
||||||
chose is wider than the one first written here: `From:` is held to exactly
|
chose is wider than the one first written here: `From:` is held to exactly
|
||||||
what the envelope is held to - any address of the application's domain, or
|
what the envelope is held to - any address of the application's domain, or
|
||||||
the addresses of its list - and anything else is refused, a stranger's domain
|
the addresses of its list - and anything else is refused, a stranger's domain
|
||||||
@@ -454,8 +456,9 @@ needs a process of its own.
|
|||||||
tenant's `From:`, for the hostname's and for an address off its list, and
|
tenant's `From:`, for the hostname's and for an address off its list, and
|
||||||
accepted for its own.
|
accepted for its own.
|
||||||
|
|
||||||
**Version:** `2.4.0` MINOR; in progress. Until it ships:
|
**Version:** shipped `2.4.0` (2026-10-12), MINOR. What it costs - the
|
||||||
[security.md](security.md) § Accepted risks.
|
panel's downtime is now mail's - is in [security.md](security.md) § Accepted
|
||||||
|
risks.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -476,6 +476,14 @@ deferred item from the roadmap.
|
|||||||
downtime and the mail deferred for it. Trigger to revisit: those numbers
|
downtime and the mail deferred for it. Trigger to revisit: those numbers
|
||||||
not staying at nothing - then the check moves into a process of its own
|
not staying at nothing - then the check moves into a process of its own
|
||||||
([plans/from-header-binding.md](plans/from-header-binding.md)).
|
([plans/from-header-binding.md](plans/from-header-binding.md)).
|
||||||
|
- **A malformed packet on a milter socket of the panel ends the panel.** The
|
||||||
|
milter library indexes into an empty packet and nobody recovers the panic,
|
||||||
|
so the process exits and supervisord starts it again. The sockets are
|
||||||
|
reachable only inside the container, by the group Postfix is in (mode
|
||||||
|
0660); the journal milter always had this, and since `2.4.0` the seconds
|
||||||
|
of the restart defer mail instead of passing it unjournalled (technical
|
||||||
|
review, 2026-10-12). Trigger to revisit: anything untrusted able to open
|
||||||
|
a Unix socket in the container.
|
||||||
- **When the hostname is itself a sending domain,** the server's mail is
|
- **When the hostname is itself a sending domain,** the server's mail is
|
||||||
signed with that domain's key. Whoever may export the domain has the key,
|
signed with that domain's key. Whoever may export the domain has the key,
|
||||||
and its applications may send as `postmaster@<hostname>` by right. The
|
and its applications may send as `postmaster@<hostname>` by right. The
|
||||||
|
|||||||
Reference in New Issue
Block a user