Repository navigation
Conversation
imaplib.IMAP4_SSL() without an ssl_context falls back to an unverified context, so any certificate is accepted and a man-in-the-middle can read the IMAP credentials. All IMAP connections (connection test, folder list, email processing) now go through connect_imap(), which uses ssl.create_default_context() and therefore verifies the certificate chain and the hostname. A certificate error is reported with a readable message. Servers with a self-signed certificate can opt out explicitly with LETTERFEED_IMAP_TLS_INSECURE=true.
Connection, login and mailbox selection errors were only logged, and POST /imap/process always answered with success, so "Process Now" in the UI reported success even when nothing could be fetched. process_emails() still processes all folders, but now raises EmailProcessingError with the collected error messages afterwards. The endpoint returns it as a 400 response with the message in "detail", the same way the connection test does, and the frontend shows it as an error toast. The scheduled job logs the error as a warning.
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.
Problem
LetterFeed connects to the IMAP server with
imaplib.IMAP4_SSL(server)without anssl_context. In that case Python usesssl._create_unverified_context(), so neither the certificate chain nor the hostname is checked. Anyone who can intercept the connection between LetterFeed and the mail server (e.g. on the network path or via DNS) can present any certificate and read the IMAP username and password.Related: when fetching fails ("Process Now"), the UI still reports success. Connection, TLS and login errors only show up in the backend log.
Changes
connect_imap()inapp/core/imap.py, used by the connection test, the folder list and email processing. It passesssl.create_default_context(), which verifies the certificate against the system CA store and checks the hostname.TLS certificate verification failed for imap.example.com: self-signed certificate. If the server uses a self-signed certificate, set LETTERFEED_IMAP_TLS_INSECURE=true.LETTERFEED_IMAP_TLS_INSECURE=true(defaultfalse, logs a warning when enabled). Documented in.env.exampleand the README.process_emails()still processes all folders, but afterwards raisesEmailProcessingErrorwith the collected errors (connection/TLS/login failure, folder that cannot be selected, errors while processing a folder). Repeated identical errors are reported once.POST /imap/processreturns these as400with the message indetail, the same wayPOST /imap/testreports a failed connection test. The existing frontend error handling already showsdetailas an error toast, so no frontend change is needed.Behavior change
Users whose IMAP server has a self-signed certificate, an expired certificate, or a certificate for a different hostname (e.g. configured by IP address) will see the connection fail after upgrading. They should configure the hostname the certificate was issued for, or set
LETTERFEED_IMAP_TLS_INSECURE=trueon the backend.Testing
ruff check app,ruff format --check appandpytestpass (79 tests, 8 new: verifying context, opt-out, certificate error message, connection/login/folder errors inprocess_emails, 400 from/imap/process, scheduler warning).LETTERFEED_IMAP_TLS_INSECURE=truethe TLS handshake succeeds again;Could not connect to IMAP server: ...as an error toast instead of the success message; switching back to the valid server fetches emails again.