Commit e57a4f9
authored
fix(smtp): prevent double STARTTLS by passing start_tls=False to aiosmtplib (#20)
## Summary
Fix SMTP STARTTLS double execution that causes `EmailConnectionError: SMTP connection error: Connection already using TLS` when using `SMTPConfig(use_tls=True, use_ssl=False)` with any STARTTLS-capable server (port 587).
Closes #19
## Problem
When connecting to an SMTP server that supports STARTTLS (e.g., `smtp.office365.com:587`), the TLS upgrade is executed **twice**:
| Step | Actor | What happens |
|------|-------|-------------|
| 1 | litestar-email | Creates `aiosmtplib.SMTP` **without passing `start_tls`** (defaults to `None`) |
| 2 | aiosmtplib | `start_tls=None` → auto-detect → server supports STARTTLS → **auto-upgrades** ✅ |
| 3 | litestar-email | `use_tls=True` → **manually calls `starttls()` again** → 💥 `Connection already using TLS` |
This affects **all SMTP servers requiring STARTTLS** (Office 365, Gmail, AWS SES, etc.), making the documented `use_tls=True` + `use_ssl=False` configuration completely broken.
## Solution
Explicitly pass `start_tls=False` to `aiosmtplib.SMTP()` to disable its auto-STARTTLS negotiation, letting litestar-email manage the STARTTLS upgrade manually as intended:
```python
self._connection = aiosmtplib.SMTP(
hostname=self._config.host,
port=self._config.port,
timeout=self._config.timeout,
use_tls=self._config.use_ssl,
start_tls=False, # Disable auto-STARTTLS; we manage it manually below
)
```
This is the minimal, non-breaking fix (Option A from the issue). The existing manual `starttls()` call remains the single point of TLS upgrade.
## Changes
- **`src/litestar_email/backends/smtp.py`** — Add `start_tls=False` parameter to `aiosmtplib.SMTP()` constructor
- **`src/tests/test_smtp_backend.py`** — Add 3 regression tests:
- `test_smtp_backend_starttls_no_double_call` — Verifies `start_tls=False` is passed and manual `starttls()` is called exactly once
- `test_smtp_backend_ssl_does_not_call_starttls` — Verifies implicit SSL (`use_ssl=True`) does not trigger manual STARTTLS
- `test_smtp_backend_no_tls_no_ssl` — Verifies plain connection does not call STARTTLS1 parent 7e5bbee commit e57a4f9
2 files changed
Lines changed: 103 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
116 | 116 | | |
117 | 117 | | |
118 | 118 | | |
| 119 | + | |
119 | 120 | | |
120 | 121 | | |
121 | 122 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
336 | 336 | | |
337 | 337 | | |
338 | 338 | | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
0 commit comments