Attempt to make Mailman leave signatures intact. Submessage parts will not get headers folded if the new Mailman.Generator.Generator class is used. Hopefully fixes, Mailman SF Bug: [ 815297 ] Breaking signatures in message/rfc822 attachement! Removed unused class ScrubberGenerator from Handlers/Scrupper.py along the way. It irritated me while searching for the solution. 20040412 Bernhard Reiter diff -ru --new-file mailman-2.1.4-1/Mailman/Generator.py mailman-2.1.4/Mailman/Generator.py --- mailman-2.1.4-1/Mailman/Generator.py 1970-01-01 01:00:00.000000000 +0100 +++ mailman-2.1.4/Mailman/Generator.py 2004-04-12 17:58:55.000000000 +0200 @@ -0,0 +1,58 @@ +# Copyright (C) 1998-2003 by the Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# Author: Bernhard Reiter + +"""Standard Mailman generator object. + +A subclass of email.Generator which only folds long headers +in the top object level. +This is needed because Mailman should leave the reveiced message parts alone. +Otherwise is might change subparts over which a signature was calculated, +breaking it while doing so. +""" + +import email +import email.Generator + + +class Generator(email.Generator.Generator): + """Generates output from a Message object tree, keeping signatures. + + Using the a trick from Mailman/Handlers/Scrubber.py (revs 2.0-2.15): + + Most other Generator will be created not setting the foldheader flag, + as we do not overwrite clone(). The original clone() does not + set foldheaders. + + So you need to set foldheaders if you want the toplevel to fold headers. + """ + def __init__(self, outfp, mangle_from_=True, + maxheaderlen=78, foldheaders=False): + email.Generator.Generator.__init__(self, outfp, mangle_from_=False) + self.__foldheaders = foldheaders + + def _write_headers(self, msg): + if self.__foldheaders: + email.Generator.Generator._write_headers(self, msg) + else: + # the following is + # unrolled from email.Generator.Generator._write_headers() + for h, v in msg.items(): + print >> self._fp, '%s:' % h, + print >> self._fp, v + print >> self._fp + diff -ru --new-file mailman-2.1.4-1/Mailman/Handlers/Scrubber.py mailman-2.1.4/Mailman/Handlers/Scrubber.py --- mailman-2.1.4-1/Mailman/Handlers/Scrubber.py 2004-04-12 16:27:40.000000000 +0200 +++ mailman-2.1.4/Mailman/Handlers/Scrubber.py 2004-04-12 17:54:27.000000000 +0200 @@ -90,26 +90,6 @@ -# We're using a subclass of the standard Generator because we want to suppress -# headers in the subparts of multiparts. We use a hack -- the ctor argument -# skipheaders to accomplish this. It's set to true for the outer Message -# object, but false for all internal objects. We recognize that -# sub-Generators will get created passing only mangle_from_ and maxheaderlen -# to the ctors. -# -# This isn't perfect because we still get stuff like the multipart boundaries, -# but see below for how we corrupt that to our nefarious goals. -class ScrubberGenerator(Generator): - def __init__(self, outfp, mangle_from_=True, - maxheaderlen=78, skipheaders=True): - Generator.__init__(self, outfp, mangle_from_=False) - self.__skipheaders = skipheaders - - def _write_headers(self, msg): - if not self.__skipheaders: - Generator._write_headers(self, msg) - - def safe_strftime(fmt, floatsecs): try: return time.strftime(fmt, floatsecs) diff -ru --new-file mailman-2.1.4-1/Mailman/Mailbox.py mailman-2.1.4/Mailman/Mailbox.py --- mailman-2.1.4-1/Mailman/Mailbox.py 2003-04-19 06:57:14.000000000 +0200 +++ mailman-2.1.4/Mailman/Mailbox.py 2004-04-12 18:00:39.000000000 +0200 @@ -22,10 +22,10 @@ import email from email.Parser import Parser -from email.Generator import Generator from email.Errors import MessageParseError from Mailman import mm_cfg +from Mailman.Generator import Generator from Mailman.Message import Message try: @@ -65,7 +65,7 @@ # Seek to the last char of the mailbox self.fp.seek(1, 2) # Create a Generator instance to write the message to the file - g = Generator(self.fp) + g = Generator(self.fp, foldheaders=True) g.flatten(msg, unixfrom=True) # Add one more trailing newline for separation with the next message # to be appended to the mbox. diff -ru --new-file mailman-2.1.4-1/Mailman/Message.py mailman-2.1.4/Mailman/Message.py --- mailman-2.1.4-1/Mailman/Message.py 2003-03-31 23:49:38.000000000 +0200 +++ mailman-2.1.4/Mailman/Message.py 2004-04-12 18:00:15.000000000 +0200 @@ -21,6 +21,8 @@ """ import re +from cStringIO import StringIO + import email import email.Message import email.Utils @@ -31,6 +33,7 @@ from Mailman import mm_cfg from Mailman import Utils +from Mailman.Generator import Generator COMMASPACE = ', ' @@ -188,6 +191,18 @@ authors.append(address) return authors + def as_string(self, unixfrom=False): + """Return entire formatted message as a string using Mailman.Generator. + + Operates like email.Message.Message.as_string, only + using Mailman's Generator class. Only the top headers will get folded. + """ + fp = StringIO() + g = Generator(fp, foldheaders=True) + g.flatten(self, unixfrom=unixfrom) + return fp.getvalue() + + class UserNotification(Message):