| OLD | NEW |
| (Empty) |
| 1 # -*- test-case-name: twisted.mail.test.test_mail -*- | |
| 2 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
| 3 # See LICENSE for details. | |
| 4 | |
| 5 | |
| 6 """Support for relaying mail for twisted.mail""" | |
| 7 | |
| 8 from twisted.mail import smtp | |
| 9 from twisted.python import log | |
| 10 from twisted.internet.address import UNIXAddress | |
| 11 | |
| 12 import os | |
| 13 | |
| 14 try: | |
| 15 import cPickle as pickle | |
| 16 except ImportError: | |
| 17 import pickle | |
| 18 | |
| 19 class DomainQueuer: | |
| 20 """An SMTP domain which add messages to a queue intended for relaying.""" | |
| 21 | |
| 22 def __init__(self, service, authenticated=False): | |
| 23 self.service = service | |
| 24 self.authed = authenticated | |
| 25 | |
| 26 def exists(self, user): | |
| 27 """Check whether we will relay | |
| 28 | |
| 29 Call overridable willRelay method | |
| 30 """ | |
| 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) | |
| 38 | |
| 39 def willRelay(self, address, protocol): | |
| 40 """Check whether we agree to relay | |
| 41 | |
| 42 The default is to relay for all connections over UNIX | |
| 43 sockets and all connections from localhost. | |
| 44 """ | |
| 45 peer = protocol.transport.getPeer() | |
| 46 return self.authed or isinstance(peer, UNIXAddress) or peer.host == '127
.0.0.1' | |
| 47 | |
| 48 def startMessage(self, user): | |
| 49 """Add envelope to queue and returns ISMTPMessage.""" | |
| 50 queue = self.service.queue | |
| 51 envelopeFile, smtpMessage = queue.createNewMessage() | |
| 52 try: | |
| 53 log.msg('Queueing mail %r -> %r' % (str(user.orig), str(user.dest))) | |
| 54 pickle.dump([str(user.orig), str(user.dest)], envelopeFile) | |
| 55 finally: | |
| 56 envelopeFile.close() | |
| 57 return smtpMessage | |
| 58 | |
| 59 class RelayerMixin: | |
| 60 | |
| 61 # XXX - This is -totally- bogus | |
| 62 # It opens about a -hundred- -billion- files | |
| 63 # and -leaves- them open! | |
| 64 | |
| 65 def loadMessages(self, messagePaths): | |
| 66 self.messages = [] | |
| 67 self.names = [] | |
| 68 for message in messagePaths: | |
| 69 fp = open(message+'-H') | |
| 70 try: | |
| 71 messageContents = pickle.load(fp) | |
| 72 finally: | |
| 73 fp.close() | |
| 74 fp = open(message+'-D') | |
| 75 messageContents.append(fp) | |
| 76 self.messages.append(messageContents) | |
| 77 self.names.append(message) | |
| 78 | |
| 79 def getMailFrom(self): | |
| 80 if not self.messages: | |
| 81 return None | |
| 82 return self.messages[0][0] | |
| 83 | |
| 84 def getMailTo(self): | |
| 85 if not self.messages: | |
| 86 return None | |
| 87 return [self.messages[0][1]] | |
| 88 | |
| 89 def getMailData(self): | |
| 90 if not self.messages: | |
| 91 return None | |
| 92 return self.messages[0][2] | |
| 93 | |
| 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. | |
| 98 """ | |
| 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') | |
| 103 del self.messages[0] | |
| 104 del self.names[0] | |
| 105 | |
| 106 class SMTPRelayer(RelayerMixin, smtp.SMTPClient): | |
| 107 def __init__(self, messagePaths, *args, **kw): | |
| 108 smtp.SMTPClient.__init__(self, *args, **kw) | |
| 109 self.loadMessages(messagePaths) | |
| 110 | |
| 111 class ESMTPRelayer(RelayerMixin, smtp.ESMTPClient): | |
| 112 def __init__(self, messagePaths, *args, **kw): | |
| 113 smtp.ESMTPClient.__init__(self, *args, **kw) | |
| 114 self.loadMessages(messagePaths) | |
| OLD | NEW |