Mercurial > p > roundup > code
annotate roundup-mailgw.py @ 10:e09edaebc9de
added more todo items
| author | Anthony Baxter <anthonybaxter@users.sourceforge.net> |
|---|---|
| date | Thu, 19 Jul 2001 06:37:07 +0000 |
| parents | 3b0a72f54613 |
| children |
| rev | line source |
|---|---|
|
0
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
1 #! /usr/bin/python |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
2 ''' |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
3 Incoming messages are examined for multiple parts. In a multipart/mixed |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
4 message or part, each subpart is extracted and examined. In a |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
5 multipart/alternative message or part, we look for a text/plain subpart and |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
6 ignore the other parts. The text/plain subparts are assembled to form the |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
7 textual body of the message, to be stored in the file associated with a |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
8 "msg" class node. Any parts of other types are each stored in separate |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
9 files and given "file" class nodes that are linked to the "msg" node. |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
10 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
11 The "summary" property on message nodes is taken from the first non-quoting |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
12 section in the message body. The message body is divided into sections by |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
13 blank lines. Sections where the second and all subsequent lines begin with |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
14 a ">" or "|" character are considered "quoting sections". The first line of |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
15 the first non-quoting section becomes the summary of the message. |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
16 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
17 All of the addresses in the To: and Cc: headers of the incoming message are |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
18 looked up among the user nodes, and the corresponding users are placed in |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
19 the "recipients" property on the new "msg" node. The address in the From: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
20 header similarly determines the "author" property of the new "msg" |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
21 node. The default handling for addresses that don't have corresponding |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
22 users is to create new users with no passwords and a username equal to the |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
23 address. (The web interface does not permit logins for users with no |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
24 passwords.) If we prefer to reject mail from outside sources, we can simply |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
25 register an auditor on the "user" class that prevents the creation of user |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
26 nodes with no passwords. |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
27 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
28 The subject line of the incoming message is examined to determine whether |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
29 the message is an attempt to create a new item or to discuss an existing |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
30 item. A designator enclosed in square brackets is sought as the first thing |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
31 on the subject line (after skipping any "Fwd:" or "Re:" prefixes). |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
32 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
33 If an item designator (class name and id number) is found there, the newly |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
34 created "msg" node is added to the "messages" property for that item, and |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
35 any new "file" nodes are added to the "files" property for the item. |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
36 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
37 If just an item class name is found there, we attempt to create a new item |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
38 of that class with its "messages" property initialized to contain the new |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
39 "msg" node and its "files" property initialized to contain any new "file" |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
40 nodes. |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
41 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
42 Both cases may trigger detectors (in the first case we are calling the |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
43 set() method to add the message to the item's spool; in the second case we |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
44 are calling the create() method to create a new node). If an auditor raises |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
45 an exception, the original message is bounced back to the sender with the |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
46 explanatory message given in the exception. |
|
5
72a0ba086b3e
Added CVS keywords $Id$ and $Log$ to all python files.
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
0
diff
changeset
|
47 |
|
9
3b0a72f54613
fixing (manually) the (dollarsign)Log(dollarsign)...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
5
diff
changeset
|
48 $Id: roundup-mailgw.py,v 1.3 2001-07-19 06:27:07 anthonybaxter Exp $ |
|
0
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
49 ''' |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
50 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
51 import sys |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
52 if int(sys.version[0]) < 2: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
53 print "Roundup requires Python 2.0 or newer." |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
54 sys.exit(0) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
55 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
56 import string, re, os, mimetools, StringIO, smtplib, socket, binascii, quopri |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
57 import config, date, roundupdb |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
58 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
59 def getPart(fp, boundary): |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
60 line = '' |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
61 s = StringIO.StringIO() |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
62 while 1: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
63 line_n = fp.readline() |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
64 if not line_n: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
65 break |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
66 line = line_n.strip() |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
67 if line == '--'+boundary+'--': |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
68 break |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
69 if line == '--'+boundary: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
70 break |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
71 s.write(line_n) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
72 if not s.getvalue().strip(): |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
73 return None |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
74 return s |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
75 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
76 subject_re = re.compile(r'(\[?(fwd|re):\s*)*' |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
77 r'(\[(?P<classname>[^\d]+)(?P<nodeid>\d+)?\])' |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
78 r'(?P<title>[^\[]+)(\[(?P<args>.+?)\])?', re.I) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
79 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
80 def roundup_mail(db, fp): |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
81 # ok, figure the subject, author, recipients and content-type |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
82 message = mimetools.Message(fp) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
83 try: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
84 handle_message(db, message) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
85 except: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
86 # send an email to the people who missed out |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
87 sendto = [message.getaddrlist('from')[0][1]] |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
88 m = ['Subject: failed issue tracker submission'] |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
89 m.append('') |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
90 # TODO as attachments? |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
91 m.append('---- traceback of failure ----') |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
92 return |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
93 s = StringIO.StringIO() |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
94 import traceback |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
95 traceback.print_exc(None, s) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
96 m.append(s.getvalue()) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
97 m.append('---- failed message follows ----') |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
98 try: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
99 fp.seek(0) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
100 except: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
101 pass |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
102 m.append(fp.read()) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
103 try: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
104 smtp = smtplib.SMTP(config.MAILHOST) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
105 smtp.sendmail(config.ADMIN_EMAIL, sendto, '\n'.join(m)) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
106 except socket.error, value: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
107 return "Couldn't send confirmation email: mailhost %s"%value |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
108 except smtplib.SMTPException, value: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
109 return "Couldn't send confirmation email: %s"%value |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
110 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
111 def handle_message(db, message): |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
112 # handle the subject line |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
113 m = subject_re.match(message.getheader('subject')) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
114 if not m: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
115 raise ValueError, 'No [designator] found in subject "%s"' |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
116 classname = m.group('classname') |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
117 nodeid = m.group('nodeid') |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
118 title = m.group('title').strip() |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
119 subject_args = m.group('args') |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
120 cl = db.getclass(classname) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
121 properties = cl.getprops() |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
122 props = {} |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
123 args = m.group('args') |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
124 if args: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
125 for prop in string.split(m.group('args'), ';'): |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
126 try: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
127 key, value = prop.split('=') |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
128 except ValueError, message: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
129 raise ValueError, 'Args list not of form [arg=value,value,...;arg=value,value,value..] (specific exception message was "%s")'%message |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
130 type = properties[key] |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
131 if type.isStringType: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
132 props[key] = value |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
133 elif type.isDateType: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
134 props[key] = date.Date(value) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
135 elif type.isIntervalType: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
136 props[key] = date.Interval(value) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
137 elif type.isLinkType: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
138 props[key] = value |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
139 elif type.isMultilinkType: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
140 props[key] = value.split(',') |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
141 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
142 # handle the users |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
143 author = db.uidFromAddress(message.getaddrlist('from')[0]) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
144 recipients = [] |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
145 for recipient in message.getaddrlist('to') + message.getaddrlist('cc'): |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
146 if recipient[1].strip().lower() == config.ISSUE_TRACKER_EMAIL: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
147 continue |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
148 recipients.append(db.uidFromAddress(recipient)) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
149 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
150 # now handle the body - find the message |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
151 content_type = message.gettype() |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
152 attachments = [] |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
153 if content_type == 'multipart/mixed': |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
154 boundary = message.getparam('boundary') |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
155 # skip over the intro to the first boundary |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
156 part = getPart(message.fp, boundary) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
157 content = None |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
158 while 1: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
159 # get the next part |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
160 part = getPart(message.fp, boundary) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
161 if part is None: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
162 break |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
163 # parse it |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
164 part.seek(0) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
165 submessage = mimetools.Message(part) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
166 subtype = submessage.gettype() |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
167 if subtype == 'text/plain' and not content: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
168 # this one's our content |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
169 content = part.read() |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
170 elif subtype == 'message/rfc822': |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
171 i = part.tell() |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
172 subsubmess = mimetools.Message(part) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
173 name = subsubmess.getheader('subject') |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
174 part.seek(i) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
175 attachments.append((name, 'message/rfc822', part.read())) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
176 else: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
177 # try name on Content-Type |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
178 name = submessage.getparam('name') |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
179 # this is just an attachment |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
180 data = part.read() |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
181 encoding = submessage.getencoding() |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
182 if encoding == 'base64': |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
183 data = binascii.a2b_base64(data) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
184 elif encoding == 'quoted-printable': |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
185 data = quopri.decode(data) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
186 elif encoding == 'uuencoded': |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
187 data = binascii.a2b_uu(data) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
188 attachments.append((name, submessage.gettype(), data)) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
189 if content is None: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
190 raise ValueError, 'No text/plain part found' |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
191 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
192 elif content_type[:10] == 'multipart/': |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
193 boundary = message.getparam('boundary') |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
194 # skip over the intro to the first boundary |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
195 getPart(message.fp, boundary) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
196 content = None |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
197 while 1: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
198 # get the next part |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
199 part = getPart(message.fp, boundary) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
200 if part is None: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
201 break |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
202 # parse it |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
203 part.seek(0) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
204 submessage = mimetools.Message(part) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
205 if submessage.gettype() == 'text/plain' and not content: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
206 # this one's our content |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
207 content = part.read() |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
208 if content is None: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
209 raise ValueError, 'No text/plain part found' |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
210 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
211 elif content_type != 'text/plain': |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
212 raise ValueError, 'No text/plain part found' |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
213 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
214 else: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
215 content = message.fp.read() |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
216 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
217 # extract out the summary from the message |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
218 summary = [] |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
219 for line in content.split('\n'): |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
220 line = line.strip() |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
221 if summary and not line: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
222 break |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
223 if not line: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
224 summary.append('') |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
225 elif line[0] not in '>|': |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
226 summary.append(line) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
227 summary = '\n'.join(summary) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
228 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
229 # handle the files |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
230 files = [] |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
231 for (name, type, data) in attachments: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
232 files.append(db.file.create(type=type, name=name, content=data)) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
233 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
234 # now handle the db stuff |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
235 if nodeid: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
236 # If an item designator (class name and id number) is found there, the |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
237 # newly created "msg" node is added to the "messages" property for |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
238 # that item, and any new "file" nodes are added to the "files" |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
239 # property for the item. |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
240 message_id = db.msg.create(author=author, recipients=recipients, |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
241 date=date.Date('.'), summary=summary, content=content, |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
242 files=files) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
243 messages = cl.get(nodeid, 'messages') |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
244 messages.append(message_id) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
245 props['messages'] = messages |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
246 apply(cl.set, (nodeid, ), props) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
247 else: |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
248 # If just an item class name is found there, we attempt to create a |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
249 # new item of that class with its "messages" property initialized to |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
250 # contain the new "msg" node and its "files" property initialized to |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
251 # contain any new "file" nodes. |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
252 message_id = db.msg.create(author=author, recipients=recipients, |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
253 date=date.Date('.'), summary=summary, content=content, |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
254 files=files) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
255 if not props.has_key('assignedto'): |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
256 props['assignedto'] = 1 # "admin" |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
257 if not props.has_key('priority'): |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
258 props['priority'] = 1 # "bug-fatal" |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
259 if not props.has_key('status'): |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
260 props['status'] = 1 # "unread" |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
261 if not props.has_key('title'): |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
262 props['title'] = title |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
263 props['messages'] = [message_id] |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
264 props['nosy'] = recipients[:] |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
265 props['nosy'].append(author) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
266 props['nosy'].sort() |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
267 nodeid = apply(cl.create, (), props) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
268 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
269 return 0 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
270 |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
271 if __name__ == '__main__': |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
272 db = roundupdb.openDB(config.DATABASE, 'admin', '1') |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
273 roundup_mail(db, sys.stdin) |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
274 db.close() |
|
5e92642cd1f8
Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
275 |
|
5
72a0ba086b3e
Added CVS keywords $Id$ and $Log$ to all python files.
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
0
diff
changeset
|
276 # |
|
72a0ba086b3e
Added CVS keywords $Id$ and $Log$ to all python files.
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
0
diff
changeset
|
277 # $Log: not supported by cvs2svn $ |
|
9
3b0a72f54613
fixing (manually) the (dollarsign)Log(dollarsign)...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
5
diff
changeset
|
278 # Revision 1.2 2001/07/19 05:52:22 anthonybaxter |
|
3b0a72f54613
fixing (manually) the (dollarsign)Log(dollarsign)...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
5
diff
changeset
|
279 # Added CVS keywords Id and Log to all python files. |
|
3b0a72f54613
fixing (manually) the (dollarsign)Log(dollarsign)...
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
5
diff
changeset
|
280 # |
|
5
72a0ba086b3e
Added CVS keywords $Id$ and $Log$ to all python files.
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
0
diff
changeset
|
281 # |
|
72a0ba086b3e
Added CVS keywords $Id$ and $Log$ to all python files.
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents:
0
diff
changeset
|
282 |
