1
# -*- test-case-name: twisted.mail.test.test_mail -*-
2
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
3
# See LICENSE for details.
6
"""Support for relaying mail for twisted.mail"""
8
from twisted.mail import smtp
9
from twisted.python import log
10
from twisted.internet.address import UNIXAddress
15
import cPickle as pickle
20
"""An SMTP domain which add messages to a queue intended for relaying."""
22
def __init__(self, service, authenticated=False):
23
self.service = service
24
self.authed = authenticated
26
def exists(self, user):
27
"""Check whether we will relay
29
Call overridable willRelay method
31
if self.willRelay(user.dest, user.protocol):
32
# The most cursor form of verification of the addresses
33
orig = filter(None, str(user.orig).split('@', 1))
34
dest = filter(None, str(user.dest).split('@', 1))
35
if len(orig) == 2 and len(dest) == 2:
36
return lambda: self.startMessage(user)
37
raise smtp.SMTPBadRcpt(user)
39
def willRelay(self, address, protocol):
40
"""Check whether we agree to relay
42
The default is to relay for all connections over UNIX
43
sockets and all connections from localhost.
45
peer = protocol.transport.getPeer()
46
return self.authed or isinstance(peer, UNIXAddress) or peer.host == '127.0.0.1'
48
def startMessage(self, user):
49
"""Add envelope to queue and returns ISMTPMessage."""
50
queue = self.service.queue
51
envelopeFile, smtpMessage = queue.createNewMessage()
53
log.msg('Queueing mail %r -> %r' % (str(user.orig), str(user.dest)))
54
pickle.dump([str(user.orig), str(user.dest)], envelopeFile)
61
# XXX - This is -totally- bogus
62
# It opens about a -hundred- -billion- files
63
# and -leaves- them open!
65
def loadMessages(self, messagePaths):
68
for message in messagePaths:
69
fp = open(message+'-H')
71
messageContents = pickle.load(fp)
74
fp = open(message+'-D')
75
messageContents.append(fp)
76
self.messages.append(messageContents)
77
self.names.append(message)
79
def getMailFrom(self):
82
return self.messages[0][0]
87
return [self.messages[0][1]]
89
def getMailData(self):
92
return self.messages[0][2]
94
def sentMail(self, code, resp, numOk, addresses, log):
95
"""Since we only use one recipient per envelope, this
96
will be called with 0 or 1 addresses. We probably want
97
to do something with the error message if we failed.
99
if code in smtp.SUCCESS:
100
# At least one, i.e. all, recipients successfully delivered
101
os.remove(self.names[0]+'-D')
102
os.remove(self.names[0]+'-H')
106
class SMTPRelayer(RelayerMixin, smtp.SMTPClient):
107
def __init__(self, messagePaths, *args, **kw):
108
smtp.SMTPClient.__init__(self, *args, **kw)
109
self.loadMessages(messagePaths)
111
class ESMTPRelayer(RelayerMixin, smtp.ESMTPClient):
112
def __init__(self, messagePaths, *args, **kw):
113
smtp.ESMTPClient.__init__(self, *args, **kw)
114
self.loadMessages(messagePaths)