Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / mail / relay.py
1 # -*- test-case-name: twisted.mail.test.test_mail -*-
2 # Copyright (c) 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)