diff --git a/roundup/mailgw.py b/roundup/mailgw.py
index b624b1bc6f560e3cc6db156344d38166c9bd7855..3898051e4aa5b30229f4f77611126b3d190e9aa5 100644 (file)
--- a/roundup/mailgw.py
+++ b/roundup/mailgw.py
an exception, the original message is bounced back to the sender with the
explanatory message given in the exception.
-$Id: mailgw.py,v 1.62 2002-02-05 14:15:29 grubert Exp $
+$Id: mailgw.py,v 1.65 2002-02-15 00:13:38 richard Exp $
'''
return Message(s)
subject_re = re.compile(r'(?P<refwd>\s*\W?\s*(fwd|re|aw)\s*\W?\s*)*'
- r'\s*(\[(?P<classname>[^\d\s]+)(?P<nodeid>\d+)?\])'
+ r'\s*(\[(?P<classname>[^\d\s]+)(?P<nodeid>\d+)?\])?'
r'\s*(?P<title>[^[]+)?(\[(?P<args>.+?)\])?', re.I)
class MailGW:
writer.lastpart()
return msg
+ def get_part_data_decoded(self,part):
+ encoding = part.getencoding()
+ data = None
+ if encoding == 'base64':
+ # BUG: is base64 really used for text encoding or
+ # are we inserting zip files here.
+ data = binascii.a2b_base64(part.fp.read())
+ elif encoding == 'quoted-printable':
+ # the quopri module wants to work with files
+ decoded = cStringIO.StringIO()
+ quopri.decode(part.fp, decoded)
+ data = decoded.getvalue()
+ elif encoding == 'uuencoded':
+ data = binascii.a2b_uu(part.fp.read())
+ else:
+ # take it as text
+ data = part.fp.read()
+ return data
+
def handle_message(self, message):
''' message - a Message instance
raise MailUsageHelp
m = subject_re.match(subject)
+
+ # check for well-formed subject line
+ if m:
+ # get the classname
+ classname = m.group('classname')
+ if classname is None:
+ # no classname, fallback on the default
+ if hasattr(self.instance, 'MAIL_DEFAULT_CLASS') and \
+ self.instance.MAIL_DEFAULT_CLASS:
+ classname = self.instance.MAIL_DEFAULT_CLASS
+ else:
+ # fail
+ m = None
+
if not m:
raise MailUsageError, '''
The message you sent to roundup did not contain a properly formed subject
Subject was: "%s"
'''%subject
- # get the classname
- classname = m.group('classname')
+ # get the class
try:
cl = self.db.getclass(classname)
except KeyError:
# handle the users
#
- # Don't create users if ANONYMOUS_REGISTER is denied
- if self.instance.ANONYMOUS_REGISTER == 'deny':
+ # Don't create users if ANONYMOUS_REGISTER_MAIL is denied
+ # ... fall back on ANONYMOUS_REGISTER if the other doesn't exist
+ create = 1
+ if hasattr(self.instance, 'ANONYMOUS_REGISTER_MAIL'):
+ if self.instance.ANONYMOUS_REGISTER_MAIL == 'deny':
+ create = 0
+ elif self.instance.ANONYMOUS_REGISTER == 'deny':
create = 0
- else:
- create = 1
+
author = self.db.uidFromAddress(message.getaddrlist('from')[0],
create=create)
if not author:
#
content_type = message.gettype()
attachments = []
+ # General multipart handling:
+ # Take the first text/plain part, anything else is considered an
+ # attachment.
+ # multipart/mixed: multiple "unrelated" parts.
+ # multipart/signed (rfc 1847):
+ # The control information is carried in the second of the two
+ # required body parts.
+ # ACTION: Default, so if content is text/plain we get it.
+ # multipart/encrypted (rfc 1847):
+ # The control information is carried in the first of the two
+ # required body parts.
+ # ACTION: Not handleable as the content is encrypted.
+ # multipart/related (rfc 1872, 2112, 2387):
+ # The Multipart/Related content-type addresses the MIME representation
+ # of compound objects.
+ # ACTION: Default. If we are lucky there is a text/plain.
+ # TODO: One should use the start part and look for an Alternative
+ # that is text/plain.
+ # multipart/Alternative (rfc 1872, 1892):
+ # only in "related" ?
+ # multipart/report (rfc 1892):
+ # e.g. mail system delivery status reports.
+ # ACTION: Default. Could be ignored or used for Delivery Notification
+ # flagging.
+ # multipart/form-data:
+ # For web forms only.
if content_type == 'multipart/mixed':
# skip over the intro to the first boundary
part = message.getPart()
# parse it
subtype = part.gettype()
if subtype == 'text/plain' and not content:
- # add all text/plain parts to the message content
- # BUG (in code or comment) only add the first one.
- if content is None:
- # try name on Content-Type
- # maybe add name to non text content ?
- name = part.getparam('name')
- # assume first part is the mail
- encoding = part.getencoding()
- if encoding == 'base64':
- # BUG: is base64 really used for text encoding or
- # are we inserting zip files here.
- data = binascii.a2b_base64(part.fp.read())
- elif encoding == 'quoted-printable':
- # the quopri module wants to work with files
- decoded = cStringIO.StringIO()
- quopri.decode(part.fp, decoded)
- data = decoded.getvalue()
- elif encoding == 'uuencoded':
- data = binascii.a2b_uu(part.fp.read())
- else:
- # take it as text
- data = part.fp.read()
- content = data
- else:
- content = content + part.fp.read()
-
+ # The first text/plain part is the message content.
+ content = self.get_part_data_decoded(part)
elif subtype == 'message/rfc822':
# handle message/rfc822 specially - the name should be
# the subject of the actual e-mail embedded here
name = mailmess.getheader('subject')
part.fp.seek(i)
attachments.append((name, 'message/rfc822', part.fp.read()))
-
else:
# try name on Content-Type
name = part.getparam('name')
# this is just an attachment
- encoding = part.getencoding()
- if encoding == 'base64':
- data = binascii.a2b_base64(part.fp.read())
- elif encoding == 'quoted-printable':
- # the quopri module wants to work with files
- decoded = cStringIO.StringIO()
- quopri.decode(part.fp, decoded)
- data = decoded.getvalue()
- elif encoding == 'uuencoded':
- data = binascii.a2b_uu(part.fp.read())
+ data = self.get_part_data_decoded(part)
attachments.append((name, part.gettype(), data))
if content is None:
raise MailUsageError, '''
break
# parse it
if part.gettype() == 'text/plain' and not content:
- # this one's our content
- content = part.fp.read()
+ content = self.get_part_data_decoded(part)
if content is None:
raise MailUsageError, '''
Roundup requires the submission to be plain text. The message parser could
'''
else:
- encoding = message.getencoding()
- if encoding == 'base64':
- # BUG: is base64 really used for text encoding or
- # are we inserting zip files here.
- data = binascii.a2b_base64(message.fp.read())
- elif encoding == 'quoted-printable':
- # the quopri module wants to work with files
- decoded = cStringIO.StringIO()
- quopri.decode(message.fp, decoded)
- data = decoded.getvalue()
- elif encoding == 'uuencoded':
- data = binascii.a2b_uu(message.fp.read())
- else:
- # take it as text
- data = message.fp.read()
- content = data
+ content = self.get_part_data_decoded(message)
summary, content = parseContent(content)
#
# $Log: not supported by cvs2svn $
+# Revision 1.64 2002/02/14 23:46:02 richard
+# . #516883 ] mail interface + ANONYMOUS_REGISTER
+#
+# Revision 1.63 2002/02/12 08:08:55 grubert
+# . Clean up mail handling, multipart handling.
+#
+# Revision 1.62 2002/02/05 14:15:29 grubert
+# . respect encodings in non multipart messages.
+#
# Revision 1.61 2002/02/04 09:40:21 grubert
# . add test for multipart messages with first part being encoded.
#