NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #1065 most downloaded on PyPI
asyncio SMTP client
Last release 28 days ago
08 Sep 2026
Ships fairly regularly
a new release about every 3 months
Most releases are documented
notes for 29 of 35 stable releases
Nothing withdrawn
no release was ever pulled
10 years old
39 releases · first in 2016
This is a follow up to the fix in 5.1.1 for CVE-2026-53533 ( GHSA-v3q9-hj7j-63hq ), which only rejected control characters. sendmail now validates all…
mail, rcpt, vrfy, expn and sendmail.user@example.com> AUTH=<attacker@example.com could smuggle additional ESMTPsendmail now validates all addresses before sending any commands.local_hostname values (and the hostname argument tohelo/ehlo) containing whitespace or control characters, so a hostnameme.example.com XCLIENT ADDR=1.2.3.4 can no longer smuggle extraSMTPAuthenticationError instead of binascii.Error when thelogin can fallconnect() so changinguse_tls/start_tls between connects no longer reuses a stale default.port/hostname are now resolved per-connect rather thanNone when unsetFuture exception was never retrieved is no longer logged on free-threaded__del__ based cleanup ran too lateSIZE parameter sent with MAIL FROM now reports the numberRuntimeError from the protocol callbackSMTPProtocol now records that it is using TLS after a successfulstart_tls, so a second upgrade attempt on the protocol is rejectedstarttls now validates its TLS options before sending EHLO, soValueError without touching the connectionhelo no longer records a failed response as last_helo_response,bytearray and memoryview values are no longer silently passedstr and bytes are accepted, asFull Changelog: v5.1.2...v5.1.3
One column per quarter.
Security: Discard any buffered server data before the STARTTLS handshake, preventing a response-injection attack where a man-in-the-middle pre-stages
__repr__ resultconnect() on an already-connected client now raises SMTPException instead of deadlocking on the connection lockAUTH= extension advertisements; all advertised methods are now kept (e.g. both PLAIN and LOGIN from AUTH=PLAIN LOGIN)Full Changelog: v5.1.1...v5.1.2
Security: Reject control characters (the C0 range 0x00-0x1F and DEL 0x7F, including CR, LF, and NUL) in SMTP command arguments, preventing command inj
Full Changelog: v5.1.0...v5.1.1
Feature: Add XOAUTH2 authentication support
BREAKING : Drop Python 3.9 support
Full Changelog: v4.0.2...v5.0.0
Bugfix: correct aexit signature to comply with async context manager protocol by @oliverlambson in #323
Full Changelog: v4.0.1...v4.0.2
Bugfix: disconnect outside of command context by @cole in #313
Full Changelog: v4.0.0...v4.0.1
Bugfix: Always clear the connect lock on connection lost, allowing client reconnect
BREAKING : Drop Python 3.8 support
Full Changelog: v3.0.2...v4.0.0
Bugfix: Type of "send" is partially unknown with pyright
Full Changelog: v3.0.1...v3.0.2
Bugfix: 'Future exception was never retrieved' warning in SMTPProtocol after successful connection close and garbage collection.
Full Changelog: v3.0.0...v3.0.1
BREAKING : Passing source_address as a string argument (deprecated in 2.0) is now an error. source_address takes a (addr, port) tuple that is used as…
source_address as a string argument (deprecated in 2.0) is now an error. source_address takes a (addr, port) tuple that is used as the local_addr param of asyncio.create_connection, allowing for binding to a specific IP. The local_hostname argument takes the value to be sent to the server with the EHLO/HELO message (which is what source_address was used for prior to 2.0).connect everywhere, only for the initial connection (credit @wombatonfire)Bugfix: don't send extra EHLO/HELO before QUIT (credit @ikrivosheev)
Bugfix: "tests" and "docs" in the sdist should be includes, not packages, so that they do not get put in site-packages.
site-packages.BREAKING: Remove deprecated loop keyword argument for the SMTP class.
BREAKING: Drop Python 3.5 and 3.6 support.
BREAKING: On connect, if the server supports STARTTLS, automatically try
to upgrade the connection. STARTTLS after connect can be turned on or off
explicitly by passing start_tls=True or start_tls=False respectively.
BREAKING: Remove deprecated loop keyword argument for the SMTP class.
Change: The source_address argument now takes a (addr, port) tuple that is
passed as the local_addr param to asyncio.create_connection, allowing
for binding to a specific IP. The new local_hostname argument that takes
the value to be sent to the server with the EHLO/HELO message. This behaviour
more closely matches smtplib.
In order to not break existing usage, passing a string instead of a tuple to
source_address will give a DeprecationWarning, and use the value as it if
had been passed for local_hostname.
Thanks @rafaelrds and @davidmcnabnz for raising and contributing work on this issue.
Bugfix: the mail_options and rcpt_options arguments to the send
coroutine no longer cause errors
Cleanup: Refactored SMTP parent classes to remove complex inheritance
structure.
Cleanup: Switched to asyncio.run for sync client methods.
Cleanup: Don't use private email.message.Message policy attribute (instead, set an appropriate policy based on message class)
Nothing published for this version
Nothing published for this version
Security: Fix a possible injection vulnerability (a variant of https://consensys.net/diligence/vulnerabilities/python-smtplib-multiple-crlf-injection/…
Security: Fix a possible injection vulnerability (a variant of https://consensys.net/diligence/vulnerabilities/python-smtplib-multiple-crlf-injection/)
Note that in order to exploit this vulnerability in aiosmtplib, the attacker would need
control of the hostname or source_address parameters. Thanks Sam Sanoop @ Snyk
for bringing this to my attention.
Bugfix: include CHANGLOG in sdist release
Type hints: fix type hints for async context exit (credit @JelleZijlstra) Full Changelog: https://github.com/cole/aiosmtplib/compare/v1.1.6...v1.1.7
Bugfix: fix authenticated test failures (credit @P-EB)
Bugfix: avoid raising asyncio.CancelledError on connection lost
asyncio.CancelledError on connection lostBugfix: parsing comma separated addresses in to header (credit @gjcarneiro)
Feature: add pause and resume writing methods to SMTPProcotol, via asyncio.streams.FlowControlMixin (thanks @ikrivosheev).
Feature: add pause and resume writing methods to SMTPProcotol, via
asyncio.streams.FlowControlMixin (thanks @ikrivosheev).
Bugfix: allow an empty sender (credit @ikrivosheev)
Cleanup: more useful error message when login called without TLS
Bugfix: removed docs and tests from wheel, they should only be in the source distribution.
docs and tests from wheel, they should only be
in the source distribution.Bugfix: Fix handling of sending legacy email API (Message) objects.
Bugfix: Fix handling of sending legacy email API (Message) objects.
Bugfix: Fix SMTPNotSupported error with UTF8 sender/recipient names on servers that don't support SMTPUTF8.
Passing an explicit event loop via the loop keyword argument is deprecated and will be removed in version 2.0.
Feature: Added send coroutine api.
Feature: Added SMTPUTF8 support for UTF8 chars in addresses.
Feature: Added connected socket and Unix socket path connection options.
Feature: Wait until the connect coroutine is awaited to get the event loop. Passing an explicit event loop via the loop keyword argument is deprecated and will be removed in version 2.0.
Cleanup: Set context for timeout and connection exceptions properly.
Cleanup: Use built in start_tls method on Python 3.7+.
Cleanup: Timeout correctly if TLS handshake takes too long on Python 3.7+.
Cleanup: Updated SMTPProcotol class and removed StreamReader/StreamWriter usage to remove deprecation warnings in 3.8.
Bugfix: EHLO/HELO if required before any command, not just when using higher level commands.
Cleanup: Replaced asserts in functions with more useful errors (e.g. RuntimeError).
Cleanup: More useful error messages for timeouts (thanks ikrivosheev!),
including two new exception classes, SMTPConnectTimeoutError and
SMTPReadTimeoutError
Nothing published for this version
Bugfix: Set default timeout to 60 seconds as per documentation (previously it was unlimited).
Bugfix: Connection is now closed if an error response is received immediately after connecting.
Bugfix: Badly encoded server response messages are now decoded to utf-8, with error chars escaped.
Bugfix: Badly encoded server response messages are now decoded to utf-8, with error chars escaped.
Cleanup: Removed handling for exceptions not raised by asyncio (in SMTPProtocol._readline)
Bugfix: Removed buggy close connection on __del__
Bugfix: Removed buggy close connection on del
Bugfix: Fixed old style auth method parsing in ESMTP response.
Bugfix: Cleanup transport on exception in connect method.
Cleanup: Simplified SMTPProtocol.connection_made, main
Bugfix: Close connection lock on on SMTPServerDisconnected
Bugfix: Close connection lock on on SMTPServerDisconnected
Feature: Added cert_bundle argument to connection init, connect and starttls methods
Bugfix: Disconnected clients would raise SMTPResponseException: (-1 ...) instead of SMTPServerDisconnected
Commands were getting out of order when using the client as a context manager within a task
Bugfix: Commands were getting out of order when using the client as a context manager within a task
Bugfix: multiple tasks calling connect would get confused
Bugfix: EHLO/HELO responses were being saved even after disconnect
Bugfix: RuntimeError on client cleanup if event loop was closed
Bugfix: CRAM-MD5 auth was not working
Bugfix: AttributeError on STARTTLS under uvloop
Initial feature complete release with stable API.
Initial feature complete release with stable API.
Initial feature complete release with stable API; future changes will be documented here.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →