I am using MimeKit to retrieve emails from an Office 365 Exchange server. I'm using the Graph API to do this, so the code to retrieve and create the MimeMessage object is simply:
var mimeContentStream = await _Client.Users[_Username].Messages[uid].Content.GetAsync();
var mimeMessage = await MimeKit.MimeMessage.LoadAsync(mimeContentStream);
When I saved this file (to disk, database, blob storage, whatever), I WriteTo a memory stream and store the byte[]:
using (var stream = new MemoryStream())
{
await mimeMessage.WriteToAsync(stream);
var byteArr = stream.ToArray();
// store byte[] somewhere
}
Anywhere that the email is retrieved from storage (disk, database, etc...) and opened in any sort of email browser or rendered, it's littered with equals signs. Sometimes they replace characters, sometimes they sit between characters.
HOWEVER, if the above is done on a Windows server, no problem. On Linux server, problem.
The extract below is just a portion of such an email (the first several lines of the text/html part of the message). For any line that does end with an equals sign, the equals sign is the 76th character in that line (followed by any line break chars).
--00000000000035163c0630224305
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8"><d=
iv dir=3D"auto"></div><br><div class=3D"gmail_quote gmail_quote_container">=
<div dir=3D"ltr" class=3D"gmail_attr">---------- Forwarded message --------=
-<br>From: <strong class=3D"gmail_sendername" dir=3D"auto">Cara Abrahamse</=
strong> <span dir=3D"auto"><<a href=3D"mailto:xxxxxxxxxx@yyyyyyyyy.com">=
xxxxxxxxxx@yyyyyyyyy.com</a>></span><br>Date: Wed, 12 Mar 2025, 11:47<br=
>Subject: Payment details AAAA 1<br>To: <a href=3D"mailto:xxxxxxxxxxxxxxxxx=
@gmail.com">xxxxxxxxxxxxxxxxx@gmail.com</a> <<a href=3D"mailto:xxxxxxxxx=
xxxxxxxx@gmail.com">xxxxxxxxxxxxxxxxx@gmail.com</a>><br></div><br><br>
<div lang=3D"EN-US" link=3D"#467886" vlink=3D"#96607D" style=3D"word-wrap:b=
reak-word">
<div class=3D"m_-8096161862487316557WordSection1">
<p class=3D"MsoNormal"><span style=3D"color:black"> </span><span style=
=3D"font-size:14.0pt;color:black">Hi Sean,<u></u><u></u></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:14.0pt;color:black"> <=
u></u><u></u></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:14.0pt;color:black">I hope =
this message finds you well. Thank you for using our services! Please find =
below payment details for the outstanding amount of R80 000.00 for services=
rendered. <u></u><u></u></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:14.0pt;color:black"> <=
u></u><u></u></span></p>
<p class=3D"MsoNormal"><b><span style=3D"font-size:14.0pt;color:black">Name=
:</span></b><span style=3D"font-size:14.0pt;color:black"> Cara Abraham=
se<u></u><u></u></span></p>
<p class=3D"MsoNormal"><b><span style=3D"font-size:14.0pt;color:black">ID N=
umber</span></b><span style=3D"font-size:14.0pt;color:black;background:whit=
e">: 7209020000000</span><span style=3D"font-size:14.0pt;color:black"><u></=
u><u></u></span></p>
<p class=3D"MsoNormal"><b><span style=3D"font-size:14.0pt;color:black">Bank=
I think that this is a line break / format / encoding issue somewhere? I've seen reference to the 'quoted-printable' transfer encoding being key to this (maybe). But I haven't been able to work out where I need to fix this. Is it in the parsing? Or the writing? Or both? Or something in the way that I'm retrieving the mail via the Graph API?
I don't know if this is truly a Windows/Linux issue, or something else - the operating system is the only difference between instances of this working and it not working at the moment.
I haven't managed to find a set of ParserOptions or FormatOptions that resolve the issue on Linux environments. Have found several issues with these "equals signs" around the web, but haven't managed to find one that led me to a solution here.
I don't know if I'll ever be good enough to understand the real reason for this, but I did find a solution to my problem.
As I write this, I realise that I'm also using MimeKit v4.8.0 while v4.11.0 is available. Not yet tested on v4.11.0
Essentially the problem seems to occur when:
Email stream is read into a new MimeMessage
WriteTo is called on that MimeMessage to write to a new stream / byte array
A new MimeMessage is created from this new stream / byte array
The solution (in my case at least) was to store the original byte array only, and not to store or reuse the output of the MimeMessage.WriteTo() method.
But again, I only hit this problem on a Linux box (Windows seemed fine), and the ONLY difference I could find (on a byte-for-byte basis) between the mails that worked and didn't work was the line endings (\r\n worked; \n did not work).
The thing was that causing all of those weird equals signs was some sort of off-by-one issue when handling the line breaks and/or line lengths.
For example, given the below 2-line snip of "quote-printable" section of the message (have added the \r\n characters for clarity):
<div lang=3D"EN-US" link=3D"#467886" vlink=3D"#96607D" style=3D"word-wrap:b=\r\n
reak-word">
this SHOULD be extracted / translate to:
<div lang=3D"EN-US" link=3D"#467886" vlink=3D"#96607D" style=3D"word-wrap:break-word">
but INSTEAD was getting extracted / translated to:
<div lang=3D"EN-US" link=3D"#467886" vlink=3D"#96607D" style=3D"word-wrap:b=eak-word">
In other words, it was keeping the "=" at the end of each line, and dropping the first character from the subsequent line. This obvious broke the HTML structure, and if it was actual content that was spanning the line break, you'd see characters being "replaced" by "=" signs.
For good measure, some commented code that illustrates the issue I was seeing:
// Gets the message stream from Microsoft Graph API
var mimeContentStream = await _Client.Users[_Username].Messages[uid].Content.GetAsync();
// Loads the message stream into a MimeMessage object
// write this mimeMessage to disk / view in email client, and I get the correct body
var mimeMessage = await MimeKit.MimeMessage.LoadAsync(mimeContentStream);
// writes the MimeMessage object to a byte array
byte[] mimeMessageArr;
using (var ms = new MemoryStream())
{
mimeMessage.WriteTo(ms);
mimeMessageArr = ms.ToArray();
}
// Loads the byte array into a new MimeMessage object
MimeMessage mimeMessageAgain;
using (var ms = new MemoryStream(mimeMessageArr))
{
mimeMessageAgain = await MimeKit.MimeMessage.LoadAsync(ms);
}
// write mimeMessageAgain to disk / view in email client, and I get lots of EQUALS signs interspersed with the (mis-formatted) body
I don't think the fact that I was retrieving this from a Microsoft Graph API call makes the difference. I have no idea why Linux/Windows would make a difference. All I know is that after 2 days I can finally sleep.