Compare commits

...
2 Commits
Author SHA1 Message Date
mixandCursor 4a51db277b release: 1.9.1
test / test (push) Has been cancelled
Fix port-25 Postfix startup when inbound relay, DMARC ingest, or antispam milter are enabled; consolidate schema-migrations and inbound antispam/quarantine roadmap docs in the changelog.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 00:47:45 +03:00
mixandCursor 6adbb41459 fix: port-25 Postfix config when inbound, DMARC, or antispam are enabled
postconf -P cannot set master.cf -o values with whitespace; patch smtp/inet
directly and route DMARC ingest through a dmarc-ingest symlink.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 00:43:59 +03:00
3 changed files with 59 additions and 16 deletions
+18 -9
View File
@@ -5,6 +5,12 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
## [Unreleased] ## [Unreleased]
## [1.9.1] - 2026-08-19
Port-25 Postfix startup when inbound relay, DMARC ingest, or the inbound antispam
milter are enabled. Schema-migration reference and roadmap plans for inbound
antispam and quarantine. Upgrading from 1.9.0 is a tag bump; no migration.
### Added ### Added
- [docs/plans/inbound-antispam-panel.md](docs/plans/inbound-antispam-panel.md) — - [docs/plans/inbound-antispam-panel.md](docs/plans/inbound-antispam-panel.md) —
@@ -13,6 +19,9 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
`1.10.0`; Composer → Opus → Fable workflow. `1.10.0`; Composer → Opus → Fable workflow.
- [docs/plans/inbound-quarantine.md](docs/plans/inbound-quarantine.md) — candidate - [docs/plans/inbound-quarantine.md](docs/plans/inbound-quarantine.md) — candidate
plan for held-mail review/release (design TBD). plan for held-mail review/release (design TBD).
- [docs/schema-migrations.md](docs/schema-migrations.md) — living reference for the
SQLite migration chain (`user_version` head, per-file history, legacy artefacts,
1.x rules, and planned 2.x squash gate).
### Changed ### Changed
@@ -20,19 +29,19 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
and `inbound-quarantine` (candidate) in the index. and `inbound-quarantine` (candidate) in the index.
- [docs/development.md](docs/development.md) — plan checklists may override - [docs/development.md](docs/development.md) — plan checklists may override
model routing with Composer → Opus → Fable. model routing with Composer → Opus → Fable.
### Added
- [docs/schema-migrations.md](docs/schema-migrations.md) — living reference for the
SQLite migration chain (`user_version` head, per-file history, legacy artefacts,
1.x rules, and planned 2.x squash gate).
### Changed
- [docs/development.md](docs/development.md), [docs/roadmap.md](docs/roadmap.md), - [docs/development.md](docs/development.md), [docs/roadmap.md](docs/roadmap.md),
and [docs/architecture.md](docs/architecture.md) link to the new file; and [docs/architecture.md](docs/architecture.md) link to the new file;
`schema-squash` defers gate thresholds to it instead of a stale v5 snapshot. `schema-squash` defers gate thresholds to it instead of a stale v5 snapshot.
### Fixed
- `build/postfix-config.sh`: enabling inbound relay, DMARC ingest, and/or the
inbound antispam milter no longer crash-loops on start — `postconf -P` cannot
set `master.cf` `-o` values that contain whitespace, so port-25
`smtpd_recipient_restrictions` and `smtpd_milters` are patched directly; DMARC
pipe `argv` uses a `dmarc-ingest` symlink instead of `panel -dmarc-ingest`.
## [1.9.0] - 2026-08-18
Application sending controls: client IP allow-list for authorization, and Application sending controls: client IP allow-list for authorization, and
level-2 rate limits that override the domain ceiling per application. level-2 rate limits that override the domain ceiling per application.
+37 -3
View File
@@ -13,6 +13,37 @@
# a fixed literal or a container environment variable (spec 7.6.3). # a fixed literal or a container environment variable (spec 7.6.3).
set -eu set -eu
# postconf -P refuses master.cf -o values that contain whitespace; inbound port
# 25 needs restriction lists and milter specs that include spaces. Patch the
# smtp/inet service stanza directly instead.
master_cf_set_smtp_inet_o() {
param="$1"
value="$2"
awk -v p="$param" -v v="$value" '
/^smtp[ \t]+inet[ \t]/ && !done {
print
print " -o " p "=" v
done = 1
in_smtp_inet = 1
next
}
in_smtp_inet && /^[ \t]+-o / {
line = $0
sub(/^[ \t]+-o /, "", line)
eq = index(line, "=")
on = substr(line, 1, eq - 1)
if (on == p) {
next
}
}
in_smtp_inet && /^[^ \t#-]/ {
in_smtp_inet = 0
}
{ print }
' /etc/postfix/master.cf > /etc/postfix/master.cf.new
mv /etc/postfix/master.cf.new /etc/postfix/master.cf
}
# --- environment knobs (spec 8) ---------------------------------------------- # --- environment knobs (spec 8) ----------------------------------------------
# Server hostname: used as HELO name AND, crucially, as the Cyrus SASL realm the # Server hostname: used as HELO name AND, crucially, as the Cyrus SASL realm the
# sasldb2 accounts are looked up under. The panel creates accounts under realm # sasldb2 accounts are looked up under. The panel creates accounts under realm
@@ -241,11 +272,12 @@ if [ "${INBOUND_RELAY_ENABLE}" = "true" ] || [ "${DMARC_REPORTS_ENABLE}" = "true
for f in "$DMARC_RECIPIENTS_MAP" "$DMARC_TRANSPORT_MAP" "$DMARC_RELAY_DOMAINS_MAP"; do for f in "$DMARC_RECIPIENTS_MAP" "$DMARC_TRANSPORT_MAP" "$DMARC_RELAY_DOMAINS_MAP"; do
[ -e "$f" ] || : > "$f" [ -e "$f" ] || : > "$f"
done done
ln -sf /usr/local/bin/panel /usr/local/bin/dmarc-ingest
postconf -M "dmarc-ingest/unix-pipe=dmarc-ingest unix - n n - - pipe" postconf -M "dmarc-ingest/unix-pipe=dmarc-ingest unix - n n - - pipe"
postconf -P \ postconf -P \
"dmarc-ingest/unix-pipe/flags=Rq" \ "dmarc-ingest/unix-pipe/flags=Rq" \
"dmarc-ingest/unix-pipe/user=panel" \ "dmarc-ingest/unix-pipe/user=panel" \
"dmarc-ingest/unix-pipe/argv=/usr/local/bin/panel -dmarc-ingest" "dmarc-ingest/unix-pipe/argv=/usr/local/bin/dmarc-ingest"
if [ -n "$RELAY_DOMAINS_SETTING" ]; then if [ -n "$RELAY_DOMAINS_SETTING" ]; then
RELAY_DOMAINS_SETTING="${RELAY_DOMAINS_SETTING} texthash:${DMARC_RELAY_DOMAINS_MAP}" RELAY_DOMAINS_SETTING="${RELAY_DOMAINS_SETTING} texthash:${DMARC_RELAY_DOMAINS_MAP}"
TRANSPORT_SETTING="${TRANSPORT_SETTING} texthash:${DMARC_TRANSPORT_MAP}" TRANSPORT_SETTING="${TRANSPORT_SETTING} texthash:${DMARC_TRANSPORT_MAP}"
@@ -311,10 +343,12 @@ if [ "${INBOUND_RELAY_ENABLE}" = "true" ] || [ "${DMARC_REPORTS_ENABLE}" = "true
"smtp/inet/smtpd_sender_restrictions=" \ "smtp/inet/smtpd_sender_restrictions=" \
"smtp/inet/smtpd_client_restrictions=" \ "smtp/inet/smtpd_client_restrictions=" \
"smtp/inet/smtpd_relay_restrictions=reject_unauth_destination" \ "smtp/inet/smtpd_relay_restrictions=reject_unauth_destination" \
"smtp/inet/smtpd_recipient_restrictions=${RECIPIENT_RESTRICTIONS}" \
"smtp/inet/smtpd_milters=${INBOUND_MILTERS}" \
"smtp/inet/smtpd_client_message_rate_limit=${PORT25_RATE}" \ "smtp/inet/smtpd_client_message_rate_limit=${PORT25_RATE}" \
"smtp/inet/message_size_limit=${PORT25_SIZE}" "smtp/inet/message_size_limit=${PORT25_SIZE}"
master_cf_set_smtp_inet_o smtpd_recipient_restrictions "${RECIPIENT_RESTRICTIONS}"
if [ -n "${INBOUND_MILTERS}" ]; then
master_cf_set_smtp_inet_o smtpd_milters "${INBOUND_MILTERS}"
fi
else else
postconf -MX "smtp/inet" 2>/dev/null || true postconf -MX "smtp/inet" 2>/dev/null || true
postconf -MX "dmarc-ingest/unix-pipe" 2>/dev/null || true postconf -MX "dmarc-ingest/unix-pipe" 2>/dev/null || true
+1 -1
View File
@@ -22,7 +22,7 @@
services: services:
selfpost: selfpost:
image: ghcr.io/mixeme/selfpost:1.9.0 image: ghcr.io/mixeme/selfpost:1.9.1
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}"