@@ -73,7 +73,7 @@ class node. Any parts of other types are each stored in separate files
7373an exception, the original message is bounced back to the sender with the
7474explanatory message given in the exception.
7575
76- $Id: mailgw.py,v 1.62 2002-02-05 14:15:29 grubert Exp $
76+ $Id: mailgw.py,v 1.63 2002-02-12 08:08:55 grubert Exp $
7777'''
7878
7979
@@ -261,6 +261,25 @@ def bounce_message(self, message, sendto, error,
261261 writer .lastpart ()
262262 return msg
263263
264+ def get_part_data_decoded (self ,part ):
265+ encoding = part .getencoding ()
266+ data = None
267+ if encoding == 'base64' :
268+ # BUG: is base64 really used for text encoding or
269+ # are we inserting zip files here.
270+ data = binascii .a2b_base64 (part .fp .read ())
271+ elif encoding == 'quoted-printable' :
272+ # the quopri module wants to work with files
273+ decoded = cStringIO .StringIO ()
274+ quopri .decode (part .fp , decoded )
275+ data = decoded .getvalue ()
276+ elif encoding == 'uuencoded' :
277+ data = binascii .a2b_uu (part .fp .read ())
278+ else :
279+ # take it as text
280+ data = part .fp .read ()
281+ return data
282+
264283 def handle_message (self , message ):
265284 ''' message - a Message instance
266285
@@ -474,6 +493,32 @@ def handle_message(self, message):
474493 #
475494 content_type = message .gettype ()
476495 attachments = []
496+ # General multipart handling:
497+ # Take the first text/plain part, anything else is considered an
498+ # attachment.
499+ # multipart/mixed: multiple "unrelated" parts.
500+ # multipart/signed (rfc 1847):
501+ # The control information is carried in the second of the two
502+ # required body parts.
503+ # ACTION: Default, so if content is text/plain we get it.
504+ # multipart/encrypted (rfc 1847):
505+ # The control information is carried in the first of the two
506+ # required body parts.
507+ # ACTION: Not handleable as the content is encrypted.
508+ # multipart/related (rfc 1872, 2112, 2387):
509+ # The Multipart/Related content-type addresses the MIME representation
510+ # of compound objects.
511+ # ACTION: Default. If we are lucky there is a text/plain.
512+ # TODO: One should use the start part and look for an Alternative
513+ # that is text/plain.
514+ # multipart/Alternative (rfc 1872, 1892):
515+ # only in "related" ?
516+ # multipart/report (rfc 1892):
517+ # e.g. mail system delivery status reports.
518+ # ACTION: Default. Could be ignored or used for Delivery Notification
519+ # flagging.
520+ # multipart/form-data:
521+ # For web forms only.
477522 if content_type == 'multipart/mixed' :
478523 # skip over the intro to the first boundary
479524 part = message .getPart ()
@@ -486,32 +531,8 @@ def handle_message(self, message):
486531 # parse it
487532 subtype = part .gettype ()
488533 if subtype == 'text/plain' and not content :
489- # add all text/plain parts to the message content
490- # BUG (in code or comment) only add the first one.
491- if content is None :
492- # try name on Content-Type
493- # maybe add name to non text content ?
494- name = part .getparam ('name' )
495- # assume first part is the mail
496- encoding = part .getencoding ()
497- if encoding == 'base64' :
498- # BUG: is base64 really used for text encoding or
499- # are we inserting zip files here.
500- data = binascii .a2b_base64 (part .fp .read ())
501- elif encoding == 'quoted-printable' :
502- # the quopri module wants to work with files
503- decoded = cStringIO .StringIO ()
504- quopri .decode (part .fp , decoded )
505- data = decoded .getvalue ()
506- elif encoding == 'uuencoded' :
507- data = binascii .a2b_uu (part .fp .read ())
508- else :
509- # take it as text
510- data = part .fp .read ()
511- content = data
512- else :
513- content = content + part .fp .read ()
514-
534+ # The first text/plain part is the message content.
535+ content = self .get_part_data_decoded (part )
515536 elif subtype == 'message/rfc822' :
516537 # handle message/rfc822 specially - the name should be
517538 # the subject of the actual e-mail embedded here
@@ -520,21 +541,11 @@ def handle_message(self, message):
520541 name = mailmess .getheader ('subject' )
521542 part .fp .seek (i )
522543 attachments .append ((name , 'message/rfc822' , part .fp .read ()))
523-
524544 else :
525545 # try name on Content-Type
526546 name = part .getparam ('name' )
527547 # this is just an attachment
528- encoding = part .getencoding ()
529- if encoding == 'base64' :
530- data = binascii .a2b_base64 (part .fp .read ())
531- elif encoding == 'quoted-printable' :
532- # the quopri module wants to work with files
533- decoded = cStringIO .StringIO ()
534- quopri .decode (part .fp , decoded )
535- data = decoded .getvalue ()
536- elif encoding == 'uuencoded' :
537- data = binascii .a2b_uu (part .fp .read ())
548+ data = self .get_part_data_decoded (part )
538549 attachments .append ((name , part .gettype (), data ))
539550 if content is None :
540551 raise MailUsageError , '''
@@ -553,8 +564,7 @@ def handle_message(self, message):
553564 break
554565 # parse it
555566 if part .gettype () == 'text/plain' and not content :
556- # this one's our content
557- content = part .fp .read ()
567+ content = self .get_part_data_decoded (part )
558568 if content is None :
559569 raise MailUsageError , '''
560570Roundup requires the submission to be plain text. The message parser could
@@ -568,22 +578,7 @@ def handle_message(self, message):
568578'''
569579
570580 else :
571- encoding = message .getencoding ()
572- if encoding == 'base64' :
573- # BUG: is base64 really used for text encoding or
574- # are we inserting zip files here.
575- data = binascii .a2b_base64 (message .fp .read ())
576- elif encoding == 'quoted-printable' :
577- # the quopri module wants to work with files
578- decoded = cStringIO .StringIO ()
579- quopri .decode (message .fp , decoded )
580- data = decoded .getvalue ()
581- elif encoding == 'uuencoded' :
582- data = binascii .a2b_uu (message .fp .read ())
583- else :
584- # take it as text
585- data = message .fp .read ()
586- content = data
581+ content = self .get_part_data_decoded (message )
587582
588583 summary , content = parseContent (content )
589584
@@ -791,6 +786,9 @@ def parseContent(content, blank_line=re.compile(r'[\r\n]+\s*[\r\n]+'),
791786
792787#
793788# $Log: not supported by cvs2svn $
789+ # Revision 1.62 2002/02/05 14:15:29 grubert
790+ # . respect encodings in non multipart messages.
791+ #
794792# Revision 1.61 2002/02/04 09:40:21 grubert
795793# . add test for multipart messages with first part being encoded.
796794#
0 commit comments