From e9fddb3a006bae8de058508f8ab5d3e0ca289ffa Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Fri, 21 Sep 2007 15:22:15 -0700 Subject: It is reported that some RedHat packages (for at least FC5 and FC6, but not FC7) contain a full working distutils in the 'python' package, but only contain the Python header files in the 'python-devel' package. This allows configure to succeed, but make install fails to setup the japanese and korean codecs. This change adds a specific test for Python.h to the distutils test. --- configure.in | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/configure.in b/configure.in index 55454148..b97df6d2 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -# Copyright (C) 1998-2006 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2007 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 @@ -101,7 +101,14 @@ else: except distutils.errors.DistutilsPlatformError: res = "no" else: - res = "yes" + # some RedHat packages put distutils in python, but the C headers + # are in python-devel so check for headers too. + import os.path + pdothpath = distutils.sysconfig.get_config_var('CONFINCLUDEPY') + if os.path.isfile(os.path.join(pdothpath, "Python.h")): + res = "yes" + else: + res = "no" fp = open("conftest.out", "w") fp.write("%s\n" % res) fp.close() @@ -117,7 +124,8 @@ then ***** Distutils is not available or is incomplete for $PYTHON ***** If you installed Python from RPM (or other package manager) ***** be sure to install the -devel package, or install Python -***** from source. See README.LINUX for details]) +***** from source. See sec. 15.1 of the Installation Manual for +***** details]) fi AC_MSG_RESULT($havedistutils) -- cgit v1.2.3 From 7678305d8118c9839ad67624c203426c4dc384f2 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Fri, 21 Sep 2007 15:41:19 -0700 Subject: It is reported that some RedHat packages (for at least FC5 and FC6, but not FC7) contain a full working distutils in the 'python' package, but only contain the Python header files in the 'python-devel' package. This allows configure to succeed, but make install fails to setup the japanese and korean codecs. This change adds a specific test for Python.h to the distutils test. --- configure | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/configure b/configure index 075541ca..3f05770b 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 7462 . +# From configure.in Revision: 8122 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59. # @@ -1446,7 +1446,14 @@ else: except distutils.errors.DistutilsPlatformError: res = "no" else: - res = "yes" + # some RedHat packages put distutils in python, but the C headers + # are in python-devel so check for headers too. + import os.path + pdothpath = distutils.sysconfig.get_config_var('CONFINCLUDEPY') + if os.path.isfile(os.path.join(pdothpath, "Python.h")): + res = "yes" + else: + res = "no" fp = open("conftest.out", "w") fp.write("%s\n" % res) fp.close() @@ -1462,13 +1469,15 @@ then ***** Distutils is not available or is incomplete for $PYTHON ***** If you installed Python from RPM (or other package manager) ***** be sure to install the -devel package, or install Python -***** from source. See README.LINUX for details" >&5 +***** from source. See sec. 15.1 of the Installation Manual for +***** details" >&5 echo "$as_me: error: ***** Distutils is not available or is incomplete for $PYTHON ***** If you installed Python from RPM (or other package manager) ***** be sure to install the -devel package, or install Python -***** from source. See README.LINUX for details" >&2;} +***** from source. See sec. 15.1 of the Installation Manual for +***** details" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: $havedistutils" >&5 @@ -4369,9 +4378,10 @@ for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_i=`echo "$ac_i" | sed 's/\$U\././;s/\.o$//;s/\.obj$//'` - # 2. Add them. - ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" - ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs -- cgit v1.2.3 From 3528bd1bc8995c31efd6863bdc70d37fa23a31b1 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Thu, 4 Oct 2007 18:35:10 -0700 Subject: /cygdrive/c/MM_bzr/log.txt --- Mailman/versions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Mailman/versions.py b/Mailman/versions.py index eff8ffdb..8a9887b6 100644 --- a/Mailman/versions.py +++ b/Mailman/versions.py @@ -483,10 +483,11 @@ def NewRequestsDatabase(l): # blow away the original timestamp and request id. This means the # request will live a little longer than it possibly should have, # but that's no big deal. + import email for p in v: author, text = p[2] reason = p[3] - msg = Message.OutgoingMessage(text) + msg = email.message_from_string(text, Message.Message) l.HoldMessage(msg, reason) del r[k] elif k == 'add_member': -- cgit v1.2.3 From 8b49009b2ae78b216f6bc9919875e52d0694908a Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Thu, 4 Oct 2007 18:40:13 -0700 Subject: /cygdrive/c/MM_bzr/log.txt --- Mailman/Queue/MaildirRunner.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) mode change 100644 => 100755 Mailman/Queue/MaildirRunner.py diff --git a/Mailman/Queue/MaildirRunner.py b/Mailman/Queue/MaildirRunner.py old mode 100644 new mode 100755 index 39971ae2..d9fe02cb --- a/Mailman/Queue/MaildirRunner.py +++ b/Mailman/Queue/MaildirRunner.py @@ -1,4 +1,4 @@ -# Copyright (C) 2002 by the Free Software Foundation, Inc. +# Copyright (C) 2002-2007 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 @@ -12,7 +12,8 @@ # # 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. """Maildir pre-queue runner. @@ -66,11 +67,22 @@ from Mailman.Logging.Syslog import syslog # listname-request@ lre = re.compile(r""" ^ # start of string - (?P[^-@]+) # listname@ or listname-subq@ + (?P[^+@]+?) # listname@ or listname-subq@ (non-greedy) (?: # non-grouping - # dash separator - (?P[^-+@]+) # everything up to + or - or @ + (?P # any known suffix + admin| + bounces| + confirm| + join| + leave| + owner| + request| + subscribe| + unsubscribe + ) )? # if it exists + [+@] # followed by + or @ """, re.VERBOSE | re.IGNORECASE) -- cgit v1.2.3 From 6789acf6fcc94a2998dda7b4665659bf53749b66 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Thu, 4 Oct 2007 18:43:42 -0700 Subject: /cygdrive/c/MM_bzr/log.txt --- Mailman/Handlers/MimeDel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mailman/Handlers/MimeDel.py b/Mailman/Handlers/MimeDel.py index 906b12c3..01b126a8 100644 --- a/Mailman/Handlers/MimeDel.py +++ b/Mailman/Handlers/MimeDel.py @@ -256,4 +256,4 @@ def get_file_ext(m): fext = fext[1:] else: fext = '' - return fext + return fext.lower() -- cgit v1.2.3 From eaa5edc3b9319c5d3d89abbd44edd27b70678ee7 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Thu, 4 Oct 2007 19:50:56 -0700 Subject: In rare cases, versions.py can encounter a very old list with held posts in its requests dictionary. It then tries to create a Message.OutgoingMessage object from the message text, but that class no longer exists. Fixed by using email.message_from_string() instead. --- Mailman/versions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mailman/versions.py b/Mailman/versions.py index 8a9887b6..cffe5c6a 100644 --- a/Mailman/versions.py +++ b/Mailman/versions.py @@ -1,4 +1,4 @@ -# Copyright (C) 1998-2005 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2007 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 -- cgit v1.2.3 From 73937af15be2c44c97a1b9d64c09d83d68d9b2bd Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Thu, 4 Oct 2007 19:52:04 -0700 Subject: MimeDel.py neglected to lower case file extensions for comparison with lower cased *_filename_extensions. Fixed. --- Mailman/Handlers/MimeDel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mailman/Handlers/MimeDel.py b/Mailman/Handlers/MimeDel.py index 01b126a8..523b3dfc 100644 --- a/Mailman/Handlers/MimeDel.py +++ b/Mailman/Handlers/MimeDel.py @@ -1,4 +1,4 @@ -# Copyright (C) 2002-2005 by the Free Software Foundation, Inc. +# Copyright (C) 2002-2007 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 -- cgit v1.2.3 -- cgit v1.2.3 From 255f1f88d6bebb782d8e806ee6e69314322c46c9 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Mon, 8 Oct 2007 22:06:49 -0400 Subject: Added a .bzrignore to ignore generated files. --- .bzrignore | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .bzrignore diff --git a/.bzrignore b/.bzrignore new file mode 100644 index 00000000..f602e80c --- /dev/null +++ b/.bzrignore @@ -0,0 +1,23 @@ +Mailman/Defaults.py +Mailman/mm_cfg.py.dist +build +config.log +config.status +cron/crontab.in +misc/JapaneseCodecs-1.4.11 +misc/KoreanCodecs-2.0.5 +misc/email-2.5.8 +misc/mailman +misc/paths.py +src/admin +src/admindb +src/confirm +src/create +src/edithtml +src/listinfo +src/mailman +src/options +src/private +src/rmlist +src/roster +src/subscribe -- cgit v1.2.3 From a4f9e4406bbf6114b6f7092acb63d93008680af9 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Thu, 18 Oct 2007 13:29:49 -0700 Subject: Added a call to warnings.filterwarnings() to misc/paths.py.in to supress the Python 2.5 DeprecationWarning on string exceptions. --- misc/paths.py.in | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/misc/paths.py.in b/misc/paths.py.in index 3566a12c..bbf18fc7 100644 --- a/misc/paths.py.in +++ b/misc/paths.py.in @@ -1,6 +1,6 @@ # -*- python -*- -# Copyright (C) 1998-2005 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2007 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 @@ -24,8 +24,9 @@ # attributes that other modules may use to get the absolute path to the # installed Mailman distribution. -import sys import os +import sys +from warnings import filterwarnings # some scripts expect this attribute to be in this module prefix = '@prefix@' @@ -35,6 +36,9 @@ exec_prefix = '@exec_prefix@' if exec_prefix == '${prefix}': exec_prefix = prefix +# Supress Python 2.5 warning about string exceptions. +filterwarnings('ignore', '.* string exception', DeprecationWarning) + # Check if ja/ko codecs are available before changing path. try: s = unicode('OK', 'iso-2022-jp') -- cgit v1.2.3 From fde2d5db792436aeedcb1e18307ff4ea85ca9343 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Thu, 18 Oct 2007 13:34:36 -0700 Subject: MailList.Create() - added an assertion that the listname is lower case. --- Mailman/MailList.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Mailman/MailList.py b/Mailman/MailList.py index e07e23aa..b08b5973 100644 --- a/Mailman/MailList.py +++ b/Mailman/MailList.py @@ -470,6 +470,7 @@ class MailList(HTMLFormatter, Deliverer, ListAdmin, # def Create(self, name, admin, crypted_password, langs=None, emailhost=None): + assert name == name.lower(), 'List name must be all lower case.' if Utils.list_exists(name): raise Errors.MMListAlreadyExistsError, name # Validate what will be the list's posting address. If that's -- cgit v1.2.3 From ea71f5ee9f0dc3386b523bcfcb2fc72b18462b36 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Sun, 4 Nov 2007 14:07:28 -0800 Subject: Changed the descriptions of the ARCHIVE_TO_MBOX settings to more accurately represent their current meaning. --- Mailman/Defaults.py.in | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Mailman/Defaults.py.in b/Mailman/Defaults.py.in index a18f3a93..8be182ac 100644 --- a/Mailman/Defaults.py.in +++ b/Mailman/Defaults.py.in @@ -217,11 +217,13 @@ DEFAULT_ARCHIVE_PRIVATE = 0 # ARCHIVE_TO_MBOX #-1 - do not do any archiving # 0 - do not archive to mbox, use builtin mailman html archiving only -# 1 - archive to mbox to use an external archiving mechanism only -# 2 - archive to both mbox and builtin mailman html archiving - -# use this to make both external archiving mechanism work and -# mailman's builtin html archiving. the flat mail file can be -# useful for searching, external archivers, etc. +# 1 - do not use builtin mailman html archiving, archive to mbox only +# 2 - archive to both mbox and builtin mailman html archiving. +# See the settings below for PUBLIC_EXTERNAL_ARCHIVER and +# PRIVATE_EXTERNAL_ARCHIVER which can be used to replace mailman's +# builtin html archiving with an external archiver. The flat mail +# mbox file can be useful for searching, and is another way to +# interface external archivers, etc. ARCHIVE_TO_MBOX = 2 # 0 - yearly -- cgit v1.2.3 From 54f06c64004d154746c26aebbd28da65e716f438 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Sun, 4 Nov 2007 14:41:26 -0800 Subject: Added removal of Authentication-Results: header. --- Mailman/Handlers/CleanseDKIM.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Mailman/Handlers/CleanseDKIM.py b/Mailman/Handlers/CleanseDKIM.py index 0c548a9a..c4b06613 100644 --- a/Mailman/Handlers/CleanseDKIM.py +++ b/Mailman/Handlers/CleanseDKIM.py @@ -29,8 +29,8 @@ from Mailman import mm_cfg def process(mlist, msg, msgdata): - if not mm_cfg.REMOVE_DKIM_HEADERS: - return - del msg['domainkey-signature'] - del msg['dkim-signature'] + if mm_cfg.REMOVE_DKIM_HEADERS: + del msg['domainkey-signature'] + del msg['dkim-signature'] + del msg['authentication-results'] -- cgit v1.2.3 From 6684e734f8e271aec3bf63233b19e2a57ce87d98 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Sun, 4 Nov 2007 15:03:38 -0800 Subject: - Cgi/options.py - fixed to not present the "empty" topic to user. - Handlers/CalcRecips.py - Changed to not process topics if topics are disabled for the list. --- Mailman/Cgi/options.py | 4 +++- Mailman/Handlers/CalcRecips.py | 9 +++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Mailman/Cgi/options.py b/Mailman/Cgi/options.py index d423f262..ab19e4e2 100644 --- a/Mailman/Cgi/options.py +++ b/Mailman/Cgi/options.py @@ -1,4 +1,4 @@ -# Copyright (C) 1998-2006 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2007 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 @@ -797,6 +797,8 @@ def options_page(mlist, doc, user, cpuser, userlang, message=''): if mlist.topics: table = Table(border="0") for name, pattern, description, emptyflag in mlist.topics: + if emptyflag: + continue quotedname = urllib.quote_plus(name) details = Link(mlist.GetScriptURL('options') + '/%s/?VARHELP=%s' % (user, quotedname), diff --git a/Mailman/Handlers/CalcRecips.py b/Mailman/Handlers/CalcRecips.py index e065ad68..75a8a457 100644 --- a/Mailman/Handlers/CalcRecips.py +++ b/Mailman/Handlers/CalcRecips.py @@ -1,4 +1,4 @@ -# Copyright (C) 1998,1999,2000,2001,2002 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2007 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 @@ -12,7 +12,8 @@ # # 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. """Calculate the regular (i.e. non-digest) recipients of the message. @@ -91,6 +92,10 @@ delivery. The original message as received by Mailman is attached. def do_topic_filters(mlist, msg, msgdata, recips): + if not mlist.topics_enabled: + # MAS: if topics are currently disabled for the list, send to all + # regardless of ReceiveNonmatchingTopics + return hits = msgdata.get('topichits') zaprecips = [] if hits: -- cgit v1.2.3 From 86384d9dc64e7e39e0c4c05847e15299dc6f9684 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Sun, 4 Nov 2007 15:19:31 -0800 Subject: Added Date and Message-ID headers to the confirm reply message that Mailman adds to the admin notification. --- Mailman/Handlers/Hold.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Mailman/Handlers/Hold.py b/Mailman/Handlers/Hold.py index f6008d45..d4af8f9a 100644 --- a/Mailman/Handlers/Hold.py +++ b/Mailman/Handlers/Hold.py @@ -1,4 +1,4 @@ -# Copyright (C) 1998-2006 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2007 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 @@ -283,6 +283,8 @@ also appear in the first line of the body of the reply.""")), dmsg['Subject'] = 'confirm ' + cookie dmsg['Sender'] = requestaddr dmsg['From'] = requestaddr + dmsg['Date'] = email.Utils.formatdate(localtime=True) + dmsg['Message-ID'] = Utils.unique_message_id(mlist) nmsg.attach(text) nmsg.attach(MIMEMessage(msg)) nmsg.attach(MIMEMessage(dmsg)) -- cgit v1.2.3 From 111095a6a719f4f155081def5615e1174c36e2ca Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Tue, 6 Nov 2007 17:41:17 -0800 Subject: - Scrubber.py Fixed an issue where an implicit text/plain part without any headers gets lost. Moved the cleansing of the filename extension to a place where it is guaranteed to be a string as opposed to an empty list. --- Mailman/Handlers/Scrubber.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Mailman/Handlers/Scrubber.py b/Mailman/Handlers/Scrubber.py index 48660038..588dd9ac 100644 --- a/Mailman/Handlers/Scrubber.py +++ b/Mailman/Handlers/Scrubber.py @@ -45,7 +45,7 @@ from Mailman.Logging.Syslog import syslog # Path characters for common platforms pre = re.compile(r'[/\\:]') # All other characters to strip out of Content-Disposition: filenames -# (essentially anything that isn't an alphanum, dot, slash, or underscore. +# (essentially anything that isn't an alphanum, dot, dash, or underscore). sre = re.compile(r'[^-\w.]') # Regexp to strip out leading dots dre = re.compile(r'^\.*') @@ -298,7 +298,7 @@ URL: %(url)s # If the message isn't a multipart, then we'll strip it out as an # attachment that would have to be separately downloaded. Pipermail # will transform the url into a hyperlink. - elif part and not part.is_multipart(): + elif part._payload and not part.is_multipart(): payload = part.get_payload(decode=True) ctype = part.get_type() # XXX Under email 2.5, it is possible that payload will be None. @@ -349,7 +349,8 @@ URL: %(url)s text = [] for part in msg.walk(): # TK: bug-id 1099138 and multipart - if not part or part.is_multipart(): + # MAS test payload - if part may fail if there are no headers. + if not part._payload or part.is_multipart(): continue # All parts should be scrubbed to text/plain by now. partctype = part.get_content_type() @@ -447,8 +448,6 @@ def save_attachment(mlist, msg, dir, filter_html=True): ext = fnext or guess_extension(ctype, fnext) else: ext = guess_extension(ctype, fnext) - # Allow only alphanumerics, dash, underscore, and dot - ext = sre.sub('', ext) if not ext: # We don't know what it is, so assume it's just a shapeless # application/octet-stream, unless the Content-Type: is @@ -458,6 +457,8 @@ def save_attachment(mlist, msg, dir, filter_html=True): ext = '.txt' else: ext = '.bin' + # Allow only alphanumerics, dash, underscore, and dot + ext = sre.sub('', ext) path = None # We need a lock to calculate the next attachment number lockfile = os.path.join(fsdir, 'attachments.lock') -- cgit v1.2.3 From 70689d7eb61f8c852a6a02be1d65c86cde06bde2 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Fri, 9 Nov 2007 12:25:33 -0800 Subject: Fixed Mailman/Queue/CommandRunner.py to decode a quoted-printable or base64 encoded message part. --- Mailman/Queue/CommandRunner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mailman/Queue/CommandRunner.py b/Mailman/Queue/CommandRunner.py index e08d02eb..5920b89f 100644 --- a/Mailman/Queue/CommandRunner.py +++ b/Mailman/Queue/CommandRunner.py @@ -1,4 +1,4 @@ -# Copyright (C) 1998-2004 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2007 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 @@ -93,7 +93,7 @@ class Results: if part is None: # E.g the outer Content-Type: was text/html return - body = part.get_payload() + body = part.get_payload(decode=True) # text/plain parts better have string payloads assert isinstance(body, StringType) or isinstance(body, UnicodeType) lines = body.splitlines() -- cgit v1.2.3