Using MimeKit MimeMessage.Load() fails to parse the entity headers of the email message

613 Views Asked by At

I have a simple string representation of an email that I've converted to a memory stream and am trying to load into a MimeMessage however the Load fails parsing the headers. I have also downloaded the trial Aspose app which will parse the email stream with no problem at all. Unfortunately for a one off my company will not pay Aspose's price and, having used MimeKit to create email messages before it seemed a good choice.

This is the code I'm using to attempt to parse the email ......

        MemoryStream ms = SerializeToStream(emailString);
        ms.Position = 0;

        MimeMessage mimeMessage = MimeMessage.Load(ms);
        private MemoryStream SerializeToStream( object obj )
        {
            MemoryStream stream = new MemoryStream();

            using (var writer = new BinaryWriter(stream, Encoding.UTF8, true))
            {
                writer.Write(obj.ToString());
            }
            return stream;
        }

And this is the email string extracted from a database that I'm trying to parse ...

MIME-Version: 1.0
From: "John Doe" <[email protected]>
To: "John Doe" <[email protected]>
Date: 04 May 2023 09:48:01 +0000
Subject: Simple no-frills email
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: quoted-printable

<html xmlns:v=3D"urn:schemas-microsoft-com:vml" xmlns:o=3D"urn:sc=
hemas-microsoft-com:office:office" xmlns:w=3D"urn:schemas-microso=
ft-com:office:word" xmlns:m=3D"http://schemas.microsoft.com/offic=
e/2004/12/omml" xmlns=3D"http://www.w3.org/TR/REC-html40"><head><=
meta name=3DGenerator content=3D"Microsoft Word 15 (filtered medi=
um)"><style><!--/* Font Definitions */@font-face\t{font-family:"Ca=
mbria Math";\tpanose-1:2 4 5 3 5 4 6 3 2 4;}@font-face\t{font-famil=
y:Calibri;\tpanose-1:2 15 5 2 2 2 4 3 2 4;}/* Style Definitions */=
p.MsoNormal, li.MsoNormal, div.MsoNormal\t{margin:0cm;\tfont-size:1=
1.0pt;\tfont-family:"Calibri",sans-serif;\tmso-ligatures:standardco=
ntextual;\tmso-fareast-language:EN-US;}span.EmailStyle17\t{mso-styl=
e-type:personal-compose;\tfont-family:"Calibri",sans-serif;\tcolor:=
windowtext;}.MsoChpDefault\t{mso-style-type:export-only;\tfont-fami=
ly:"Calibri",sans-serif;\tmso-ligatures:standardcontextual;\tmso-fa=
reast-language:EN-US;}@page WordSection1\t{size:612.0pt 792.0pt;\tm=
argin:72.0pt 72.0pt 72.0pt 72.0pt;}div.WordSection1\t{page:WordSec=
tion1;}--></style><!--[if gte mso 9]><xml><o:shapedefaults v:ext=3D=
"edit" spidmax=3D"1026" /></xml><![endif]--><!--[if gte mso 9]><x=
ml><o:shapelayout v:ext=3D"edit"><o:idmap v:ext=3D"edit" data=3D"=
1" /></o:shapelayout></xml><![endif]--></head><body lang=3DEN-GB =
link=3D"#0563C1" vlink=3D"#954F72" style=3D'word-wrap:break-word'=
><div class=3DWordSection1><p class=3DMsoNormal>Hello<o:p></o:p><=
/p><p class=3DMsoNormal><o:p>&nbsp;</o:p></p><p class=3DMsoNormal=
><span style=3D'font-size:10.0pt;color:black;mso-ligatures:none;m=
so-fareast-language:EN-GB'>John Doe | Technical Consultant</span=
><span style=3D'mso-ligatures:none;mso-fareast-language:EN-GB'> <=
br></span><span style=3D'font-size:10.0pt;color:black;mso-ligatur=
es:none;mso-fareast-language:EN-GB'>T: +44 (0)1959 560410</span><=
span style=3D'mso-ligatures:none;mso-fareast-language:EN-GB'> <br=
></span><span style=3D'font-size:10.0pt;color:black;mso-ligatures=
:none;mso-fareast-language:EN-GB'>Any Company | the CRM exper=
ts</span><span style=3D'mso-ligatures:none;mso-fareast-language:E=
N-GB'> <br>&nbsp; </span><o:p></o:p></p></div></body></html>

I've tried just passing the memory stream to the Load with the default parserOptions and also changing a few options and passing those to the Load in addition but I keep hitting the same problem.

1

There are 1 best solutions below

1
jstedfast On BEST ANSWER

BinaryWriter is going to write binary garbage to the stream that cannot be parsed by a MIME parser.

Do this instead:

private MemoryStream SerializeToStream( object obj )
{
    return new MemoryStream(Encoding.ASCII.GetBytes(obj.ToString()), false);
}

Even better would be to never read email message content from a database as a string and instead read it directly as a byte[] or stream.

Once you convert a raw email message from a byte[] into a string, you can't reliably convert it back because MIME allows each body part (and the headers) to all be in different text encodings.