Legacy sign-in is refused while the switch is off (LP-6) #3

Merged
jcoffey-dev merged 1 commits from feat/legacy-signin-refusal into main 2026-09-21 17:05:14 +00:00
Owner

The second lock. While legacy mail protocols are off, a sign-in over IMAP,
POP3, ManageSieve or SMTP AUTH is refused for every account, so a listener
that exists by mistake -- or submission, which the SMTP lock keeps open --
still lets nobody in.

The check sits at the top of each protocol's sign-in, before the
credentials are looked at. So the answer is the same for a right password,
a wrong one and an account that doesn't exist; it isn't auth.failed, so it
counts nothing against the account and never feeds the auto-ban; and the
session stays open, since the mail app is being told, not thrown off.

Mail apps read the spec's words (LP-12, at server scope):

IMAP NO [ALERT] This server allows only INBUXA webmail and JMAP
apps. This mail app can't sign in.
POP3 -ERR [AUTH] ...the same...
ManageSieve NO "This server allows only INBUXA webmail and JMAP apps."
SMTP 535 5.7.0 This server allows only INBUXA webmail and JMAP
apps. This mail app can't send.

SMTP AUTH is refused on every SMTP listener, port 25 included: only mail
apps authenticate, so inbound delivery is untouched. LMTP is left alone.

The policy is read from the store on each sign-in rather than cached, so
every node of a cluster answers the same the moment the switch turns.

Each refusal raises a new event, auth.legacy-protocol-refused (id 642, info
level, also in the packaged schema), with the protocol as source, the
policy's scope and the domain -- never the account. The session adds the
listener and remote IP.

tests/e2e/legacy_protocols.py now also proves, on a running server: a
normal IMAP and submission sign-in works with the switch on, before and
after; while off, submission refuses the right password and six wrong ones
with the same words and without hanging up; and an IMAP listener created by
mistake while off refuses the right password, a wrong one and an account
that doesn't exist. All 33 checks pass. SMTP sign-ins in the script wait
out a second first: every connection arrives from Docker's gateway, and the
stock inbound throttle takes five a second from one IP.

The second lock. While legacy mail protocols are off, a sign-in over IMAP, POP3, ManageSieve or SMTP AUTH is refused for every account, so a listener that exists by mistake -- or submission, which the SMTP lock keeps open -- still lets nobody in. The check sits at the top of each protocol's sign-in, before the credentials are looked at. So the answer is the same for a right password, a wrong one and an account that doesn't exist; it isn't auth.failed, so it counts nothing against the account and never feeds the auto-ban; and the session stays open, since the mail app is being told, not thrown off. Mail apps read the spec's words (LP-12, at server scope): IMAP NO [ALERT] This server allows only INBUXA webmail and JMAP apps. This mail app can't sign in. POP3 -ERR [AUTH] ...the same... ManageSieve NO "This server allows only INBUXA webmail and JMAP apps." SMTP 535 5.7.0 This server allows only INBUXA webmail and JMAP apps. This mail app can't send. SMTP AUTH is refused on every SMTP listener, port 25 included: only mail apps authenticate, so inbound delivery is untouched. LMTP is left alone. The policy is read from the store on each sign-in rather than cached, so every node of a cluster answers the same the moment the switch turns. Each refusal raises a new event, auth.legacy-protocol-refused (id 642, info level, also in the packaged schema), with the protocol as source, the policy's scope and the domain -- never the account. The session adds the listener and remote IP. tests/e2e/legacy_protocols.py now also proves, on a running server: a normal IMAP and submission sign-in works with the switch on, before and after; while off, submission refuses the right password and six wrong ones with the same words and without hanging up; and an IMAP listener created by mistake while off refuses the right password, a wrong one and an account that doesn't exist. All 33 checks pass. SMTP sign-ins in the script wait out a second first: every connection arrives from Docker's gateway, and the stock inbound throttle takes five a second from one IP.
Author
Owner

assigned to @jcoffey-dev

assigned to @jcoffey-dev
Author
Owner

approved this merge request

approved this merge request
jcoffey-dev scheduled this pull request to auto merge when all checks succeed 2026-09-21 16:52:17 +00:00
Author
Owner

mentioned in commit 6b1e5c67e3

mentioned in commit 6b1e5c67e38527c030d0d4c62410762289906dda
jcoffey-dev merged commit 6b1e5c67e3 into main 2026-09-21 17:05:14 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: inbuxa/inbuxa-server#3