Verify every email address by a message with a unique link or code; keep one primary among several #3

Closed
opened 2026-09-05 11:47:57 +00:00 by tiagoagueda · 0 comments
Owner

Observation

additionally email can be added but only one can be defined as primary
all address must be validated using a SMTP message with a unique link / code

What happens today

Several addresses, one primary — already exists. django-allauth's EmailAddress model holds any number of addresses per account with exactly one flagged primary, and the management page is at /accounts/email/, linked from Your details as "Email addresses". It renders inside Postulo's own shell (templates/account/base_manage_email.html). Worth confirming the flow — add, verify, make primary, remove — against the observation rather than assuming, but the mechanism is there.

Verification is not required. src/postulo/config/settings/base.py sets ACCOUNT_EMAIL_VERIFICATION = "optional": a verification message is sent when an address is added, but nothing is refused if it is never acted on. An unverified address signs in, becomes primary, and receives password resets. That is the gap.

Verification is by link. allauth 65.19.2 (the installed version) also supports a code typed into a form: ACCOUNT_EMAIL_VERIFICATION_BY_CODE_ENABLED = True, with ACCOUNT_EMAIL_VERIFICATION_BY_CODE_MAX_ATTEMPTS. It is one or the other, not both.

What changes

  • ACCOUNT_EMAIL_VERIFICATION = "mandatory": an address must be verified before it can be used to sign in or made primary.
  • Choose link or code (see questions) and set ACCOUNT_EMAIL_VERIFICATION_BY_CODE_ENABLED accordingly; consider ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION for the signup path.
  • Consider ACCOUNT_MAX_EMAIL_ADDRESSES so an account cannot accumulate addresses without bound.
  • Accounts created from the command line: createsuperuser creates no EmailAddress row at all, so under mandatory the first administrator could be locked out until they verify — and on an instance whose SMTP is not yet configured, could never verify. Needs either a verified EmailAddress created alongside the superuser, or a management command to mark an address verified by hand.
  • Existing accounts: a data migration that marks each account's current email as a verified primary EmailAddress, so upgrading does not lock anybody out.
  • Documentation: the wiki's Configuration page currently says email is used only for password resets and that "an instance with a single user who never forgets their password can ignore this section entirely". That becomes false — SMTP becomes a requirement for onboarding anyone — and Installing Postulo, Accounts and invitations and Troubleshooting need the same correction.

Why this is a breaking change

It is a change in what an operator must provide. Today an instance runs with no email at all; afterwards, without working SMTP, nobody new can complete signup and an unverified existing account cannot sign in. The upgrade needs the grandfathering migration above and a clear note in the changelog.

Under today's optional setting a verification message is still sent at signup. The production settings default SMTP to localhost:25. Whether a failed send aborts an invited signup with an error, or is swallowed, has not been checked — the test instance on ragnar has no SMTP configured, so it is the place to find out.

Open questions

  1. Link or code? A link is one click; a code survives an email client that rewrites or pre-fetches links, and reads more naturally on a phone. allauth makes it one or the other.
  2. Should adding a second address require re-entering the password, as a guard against a hijacked session quietly adding a recovery address?
  3. What the CLI story is for an operator setting up their first account before SMTP works.

Related: #1 (username as identifier, email as alternative sign-in) and #2 (obligatory full name).

## Observation > additionally email can be added but only one can be defined as primary > all address must be validated using a SMTP message with a unique link / code ## What happens today **Several addresses, one primary — already exists.** django-allauth's `EmailAddress` model holds any number of addresses per account with exactly one flagged `primary`, and the management page is at `/accounts/email/`, linked from *Your details* as "Email addresses". It renders inside Postulo's own shell (`templates/account/base_manage_email.html`). Worth confirming the flow — add, verify, make primary, remove — against the observation rather than assuming, but the mechanism is there. **Verification is not required.** `src/postulo/config/settings/base.py` sets `ACCOUNT_EMAIL_VERIFICATION = "optional"`: a verification message is sent when an address is added, but nothing is refused if it is never acted on. An unverified address signs in, becomes primary, and receives password resets. That is the gap. **Verification is by link.** allauth 65.19.2 (the installed version) also supports a code typed into a form: `ACCOUNT_EMAIL_VERIFICATION_BY_CODE_ENABLED = True`, with `ACCOUNT_EMAIL_VERIFICATION_BY_CODE_MAX_ATTEMPTS`. It is one or the other, not both. ## What changes - `ACCOUNT_EMAIL_VERIFICATION = "mandatory"`: an address must be verified before it can be used to sign in or made primary. - Choose link or code (see questions) and set `ACCOUNT_EMAIL_VERIFICATION_BY_CODE_ENABLED` accordingly; consider `ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION` for the signup path. - Consider `ACCOUNT_MAX_EMAIL_ADDRESSES` so an account cannot accumulate addresses without bound. - Accounts created from the command line: `createsuperuser` creates no `EmailAddress` row at all, so under *mandatory* the first administrator could be locked out until they verify — and on an instance whose SMTP is not yet configured, could never verify. Needs either a verified `EmailAddress` created alongside the superuser, or a management command to mark an address verified by hand. - Existing accounts: a data migration that marks each account's current `email` as a verified primary `EmailAddress`, so upgrading does not lock anybody out. - Documentation: the wiki's *Configuration* page currently says email is used only for password resets and that "an instance with a single user who never forgets their password can ignore this section entirely". That becomes false — SMTP becomes a requirement for onboarding anyone — and *Installing Postulo*, *Accounts and invitations* and *Troubleshooting* need the same correction. ## Why this is a breaking change It is a change in what an operator must provide. Today an instance runs with no email at all; afterwards, without working SMTP, nobody new can complete signup and an unverified existing account cannot sign in. The upgrade needs the grandfathering migration above and a clear note in the changelog. ## A related thing to verify while here Under today's *optional* setting a verification message is still sent at signup. The production settings default SMTP to `localhost:25`. Whether a failed send aborts an invited signup with an error, or is swallowed, has not been checked — the test instance on ragnar has no SMTP configured, so it is the place to find out. ## Open questions 1. Link or code? A link is one click; a code survives an email client that rewrites or pre-fetches links, and reads more naturally on a phone. allauth makes it one or the other. 2. Should adding a second address require re-entering the password, as a guard against a hijacked session quietly adding a recovery address? 3. What the CLI story is for an operator setting up their first account before SMTP works. Related: #1 (username as identifier, email as alternative sign-in) and #2 (obligatory full name).
tiagoagueda added this to the 0.2.0 milestone 2026-09-05 11:47:57 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Postulo/postulo#3
No description provided.