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

Side by Side Diff: third_party/twisted_8_1/twisted/mail/scripts/mailmail.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
2 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
3 # See LICENSE for details.
4
5 #
6
7 """
8 Implementation module for the `newtexaco` command.
9
10 The name is preliminary and subject to change.
11 """
12
13 import os
14 import sys
15 import rfc822
16 import socket
17 import getpass
18 from ConfigParser import ConfigParser
19
20 try:
21 import cStringIO as StringIO
22 except:
23 import StringIO
24
25 from twisted.internet import reactor
26 from twisted.mail import bounce, smtp
27
28 GLOBAL_CFG = "/etc/mailmail"
29 LOCAL_CFG = os.path.expanduser("~/.twisted/mailmail")
30 SMARTHOST = '127.0.0.1'
31
32 ERROR_FMT = """\
33 Subject: Failed Message Delivery
34
35 Message delivery failed. The following occurred:
36
37 %s
38 --
39 The Twisted sendmail application.
40 """
41
42 def log(message, *args):
43 sys.stderr.write(str(message) % args + '\n')
44
45 class Options:
46 """
47 @type to: C{list} of C{str}
48 @ivar to: The addresses to which to deliver this message.
49
50 @type sender: C{str}
51 @ivar sender: The address from which this message is being sent.
52
53 @type body: C{file}
54 @ivar body: The object from which the message is to be read.
55 """
56
57 def getlogin():
58 try:
59 return os.getlogin()
60 except:
61 return getpass.getuser()
62
63
64 def parseOptions(argv):
65 o = Options()
66 o.to = [e for e in argv if not e.startswith('-')]
67 o.sender = getlogin()
68
69 # Just be very stupid
70
71 # Skip -bm -- it is the default
72
73 # -bp lists queue information. Screw that.
74 if '-bp' in argv:
75 raise ValueError, "Unsupported option"
76
77 # -bs makes sendmail use stdin/stdout as its transport. Screw that.
78 if '-bs' in argv:
79 raise ValueError, "Unsupported option"
80
81 # -F sets who the mail is from, but is overridable by the From header
82 if '-F' in argv:
83 o.sender = argv[argv.index('-F') + 1]
84 o.to.remove(o.sender)
85
86 # -i and -oi makes us ignore lone "."
87 if ('-i' in argv) or ('-oi' in argv):
88 raise ValueError, "Unsupported option"
89
90 # -odb is background delivery
91 if '-odb' in argv:
92 o.background = True
93 else:
94 o.background = False
95
96 # -odf is foreground delivery
97 if '-odf' in argv:
98 o.background = False
99 else:
100 o.background = True
101
102 # -oem and -em cause errors to be mailed back to the sender.
103 # It is also the default.
104
105 # -oep and -ep cause errors to be printed to stderr
106 if ('-oep' in argv) or ('-ep' in argv):
107 o.printErrors = True
108 else:
109 o.printErrors = False
110
111 # -om causes a copy of the message to be sent to the sender if the sender
112 # appears in an alias expansion. We do not support aliases.
113 if '-om' in argv:
114 raise ValueError, "Unsupported option"
115
116 # -t causes us to pick the recipients of the message from the To, Cc, and Bc c
117 # headers, and to remove the Bcc header if present.
118 if '-t' in argv:
119 o.recipientsFromHeaders = True
120 o.excludeAddresses = o.to
121 o.to = []
122 else:
123 o.recipientsFromHeaders = False
124 o.exludeAddresses = []
125
126 requiredHeaders = {
127 'from': [],
128 'to': [],
129 'cc': [],
130 'bcc': [],
131 'date': [],
132 }
133
134 headers = []
135 buffer = StringIO.StringIO()
136 while 1:
137 write = 1
138 line = sys.stdin.readline()
139 if not line.strip():
140 break
141
142 hdrs = line.split(': ', 1)
143
144 hdr = hdrs[0].lower()
145 if o.recipientsFromHeaders and hdr in ('to', 'cc', 'bcc'):
146 o.to.extend([
147 a[1] for a in rfc822.AddressList(hdrs[1]).addresslist
148 ])
149 if hdr == 'bcc':
150 write = 0
151 elif hdr == 'from':
152 o.sender = rfc822.parseaddr(hdrs[1])[1]
153
154 if hdr in requiredHeaders:
155 requiredHeaders[hdr].append(hdrs[1])
156
157 if write:
158 buffer.write(line)
159
160 if not requiredHeaders['from']:
161 buffer.write('From: %s\r\n' % (o.sender,))
162 if not requiredHeaders['to']:
163 if not o.to:
164 raise ValueError, "No recipients specified"
165 buffer.write('To: %s\r\n' % (', '.join(o.to),))
166 if not requiredHeaders['date']:
167 buffer.write('Date: %s\r\n' % (smtp.rfc822date(),))
168
169 buffer.write(line)
170
171 if o.recipientsFromHeaders:
172 for a in o.excludeAddresses:
173 try:
174 o.to.remove(a)
175 except:
176 pass
177
178 buffer.seek(0, 0)
179 o.body = StringIO.StringIO(buffer.getvalue() + sys.stdin.read())
180 return o
181
182 class Configuration:
183 """
184 @ivar allowUIDs: A list of UIDs which are allowed to send mail.
185 @ivar allowGIDs: A list of GIDs which are allowed to send mail.
186 @ivar denyUIDs: A list of UIDs which are not allowed to send mail.
187 @ivar denyGIDs: A list of GIDs which are not allowed to send mail.
188
189 @type defaultAccess: C{bool}
190 @ivar defaultAccess: C{True} if access will be allowed when no other access
191 control rule matches or C{False} if it will be denied in that case.
192
193 @ivar useraccess: Either C{'allow'} to check C{allowUID} first
194 or C{'deny'} to check C{denyUID} first.
195
196 @ivar groupaccess: Either C{'allow'} to check C{allowGID} first or
197 C{'deny'} to check C{denyGID} first.
198
199 @ivar identities: A C{dict} mapping hostnames to credentials to use when
200 sending mail to that host.
201
202 @ivar smarthost: C{None} or a hostname through which all outgoing mail will
203 be sent.
204
205 @ivar domain: C{None} or the hostname with which to identify ourselves when
206 connecting to an MTA.
207 """
208 def __init__(self):
209 self.allowUIDs = []
210 self.denyUIDs = []
211 self.allowGIDs = []
212 self.denyGIDs = []
213 self.useraccess = 'deny'
214 self.groupaccess= 'deny'
215
216 self.identities = {}
217 self.smarthost = None
218 self.domain = None
219
220 self.defaultAccess = True
221
222
223 def loadConfig(path):
224 # [useraccess]
225 # allow=uid1,uid2,...
226 # deny=uid1,uid2,...
227 # order=allow,deny
228 # [groupaccess]
229 # allow=gid1,gid2,...
230 # deny=gid1,gid2,...
231 # order=deny,allow
232 # [identity]
233 # host1=username:password
234 # host2=username:password
235 # [addresses]
236 # smarthost=a.b.c.d
237 # default_domain=x.y.z
238
239 c = Configuration()
240
241 if not os.access(path, os.R_OK):
242 return c
243
244 p = ConfigParser()
245 p.read(path)
246
247 au = c.allowUIDs
248 du = c.denyUIDs
249 ag = c.allowGIDs
250 dg = c.denyGIDs
251 for (section, a, d) in (('useraccess', au, du), ('groupaccess', ag, dg)):
252 if p.has_section(section):
253 for (mode, L) in (('allow', a), ('deny', d)):
254 if p.has_option(section, mode) and p.get(section, mode):
255 for id in p.get(section, mode).split(','):
256 try:
257 id = int(id)
258 except ValueError:
259 log("Illegal %sID in [%s] section: %s", section[0].u pper(), section, id)
260 else:
261 L.append(id)
262 order = p.get(section, 'order')
263 order = map(str.split, map(str.lower, order.split(',')))
264 if order[0] == 'allow':
265 setattr(c, section, 'allow')
266 else:
267 setattr(c, section, 'deny')
268
269 if p.has_section('identity'):
270 for (host, up) in p.items('identity'):
271 parts = up.split(':', 1)
272 if len(parts) != 2:
273 log("Illegal entry in [identity] section: %s", up)
274 continue
275 p.identities[host] = parts
276
277 if p.has_section('addresses'):
278 if p.has_option('addresses', 'smarthost'):
279 c.smarthost = p.get('addresses', 'smarthost')
280 if p.has_option('addresses', 'default_domain'):
281 c.domain = p.get('addresses', 'default_domain')
282
283 return c
284
285 def success(result):
286 reactor.stop()
287
288 failed = None
289 def failure(f):
290 global failed
291 reactor.stop()
292 failed = f
293
294 def sendmail(host, options, ident):
295 d = smtp.sendmail(host, options.sender, options.to, options.body)
296 d.addCallbacks(success, failure)
297 reactor.run()
298
299 def senderror(failure, options):
300 recipient = [options.sender]
301 sender = '"Internally Generated Message (%s)"<postmaster@%s>' % (sys.argv[0] , smtp.DNSNAME)
302 error = StringIO.StringIO()
303 failure.printTraceback(file=error)
304 body = StringIO.StringIO(ERROR_FMT % error.getvalue())
305
306 d = smtp.sendmail('localhost', sender, recipient, body)
307 d.addBoth(lambda _: reactor.stop())
308
309 def deny(conf):
310 uid = os.getuid()
311 gid = os.getgid()
312
313 if conf.useraccess == 'deny':
314 if uid in conf.denyUIDs:
315 return True
316 if uid in conf.allowUIDs:
317 return False
318 else:
319 if uid in conf.allowUIDs:
320 return False
321 if uid in conf.denyUIDs:
322 return True
323
324 if conf.groupaccess == 'deny':
325 if gid in conf.denyGIDs:
326 return True
327 if gid in conf.allowGIDs:
328 return False
329 else:
330 if gid in conf.allowGIDs:
331 return False
332 if gid in conf.denyGIDs:
333 return True
334
335 return not conf.defaultAccess
336
337 def run():
338 o = parseOptions(sys.argv[1:])
339 gConf = loadConfig(GLOBAL_CFG)
340 lConf = loadConfig(LOCAL_CFG)
341
342 if deny(gConf) or deny(lConf):
343 log("Permission denied")
344 return
345
346 host = lConf.smarthost or gConf.smarthost or SMARTHOST
347
348 ident = gConf.identities.copy()
349 ident.update(lConf.identities)
350
351 if lConf.domain:
352 smtp.DNSNAME = lConf.domain
353 elif gConf.domain:
354 smtp.DNSNAME = gConf.domain
355
356 sendmail(host, o, ident)
357
358 if failed:
359 if o.printErrors:
360 failed.printTraceback(file=sys.stderr)
361 raise SystemExit(1)
362 else:
363 senderror(failed, o)
OLDNEW
« no previous file with comments | « third_party/twisted_8_1/twisted/mail/scripts/__init__.py ('k') | third_party/twisted_8_1/twisted/mail/smtp.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698