0
# High-Level Email Sending API
1
2
The `send()` function provides a simple, one-function interface for sending emails asynchronously. It handles connection management, authentication, and cleanup automatically, making it ideal for applications that need to send emails without managing persistent connections.
3
4
## Capabilities
5
6
### Basic Email Sending
7
8
Send emails using the high-level `send()` function with automatic connection management.
9
10
```python { .api }
11
async def send(
12
message: Union[EmailMessage, Message, str, bytes],
13
/,
14
*,
15
sender: Optional[str] = None,
16
recipients: Optional[Union[str, Sequence[str]]] = None,
17
mail_options: Optional[Sequence[str]] = None,
18
rcpt_options: Optional[Sequence[str]] = None,
19
hostname: Optional[str] = "localhost",
20
port: Optional[int] = None,
21
username: Optional[Union[str, bytes]] = None,
22
password: Optional[Union[str, bytes]] = None,
23
local_hostname: Optional[str] = None,
24
source_address: Optional[tuple[str, int]] = None,
25
timeout: Optional[float] = 60,
26
use_tls: bool = False,
27
start_tls: Optional[bool] = None,
28
validate_certs: bool = True,
29
client_cert: Optional[str] = None,
30
client_key: Optional[str] = None,
31
tls_context: Optional[ssl.SSLContext] = None,
32
cert_bundle: Optional[str] = None,
33
socket_path: Optional[SocketPathType] = None,
34
sock: Optional[socket.socket] = None,
35
) -> tuple[dict[str, SMTPResponse], str]:
36
"""
37
Send an email message with automatic connection management.
38
39
Parameters:
40
- message: Email content as EmailMessage, Message, str, or bytes
41
- sender: From email address (optional if message has From header)
42
- recipients: Recipient email addresses (optional if message has To/Cc/Bcc headers)
43
- mail_options: SMTP MAIL command options
44
- rcpt_options: SMTP RCPT command options
45
- hostname: SMTP server hostname or IP
46
- port: SMTP server port (defaults based on TLS settings)
47
- username: Authentication username
48
- password: Authentication password
49
- local_hostname: Local hostname for HELO/EHLO
50
- source_address: Source address tuple (host, port)
51
- timeout: Connection timeout in seconds
52
- use_tls: Use direct TLS/SSL connection
53
- start_tls: Use STARTTLS upgrade (None=auto, True=required, False=disabled)
54
- validate_certs: Validate server certificates
55
- client_cert: Path to client certificate file
56
- client_key: Path to client private key file
57
- tls_context: Custom SSL context
58
- cert_bundle: Path to CA certificate bundle
59
- socket_path: Unix domain socket path
60
- sock: Existing connected socket
61
62
Returns:
63
Tuple of (response_dict, data_response) where response_dict maps
64
recipient addresses to their SMTP responses
65
66
Raises:
67
- ValueError: If required arguments are missing
68
- SMTPConnectError: If connection fails
69
- SMTPAuthenticationError: If authentication fails
70
- SMTPException: For other SMTP-related errors
71
"""
72
```
73
74
### Usage Examples
75
76
#### Basic Email with EmailMessage
77
78
```python
79
import asyncio
80
from email.message import EmailMessage
81
import aiosmtplib
82
83
async def send_basic_email():
84
message = EmailMessage()
85
message["From"] = "sender@example.com"
86
message["To"] = "recipient@example.com"
87
message["Subject"] = "Hello from aiosmtplib"
88
message.set_content("This is the email body.")
89
90
response = await aiosmtplib.send(
91
message,
92
hostname="smtp.gmail.com",
93
port=587,
94
start_tls=True,
95
username="your-email@gmail.com",
96
password="your-password"
97
)
98
print(f"Email sent: {response}")
99
100
asyncio.run(send_basic_email())
101
```
102
103
#### Sending Raw Message
104
105
```python
106
import asyncio
107
import aiosmtplib
108
109
async def send_raw_email():
110
raw_message = """From: sender@example.com
111
To: recipient@example.com
112
Subject: Raw Message
113
114
This is a raw email message.
115
"""
116
117
response = await aiosmtplib.send(
118
raw_message,
119
sender="sender@example.com",
120
recipients=["recipient@example.com"],
121
hostname="localhost",
122
port=1025
123
)
124
print(f"Raw email sent: {response}")
125
126
asyncio.run(send_raw_email())
127
```
128
129
#### Multiple Recipients
130
131
```python
132
import asyncio
133
from email.message import EmailMessage
134
import aiosmtplib
135
136
async def send_to_multiple():
137
message = EmailMessage()
138
message["From"] = "sender@example.com"
139
message["To"] = "recipient1@example.com, recipient2@example.com"
140
message["Cc"] = "cc@example.com"
141
message["Subject"] = "Email to Multiple Recipients"
142
message.set_content("This email goes to multiple people.")
143
144
response = await aiosmtplib.send(
145
message,
146
hostname="smtp.example.com",
147
port=587,
148
start_tls=True,
149
username="sender@example.com",
150
password="password"
151
)
152
153
# Check individual recipient responses
154
for recipient, smtp_response in response[0].items():
155
print(f"{recipient}: {smtp_response}")
156
157
asyncio.run(send_to_multiple())
158
```
159
160
#### TLS/SSL Configuration
161
162
```python
163
import asyncio
164
import ssl
165
from email.message import EmailMessage
166
import aiosmtplib
167
168
async def send_with_custom_tls():
169
message = EmailMessage()
170
message["From"] = "sender@example.com"
171
message["To"] = "recipient@example.com"
172
message["Subject"] = "Secure Email"
173
message.set_content("This email uses custom TLS settings.")
174
175
# Custom SSL context
176
context = ssl.create_default_context()
177
context.check_hostname = False
178
context.verify_mode = ssl.CERT_NONE
179
180
response = await aiosmtplib.send(
181
message,
182
hostname="smtp.example.com",
183
port=465,
184
use_tls=True, # Direct TLS connection
185
tls_context=context,
186
username="sender@example.com",
187
password="password"
188
)
189
print(f"Secure email sent: {response}")
190
191
asyncio.run(send_with_custom_tls())
192
```
193
194
#### Error Handling
195
196
```python
197
import asyncio
198
from email.message import EmailMessage
199
import aiosmtplib
200
201
async def send_with_error_handling():
202
message = EmailMessage()
203
message["From"] = "sender@example.com"
204
message["To"] = "recipient@example.com"
205
message["Subject"] = "Test Email"
206
message.set_content("Testing error handling.")
207
208
try:
209
response = await aiosmtplib.send(
210
message,
211
hostname="smtp.example.com",
212
port=587,
213
start_tls=True,
214
username="sender@example.com",
215
password="wrong-password",
216
timeout=30
217
)
218
print(f"Email sent successfully: {response}")
219
220
except aiosmtplib.SMTPAuthenticationError as e:
221
print(f"Authentication failed: {e}")
222
except aiosmtplib.SMTPConnectError as e:
223
print(f"Connection failed: {e}")
224
except aiosmtplib.SMTPTimeoutError as e:
225
print(f"Operation timed out: {e}")
226
except aiosmtplib.SMTPException as e:
227
print(f"SMTP error: {e}")
228
229
asyncio.run(send_with_error_handling())
230
```
231
232
## Connection Options
233
234
### Port Selection
235
236
The `send()` function automatically selects default ports based on encryption settings:
237
238
- **Port 25**: Standard SMTP (no encryption)
239
- **Port 587**: STARTTLS submission port (when `start_tls=True`)
240
- **Port 465**: Direct TLS/SSL (when `use_tls=True`)
241
242
### TLS/SSL Options
243
244
- **`use_tls=True`**: Direct TLS/SSL connection (usually port 465)
245
- **`start_tls=True`**: Upgrade to TLS after initial connection (usually port 587)
246
- **`start_tls=None`**: Auto-detect STARTTLS support (default)
247
- **`start_tls=False`**: Disable TLS encryption
248
249
### Authentication
250
251
Authentication is performed automatically if `username` and `password` are provided. The function supports all authentication methods available in the underlying SMTP client (CRAM-MD5, PLAIN, LOGIN).
252
253
## Return Value
254
255
The `send()` function returns a tuple containing:
256
257
1. **Response Dictionary**: Maps recipient email addresses to their `SMTPResponse` objects
258
2. **Data Response**: String containing the final server response after data transmission
259
260
```python
261
response_dict, data_response = await aiosmtplib.send(message, ...)
262
263
# Check individual recipient responses
264
for recipient, smtp_response in response_dict.items():
265
print(f"{recipient}: {smtp_response.code} {smtp_response.message}")
266
267
print(f"Final response: {data_response}")
268
```