0
# Exception Handling
1
2
aiosmtplib provides a comprehensive exception hierarchy for handling different types of SMTP errors. These exceptions allow applications to handle specific error conditions appropriately and provide meaningful error messages to users.
3
4
## Capabilities
5
6
### Exception Hierarchy
7
8
The exception hierarchy is designed to allow both specific and general error handling.
9
10
```python { .api }
11
class SMTPException(Exception):
12
"""
13
Base class for all SMTP exceptions.
14
15
Attributes:
16
- message: str - Error message
17
"""
18
def __init__(self, message: str, /) -> None: ...
19
20
class SMTPServerDisconnected(SMTPException, ConnectionError):
21
"""
22
The connection was lost unexpectedly, or a command was run that requires
23
a connection.
24
"""
25
26
class SMTPConnectError(SMTPException, ConnectionError):
27
"""
28
An error occurred while connecting to the SMTP server.
29
"""
30
31
class SMTPTimeoutError(SMTPException, TimeoutError):
32
"""
33
A timeout occurred while performing a network operation.
34
"""
35
36
class SMTPConnectTimeoutError(SMTPTimeoutError, SMTPConnectError):
37
"""
38
A timeout occurred while connecting to the SMTP server.
39
"""
40
41
class SMTPReadTimeoutError(SMTPTimeoutError):
42
"""
43
A timeout occurred while waiting for a response from the SMTP server.
44
"""
45
46
class SMTPNotSupported(SMTPException):
47
"""
48
A command or argument sent to the SMTP server is not supported.
49
"""
50
```
51
52
### Server Response Exceptions
53
54
Exceptions that correspond to specific SMTP server response codes.
55
56
```python { .api }
57
class SMTPResponseException(SMTPException):
58
"""
59
Base class for all server responses with error codes.
60
61
Attributes:
62
- code: int - SMTP response code
63
- message: str - SMTP response message
64
"""
65
def __init__(self, code: int, message: str, /) -> None: ...
66
67
class SMTPConnectResponseError(SMTPResponseException, SMTPConnectError):
68
"""
69
The SMTP server returned an invalid response code after connecting.
70
"""
71
72
class SMTPHeloError(SMTPResponseException):
73
"""
74
Server refused HELO or EHLO.
75
"""
76
77
class SMTPDataError(SMTPResponseException):
78
"""
79
Server refused DATA content.
80
"""
81
82
class SMTPAuthenticationError(SMTPResponseException):
83
"""
84
Server refused our AUTH request; may be caused by invalid credentials.
85
"""
86
```
87
88
### Recipient and Sender Exceptions
89
90
Specific exceptions for email address-related errors.
91
92
```python { .api }
93
class SMTPSenderRefused(SMTPResponseException):
94
"""
95
SMTP server refused the message sender.
96
97
Attributes:
98
- code: int - SMTP response code
99
- message: str - SMTP response message
100
- sender: str - The refused sender address
101
"""
102
def __init__(self, code: int, message: str, sender: str, /) -> None: ...
103
104
class SMTPRecipientRefused(SMTPResponseException):
105
"""
106
SMTP server refused a message recipient.
107
108
Attributes:
109
- code: int - SMTP response code
110
- message: str - SMTP response message
111
- recipient: str - The refused recipient address
112
"""
113
def __init__(self, code: int, message: str, recipient: str, /) -> None: ...
114
115
class SMTPRecipientsRefused(SMTPException):
116
"""
117
SMTP server refused multiple recipients.
118
119
Attributes:
120
- recipients: list[SMTPRecipientRefused] - List of refused recipient errors
121
"""
122
def __init__(self, recipients: list[SMTPRecipientRefused], /) -> None: ...
123
```
124
125
## Usage Examples
126
127
### Basic Exception Handling
128
129
```python
130
import asyncio
131
import aiosmtplib
132
from email.message import EmailMessage
133
134
async def basic_error_handling():
135
message = EmailMessage()
136
message["From"] = "sender@example.com"
137
message["To"] = "recipient@example.com"
138
message["Subject"] = "Test Email"
139
message.set_content("Test message")
140
141
try:
142
response = await aiosmtplib.send(
143
message,
144
hostname="smtp.example.com",
145
port=587,
146
start_tls=True,
147
username="user@example.com",
148
password="password"
149
)
150
print(f"Email sent successfully: {response}")
151
152
except aiosmtplib.SMTPException as e:
153
print(f"SMTP error occurred: {e}")
154
155
asyncio.run(basic_error_handling())
156
```
157
158
### Specific Exception Handling
159
160
```python
161
import asyncio
162
import aiosmtplib
163
from email.message import EmailMessage
164
165
async def specific_error_handling():
166
message = EmailMessage()
167
message["From"] = "sender@example.com"
168
message["To"] = "invalid@nonexistent.domain"
169
message["Subject"] = "Test Email"
170
message.set_content("Test message")
171
172
try:
173
response = await aiosmtplib.send(
174
message,
175
hostname="smtp.example.com",
176
port=587,
177
start_tls=True,
178
username="user@example.com",
179
password="wrong-password",
180
timeout=10
181
)
182
print(f"Email sent: {response}")
183
184
except aiosmtplib.SMTPConnectTimeoutError as e:
185
print(f"Connection timed out: {e}")
186
# Maybe retry with longer timeout
187
188
except aiosmtplib.SMTPConnectError as e:
189
print(f"Failed to connect to server: {e}")
190
# Maybe try alternative server
191
192
except aiosmtplib.SMTPAuthenticationError as e:
193
print(f"Authentication failed (code {e.code}): {e.message}")
194
# Prompt user for correct credentials
195
196
except aiosmtplib.SMTPSenderRefused as e:
197
print(f"Sender '{e.sender}' refused (code {e.code}): {e.message}")
198
# Use different sender address
199
200
except aiosmtplib.SMTPRecipientRefused as e:
201
print(f"Recipient '{e.recipient}' refused (code {e.code}): {e.message}")
202
# Remove invalid recipient
203
204
except aiosmtplib.SMTPRecipientsRefused as e:
205
print("Multiple recipients refused:")
206
for recipient_error in e.recipients:
207
print(f" {recipient_error.recipient}: {recipient_error.message}")
208
# Handle each refused recipient
209
210
except aiosmtplib.SMTPDataError as e:
211
print(f"Message content refused (code {e.code}): {e.message}")
212
# Modify message content
213
214
except aiosmtplib.SMTPReadTimeoutError as e:
215
print(f"Server response timed out: {e}")
216
# Maybe retry operation
217
218
except aiosmtplib.SMTPNotSupported as e:
219
print(f"Operation not supported: {e}")
220
# Use alternative approach
221
222
except aiosmtplib.SMTPServerDisconnected as e:
223
print(f"Server disconnected unexpectedly: {e}")
224
# Reconnect and retry
225
226
except aiosmtplib.SMTPTimeoutError as e:
227
print(f"General timeout error: {e}")
228
# Increase timeout and retry
229
230
except aiosmtplib.SMTPResponseException as e:
231
print(f"Server error (code {e.code}): {e.message}")
232
# Handle other server response errors
233
234
except aiosmtplib.SMTPException as e:
235
print(f"General SMTP error: {e}")
236
# Handle any other SMTP-related errors
237
238
asyncio.run(specific_error_handling())
239
```
240
241
### Client Error Handling
242
243
```python
244
import asyncio
245
import aiosmtplib
246
247
async def client_error_handling():
248
smtp = aiosmtplib.SMTP(hostname="smtp.example.com", port=587)
249
250
try:
251
# Connection errors
252
await smtp.connect()
253
254
except aiosmtplib.SMTPConnectTimeoutError as e:
255
print(f"Connection timed out: {e}")
256
return
257
except aiosmtplib.SMTPConnectError as e:
258
print(f"Connection failed: {e}")
259
return
260
261
try:
262
# Authentication errors
263
await smtp.login("user", "password")
264
265
except aiosmtplib.SMTPAuthenticationError as e:
266
print(f"Authentication failed: {e.code} {e.message}")
267
smtp.close()
268
return
269
except aiosmtplib.SMTPNotSupported as e:
270
print(f"Authentication not supported: {e}")
271
# Continue without authentication
272
273
try:
274
# Sending errors
275
response = await smtp.sendmail(
276
"sender@example.com",
277
["recipient1@example.com", "invalid@bad.domain"],
278
"Subject: Test\n\nTest message"
279
)
280
281
# Check individual recipient responses
282
for recipient, smtp_response in response[0].items():
283
print(f"{recipient}: {smtp_response}")
284
285
except aiosmtplib.SMTPSenderRefused as e:
286
print(f"Sender refused: {e.sender} - {e.message}")
287
except aiosmtplib.SMTPRecipientsRefused as e:
288
print("Some recipients refused:")
289
for error in e.recipients:
290
print(f" {error.recipient}: {error.message}")
291
except aiosmtplib.SMTPDataError as e:
292
print(f"Message data refused: {e.message}")
293
except aiosmtplib.SMTPServerDisconnected as e:
294
print(f"Connection lost during operation: {e}")
295
296
finally:
297
if smtp.is_connected:
298
try:
299
await smtp.quit()
300
except aiosmtplib.SMTPException:
301
# Force close if quit fails
302
smtp.close()
303
304
asyncio.run(client_error_handling())
305
```
306
307
### Error Recovery Strategies
308
309
```python
310
import asyncio
311
import aiosmtplib
312
from email.message import EmailMessage
313
314
async def error_recovery_example():
315
message = EmailMessage()
316
message["From"] = "sender@example.com"
317
message["To"] = "recipient@example.com"
318
message["Subject"] = "Test with Recovery"
319
message.set_content("Test message with error recovery")
320
321
# List of backup servers
322
smtp_servers = [
323
{"hostname": "smtp.primary.com", "port": 587},
324
{"hostname": "smtp.backup.com", "port": 587},
325
{"hostname": "smtp.fallback.com", "port": 25},
326
]
327
328
for server_config in smtp_servers:
329
try:
330
response = await aiosmtplib.send(
331
message,
332
hostname=server_config["hostname"],
333
port=server_config["port"],
334
start_tls=True,
335
username="user@example.com",
336
password="password",
337
timeout=30
338
)
339
print(f"Email sent via {server_config['hostname']}: {response}")
340
break # Success, exit loop
341
342
except aiosmtplib.SMTPConnectError as e:
343
print(f"Failed to connect to {server_config['hostname']}: {e}")
344
continue # Try next server
345
346
except aiosmtplib.SMTPTimeoutError as e:
347
print(f"Timeout with {server_config['hostname']}: {e}")
348
continue # Try next server
349
350
except aiosmtplib.SMTPAuthenticationError as e:
351
print(f"Auth failed with {server_config['hostname']}: {e}")
352
# Authentication issue - don't retry with other servers
353
break
354
355
except aiosmtplib.SMTPException as e:
356
print(f"SMTP error with {server_config['hostname']}: {e}")
357
continue # Try next server
358
else:
359
print("Failed to send email with all configured servers")
360
361
asyncio.run(error_recovery_example())
362
```
363
364
### Exception Information Access
365
366
```python
367
import asyncio
368
import aiosmtplib
369
370
async def exception_info_example():
371
smtp = aiosmtplib.SMTP(hostname="smtp.example.com", port=587)
372
373
try:
374
await smtp.connect()
375
await smtp.sendmail(
376
"invalid-sender", # Invalid sender format
377
["recipient@example.com"],
378
"Subject: Test\n\nTest message"
379
)
380
381
except aiosmtplib.SMTPSenderRefused as e:
382
print("Sender refused details:")
383
print(f" Response code: {e.code}")
384
print(f" Server message: {e.message}")
385
print(f" Refused sender: {e.sender}")
386
print(f" Exception args: {e.args}")
387
388
except aiosmtplib.SMTPRecipientRefused as e:
389
print("Recipient refused details:")
390
print(f" Response code: {e.code}")
391
print(f" Server message: {e.message}")
392
print(f" Refused recipient: {e.recipient}")
393
394
except aiosmtplib.SMTPResponseException as e:
395
print("Server response error:")
396
print(f" Response code: {e.code}")
397
print(f" Server message: {e.message}")
398
399
except aiosmtplib.SMTPException as e:
400
print("General SMTP error:")
401
print(f" Error message: {e.message}")
402
print(f" Exception type: {type(e).__name__}")
403
404
finally:
405
smtp.close()
406
407
asyncio.run(exception_info_example())
408
```
409
410
## Exception Categories
411
412
### Connection Exceptions
413
- `SMTPConnectError`: General connection failures
414
- `SMTPConnectTimeoutError`: Connection timeouts
415
- `SMTPServerDisconnected`: Unexpected disconnections
416
- `SMTPConnectResponseError`: Invalid server greeting
417
418
### Authentication Exceptions
419
- `SMTPAuthenticationError`: Authentication failures
420
- `SMTPNotSupported`: Unsupported features/commands
421
422
### Message Exceptions
423
- `SMTPSenderRefused`: Sender address rejected
424
- `SMTPRecipientRefused`: Recipient address rejected
425
- `SMTPRecipientsRefused`: Multiple recipients rejected
426
- `SMTPDataError`: Message content rejected
427
428
### Operation Exceptions
429
- `SMTPTimeoutError`: General operation timeouts
430
- `SMTPReadTimeoutError`: Server response timeouts
431
- `SMTPHeloError`: HELO/EHLO command failures
432
- `SMTPResponseException`: General server response errors
433
434
### General Exception
435
- `SMTPException`: Base class for all SMTP-related errors