fix: IPv4 preference + DNS cache fallback for stable POP3/IMAP connections
- Add DNS_CACHE_FALLBACK_ENABLED setting (default: true) - Add in-process DNS cache (_dns_cache, _dns_cache_lock, _get/_set_cached_ipv4) - Add _resolve_ipv4 (async) and _resolve_ipv4_sync: AF_INET lookup, cache on success, return cached IP on EAI_AGAIN when fallback enabled - Add _IMAP4SSLwithSNI: connects to pre-resolved IPv4 but uses original hostname for TLS SNI/cert verification - Add _POP3SSLWithIPv4Pref / _POP3WithIPv4Pref: override _create_socket to use pre-resolved IPv4 while keeping original host for POP3_SSL SNI - Add _make_pop3_conn factory and _make_imap_client async factory - Wire IPv4/cache helpers into all 6 connection call-sites (IMAP x3, POP3 x3) - Distinguish transient DNS (EAI_AGAIN) from permanent in _format_connection_error - Replace asyncio.get_event_loop() with get_running_loop() in 4 async sites - All 75 existing unit tests pass unchanged Agent-Logs-Url: https://github.com/christianlouis/InboxConverge/sessions/be0a3bbd-1af1-408e-b918-84753723154b Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
89ebdd2b79
commit
45a2dd8be2
@@ -30,6 +30,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Added
|
||||
|
||||
- **IPv4 preference for all POP3 and IMAP connections**: The app now resolves
|
||||
every mail-server hostname to an IPv4 address before connecting. This
|
||||
prevents `ENETUNREACH` / `Network is unreachable` errors and IMAP/POP3
|
||||
connection timeouts that occur on Docker hosts where IPv6 traffic is not
|
||||
routed to the internet but dual-stack DNS returns AAAA records first.
|
||||
|
||||
- **In-process DNS cache with automatic fallback** (`DNS_CACHE_FALLBACK_ENABLED`,
|
||||
enabled by default): The last successfully resolved IPv4 address for each
|
||||
mail-server hostname is stored in memory. When a subsequent DNS lookup fails
|
||||
with `EAI_AGAIN` (Temporary failure in name resolution) the cached address is
|
||||
used instead, keeping mail delivery alive through transient resolver outages.
|
||||
Set `DNS_CACHE_FALLBACK_ENABLED=false` in the environment to disable.
|
||||
|
||||
- **Friendly error messages**: Introduced `_format_connection_error()` helper in
|
||||
`mail_processor.py` that translates raw OS/socket/SSL/POP3/IMAP exceptions into
|
||||
human-readable sentences including the host:port and actionable guidance (DNS
|
||||
@@ -58,6 +71,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Transient DNS errors now produce a clear, accurate message**: `EAI_AGAIN`
|
||||
errors (errno -3 – resolver temporarily unavailable) are now reported as
|
||||
"Temporary DNS failure while resolving '…'" instead of the misleading "check
|
||||
that the server address is correct" message that was shown for all DNS errors.
|
||||
|
||||
- **`asyncio.get_event_loop()` replaced with `asyncio.get_running_loop()`** in
|
||||
`_test_pop3_connection`, `_fetch_pop3_emails`, `post_process_pop3`, and
|
||||
`forward_email`, silencing deprecation warnings in Python ≥ 3.10 and avoiding
|
||||
potential `DeprecationWarning → RuntimeError` in a future Python release.
|
||||
|
||||
- **Empty IMAP error messages** — `IMAP fetch error:` with a blank suffix was
|
||||
caused by `asyncio.TimeoutError` and `aioimaplib.Abort` having an empty
|
||||
`str()`. The new `_format_connection_error()` helper always produces a
|
||||
|
||||
Reference in New Issue
Block a user