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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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

Roundup Issue Tracker: http://roundup-tracker.org/