Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(24)

Side by Side Diff: third_party/twisted_8_1/twisted/mail/mail.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # -*- test-case-name: twisted.mail.test.test_mail -*-
2 # Copyright (c) 2001-2007 Twisted Matrix Laboratories.
3 # See LICENSE for details.
4
5
6 """Mail support for twisted python.
7 """
8
9 # Twisted imports
10 from twisted.internet import defer
11 from twisted.application import service, internet
12 from twisted.python import util
13 from twisted.python import log
14
15 from twisted import cred
16 import twisted.cred.portal
17
18 # Sibling imports
19 from twisted.mail import protocols, smtp
20
21 # System imports
22 import os
23 from zope.interface import implements, Interface
24
25
26 class DomainWithDefaultDict:
27 '''Simulate a dictionary with a default value for non-existing keys.
28 '''
29 def __init__(self, domains, default):
30 self.domains = domains
31 self.default = default
32
33 def setDefaultDomain(self, domain):
34 self.default = domain
35
36 def has_key(self, name):
37 return 1
38
39 def fromkeys(klass, keys, value=None):
40 d = klass()
41 for k in keys:
42 d[k] = value
43 return d
44 fromkeys = classmethod(fromkeys)
45
46 def __contains__(self, name):
47 return 1
48
49 def __getitem__(self, name):
50 return self.domains.get(name, self.default)
51
52 def __setitem__(self, name, value):
53 self.domains[name] = value
54
55 def __delitem__(self, name):
56 del self.domains[name]
57
58 def __iter__(self):
59 return iter(self.domains)
60
61 def __len__(self):
62 return len(self.domains)
63
64
65 def __str__(self):
66 """
67 Return a string describing the underlying domain mapping of this
68 object.
69 """
70 return '<DomainWithDefaultDict %s>' % (self.domains,)
71
72
73 def __repr__(self):
74 """
75 Return a pseudo-executable string describing the underlying domain
76 mapping of this object.
77 """
78 return 'DomainWithDefaultDict(%s)' % (self.domains,)
79
80
81 def get(self, key, default=None):
82 return self.domains.get(key, default)
83
84 def copy(self):
85 return DomainWithDefaultDict(self.domains.copy(), self.default)
86
87 def iteritems(self):
88 return self.domains.iteritems()
89
90 def iterkeys(self):
91 return self.domains.iterkeys()
92
93 def itervalues(self):
94 return self.domains.itervalues()
95
96 def keys(self):
97 return self.domains.keys()
98
99 def values(self):
100 return self.domains.values()
101
102 def items(self):
103 return self.domains.items()
104
105 def popitem(self):
106 return self.domains.popitem()
107
108 def update(self, other):
109 return self.domains.update(other)
110
111 def clear(self):
112 return self.domains.clear()
113
114 def setdefault(self, key, default):
115 return self.domains.setdefault(key, default)
116
117 class IDomain(Interface):
118 """An email domain."""
119
120 def exists(user):
121 """
122 Check whether or not the specified user exists in this domain.
123
124 @type user: C{twisted.protocols.smtp.User}
125 @param user: The user to check
126
127 @rtype: No-argument callable
128 @return: A C{Deferred} which becomes, or a callable which
129 takes no arguments and returns an object implementing C{IMessage}.
130 This will be called and the returned object used to deliver the
131 message when it arrives.
132
133 @raise twisted.protocols.smtp.SMTPBadRcpt: Raised if the given
134 user does not exist in this domain.
135 """
136
137 def addUser(user, password):
138 """Add a username/password to this domain."""
139
140 def startMessage(user):
141 """Create and return a new message to be delivered to the given user.
142
143 DEPRECATED. Implement validateTo() correctly instead.
144 """
145
146 def getCredentialsCheckers():
147 """Return a list of ICredentialsChecker implementors for this domain.
148 """
149
150 class IAliasableDomain(IDomain):
151 def setAliasGroup(aliases):
152 """Set the group of defined aliases for this domain
153
154 @type aliases: C{dict}
155 @param aliases: Mapping of domain names to objects implementing
156 C{IAlias}
157 """
158
159 def exists(user, memo=None):
160 """
161 Check whether or not the specified user exists in this domain.
162
163 @type user: C{twisted.protocols.smtp.User}
164 @param user: The user to check
165
166 @type memo: C{dict}
167 @param memo: A record of the addresses already considered while
168 resolving aliases. The default value should be used by all
169 external code.
170
171 @rtype: No-argument callable
172 @return: A C{Deferred} which becomes, or a callable which
173 takes no arguments and returns an object implementing C{IMessage}.
174 This will be called and the returned object used to deliver the
175 message when it arrives.
176
177 @raise twisted.protocols.smtp.SMTPBadRcpt: Raised if the given
178 user does not exist in this domain.
179 """
180
181 class BounceDomain:
182 """A domain in which no user exists.
183
184 This can be used to block off certain domains.
185 """
186
187 implements(IDomain)
188
189 def exists(self, user):
190 raise smtp.SMTPBadRcpt(user)
191
192 def willRelay(self, user, protocol):
193 return False
194
195 def addUser(self, user, password):
196 pass
197
198 def startMessage(self, user):
199 """
200 No code should ever call this function.
201 """
202 raise NotImplementedError(
203 "No code should ever call this method for any reason")
204
205 def getCredentialsCheckers(self):
206 return []
207
208
209 class FileMessage:
210 """A file we can write an email too."""
211
212 implements(smtp.IMessage)
213
214 def __init__(self, fp, name, finalName):
215 self.fp = fp
216 self.name = name
217 self.finalName = finalName
218
219 def lineReceived(self, line):
220 self.fp.write(line+'\n')
221
222 def eomReceived(self):
223 self.fp.close()
224 os.rename(self.name, self.finalName)
225 return defer.succeed(self.finalName)
226
227 def connectionLost(self):
228 self.fp.close()
229 os.remove(self.name)
230
231
232 class MailService(service.MultiService):
233 """An email service."""
234
235 queue = None
236 domains = None
237 portals = None
238 aliases = None
239 smtpPortal = None
240
241 def __init__(self):
242 service.MultiService.__init__(self)
243 # Domains and portals for "client" protocols - POP3, IMAP4, etc
244 self.domains = DomainWithDefaultDict({}, BounceDomain())
245 self.portals = {}
246
247 self.monitor = FileMonitoringService()
248 self.monitor.setServiceParent(self)
249 self.smtpPortal = cred.portal.Portal(self)
250
251 def getPOP3Factory(self):
252 return protocols.POP3Factory(self)
253
254 def getSMTPFactory(self):
255 return protocols.SMTPFactory(self, self.smtpPortal)
256
257 def getESMTPFactory(self):
258 return protocols.ESMTPFactory(self, self.smtpPortal)
259
260 def addDomain(self, name, domain):
261 portal = cred.portal.Portal(domain)
262 map(portal.registerChecker, domain.getCredentialsCheckers())
263 self.domains[name] = domain
264 self.portals[name] = portal
265 if self.aliases and IAliasableDomain.providedBy(domain):
266 domain.setAliasGroup(self.aliases)
267
268 def setQueue(self, queue):
269 """Set the queue for outgoing emails."""
270 self.queue = queue
271
272 def requestAvatar(self, avatarId, mind, *interfaces):
273 if smtp.IMessageDelivery in interfaces:
274 a = protocols.ESMTPDomainDelivery(self, avatarId)
275 return smtp.IMessageDelivery, a, lambda: None
276 raise NotImplementedError()
277
278 def lookupPortal(self, name):
279 return self.portals[name]
280
281 def defaultPortal(self):
282 return self.portals['']
283
284
285 class FileMonitoringService(internet.TimerService):
286
287 def __init__(self):
288 self.files = []
289 self.intervals = iter(util.IntervalDifferential([], 60))
290
291 def startService(self):
292 service.Service.startService(self)
293 self._setupMonitor()
294
295 def _setupMonitor(self):
296 from twisted.internet import reactor
297 t, self.index = self.intervals.next()
298 self._call = reactor.callLater(t, self._monitor)
299
300 def stopService(self):
301 service.Service.stopService(self)
302 if self._call:
303 self._call.cancel()
304 self._call = None
305
306 def monitorFile(self, name, callback, interval=10):
307 try:
308 mtime = os.path.getmtime(name)
309 except:
310 mtime = 0
311 self.files.append([interval, name, callback, mtime])
312 self.intervals.addInterval(interval)
313
314 def unmonitorFile(self, name):
315 for i in range(len(self.files)):
316 if name == self.files[i][1]:
317 self.intervals.removeInterval(self.files[i][0])
318 del self.files[i]
319 break
320
321 def _monitor(self):
322 self._call = None
323 if self.index is not None:
324 name, callback, mtime = self.files[self.index][1:]
325 try:
326 now = os.path.getmtime(name)
327 except:
328 now = 0
329 if now > mtime:
330 log.msg("%s changed, notifying listener" % (name,))
331 self.files[self.index][3] = now
332 callback(name)
333 self._setupMonitor()
OLDNEW
« no previous file with comments | « third_party/twisted_8_1/twisted/mail/imap4.py ('k') | third_party/twisted_8_1/twisted/mail/maildir.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698