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
|
# -*- test-case-name: twisted.mail.test.test_mail -*-
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
"""Support for relaying mail for twisted.mail"""
from twisted.mail import smtp
from twisted.python import log
from twisted.internet.address import UNIXAddress
import os
try:
import cPickle as pickle
except ImportError:
import pickle
class DomainQueuer:
"""An SMTP domain which add messages to a queue intended for relaying."""
def __init__(self, service, authenticated=False):
self.service = service
self.authed = authenticated
def exists(self, user):
"""Check whether we will relay
Call overridable willRelay method
"""
if self.willRelay(user.dest, user.protocol):
# The most cursor form of verification of the addresses
orig = filter(None, str(user.orig).split('@', 1))
dest = filter(None, str(user.dest).split('@', 1))
if len(orig) == 2 and len(dest) == 2:
return lambda: self.startMessage(user)
raise smtp.SMTPBadRcpt(user)
def willRelay(self, address, protocol):
"""Check whether we agree to relay
The default is to relay for all connections over UNIX
sockets and all connections from localhost.
"""
peer = protocol.transport.getPeer()
return self.authed or isinstance(peer, UNIXAddress) or peer.host == '127.0.0.1'
def startMessage(self, user):
"""Add envelope to queue and returns ISMTPMessage."""
queue = self.service.queue
envelopeFile, smtpMessage = queue.createNewMessage()
try:
log.msg('Queueing mail %r -> %r' % (str(user.orig), str(user.dest)))
pickle.dump([str(user.orig), str(user.dest)], envelopeFile)
finally:
envelopeFile.close()
return smtpMessage
class RelayerMixin:
# XXX - This is -totally- bogus
# It opens about a -hundred- -billion- files
# and -leaves- them open!
def loadMessages(self, messagePaths):
self.messages = []
self.names = []
for message in messagePaths:
fp = open(message+'-H')
try:
messageContents = pickle.load(fp)
finally:
fp.close()
fp = open(message+'-D')
messageContents.append(fp)
self.messages.append(messageContents)
self.names.append(message)
def getMailFrom(self):
if not self.messages:
return None
return self.messages[0][0]
def getMailTo(self):
if not self.messages:
return None
return [self.messages[0][1]]
def getMailData(self):
if not self.messages:
return None
return self.messages[0][2]
def sentMail(self, code, resp, numOk, addresses, log):
"""Since we only use one recipient per envelope, this
will be called with 0 or 1 addresses. We probably want
to do something with the error message if we failed.
"""
if code in smtp.SUCCESS:
# At least one, i.e. all, recipients successfully delivered
os.remove(self.names[0]+'-D')
os.remove(self.names[0]+'-H')
del self.messages[0]
del self.names[0]
class SMTPRelayer(RelayerMixin, smtp.SMTPClient):
def __init__(self, messagePaths, *args, **kw):
smtp.SMTPClient.__init__(self, *args, **kw)
self.loadMessages(messagePaths)
class ESMTPRelayer(RelayerMixin, smtp.ESMTPClient):
def __init__(self, messagePaths, *args, **kw):
smtp.ESMTPClient.__init__(self, *args, **kw)
self.loadMessages(messagePaths)
|