shivaam opened a new pull request, #75529:
URL: https://github.com/apache/airflow/pull/75529

   `SmtpHook.aget_conn()` fails with `SMTPException: Connection already using 
TLS` for every async connection that uses STARTTLS (`disable_ssl: true` with 
TLS left enabled, the documented port 587 setup), even when the server 
certificate is valid. This breaks `SmtpNotifier.async_notify()`; the sync path 
is not affected.
   
   `_build_client_kwargs(is_async=True)` creates the `aiosmtplib.SMTP` client 
with `start_tls=True` and the hook's `tls_context`, so aiosmtplib's `connect()` 
already performs the STARTTLS upgrade and validates the certificate. 
`aget_conn()` then called `starttls()` a second time, which aiosmtplib rejects. 
This removes that second call. The `ehlo()` in `_abuild_client()` still runs on 
the upgraded connection before login.
   
   The provider declared `aiosmtplib>=0.1.6`, which cannot work with the hook: 
0.1.6 rejects the `start_tls` argument, and the async OAuth2 path calls 
`SMTP.auth_xoauth2()`, which first shipped in aiosmtplib 5.1.0. The minimum is 
raised to 5.1.0. That is the version in the 2.11.2, 3.1.8 and 3.2.2 constraints 
(main has 5.1.3), so the lowest-dependency CI run now tests a version the hook 
supports.
   
   One side effect: when SSL and STARTTLS are both left enabled (the defaults 
of the connection extras), the async path no longer sends STARTTLS over the 
implicit-TLS connection, so it connects instead of failing. The sync path is 
unchanged.
   
   Checked against real Mailpit servers with a self-signed certificate, on 
aiosmtplib 5.1.0 and 5.1.3:
   
   - trusted certificate: async STARTTLS and send work with exactly one 
STARTTLS command, over TLSv1.3, and the message is delivered. On main the same 
setup fails with `Connection already using TLS` after two STARTTLS commands.
   - untrusted certificate: fails with `SSLCertVerificationError` before AUTH, 
no client is cached, the socket is closed and nothing is delivered (unchanged 
from main).
   
   related: #74185 (touches the same `aget_conn()` block; whichever lands 
second needs a small rebase, including dropping the async `starttls`/`ehlo` 
failure cases from its `test_discards_failed_setup`, since `aget_conn()` no 
longer makes those calls)
   
   ---
   
   ##### Was generative AI tooling used to co-author this PR?
   
   - [X] Yes — Claude Code (Opus 5.5)
   
   Generated-by: Claude Code (Opus 5.5) following [the 
guidelines](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to