File: client.rst

package info (click to toggle)
aiosmtplib 4.0.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 572 kB
  • sloc: python: 5,516; makefile: 20; sh: 6
file content (198 lines) | stat: -rw-r--r-- 5,646 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
 .. py:currentmodule:: aiosmtplib

The SMTP Client Class
=====================

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


Connecting to an SMTP Server
----------------------------

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

.. testcode::

    import asyncio

    from aiosmtplib import SMTP


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


Connecting over TLS/SSL
~~~~~~~~~~~~~~~~~~~~~~~

.. seealso:: For details on different connection types, see :ref:`connection-types`.

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

.. code-block:: python

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


STARTTLS connections
~~~~~~~~~~~~~~~~~~~~

.. seealso:: For details on different connection types, see :ref:`connection-types`.

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 :meth:`SMTP.starttls` if needed.

.. code-block:: python

    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 :class:`SMTP` class can also be used as an async context
manager, which will automatically connect/disconnect on entry/exit.

.. testcode::

    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
----------------

:meth:`SMTP.send_message`
~~~~~~~~~~~~~~~~~~~~~~~~~

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

For details on creating :py:class:`email.message.EmailMessage` objects, see `the
stdlib documentation examples
<https://docs.python.org/3.11/library/email.examples.html>`_.

.. testcode::

    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 :py:class:`email.mime.multipart.MIMEMultipart` objects to
:meth:`SMTP.send_message` to send messages with both HTML text and plain text
alternatives.

.. testcode::

    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))


:meth:`SMTP.sendmail`
~~~~~~~~~~~~~~~~~~~~~

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

.. testcode::

    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 :meth:`SMTP.send_message` tasks in parallel (i.e. with
:py:func:`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
(:class:`SMTP` instances) and splitting the work between them.