diff --git a/docs/assets/panel-redesign/panel/confirm-email-signin.html b/docs/assets/panel-redesign/panel/confirm-email-signin.html new file mode 100644 index 0000000..6bf6494 --- /dev/null +++ b/docs/assets/panel-redesign/panel/confirm-email-signin.html @@ -0,0 +1,32 @@ + + + + + +Confirm e-mail · SelfPost + + + + + + +
+
+
+ SelfPost +

YOUR SMTP. YOUR RULES.

+
+
+
+
+

mail.example.org

+

Confirm e-mail

+
Sign in to the account in this browser, then open the link again.
+

Sign in

+
+

Copyright © 2026 Mikhail Yenuchenko · License (AGPL-3.0) · Source · No warranty

+
+
+ + + diff --git a/docs/assets/panel-redesign/panel/dmarc-report.html b/docs/assets/panel-redesign/panel/dmarc-report.html index d4ea3af..4597c38 100644 --- a/docs/assets/panel-redesign/panel/dmarc-report.html +++ b/docs/assets/panel-redesign/panel/dmarc-report.html @@ -81,7 +81,7 @@
Reporter
Outlook.com
Report id
5f1c9a0e7b2d4e61a3
-
Window
20 Sep 00:00 – 21 Sep 00:00
+
Window
20 Sep 03:00 – 21 Sep 03:00
The reporter's day, 20 Sep: reports count their days in UTC, and the title and the lists name that day. The times are this panel's zone.
Received
2026-09-21 04:40
diff --git a/docs/assets/panel-redesign/panel/help.html b/docs/assets/panel-redesign/panel/help.html index 4713fab..8f542a9 100644 --- a/docs/assets/panel-redesign/panel/help.html +++ b/docs/assets/panel-redesign/panel/help.html @@ -131,7 +131,7 @@

Rate limits

Level 1 is a per-IP ceiling set in .env. Level 2 is optional, per domain and per application, entered by hand or computed from the last 30 days of sending, and can never exceed level 1. An application's own limit replaces its domain's.

Outbound log

One row per message and recipient (a message refused for its From: or Sender: line is one row, however many recipients it had), with the status Postfix last reported: queued (accepted, nothing reported yet), sent (the receiving server took it; what the mailbox does next is not reported back), deferred (not taken yet, Postfix tries again), bounced (failed for good, or the queue lifetime ran out; or closed by the panel when Postfix no longer held the message and mail.log never said what became of it) and rejected (refused before queueing, so it never reached the queue: under a level-2 rate limit, from a client address the application does not allow, or for a From: or Sender: line that is not the application's - the message's page says which). A message's page lists these steps and the lines Postfix wrote about it in mail.log, found by queue id - and for a message refused before it had one, Postfix's one line about the refusal. The lines are kept with the row: they stay on the page after that file has rotated, for as long as the row does. A message accepted before version 2.2.0 shows them only while they are still in the current file. Rows are deleted after the retention set in Server › Settings, 90 days by default, and their lines with them. A domain administrator sees only the rows of their own domains.

Queue and retries

The page lists, as postqueue -p prints it, the messages Postfix has accepted and not yet delivered: mail being sent right now and mail deferred for a later attempt. Only the global role can open it, and it only shows; nothing here deletes or forces a message. A deferred message is tried again after the first retry delay, then at gaps that double up to a cap, until the receiving server takes it or the queue lifetime runs out and it bounces; there is no attempt counter, and the box on the page shows this server's values. A queue that keeps growing means a receiver is refusing or not answering: open the message from the Outbound log to read the reason Postfix logged.

-

DMARC reports

An aggregate report is the summary a receiving provider sends, usually daily, to the rua= address of your DMARC record: which servers sent mail as your domain and whether SPF or DKIM passed for it. A domain's report address is one of three choices, set in its Domain settings: no reports (the default for a new domain), the SelfPost hosted address (an address on this server whose reports are parsed and shown under DMARC reports; offered only while hosted reports are enabled on the server), or an address typed for the domain (an ordinary mailbox that receives the raw XML; a button fills in your own profile e-mail). When the typed address is on another domain than the one sending, that domain must publish a report-authorization record, or providers will not send; the domain's page shows it with the other DNS records and checks it. In the tables pass means SPF or DKIM passed and aligned, fail means neither did, and your own server shows as this relay. A fail from any other source is someone else sending as your domain — a forwarder, an application you forgot, or abuse — so do not tighten p= until that sender is fixed or removed. A domain administrator reads the reports of their own domains.

+

DMARC reports

An aggregate report is the summary a receiving provider sends, usually daily, to the rua= address of your DMARC record - its day is the reporter's, counted in UTC, and that is the day the lists and a report's title name, while the report's page gives its window in this panel's zone: which servers sent mail as your domain and whether SPF or DKIM passed for it. A domain's report address is one of three choices, set in its Domain settings: no reports (the default for a new domain), the SelfPost hosted address (an address on this server whose reports are parsed and shown under DMARC reports; offered only while hosted reports are enabled on the server), or an address typed for the domain (an ordinary mailbox that receives the raw XML; a button fills in your own profile e-mail). When the typed address is on another domain than the one sending, that domain must publish a report-authorization record, or providers will not send; the domain's page shows it with the other DNS records and checks it. In the tables pass means SPF or DKIM passed and aligned, fail means neither did, and your own server shows as this relay. A fail from any other source is someone else sending as your domain — a forwarder, an application you forgot, or abuse — so do not tighten p= until that sender is fixed or removed. A domain administrator reads the reports of their own domains.

03

Inbound

@@ -146,7 +146,7 @@
04

Server

Backup and moving a domain

Full backup downloads one archive of the whole instance: data/ (the database, DKIM keys and application credentials), docker-compose.yml, .env and certs/. Both it and a domain's export ask for your account password - the one you sign in with - at every download, so a session left open is not enough to take them; every attempt, right or wrong, counts against the limit of a password change, ten in 15 minutes. The Postfix queue is not in it. The backup is taken while the server is running, and Postfix keeps moving messages through the queue, so a copy could hold a message twice or miss it; mail still waiting for delivery is therefore not carried over, and a restored server starts with an empty queue. To keep the queue, stop the container and archive the project directory instead. The private key in certs/ has to be readable by the panel: give it to group 10998 on the host (chgrp 10998, chmod 640). Until then the panel refuses to make a backup and names the file, rather than hand over an archive without the key. It holds secrets, so leave Encrypt with a password ticked: the file is sealed as .spbk, the password is not stored, and without it nothing can be recovered. To restore, unpack it into an empty project directory (decrypt a .spbk first with selfpost-backup -decrypt) and start the same SelfPost version that made it; the panel refuses data from another version. The reverse-proxy configuration and mail.log are not included. One domain moves on its own: Export domain on its settings page writes a .json (or encrypted .spde) with its DKIM key and its applications' passwords, and Import a domain here reads it into another instance, so the published DNS needs no change.

Users and roles

The two roles are a reach, not a rank: every user is an administrator and signs in with a username and password. Global reaches the whole server — Overview, Server, the queue and every domain — and is the only role that adds or deletes domains and users. Domain reaches only the domains assigned to it, outbound and inbound separately (the same name on both lists is two assignments); All includes domains added later, and a domain user needs at least one domain or All on either list. The only global user cannot be demoted or deleted, and you cannot delete the account you are signed in with. A new password set here signs that user out everywhere; set for yourself, it keeps the session you set it from.

-

Settings

Settings holds what is true of the whole instance. The time zone is the container's, TZ in .env (UTC when it is not set): every time the panel shows and every day it counts is that zone's, as are the stamps Postfix writes in mail.log, so the two always agree; changing it is a restart of the container. Log retention is how many days the Outbound log keeps its rows, from 7 to 365 and 90 by default; a sweep every six hours deletes older ones, and it is the main driver of how fast /data grows. With the inbound relay on there is a second number, for the Inbound log, with the same range. It does not change the rotation of mail.log, which is daily with about two weeks kept. The sending rate limit shown under it is level 1, the per-client-IP ceiling set in .env: changing it needs a restart, and no level-2 limit can exceed it. Notifications are turned on or off here for everyone.

+

Settings

Settings holds what is true of the whole instance. The time zone is the container's, TZ in .env (UTC when it is not set): every time the panel shows and every day it counts is that zone's, as are the stamps Postfix writes in mail.log, so the two always agree; changing it is a restart of the container. The one exception is the day a DMARC report covers, which is the reporter's, counted in UTC. Log retention is how many days the Outbound log keeps its rows, from 7 to 365 and 90 by default; a sweep every six hours deletes older ones, and it is the main driver of how fast /data grows. With the inbound relay on there is a second number, for the Inbound log, with the same range. It does not change the rotation of mail.log, which is daily with about two weeks kept. The sending rate limit shown under it is level 1, the per-client-IP ceiling set in .env: changing it needs a restart, and no level-2 limit can exceed it. Notifications are turned on or off here for everyone.

Notifications

The panel writes to its users when something needs them, from postmaster@ the server's hostname. Four things are reported. A sending domain's SPF, DKIM or DMARC record stops matching: sent once two hourly checks in a row have found it so, and once more when the record matches again. A level-2 rate limit refuses mail: sent at the first refusal, then at most once a day for the same sending domain. The TLS certificate is 14 days from expiry, and again at 3 days if it is still the same certificate. A message has waited in the queue for more than three days, with one more message when none is left. A global user is told all of it; a domain administrator is told about the DNS records and limits of their own domains.

Each user turns notifications on or off under Account and needs an e-mail there; Server › Settings turns them off for everyone. They are the panel's own mail: not rows of the Outbound log, and not counted against any limit.

For that mail to arrive, the server's own name needs two DNS records of its own, as each of your domains does: a DKIM key, which the panel generates and signs notifications with, and an SPF record, v=spf1 a -all. Server › Settings gives both with the values to publish and whether they are in place, and its Re-check DNS checks them again once they are published; Server › Health shows them too. Without them notifications are still sent, and a receiver may file them as spam. Mail of your domains does not depend on either.

diff --git a/docs/assets/panel-redesign/panel/settings.html b/docs/assets/panel-redesign/panel/settings.html index 3b545d2..ce70198 100644 --- a/docs/assets/panel-redesign/panel/settings.html +++ b/docs/assets/panel-redesign/panel/settings.html @@ -146,7 +146,7 @@
Zone
Europe/Moscow
UTC+03:00. Set in .env (TZ); restart to change.
-

Every time the panel shows, and every day it counts - today on Health, the days of the statistics - is this zone's, and so are the stamps of mail.log.

+

Every time the panel shows, and every day it counts - today on Health, the days of the statistics - is this zone's, and so are the stamps of mail.log. One exception: the day a DMARC report covers is the reporter's, in UTC.

diff --git a/docs/assets/panel-redesign/panel/src/confirm-email-signin.html b/docs/assets/panel-redesign/panel/src/confirm-email-signin.html new file mode 100644 index 0000000..d62fa86 --- /dev/null +++ b/docs/assets/panel-redesign/panel/src/confirm-email-signin.html @@ -0,0 +1,18 @@ + +
+
+
+ SelfPost +

YOUR SMTP. YOUR RULES.

+
+
+
+
+

mail.example.org

+

Confirm e-mail

+
Sign in to the account in this browser, then open the link again.
+

Sign in

+
+

Copyright © 2026 Mikhail Yenuchenko · License (AGPL-3.0) · Source · No warranty

+
+
diff --git a/docs/assets/panel-redesign/panel/src/dmarc-report.html b/docs/assets/panel-redesign/panel/src/dmarc-report.html index e2e3d67..3c4d166 100644 --- a/docs/assets/panel-redesign/panel/src/dmarc-report.html +++ b/docs/assets/panel-redesign/panel/src/dmarc-report.html @@ -15,7 +15,7 @@
Reporter
Outlook.com
Report id
5f1c9a0e7b2d4e61a3
-
Window
20 Sep 00:00 – 21 Sep 00:00
+
Window
20 Sep 03:00 – 21 Sep 03:00
The reporter's day, 20 Sep: reports count their days in UTC, and the title and the lists name that day. The times are this panel's zone.
Received
2026-09-21 04:40
diff --git a/docs/assets/panel-redesign/panel/src/help.html b/docs/assets/panel-redesign/panel/src/help.html index 3b260f9..0ef57c1 100644 --- a/docs/assets/panel-redesign/panel/src/help.html +++ b/docs/assets/panel-redesign/panel/src/help.html @@ -65,7 +65,7 @@

Rate limits

Level 1 is a per-IP ceiling set in .env. Level 2 is optional, per domain and per application, entered by hand or computed from the last 30 days of sending, and can never exceed level 1. An application's own limit replaces its domain's.

Outbound log

One row per message and recipient (a message refused for its From: or Sender: line is one row, however many recipients it had), with the status Postfix last reported: queued (accepted, nothing reported yet), sent (the receiving server took it; what the mailbox does next is not reported back), deferred (not taken yet, Postfix tries again), bounced (failed for good, or the queue lifetime ran out; or closed by the panel when Postfix no longer held the message and mail.log never said what became of it) and rejected (refused before queueing, so it never reached the queue: under a level-2 rate limit, from a client address the application does not allow, or for a From: or Sender: line that is not the application's - the message's page says which). A message's page lists these steps and the lines Postfix wrote about it in mail.log, found by queue id - and for a message refused before it had one, Postfix's one line about the refusal. The lines are kept with the row: they stay on the page after that file has rotated, for as long as the row does. A message accepted before version 2.2.0 shows them only while they are still in the current file. Rows are deleted after the retention set in Server › Settings, 90 days by default, and their lines with them. A domain administrator sees only the rows of their own domains.

Queue and retries

The page lists, as postqueue -p prints it, the messages Postfix has accepted and not yet delivered: mail being sent right now and mail deferred for a later attempt. Only the global role can open it, and it only shows; nothing here deletes or forces a message. A deferred message is tried again after the first retry delay, then at gaps that double up to a cap, until the receiving server takes it or the queue lifetime runs out and it bounces; there is no attempt counter, and the box on the page shows this server's values. A queue that keeps growing means a receiver is refusing or not answering: open the message from the Outbound log to read the reason Postfix logged.

-

DMARC reports

An aggregate report is the summary a receiving provider sends, usually daily, to the rua= address of your DMARC record: which servers sent mail as your domain and whether SPF or DKIM passed for it. A domain's report address is one of three choices, set in its Domain settings: no reports (the default for a new domain), the SelfPost hosted address (an address on this server whose reports are parsed and shown under DMARC reports; offered only while hosted reports are enabled on the server), or an address typed for the domain (an ordinary mailbox that receives the raw XML; a button fills in your own profile e-mail). When the typed address is on another domain than the one sending, that domain must publish a report-authorization record, or providers will not send; the domain's page shows it with the other DNS records and checks it. In the tables pass means SPF or DKIM passed and aligned, fail means neither did, and your own server shows as this relay. A fail from any other source is someone else sending as your domain — a forwarder, an application you forgot, or abuse — so do not tighten p= until that sender is fixed or removed. A domain administrator reads the reports of their own domains.

+

DMARC reports

An aggregate report is the summary a receiving provider sends, usually daily, to the rua= address of your DMARC record - its day is the reporter's, counted in UTC, and that is the day the lists and a report's title name, while the report's page gives its window in this panel's zone: which servers sent mail as your domain and whether SPF or DKIM passed for it. A domain's report address is one of three choices, set in its Domain settings: no reports (the default for a new domain), the SelfPost hosted address (an address on this server whose reports are parsed and shown under DMARC reports; offered only while hosted reports are enabled on the server), or an address typed for the domain (an ordinary mailbox that receives the raw XML; a button fills in your own profile e-mail). When the typed address is on another domain than the one sending, that domain must publish a report-authorization record, or providers will not send; the domain's page shows it with the other DNS records and checks it. In the tables pass means SPF or DKIM passed and aligned, fail means neither did, and your own server shows as this relay. A fail from any other source is someone else sending as your domain — a forwarder, an application you forgot, or abuse — so do not tighten p= until that sender is fixed or removed. A domain administrator reads the reports of their own domains.

03

Inbound

@@ -80,7 +80,7 @@
04

Server

Backup and moving a domain

Full backup downloads one archive of the whole instance: data/ (the database, DKIM keys and application credentials), docker-compose.yml, .env and certs/. Both it and a domain's export ask for your account password - the one you sign in with - at every download, so a session left open is not enough to take them; every attempt, right or wrong, counts against the limit of a password change, ten in 15 minutes. The Postfix queue is not in it. The backup is taken while the server is running, and Postfix keeps moving messages through the queue, so a copy could hold a message twice or miss it; mail still waiting for delivery is therefore not carried over, and a restored server starts with an empty queue. To keep the queue, stop the container and archive the project directory instead. The private key in certs/ has to be readable by the panel: give it to group 10998 on the host (chgrp 10998, chmod 640). Until then the panel refuses to make a backup and names the file, rather than hand over an archive without the key. It holds secrets, so leave Encrypt with a password ticked: the file is sealed as .spbk, the password is not stored, and without it nothing can be recovered. To restore, unpack it into an empty project directory (decrypt a .spbk first with selfpost-backup -decrypt) and start the same SelfPost version that made it; the panel refuses data from another version. The reverse-proxy configuration and mail.log are not included. One domain moves on its own: Export domain on its settings page writes a .json (or encrypted .spde) with its DKIM key and its applications' passwords, and Import a domain here reads it into another instance, so the published DNS needs no change.

Users and roles

The two roles are a reach, not a rank: every user is an administrator and signs in with a username and password. Global reaches the whole server — Overview, Server, the queue and every domain — and is the only role that adds or deletes domains and users. Domain reaches only the domains assigned to it, outbound and inbound separately (the same name on both lists is two assignments); All includes domains added later, and a domain user needs at least one domain or All on either list. The only global user cannot be demoted or deleted, and you cannot delete the account you are signed in with. A new password set here signs that user out everywhere; set for yourself, it keeps the session you set it from.

-

Settings

Settings holds what is true of the whole instance. The time zone is the container's, TZ in .env (UTC when it is not set): every time the panel shows and every day it counts is that zone's, as are the stamps Postfix writes in mail.log, so the two always agree; changing it is a restart of the container. Log retention is how many days the Outbound log keeps its rows, from 7 to 365 and 90 by default; a sweep every six hours deletes older ones, and it is the main driver of how fast /data grows. With the inbound relay on there is a second number, for the Inbound log, with the same range. It does not change the rotation of mail.log, which is daily with about two weeks kept. The sending rate limit shown under it is level 1, the per-client-IP ceiling set in .env: changing it needs a restart, and no level-2 limit can exceed it. Notifications are turned on or off here for everyone.

+

Settings

Settings holds what is true of the whole instance. The time zone is the container's, TZ in .env (UTC when it is not set): every time the panel shows and every day it counts is that zone's, as are the stamps Postfix writes in mail.log, so the two always agree; changing it is a restart of the container. The one exception is the day a DMARC report covers, which is the reporter's, counted in UTC. Log retention is how many days the Outbound log keeps its rows, from 7 to 365 and 90 by default; a sweep every six hours deletes older ones, and it is the main driver of how fast /data grows. With the inbound relay on there is a second number, for the Inbound log, with the same range. It does not change the rotation of mail.log, which is daily with about two weeks kept. The sending rate limit shown under it is level 1, the per-client-IP ceiling set in .env: changing it needs a restart, and no level-2 limit can exceed it. Notifications are turned on or off here for everyone.

Notifications

The panel writes to its users when something needs them, from postmaster@ the server's hostname. Four things are reported. A sending domain's SPF, DKIM or DMARC record stops matching: sent once two hourly checks in a row have found it so, and once more when the record matches again. A level-2 rate limit refuses mail: sent at the first refusal, then at most once a day for the same sending domain. The TLS certificate is 14 days from expiry, and again at 3 days if it is still the same certificate. A message has waited in the queue for more than three days, with one more message when none is left. A global user is told all of it; a domain administrator is told about the DNS records and limits of their own domains.

Each user turns notifications on or off under Account and needs an e-mail there; Server › Settings turns them off for everyone. They are the panel's own mail: not rows of the Outbound log, and not counted against any limit.

For that mail to arrive, the server's own name needs two DNS records of its own, as each of your domains does: a DKIM key, which the panel generates and signs notifications with, and an SPF record, v=spf1 a -all. Server › Settings gives both with the values to publish and whether they are in place, and its Re-check DNS checks them again once they are published; Server › Health shows them too. Without them notifications are still sent, and a receiver may file them as spam. Mail of your domains does not depend on either.

diff --git a/docs/assets/panel-redesign/panel/src/settings.html b/docs/assets/panel-redesign/panel/src/settings.html index 5ba9185..92a35b6 100644 --- a/docs/assets/panel-redesign/panel/src/settings.html +++ b/docs/assets/panel-redesign/panel/src/settings.html @@ -80,7 +80,7 @@
Zone
Europe/Moscow
UTC+03:00. Set in .env (TZ); restart to change.
-

Every time the panel shows, and every day it counts - today on Health, the days of the statistics - is this zone's, and so are the stamps of mail.log.

+

Every time the panel shows, and every day it counts - today on Health, the days of the statistics - is this zone's, and so are the stamps of mail.log. One exception: the day a DMARC report covers is the reporter's, in UTC.