0
# Email Protocols
1
2
Complete email protocol implementations including SMTP, POP3, and IMAP4 with support for both client and server operations. Twisted provides comprehensive email handling capabilities.
3
4
## Capabilities
5
6
### SMTP (Simple Mail Transfer Protocol)
7
8
SMTP server and client implementations for sending and receiving email.
9
10
```python { .api }
11
class smtp.SMTP:
12
"""
13
SMTP server protocol implementation.
14
15
Attributes:
16
- host: Server hostname
17
- portal: Authentication portal
18
- challenger: Authentication challenger
19
"""
20
host = None
21
portal = None
22
challenger = None
23
24
def greeting(self):
25
"""
26
Get server greeting message.
27
28
Returns:
29
str: SMTP greeting
30
"""
31
32
def extensions(self):
33
"""
34
Get supported SMTP extensions.
35
36
Returns:
37
dict: Extension capabilities
38
"""
39
40
def validateTo(self, user):
41
"""
42
Validate recipient address.
43
44
Args:
45
user: User address object
46
47
Returns:
48
callable: Message delivery callable
49
"""
50
51
def validateFrom(self, helo, origin):
52
"""
53
Validate sender address.
54
55
Args:
56
helo (bytes): HELO/EHLO string
57
origin: Sender address object
58
59
Returns:
60
Deferred: Validation result
61
"""
62
63
class smtp.ESMTP(smtp.SMTP):
64
"""
65
Extended SMTP server with additional features.
66
67
Supports SMTP extensions like authentication, TLS, etc.
68
"""
69
70
def ext_AUTH(self, args):
71
"""Handle AUTH extension."""
72
73
def ext_STARTTLS(self, args):
74
"""Handle STARTTLS extension."""
75
76
def ext_SIZE(self, args):
77
"""Handle SIZE extension."""
78
79
class smtp.ESMTPSender:
80
"""
81
SMTP client for sending email messages.
82
"""
83
def __init__(self, username=None, password=None, contextFactory=None, **kwargs):
84
"""
85
Args:
86
username (bytes): SMTP username
87
password (bytes): SMTP password
88
contextFactory: SSL context factory for STARTTLS
89
**kwargs: Additional connection parameters
90
"""
91
92
def sendmail(self, from_addr, to_addrs, msg, response=None):
93
"""
94
Send email message.
95
96
Args:
97
from_addr (str): Sender address
98
to_addrs (list): Recipient addresses
99
msg (bytes): Email message content
100
response: Response handler
101
102
Returns:
103
Deferred: Delivery result
104
"""
105
106
class smtp.SMTPSenderFactory:
107
"""
108
Factory for creating SMTP sender connections.
109
"""
110
def __init__(self, fromEmail, toEmail, file, deferred, retries=5, timeout=None):
111
"""
112
Args:
113
fromEmail (str): Sender address
114
toEmail (str): Recipient address
115
file: File-like object with message content
116
deferred: Deferred to fire when complete
117
retries (int): Number of retry attempts
118
timeout (int): Connection timeout
119
"""
120
121
def buildProtocol(self, addr):
122
"""
123
Build SMTP sender protocol.
124
125
Args:
126
addr: Connection address
127
128
Returns:
129
ESMTPSender: SMTP sender instance
130
"""
131
132
class smtp.SMTPFactory:
133
"""
134
SMTP server factory.
135
"""
136
def __init__(self):
137
self.deliveryClass = smtp.SMTPDelivery
138
self.portal = None
139
self.challenger = None
140
141
def buildProtocol(self, addr):
142
"""
143
Build SMTP server protocol.
144
145
Args:
146
addr: Connection address
147
148
Returns:
149
SMTP: SMTP server instance
150
"""
151
```
152
153
**SMTP Usage Example**:
154
155
```python
156
from twisted.mail import smtp
157
from twisted.internet import reactor, defer, endpoints
158
from twisted.cred import portal, checkers
159
160
# SMTP Client - Send email
161
@defer.inlineCallbacks
162
def send_email():
163
sender_factory = smtp.SMTPSenderFactory(
164
fromEmail="sender@example.com",
165
toEmail="recipient@example.com",
166
file=io.StringIO("Subject: Test\n\nHello, World!"),
167
deferred=defer.Deferred()
168
)
169
170
endpoint = endpoints.TCP4ClientEndpoint(reactor, "smtp.example.com", 25)
171
yield endpoint.connect(sender_factory)
172
173
# SMTP Server
174
class MyDelivery:
175
"""Custom message delivery handler."""
176
177
def receivedHeader(self, helo, origin, recipients):
178
return "Received: from %s" % (helo,)
179
180
def validateTo(self, user):
181
# Validate recipient
182
if user.dest.local == "postmaster":
183
return lambda: MyMessage()
184
raise smtp.SMTPBadRcpt(user)
185
186
def validateFrom(self, helo, origin):
187
# Validate sender
188
return origin
189
190
class MyMessage:
191
"""Message storage handler."""
192
193
def eomReceived(self):
194
# Called when message is complete
195
print("Message received")
196
return defer.succeed("250 Message accepted")
197
198
# Set up SMTP server
199
factory = smtp.SMTPFactory()
200
factory.delivery = MyDelivery()
201
factory.portal = portal.Portal(realm, [checker])
202
203
endpoint = endpoints.TCP4ServerEndpoint(reactor, 25)
204
endpoint.listen(factory)
205
```
206
207
### POP3 (Post Office Protocol)
208
209
POP3 server and client for retrieving email from mailboxes.
210
211
```python { .api }
212
class pop3.POP3:
213
"""
214
POP3 server protocol implementation.
215
216
Attributes:
217
- mbox: Mailbox object
218
- portal: Authentication portal
219
"""
220
mbox = None
221
portal = None
222
223
def authenticateUserAPOP(self, user, digest):
224
"""
225
Authenticate using APOP.
226
227
Args:
228
user (bytes): Username
229
digest (bytes): APOP digest
230
231
Returns:
232
Deferred: Authentication result
233
"""
234
235
def authenticateUserPASS(self, user, password):
236
"""
237
Authenticate using USER/PASS.
238
239
Args:
240
user (bytes): Username
241
password (bytes): Password
242
243
Returns:
244
Deferred: Authentication result
245
"""
246
247
class pop3.POP3Client:
248
"""
249
POP3 client protocol implementation.
250
"""
251
def login(self, username, password):
252
"""
253
Login to POP3 server.
254
255
Args:
256
username (bytes): Username
257
password (bytes): Password
258
259
Returns:
260
Deferred: Login result
261
"""
262
263
def listMessages(self):
264
"""
265
List messages in mailbox.
266
267
Returns:
268
Deferred[list]: List of (message_num, size) tuples
269
"""
270
271
def getMessage(self, index):
272
"""
273
Retrieve message by index.
274
275
Args:
276
index (int): Message index
277
278
Returns:
279
Deferred[list]: Message lines
280
"""
281
282
def deleteMessage(self, index):
283
"""
284
Mark message for deletion.
285
286
Args:
287
index (int): Message index
288
289
Returns:
290
Deferred: Deletion result
291
"""
292
293
def quit(self):
294
"""
295
Quit POP3 session.
296
297
Returns:
298
Deferred: Quit result
299
"""
300
301
class pop3.POP3Factory:
302
"""
303
POP3 server factory.
304
"""
305
def __init__(self):
306
self.portal = None
307
308
def buildProtocol(self, addr):
309
"""
310
Build POP3 server protocol.
311
312
Args:
313
addr: Connection address
314
315
Returns:
316
POP3: POP3 server instance
317
"""
318
319
class pop3.POP3ClientFactory:
320
"""
321
POP3 client factory.
322
"""
323
def __init__(self, username, password, **kwargs):
324
"""
325
Args:
326
username (str): POP3 username
327
password (str): POP3 password
328
**kwargs: Additional parameters
329
"""
330
```
331
332
**POP3 Usage Example**:
333
334
```python
335
from twisted.mail import pop3
336
from twisted.internet import reactor, defer, endpoints
337
338
# POP3 Client
339
@defer.inlineCallbacks
340
def retrieve_mail():
341
factory = pop3.POP3ClientFactory("username", "password")
342
endpoint = endpoints.TCP4ClientEndpoint(reactor, "pop.example.com", 110)
343
344
protocol = yield endpoint.connect(factory)
345
yield protocol.login(b"username", b"password")
346
347
messages = yield protocol.listMessages()
348
print(f"Found {len(messages)} messages")
349
350
# Retrieve first message
351
if messages:
352
message_lines = yield protocol.getMessage(0)
353
message = b'\n'.join(message_lines)
354
print(f"Message: {message.decode()}")
355
356
yield protocol.quit()
357
358
# POP3 Server with custom mailbox
359
class MyMailbox:
360
"""Custom mailbox implementation."""
361
362
def __init__(self, messages):
363
self.messages = messages
364
365
def listMessages(self):
366
return [(i, len(msg)) for i, msg in enumerate(self.messages)]
367
368
def getMessage(self, i):
369
return self.messages[i].split(b'\n')
370
371
def deleteMessage(self, i):
372
del self.messages[i]
373
374
class MyRealm:
375
def requestAvatar(self, avatarId, mind, *interfaces):
376
# Create mailbox for user
377
messages = [b"Subject: Test\n\nHello!"]
378
mailbox = MyMailbox(messages)
379
return (pop3.IMailbox, mailbox, lambda: None)
380
381
# Set up POP3 server
382
realm = MyRealm()
383
checker = checkers.InMemoryUsernamePasswordDatabaseDontUse()
384
checker.addUser(b"testuser", b"password")
385
386
factory = pop3.POP3Factory()
387
factory.portal = portal.Portal(realm, [checker])
388
389
endpoint = endpoints.TCP4ServerEndpoint(reactor, 110)
390
endpoint.listen(factory)
391
```
392
393
### IMAP4 (Internet Message Access Protocol)
394
395
IMAP4 server and client for advanced email access and management.
396
397
```python { .api }
398
class imap4.IMAP4Server:
399
"""
400
IMAP4 server protocol implementation.
401
402
Attributes:
403
- portal: Authentication portal
404
- account: User account object
405
"""
406
portal = None
407
account = None
408
409
def authenticateLogin(self, username, password):
410
"""
411
Authenticate with LOGIN command.
412
413
Args:
414
username (bytes): Username
415
password (bytes): Password
416
417
Returns:
418
Deferred: Authentication result
419
"""
420
421
def do_SELECT(self, tag, messages):
422
"""Handle SELECT command."""
423
424
def do_EXAMINE(self, tag, messages):
425
"""Handle EXAMINE command."""
426
427
def do_FETCH(self, tag, messages):
428
"""Handle FETCH command."""
429
430
def do_SEARCH(self, tag, messages):
431
"""Handle SEARCH command."""
432
433
def do_STORE(self, tag, messages):
434
"""Handle STORE command."""
435
436
class imap4.IMAP4Client:
437
"""
438
IMAP4 client protocol implementation.
439
"""
440
def login(self, username, password):
441
"""
442
Login to IMAP4 server.
443
444
Args:
445
username (str): Username
446
password (str): Password
447
448
Returns:
449
Deferred: Login result
450
"""
451
452
def list(self, reference, name):
453
"""
454
List mailboxes.
455
456
Args:
457
reference (str): Reference name
458
name (str): Mailbox name pattern
459
460
Returns:
461
Deferred[list]: List of mailboxes
462
"""
463
464
def select(self, mailbox):
465
"""
466
Select mailbox.
467
468
Args:
469
mailbox (str): Mailbox name
470
471
Returns:
472
Deferred[dict]: Mailbox status
473
"""
474
475
def search(self, *query):
476
"""
477
Search for messages.
478
479
Args:
480
*query: Search criteria
481
482
Returns:
483
Deferred[list]: Message numbers
484
"""
485
486
def fetch(self, messages, *query):
487
"""
488
Fetch message data.
489
490
Args:
491
messages: Message set
492
*query: Fetch items
493
494
Returns:
495
Deferred[dict]: Message data
496
"""
497
498
def store(self, messages, command, flags):
499
"""
500
Store message flags.
501
502
Args:
503
messages: Message set
504
command (str): Store command
505
flags (list): Message flags
506
507
Returns:
508
Deferred: Store result
509
"""
510
511
def expunge(self):
512
"""
513
Expunge deleted messages.
514
515
Returns:
516
Deferred[list]: Expunged message numbers
517
"""
518
519
class imap4.IMAP4Factory:
520
"""
521
IMAP4 server factory.
522
"""
523
def __init__(self):
524
self.portal = None
525
self.timeOut = 30 * 60 # 30 minutes
526
527
def buildProtocol(self, addr):
528
"""
529
Build IMAP4 server protocol.
530
531
Args:
532
addr: Connection address
533
534
Returns:
535
IMAP4Server: IMAP4 server instance
536
"""
537
538
class imap4.IMAP4ClientFactory:
539
"""
540
IMAP4 client factory.
541
"""
542
def __init__(self, username, password, **kwargs):
543
"""
544
Args:
545
username (str): IMAP username
546
password (str): IMAP password
547
**kwargs: Additional parameters
548
"""
549
```
550
551
### Email Message Handling
552
553
Utilities for parsing, creating, and manipulating email messages.
554
555
```python { .api }
556
class mail.MailService:
557
"""
558
Service for handling email delivery.
559
560
Attributes:
561
- domains: List of handled domains
562
- portals: Authentication portals
563
"""
564
domains = None
565
portals = None
566
567
def addDomain(self, domain):
568
"""
569
Add domain to handle.
570
571
Args:
572
domain (str): Domain name
573
"""
574
575
def setQueue(self, queue):
576
"""
577
Set message queue.
578
579
Args:
580
queue: Queue object for messages
581
"""
582
583
class mail.FileMessage:
584
"""
585
File-based email message storage.
586
"""
587
def __init__(self, fp, name, finalName):
588
"""
589
Args:
590
fp: File pointer
591
name (str): Temporary filename
592
finalName (str): Final filename
593
"""
594
595
def eomReceived(self):
596
"""
597
Called when end of message is received.
598
599
Returns:
600
Deferred: Processing result
601
"""
602
603
# Email address parsing
604
class smtp.Address:
605
"""
606
Email address representation.
607
608
Attributes:
609
- local: Local part of address
610
- domain: Domain part of address
611
"""
612
local = None
613
domain = None
614
615
def __init__(self, local, domain=None):
616
"""
617
Args:
618
local (str): Local part
619
domain (str): Domain part
620
"""
621
622
def __str__(self):
623
"""String representation of address."""
624
```
625
626
### Maildir Support
627
628
Maildir format support for mail storage.
629
630
```python { .api }
631
class maildir.MaildirMessage:
632
"""
633
Maildir format message.
634
"""
635
def __init__(self, file, flags=None):
636
"""
637
Args:
638
file: Message file
639
flags (str): Message flags
640
"""
641
642
class maildir.AbstractMaildirDomain:
643
"""
644
Abstract Maildir domain handler.
645
"""
646
def __init__(self, root):
647
"""
648
Args:
649
root (str): Maildir root directory
650
"""
651
652
def userDirectory(self, user):
653
"""
654
Get user's maildir directory.
655
656
Args:
657
user (str): Username
658
659
Returns:
660
str: User directory path
661
"""
662
```
663
664
**Email Message Example**:
665
666
```python
667
from twisted.mail import smtp, mail
668
from twisted.internet import defer
669
import email.mime.text
670
671
# Create and send email message
672
def create_message():
673
msg = email.mime.text.MIMEText("Hello, World!")
674
msg['From'] = "sender@example.com"
675
msg['To'] = "recipient@example.com"
676
msg['Subject'] = "Test Message"
677
return msg.as_bytes()
678
679
@defer.inlineCallbacks
680
def send_message():
681
message_data = create_message()
682
683
factory = smtp.SMTPSenderFactory(
684
fromEmail="sender@example.com",
685
toEmail="recipient@example.com",
686
file=io.BytesIO(message_data),
687
deferred=defer.Deferred()
688
)
689
690
endpoint = endpoints.TCP4ClientEndpoint(reactor, "smtp.example.com", 25)
691
yield endpoint.connect(factory)
692
print("Email sent successfully")
693
694
# Handle incoming email
695
class CustomDelivery:
696
def validateTo(self, user):
697
# Accept all messages
698
return lambda: CustomMessage(user)
699
700
def validateFrom(self, helo, origin):
701
return origin
702
703
class CustomMessage:
704
def __init__(self, user):
705
self.user = user
706
self.lines = []
707
708
def lineReceived(self, line):
709
self.lines.append(line)
710
711
def eomReceived(self):
712
# Process complete message
713
message = b'\n'.join(self.lines)
714
print(f"Received message for {self.user}: {message}")
715
return defer.succeed("250 Message accepted")
716
```