Add deploy preflight checks for email configuration - #102
Draft
davegaeddert wants to merge 2 commits into
Draft
Conversation
Email misconfiguration is a silent failure: the console, preview, and locmem backends all report every send as a success, so nothing raises and no exception tracker sees the loss. Anything depending on email (password resets, login links) just stops working. Add two `deploy=True` preflight checks in plain.email: - `email.backend` (error) flags a non-delivering backend. - `email.smtp_host` (warning) flags the SMTP backend still pointed at the default "localhost". Only a warning — a local mail relay is a legitimate setup — but it closes the gap where a correct-looking SMTP config fails at send time. Backend import paths move to plain/email/backends/__init__.py so the toolbar, the mailoutbox fixture, and the checks share one definition. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015tkqCu7EDmedbxieWcHSLk
- email.smtp_host now flags an empty EMAIL_HOST as an error. smtplib skips connecting when the host is falsy, so starttls() raises SMTPServerDisconnected on the first send — exactly the failure the check exists to catch, previously passing because it only matched "localhost". - Document both silenceable result ids in the README. The local-relay setup the docs call legitimate had no id to copy, and a guess would trip preflight.unused_silence. - Correct the module docstring: deploy checks also run from the admin preflight view and toolbar badge whenever DEBUG is False, not only under `plain preflight --deploy`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015tkqCu7EDmedbxieWcHSLk
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Email misconfiguration is a silent failure. The console, preview, and locmem backends all return a success count from
send_messages()— nothing raises, so no exception tracker sees the loss. Anything that depends on email (password resets viaplain.passwords, login links viaplain.loginlink) just stops working with no signal.Adds two
deploy=Truepreflight checks inplain.email, following thesecurity.debugpattern for "dev convenience left on in production."Checks
email.backendemail.backend_does_not_deliverEMAIL_BACKENDset to the console, preview, or in-memory backendemail.smtp_hostemail.smtp_host_emptyEMAIL_HOSTemail.smtp_hostemail.smtp_host_is_defaultEMAIL_HOSTstill at its default"localhost"email.smtp_hostexists soemail.backenddoesn't hand out false confidence: the more common production failure isn't the console backend left on, it's a correct-looking SMTP config that was never pointed at a mail server. An empty host is an error becausesmtplibskips connecting when the host is falsy, sostarttls()raisesSMTPServerDisconnectedon the first send. The default"localhost"is only a warning — a mail relay on the same host is a legitimate setup.Deployments that intentionally send no email silence by result id; the README documents both ids.
Notes
plain.emailis inINSTALLED_PACKAGES.plain/email/backends/__init__.py, so the toolbar, themailoutboxfixture, and the checks share one definition instead of three copies of the same string.example/app/settings.pyuses the preview backend, soplain preflight --deploythere now errors. That's the check working as intended; no CI job passes--deploy.Testing
plain-email/tests/public/test_preflight.py(22 pass in the package).plain preflight --deployin the test app reportsemail.backend_does_not_deliveragainst its console backend, and a run without--deployskips both checks.ruff check/ruff format --check/./scripts/type-check plain-emailall clean.The full
./scripts/testand./scripts/fixruns could not complete in this environment — no Postgres available, and the oxlint/oxfmt download is blocked by the sandbox proxy. Python linting, formatting, type checks, and theplain-emailsuite were all run directly instead.Generated by Claude Code