Skip to content
Back to top
View this page

# The SMTP Client Class

Use the `SMTP` class as a client directly when you want more control over the email sending process than the `send()` async function provides.

## Connecting to an SMTP Server

Initialize a new `SMTP` instance, then await its `SMTP.connect()` coroutine. Initializing an instance does not automatically connect to the server, as that is a blocking operation.

    import asyncio

    from aiosmtplib import SMTP

    client = SMTP()
    asyncio.run(client.connect(hostname="127.0.0.1", port=1025))

### Connecting over TLS/SSL

See also

For details on different connection types, see TLS, SSL & STARTTLS.

If an SMTP server supports direct connection via TLS/SSL, pass `use_tls=True` when initializing the SMTP instance (or when calling `SMTP.connect()`).

    smtp_client = aiosmtplib.SMTP(hostname="smtp.gmail.com", port=465, use_tls=True)
    await smtp_client.connect()

### STARTTLS connections

See also

For details on different connection types, see TLS, SSL & STARTTLS.

By default, if the server advertises STARTTLS support, aiosmtplib will upgrade the connection automatically. Setting `use_tls=True` for STARTTLS servers will typically result in a connection error.

To opt out of STARTTLS on connect, pass `start_tls=False`. You may then manually call `SMTP.starttls()` if needed.

    smtp_client = aiosmtplib.SMTP(
        hostname="smtp.gmail.com",
        port=587,
        start_tls=False,
        use_tls=False,
    )
    await smtp_client.connect()
    await smtp_client.starttls()

### Connecting via Async Context Manager

Instances of the `SMTP` class can also be used as an async context manager, which will automatically connect/disconnect on entry/exit.

    import asyncio
    from email.message import EmailMessage

    from aiosmtplib import SMTP

    async def say_hello():
        message = EmailMessage()
        message["From"] = "root@localhost"
        message["To"] = "somebody@example.com"
        message["Subject"] = "Hello World!"
        message.set_content("Sent via aiosmtplib")

        smtp_client = SMTP(hostname="127.0.0.1", port=1025)
        async with smtp_client:
            await smtp_client.send_message(message)

    asyncio.run(say_hello())

## Sending Messages

### `SMTP.send_message()`

Use this method to send `email.message.EmailMessage` objects, including `email.mime` subclasses such as `email.mime.text.MIMEText`.

For details on creating `email.message.EmailMessage` objects, see the stdlib documentation examples.

    import asyncio
    from email.mime.text import MIMEText

    from aiosmtplib import SMTP

    mime_message = MIMEText("Sent via aiosmtplib")
    mime_message["From"] = "root@localhost"
    mime_message["To"] = "somebody@example.com"
    mime_message["Subject"] = "Hello World!"

    async def send_with_send_message(message):
        smtp_client = SMTP(hostname="127.0.0.1", port=1025)
        await smtp_client.connect()
        await smtp_client.send_message(message)
        await smtp_client.quit()

    asyncio.run(send_with_send_message(mime_message))

Pass `email.mime.multipart.MIMEMultipart` objects to `SMTP.send_message()` to send messages with both HTML text and plain text alternatives.

    from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText

    message = MIMEMultipart("alternative")
    message["From"] = "root@localhost"
    message["To"] = "somebody@example.com"
    message["Subject"] = "Hello World!"

    message.attach(MIMEText("hello", "plain", "utf-8"))
    message.attach(MIMEText("<html><body><h1>Hello</h1></body></html>", "html", "utf-8"))

    async def send_multipart_message(message):
        smtp_client = SMTP(hostname="127.0.0.1", port=1025)
        await smtp_client.connect()
        await smtp_client.send_message(message)
        await smtp_client.quit()

    asyncio.run(send_multipart_message(message))

### `SMTP.sendmail()`

Use `SMTP.sendmail()` to send raw messages. Note that when using this method, you must format the message headers yourself.

    import asyncio

    from aiosmtplib import SMTP

    sender = "root@localhost"
    recipients = ["somebody@example.com"]
    message = """To: somebody@example.com
    From: root@localhost
    Subject: Hello World!

    Sent via aiosmtplib
    """

    async def send_with_sendmail():
        smtp_client = SMTP(hostname="127.0.0.1", port=1025)
        await smtp_client.connect()
        await smtp_client.sendmail(sender, recipients, message)
        await smtp_client.quit()

    asyncio.run(send_with_sendmail())

## Parallel Execution

SMTP is a sequential protocol. Multiple commands must be sent to send an email, and they must be sent in the correct sequence. As a consequence of this, executing multiple `SMTP.send_message()` tasks in parallel (i.e. with `asyncio.gather()`) is not any more efficient than executing in sequence, as the client must wait until one mail is sent before beginning the next.

If you have a lot of emails to send, consider creating multiple connections (`SMTP` instances) and splitting the work between them.