# Email processor for DMARC - Take in an email message, output DMARC-compliant message

NOTE: This is for Python 2.7 currently, NOT Python 3. There's some type of black magic at work for Content Disposition that doesn't properly work on Py3, so I have to fix that first before I have a Py3 version of this...

This is an excerpt of another program, but can work as a standalone tool. This tool works to take any inbound email message passed into it (in this case, stored in a file as a string) and output a DMARC-compliant message. DMARC operates on verifying SPF and DKIM signatures, so any received message has to be rebroadcast in a way that completely strips out any other authentication or signatures and basically use a 'brand new message' that originates from the mail server / listserv.

This basically means that, for any given email list system, we should accept an email message, retain all parts of its payload (text components and attachments), but retransmit the message as the ListServ with the "From" address being the listserv, while retaining the original sender's name in the descriptive "From" field and putting the original "From" address into the "Reply-To" field.

Now, this works. When put into a Python script, you can execute it with python dmarc_convert_message.py PATHTOMESSAGEFILE where PATHTOMESSAGEFILE is the path to an email message's source. It will then read the data in and process it.

There's two components - the script, and a test message to use. The third is the converted email message output to a file.

I've constructed a test message you can use to test things here, and a valid 'output' (note that your output may differ because the MIMEMultipart boundary IDs change with each message being generated, but the rest of the message content should be nearly identical). All these are in a Gist on GitHub but otherwise are here below.

Every suggestion for improvement is valid, however I use a lot of repeated code, so any way to reduce the amount of repeated code in here is going to be given a priority.

I would prefer not to be given recommendations on PEP8 or style rules, because for this, I don't care much about them. I care about improving the code within reason, but not redoing everything for style.

dmarc_convert_message.py:

# coding=utf-8
import sys
import email
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart

# noinspection PyTypeChecker
def disposition_dict(dispstr):
# type: (str) -> dict
"""
Converts a string which contains a Content-Disposition
:param dispstr: String with Content-Disposition value
:return: Dictionary of Content-Disposition values.
"""
return dict(
[map(str.strip, pt.split("=", 1))
if len(map(str.lower, pt.split("=", 1))) > 1 else [str(pt.strip().lower()), None]
for pt in dispstr.split(";")]
)

# Open the file path specified as the first argument to the script at runtime, which
# contains the full path to the raw source message.

multipart = msg.is_multipart()
# Construct the msg_components dictionary to hold the components which will go into
# the new email message.  This is built from the original message.
msg_components = {'To': msg['To'], 'From': msg['From'], 'Subject': msg['Subject'],
'Message-ID': email.utils.make_msgid(), 'Date': msg['Date'], 'Payloads': []}

# Iterate through all parts of the email message.
for part in msg.walk():
if not part.is_multipart():
# If we hit a non-multipart piece, we need to do stuff with it.
# First, extract MIMEType data.
maintype, subtype = part.get_content_type().split('/', 1)
# Next, get the Content-Disposition.
cdisp = part.get("Content-Disposition")
if cdisp and not part.is_multipart():
# If we have a Content-Disposition and we're not in a multipart piece of the message...
cdisp_d = disposition_dict(cdisp)  # ... create a dict for easier searching of the cdisp.
if 'attachment' or 'inline' in cdisp_d:
# And if we're an attachment of some sort...

# Sanitize the filename.
attachfname = cdisp_d['filename'].strip('"')
attachfname = attachfname.replace('\r', '')
attachfname = attachfname.replace('\n', '')

# Construct the MIMEBase message part for this MIMEType...
data = MIMEBase(maintype, subtype)
# ... and sets the Content-Type parameters to whatever they were in the original part...
for param in part.get_params():
if param not in data.get_params():
data.set_param(param[0], param[1])
# ... and sets the Content-Transfer-Encoding from the original part...
if 'Content-Transfer-Encoding' in part.keys():
# ... then sets the Payload for the part...
# ... and finally add it into the Payloads section of the components,
# as a tuple so we can identify it's got a filename and is an attachment.
else:
# If we're not an attachment, we're probably something else.
if part.is_multipart():
# Skip if multipart part.
continue

if maintype == "text":
# We might be text, either Plain or HTML, so we need to add that to the payloads
# ... by constructing the text message part...
else:
# Any other MIMEType isn't to be handled and we just skip over that part
continue

if multipart:
# The new message we send, however, is going to be a multipart message.
newmsg = MIMEMultipart('alternative')  # Email compliance for Multipart: have it a multipart/alternative type.
newmsg['Subject'] = msg_components['Subject']  # Set the subject to match.
newmsg['To'] = msg_components['To']  # Set the "To" field to be the original "To" address
if len(msg['From'].split('<')) > 1:  # Determine if 'From' is formatted a specific way.
# If it has 'Thomas Ward <teward@foo.bar>' for example, we need to split out the name for the restructuring.
'Example List', 'list@example.com'))
else:
# Otherwise, we just use the email address.
if 'List-Id' in msg.keys():
newmsg['List-Id'] = msg['List-Id']
if 'List-Post' in msg.keys():
newmsg['List-Post'] = 'nowhere@dark-net.localtesting'
# We created a new MessageID earlier, so we'll use that.
newmsg['Message-ID'] = msg_components['Message-ID']
# We are using the original date from the first message.
newmsg['Date'] = msg_components['Date']
# Iterate over all payload parts and attach them to the new multipart message.
else:
# Tuple payload values are attachments, so handle them as such...
# ... then adding the attachment to the message.
else:
# If we're not making a multipart message, then only build a single-part message to send.
# However, if we aren't a multipart message and try to include more than one payload,
# that's illegal and something is horribly wrong. So error.
raise TypeError("You cannot have a non-multipart message with multiple payloads.")

maintype, subtype = mimepart.get_content_type().split('/', 1)
newmsg = MIMEBase(maintype, subtype)
newmsg['Subject'] = msg_components['Subject']  # Set the subject to match.
newmsg['To'] = msg_components['To']  # Set the "To" field to be the original "To" address
if len(msg['From'].split('<')) > 1:  # Determine if 'From' is formatted a specific way.
# If it has 'Thomas Ward <teward@foo.bar>' for example, we need to split out the name for the restructuring.
'Example List', 'list@example.com'))
else:
# Otherwise, we just use the email address.
if 'List-Id' in msg.keys():
newmsg['List-Id'] = msg['List-Id']
if 'List-Post' in msg.keys():
newmsg['List-Post'] = msg['List-Post']
# We created a new MessageID earlier, so we'll use that.
newmsg['Message-ID'] = msg_components['Message-ID']
# We are using the original date from the first message.
newmsg['Date'] = msg_components['Date']
# Now we set the payload.

# Write the newly constructed message to a file, so we can process it later as part of an email sender.
open('converted_message', mode='w').write(newmsg.as_string())


testmsg:

Return-Path: <teward@localtest>
X-Original-To: teward@localtest
Delivered-To: teward@localtest
by mail.localtest (Postfix) with ESMTP id 58318104458
for <teward@localtest>; Sat, 11 Nov 2017 12:07:17 -0500 (EST)
X-Spam-Flag: NO
X-Spam-Score: 0.003
X-Spam-Level:
X-Spam-Status: No, score=0.003 tagged_above=-999 required=6.31
tests=[ALL_TRUSTED=-1, DKIM_SIGNED=0.1, DKIM_VALID=-0.1,
DKIM_VALID_AU=-0.1, HTML_MESSAGE=0.001, TRACKER_ID=1.102]
autolearn=no autolearn_force=no
by localhost (mail.localtest [127.0.0.1]) (amavisd-new, port 10024)
with ESMTP id cHuL-_keSoBU for <teward@localtest>;
Sat, 11 Nov 2017 12:07:17 -0500 (EST)
(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
(No client certificate requested)
by mail.dark-net.io (Postfix) with ESMTPSA id CA598FF786
for <teward@localtest>; Sat, 11 Nov 2017 12:07:16 -0500 (EST)
To: Thomas Ward <teward@localtest>
From: Thomas Ward <teward@localtest>
Subject: Testing Message
Message-ID: <91ccb8dc-a880-d872-c314-f0ec4a732aa1@localtest>
Date: Sat, 11 Nov 2017 12:07:15 -0500
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101
Thunderbird/52.4.0
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="------------09F884363E8CBC93E6E5E0EF"
Content-Language: en-US

This is a multi-part message in MIME format.
--------------09F884363E8CBC93E6E5E0EF
Content-Type: multipart/alternative;
boundary="------------4DF4329FEFF250E03CF3D624"

--------------4DF4329FEFF250E03CF3D624
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit

Test Message with Attachment.

--------------4DF4329FEFF250E03CF3D624
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 7bit

<html>

<meta http-equiv="content-type" content="text/html; charset=utf-8">
<body text="#000000" bgcolor="#FFFFFF">
Test Message with Attachment.<br>
</body>
</html>

--------------4DF4329FEFF250E03CF3D624--

--------------09F884363E8CBC93E6E5E0EF
Content-Type: application/msword;
name="test.doc"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="test.doc"

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
///////////////////////////////////9//////////7///8EAAAABQAAAAYAAAAHAAAA
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////1IA
AAAAAAAAAAAWAAUA////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA/v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//
/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7///8AAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAA/v///wAAAAAAAAAAAQAAAP7////+////BAAAAAUAAAAGAAAABwAAAAgA
//8kAAAAJQAAACYAAAAnAAAAKAAAACkAAAAqAAAAKwAAACwAAAAtAAAALgAAAC8AAAAwAAAA
AAA/AAAAQAAAAEEAAABCAAAAQwAAAEQAAABFAAAARgAAAEcAAABIAAAASQAAAEoAAABLAAAA
TAAAAE0AAABOAAAATwAAAFAAAABRAAAAUgAAAFMAAABUAAAAVQAAAFYAAABXAAAAWAAAAFkA
AABaAAAAWwAAAP7///9dAAAA/v//////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////8BAP7/
AwoAAP////8GCQIAAAAAAMAAAAAAAABGGAAAAE1pY3Jvc29mdCBXb3JkLURva3VtZW50AAoA
AAAAAAAAAAAAAAAAAAAAAAEAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
WgAAAAYATgBvAHIAbQBhAGwAAAAIAAAAMSQBKiQBMwBCKgBPSgMAUUoDAENKGABtSAkEc0gJ
BEtIAQBQSgQAbkgECHRIBAheSgUAYUoYAF9IOQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
BwBAACIQAQAiAUAAAAAHAEMAYQBwAHQAaQBvAG4AAAANABIAE6R4ABSkeAAMJAEAEgBDShgA
NggBXkoHAGFKGABdCAEmAP4fAQAyASYAAAAFAEkAbgBkAGUAeAAAAAUAEwAMJAEABABeSgcA
AAACEAAAAAAAAAAPAAAAUAAACAAAAAAIAAAARxaQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAFQAaQBtAGUAcwAgAE4AZQB3ACAAUgBvAG0AYQBuAAAANRaQAQIAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFMAeQBtAGIAbwBsAAAAMyaQAQAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEAcgBpAGEAbAAAAGkWkAEBEQAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMAGkAYgBlAHIAYQB0AGkAbwBuACAAUwBl
AHIAaQBmAAAAVABpAG0AZQBzACAATgBlAHcAIABSAG8AbQBhAG4AAABZBpABAQAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATgBvAHQAbwAgAFMAYQBuAHMAIABDAEoASwAg
AFMAQwAgAFIAZQBnAHUAbABhAHIAAAA5BpABAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAARgByAGUAZQBTAGEAbgBzAAAAUyaQAQEQAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAEwAaQBiAGUAcgBhAHQAaQBvAG4AIABTAGEAbgBzAAAAQQByAGkAYQBs
AAAAOSSQAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEYAcgBlAGUAUwBh
AAEAAAAEAIOQAQAAAAEAAAAOAAAAAQABAAAAAQAAAAAAAABnBAAgAAAAAAAEAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEjAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAIAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAeAAAAAQAAAAAAAAAeAAAAAQAAAAAAAAAeAAAAAQAAAAAAAAAeAAAAAQAAAAAAAAAeAAAA
DgBDYW9sYW44MAAAAAAAAAAAAAAAAAAAAAAAAAkEFgAkDgAAAAAAAAAAAAAPAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//DwAFAAAAAQAAAP//DwAGAAAAAQAAAP//DwAAAAAA
AAAAAAAAAAAAAAAAiAAAAAAAlgEAAAAAAACWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAACWAQAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACUEAABiAgAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAACANkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAYgBlAHcAbwB3AGgAZQByAG8AYQByAHEAZgBhAA0AAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAHggAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAQAIAAAeCAAA/QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABIgAfsNAvILDgPSGw
AAABAAIAAAAAAAAAAAAAAAAAAAAAAAIAAAAC1c3VnC4bEJOXCAArLPmuRAAAAAXVzdWcLhsQ
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSAG8AbwB0ACAARQBuAHQA
cgB5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgAFAP//
////////AQAAAAYJAgAAAAAAwAAAAAAAAEYAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAACAFwAA
AAAAAAEAQwBvAG0AcABPAGIAagAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAGoAAAAAAAAAAQBPAGwAZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAgD/////AwAAAP////8AAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAFAAAAAAAAAAxAFQAYQBiAGwA
ZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
DgACAP///////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMA
AACHBgAAAAAAAAUAUwB1AG0AbQBhAHIAeQBJAG4AZgBvAHIAbQBhAHQAaQBvAG4AAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABoAAgD/////////////
//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjAAAAJA4AAAAAAAAFAEQA
AAAAAAAAOAACAP///////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAFwAAAB0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////////AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v///wAAAAAAAAAA
--------------09F884363E8CBC93E6E5E0EF
Content-Type: text/plain; charset=UTF-8;
name="foo.txt"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="foo.txt"

aW9hd2VocnA5YXdoZnA5OGFod2VyZnA5YXI4cDl0ODlhZXJoZWFyZmFlcmYK
--------------09F884363E8CBC93E6E5E0EF--


Proper output (in a file called converted_message):

Content-Type: multipart/alternative;
boundary="===============0260810760593589585=="
MIME-Version: 1.0
Subject: Testing Message
To: Thomas Ward <teward@localtest>
From: 'Thomas Ward' via 'Example List' <list@example.com>
Message-ID: <151042736894.30764.610196434709261357@overlord>
Date: Sat, 11 Nov 2017 12:07:15 -0500

--===============0260810760593589585==
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit

Test Message with Attachment.

--===============0260810760593589585==
Content-Type: text/html; charset="us-ascii"
Content-Transfer-Encoding: 7bit

<html>

<meta http-equiv="content-type" content="text/html; charset=utf-8">
<body text="#000000" bgcolor="#FFFFFF">
Test Message with Attachment.<br>
</body>
</html>

--===============0260810760593589585==
Content-Type: application/msword; name="test.doc"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="test.doc"

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
///////////////////////////////////9//////////7///8EAAAABQAAAAYAAAAHAAAA
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////1IA
AAAAAAAAAAAWAAUA////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA/v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//
/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7///8AAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAA/v///wAAAAAAAAAAAQAAAP7////+////BAAAAAUAAAAGAAAABwAAAAgA
//8kAAAAJQAAACYAAAAnAAAAKAAAACkAAAAqAAAAKwAAACwAAAAtAAAALgAAAC8AAAAwAAAA
AAA/AAAAQAAAAEEAAABCAAAAQwAAAEQAAABFAAAARgAAAEcAAABIAAAASQAAAEoAAABLAAAA
TAAAAE0AAABOAAAATwAAAFAAAABRAAAAUgAAAFMAAABUAAAAVQAAAFYAAABXAAAAWAAAAFkA
AABaAAAAWwAAAP7///9dAAAA/v//////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////8BAP7/
AwoAAP////8GCQIAAAAAAMAAAAAAAABGGAAAAE1pY3Jvc29mdCBXb3JkLURva3VtZW50AAoA
AAAAAAAAAAAAAAAAAAAAAAEAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
WgAAAAYATgBvAHIAbQBhAGwAAAAIAAAAMSQBKiQBMwBCKgBPSgMAUUoDAENKGABtSAkEc0gJ
BEtIAQBQSgQAbkgECHRIBAheSgUAYUoYAF9IOQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
BwBAACIQAQAiAUAAAAAHAEMAYQBwAHQAaQBvAG4AAAANABIAE6R4ABSkeAAMJAEAEgBDShgA
NggBXkoHAGFKGABdCAEmAP4fAQAyASYAAAAFAEkAbgBkAGUAeAAAAAUAEwAMJAEABABeSgcA
AAACEAAAAAAAAAAPAAAAUAAACAAAAAAIAAAARxaQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAFQAaQBtAGUAcwAgAE4AZQB3ACAAUgBvAG0AYQBuAAAANRaQAQIAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFMAeQBtAGIAbwBsAAAAMyaQAQAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEAcgBpAGEAbAAAAGkWkAEBEQAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMAGkAYgBlAHIAYQB0AGkAbwBuACAAUwBl
AHIAaQBmAAAAVABpAG0AZQBzACAATgBlAHcAIABSAG8AbQBhAG4AAABZBpABAQAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATgBvAHQAbwAgAFMAYQBuAHMAIABDAEoASwAg
AFMAQwAgAFIAZQBnAHUAbABhAHIAAAA5BpABAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAARgByAGUAZQBTAGEAbgBzAAAAUyaQAQEQAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAEwAaQBiAGUAcgBhAHQAaQBvAG4AIABTAGEAbgBzAAAAQQByAGkAYQBs
AAAAOSSQAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEYAcgBlAGUAUwBh
AAEAAAAEAIOQAQAAAAEAAAAOAAAAAQABAAAAAQAAAAAAAABnBAAgAAAAAAAEAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEjAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAIAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAeAAAAAQAAAAAAAAAeAAAAAQAAAAAAAAAeAAAAAQAAAAAAAAAeAAAAAQAAAAAAAAAeAAAA
DgBDYW9sYW44MAAAAAAAAAAAAAAAAAAAAAAAAAkEFgAkDgAAAAAAAAAAAAAPAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//DwAFAAAAAQAAAP//DwAGAAAAAQAAAP//DwAAAAAA
AAAAAAAAAAAAAAAAiAAAAAAAlgEAAAAAAACWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAACWAQAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACUEAABiAgAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAACANkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAYgBlAHcAbwB3AGgAZQByAG8AYQByAHEAZgBhAA0AAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAHggAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAQAIAAAeCAAA/QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABIgAfsNAvILDgPSGw
AAABAAIAAAAAAAAAAAAAAAAAAAAAAAIAAAAC1c3VnC4bEJOXCAArLPmuRAAAAAXVzdWcLhsQ
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSAG8AbwB0ACAARQBuAHQA
cgB5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgAFAP//
////////AQAAAAYJAgAAAAAAwAAAAAAAAEYAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAACAFwAA
AAAAAAEAQwBvAG0AcABPAGIAagAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAGoAAAAAAAAAAQBPAGwAZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAgD/////AwAAAP////8AAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAFAAAAAAAAAAxAFQAYQBiAGwA
ZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
DgACAP///////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMA
AACHBgAAAAAAAAUAUwB1AG0AbQBhAHIAeQBJAG4AZgBvAHIAbQBhAHQAaQBvAG4AAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABoAAgD/////////////
//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjAAAAJA4AAAAAAAAFAEQA
AAAAAAAAOAACAP///////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAFwAAAB0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////////AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v///wAAAAAAAAAA
--===============0260810760593589585==
Content-Type: text/plain; charset="UTF-8"; name="foo.txt"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="foo.txt"

aW9hd2VocnA5YXdoZnA5OGFod2VyZnA5YXI4cDl0ODlhZXJoZWFyZmFlcmYK
--===============0260810760593589585==--


Possible improvements:

• disposition_dict doesn't need the outer list comprehension, you can just use an implicit generator comprehension. This just removes some unneeded complexity.
• Your turnery didn't look like one at first, and so threw me when I noticed it was one.
• Your conditional is over complicated, you don't need the map.
• You don't need a conditional, you can instead use a slice.

(map(str.strip, pt.split('=', 1)) + [None])[:2]

• It's discouraged to use map, I'd recommend that you instead just use a list comprehension.

• Always use with when using open. Your code doesn't guarantee that any file you open is actually closed.
• Use if __name__ == '__main__':.
• Use more functions, you won't need comments if you have well named functions.
• You may want to look into argparse, rather than using sys.argv.
• if 'attachment' or 'inline' in cdisp_d: is always true, you probably should use something like:

any(key in cdisp_d for key in ('attachment', 'inline'))
'attachment' in cdisp_d or 'inline' in cdisp_d

• You can use str.translate, rather than multiple str.replaces or str.strips. Since you're str.replaceing to an empty string, on both your attachfnames, you don't even need to use string.maketrans.

>>> 'a\rb\nc"d'.translate(None, '\r\n"')
'abcd'

• You can restructure your first main for loop, so that it's easier to read, by moving the part.is_multipart to the beginning of the if, so the rest of the code doesn't include it. You can also reduce the second if, from multiple ifs, to just one elif.

if part.is_multipart():
continue
elif cdisp:
...
elif maintype == "text":
...

• Don't use a hanging indent, if you have only like 10 chars left of vertical space. Instead I'd recomend using:

newmsg.add_header('From', "'{}' via '{}' <{}>".format(
msg['From'].split('<')[0].strip(),
'Example List',
'list@example.com'
))

• Make your code a little more dry, by merging your ifs for the above print. Take the following conditional, and usages:

len(msg['From'].split('<')) > 1
if: msg['From'].split('<')[0].strip()
else: msg['From']


The only difference is that one uses .strip(), where the other doesn't. And so I'd use:

from_, other = msg['From'].split('<')
if other:
from_ = from_.strip()
...


Even better, you may want to strip both, and so you can just use one line of code for them.

• It's discouraged to use type(a) is b. Instead use isinstance(a, b).

• You can rearrange your if multipart code, so that it's less WET. You only change how the newmsg is created, and have quite a lot of the same code. And some final changes.

And so I'd change your code more to:

# coding=utf-8
import sys
import email
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart

# noinspection PyTypeChecker
def disposition_dict(dispstr):
# type: (str) -> dict
"""
Converts a string which contains a Content-Disposition
:param dispstr: String with Content-Disposition value
:return: Dictionary of Content-Disposition values.
"""
return dict(
([i.strip() for i in pt.split('=', 1)] + [None])[:2]
for pt in dispstr.split(";")
)

with open(sys.argv[1], mode="r") as f:
multipart = msg.is_multipart()
msg_components = {'To': msg['To'], 'From': msg['From'], 'Subject': msg['Subject'],
'Message-ID': email.utils.make_msgid(), 'Date': msg['Date'], 'Payloads': []}

for part in msg.walk():
if not part.is_multipart():
maintype, subtype = part.get_content_type().split('/', 1)
cdisp = part.get("Content-Disposition")
if part.is_multipart():
continue
elif cdisp:
cdisp_d = disposition_dict(cdisp)
if any(key in cdisp_d for key in ('attachment', 'inline')):
attachfname = cdisp_d['filename'].translate(None, '\r\n"')
data = MIMEBase(maintype, subtype)
for param in part.get_params():
if param not in data.get_params():
data.set_param(param[0], param[1])
if 'Content-Transfer-Encoding' in part.keys():
elif maintype == "text":

if multipart:
newmsg = MIMEMultipart('alternative')
else:
raise TypeError("You cannot have a non-multipart message with multiple payloads.")

maintype, subtype = mimepart.get_content_type().split('/', 1)
newmsg = MIMEBase(maintype, subtype)

newmsg['Subject'] = msg_components['Subject']
newmsg['To'] = msg_components['To']
from_, other = msg['From'].split('<')
if other:
from_ = from_.strip()
from_,
'Example List',
'list@example.com'
))
if 'List-Id' in msg.keys():
newmsg['List-Id'] = msg['List-Id']
if 'List-Post' in msg.keys():
if multipart:
newmsg['List-Post'] = 'nowhere@dark-net.localtesting'
else:
newmsg['List-Post'] = msg['List-Post']
newmsg['Message-ID'] = msg_components['Message-ID']
newmsg['Date'] = msg_components['Date']

if not multipart:
else: