Show this Postfix's retry policy on Mail queue and delivery history.
test / test (push) Waiting to run
test / test (push) Waiting to run
Numbers come from a one-shot postconf -h at panel start so a manual override is visible after restart, without inventing an attempt count. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+12
-3
@@ -78,7 +78,14 @@ by the panel. Socket `/run/opendkim/opendkim.sock`.
|
||||
One process, three roles:
|
||||
|
||||
1. **HTTP server** — `:8080` (`PANEL_HTTP_ADDR`); HTTPS terminated by reverse
|
||||
proxy only.
|
||||
proxy only. On start it runs `postconf -h` once for the deferred-mail retry
|
||||
parameters (`queue_run_delay`, `minimal_backoff_time`,
|
||||
`maximal_backoff_time`, `maximal_queue_lifetime`, `bounce_queue_lifetime`,
|
||||
`delay_warning_time`) and caches the snapshot on the handlers config. The
|
||||
Mail queue card and a delivery's `deferred` / `bounced` history print those
|
||||
numbers; they never call `postconf` per request. If `postconf` is missing,
|
||||
the panel logs a warning and uses Postfix 3.x compiled-in defaults
|
||||
(`300s` / `4000s` / `5d` / `0`) with a muted note on the card.
|
||||
2. **journal-milter** — unix socket `JOURNAL_MILTER_SOCKET`; records From/To/
|
||||
Subject/SASL user at DATA; enforces level-2 rate limits; **fail-open**
|
||||
(`default_action=accept`) so milter failure does not stop mail. Domain
|
||||
@@ -173,7 +180,7 @@ below is a summary — HTMX fragment endpoints
|
||||
| `/domains/{id}`, `/domains/{id}/*` | Assigned-domain detail for domain-admins; delete domain is **global** |
|
||||
| `/domains/import` | **Global.** Domain import (`POST`; form on the Backup page) |
|
||||
| `/deliveries`, `/deliveries/{id}` | Send log with filters; scoped to assigned domains for domain-admins |
|
||||
| `/mail-queue`, `/mail-queue/*` | **Global.** Postfix queue view |
|
||||
| `/mail-queue`, `/mail-queue/*` | **Global.** Postfix queue view; retry-policy card on the page (not the HTMX fragment) |
|
||||
| `/system-log`, `/system-log/*` | **Global.** `mail.log` tail |
|
||||
| `/reload` | **Global.** `POST` — reload OpenDKIM + Postfix maps |
|
||||
| `/backup`, `/backup/*` | **Global.** Full backup download (page also hosts the import form) |
|
||||
@@ -184,7 +191,9 @@ HTMX polling refreshes monitoring fragments (5 s while the operator is active on
|
||||
the page, 30 s when the tab is visible but idle, none when hidden — scheduled in
|
||||
`panel.js` via `data-poll`, not `hx-trigger="every …"`); polling does not extend
|
||||
session idle timeout (only non-`HX-Request` GET and mutating requests count as
|
||||
activity).
|
||||
activity). The Mail queue retry-policy card is outside that fragment: it is the
|
||||
start-up `postconf -h` snapshot (see [Panel binary](#panel-binary-cmdpanel)),
|
||||
not a live re-read.
|
||||
|
||||
### Sessions
|
||||
|
||||
|
||||
+11
-3
@@ -319,7 +319,12 @@ the panel shows after manual edits under `/data`.
|
||||
### Mail queue and System log
|
||||
|
||||
- **Mail queue** (`/mail-queue`) — live view of messages Postfix is still
|
||||
trying to deliver or deferring.
|
||||
trying to deliver or deferring. A card at the top states this instance's
|
||||
retry policy — first retry delay, later backoff cap, how long a message
|
||||
stays in the queue — from `postconf -h`, read once when the panel starts.
|
||||
A `postconf -e` override inside the container is visible after the next
|
||||
panel (or container) restart. There is no maximum attempt count: Postfix
|
||||
retries until the message is delivered or the queue lifetime runs out.
|
||||
- **System log** (`/system-log`) — tail of `/data/log/mail.log` (Postfix and
|
||||
related daemon lines). The log rotates daily (14 files kept) with a
|
||||
`postfix reload` after each rotation; a background loop checks every six
|
||||
@@ -668,8 +673,11 @@ by a [level-2 rate limit](#rate-limiting--level-2-domain-and-application));
|
||||
*Details* opens that row's own page (`/deliveries/{id}`). That page carries
|
||||
the sending domain, the application it was submitted under, the Postfix
|
||||
queue id and the journal id, beside the message's history — when it was
|
||||
accepted and what Postfix later reported for the recipient — and, under
|
||||
both, the `mail.log` lines for its queue id: the connection to the
|
||||
accepted and what Postfix later reported for the recipient. A `deferred`
|
||||
or `bounced` row includes this Postfix's retry intervals (first delay,
|
||||
backoff cap, queue lifetime), the same numbers Mail queue shows; domain
|
||||
administrators see them here because they cannot open Mail queue. Under
|
||||
both sit the `mail.log` lines for its queue id: the connection to the
|
||||
receiving server, the server's reply, and the status that reply was filed
|
||||
as. Rows outlive `mail.log`, so an older message's lines may have rotated
|
||||
away; the page says so. Retention is controlled by
|
||||
|
||||
+10
-10
@@ -1,6 +1,6 @@
|
||||
# Plan: queue-retries (Postfix retry policy in the panel)
|
||||
|
||||
**Status:** agreed
|
||||
**Status:** implemented (2026-08-17); version cut `1.3.1` pending
|
||||
**Date:** 2026-08-13
|
||||
**Version:** patch; no schema, no configuration surface.
|
||||
**Order:** small panel item; does not wait on inbound-relay.
|
||||
@@ -145,12 +145,12 @@ lifetime runs out.
|
||||
Target version cut: **`1.3.1`** (PATCH). One commit per step; see
|
||||
[development.md](../development.md) § Plan checklists.
|
||||
|
||||
- [ ] `internal/postfix`: parse Postfix time units (`5d`, `300s`, bare seconds) + tests — **Opus**
|
||||
- [ ] `internal/postfix`: one-shot `postconf -h` (six keys), fallback + warn — **Opus**
|
||||
- [ ] Load policy at HTTP start in `cmd/panel/httpserver.go`; cache on handlers config — **Opus**
|
||||
- [ ] Human-readable duration formatter (shared by Mail queue card and delivery history) — **Sonnet**
|
||||
- [ ] «How delivery retries work» card on `/mail-queue` (outside HTMX fragment) — **Sonnet**
|
||||
- [ ] `deliveryEvents(row, policy)` — intervals in deferred/bounced copy — **Sonnet**
|
||||
- [ ] Handler and template tests (`handlers_monitor_test.go`, `templates_test.go`) — **Sonnet**
|
||||
- [ ] [guide.md](../guide.md) and [architecture.md](../architecture.md) — **Sonnet**
|
||||
- [ ] `go vet`, `go test` on touched packages — **Haiku**
|
||||
- [x] `internal/postfix`: parse Postfix time units (`5d`, `300s`, bare seconds) + tests — **Opus**
|
||||
- [x] `internal/postfix`: one-shot `postconf -h` (six keys), fallback + warn — **Opus**
|
||||
- [x] Load policy at HTTP start in `cmd/panel/httpserver.go`; cache on handlers config — **Opus**
|
||||
- [x] Human-readable duration formatter (shared by Mail queue card and delivery history) — **Sonnet**
|
||||
- [x] «How delivery retries work» card on `/mail-queue` (outside HTMX fragment) — **Sonnet**
|
||||
- [x] `deliveryEvents(row, policy)` — intervals in deferred/bounced copy — **Sonnet**
|
||||
- [x] Handler and template tests (`handlers_monitor_test.go`, `templates_test.go`) — **Sonnet**
|
||||
- [x] [guide.md](../guide.md) and [architecture.md](../architecture.md) — **Sonnet**
|
||||
- [x] `go vet`, `go test` on touched packages — **Haiku**
|
||||
|
||||
+5
-2
@@ -28,7 +28,7 @@ in `git log` and [CHANGELOG.md](../CHANGELOG.md).
|
||||
|
||||
| ID | Topic | Status | Progress | Plan |
|
||||
|---|---|---|---|---|
|
||||
| queue-retries | Postfix retry policy in the panel (queue lifetime, backoff) | **agreed** | 0/9 | [plans/queue-retries.md](plans/queue-retries.md) |
|
||||
| queue-retries | Postfix retry policy in the panel (queue lifetime, backoff) | **agreed** | 9/9 | [plans/queue-retries.md](plans/queue-retries.md) |
|
||||
| inbound-relay | Inbound relay (backup-MX / forwarding) | **agreed** | 0/15 | [plans/inbound-relay.md](plans/inbound-relay.md) |
|
||||
| send-log-retention | Send-log retention days in panel Settings | candidate | 0/8 | [plans/send-log-retention.md](plans/send-log-retention.md) |
|
||||
| domain-stats-auto-ratelimit | 30-day send stats + auto level-2 rate limit | candidate | 0/11 | [plans/domain-stats-auto-ratelimit.md](plans/domain-stats-auto-ratelimit.md) |
|
||||
@@ -65,7 +65,10 @@ panel knobs for queue lifetime, no schema change. Domain administrators see
|
||||
the intervals on `/deliveries/{id}` (they cannot open Mail queue).
|
||||
|
||||
**Done when:** see the criteria in
|
||||
[plans/queue-retries.md](plans/queue-retries.md).
|
||||
[plans/queue-retries.md](plans/queue-retries.md). Implementation is on
|
||||
`main` (checklist 9/9); the `1.3.1` version cut is still pending because
|
||||
`[Unreleased]` also holds unrelated work (including a breaking backup-layout
|
||||
change).
|
||||
|
||||
**Dependencies / risks:** `postconf` unavailable outside the container
|
||||
(fallback + muted note). Copy must stay time-based — Postfix has no max
|
||||
|
||||
Reference in New Issue
Block a user