I am working on a project where I am building my own SMTP server. (please nobody ask why or provide me with things like Postfix, I have my reasons).
It is mostly working fine except with Outlook there seems to be some problem with encoding of the data that I am encoding from Outlook.
I keep getting content as follows:
<html xmlns:v=3D"urn:schemas-microsoft-com:vml" =
xmlns:o=3D"urn:schemas-microsoft-com:office:office" =
xmlns:w=3D"urn:schemas-microsoft-com:office:word" =
Instead of:
<html xmlns:v="urn:schemas-microsoft-com:vml" =
xmlns:o="urn:schemas-microsoft-com:office:office" =
xmlns:w="urn:schemas-microsoft-com:office:word" =
Notice the 3D isn't there on the valid content.
I have a function that listens to the socket for SMTP data which looks like the following:
if (stream.CanRead)
{
byte[] serverData = new byte[1024];
StringBuilder stringBuilder = new StringBuilder();
int numberOfBytesRead = 0;
do
{
numberOfBytesRead = stream.Read(serverData, 0, serverData.Length);
Encoding encoding = Encoding.GetEncoding("UTF-7", new FallbackEncoding(), new FallbackDecoding());
stringBuilder.AppendFormat("{0}", encoding.GetString(serverData, 0, numberOfBytesRead));
} while (stream.DataAvailable);
return stringBuilder.ToString();
In my FallbackDecoding function I have the following code
class FallbackDecoding : DecoderFallback
{
public override int MaxCharCount
{
get
{
return 1;
}
}
public override DecoderFallbackBuffer CreateFallbackBuffer()
{
return new Buffer();
}
private class Buffer : DecoderFallbackBuffer
{
private int _fallbackIndex;
private string _fallbackString;
public override int Remaining
{
get
{
return _fallbackString.Length - _fallbackIndex;
}
}
public override bool Fallback(byte[] bytesUnknown, int index)
{
byte unknownChar = bytesUnknown[index];
_fallbackString = Encoding.ASCII.GetString(new[] { (byte)(unknownChar & 127) });
_fallbackIndex = 0;
return true;
}
public override char GetNextChar()
{
if (Remaining > 0)
{
return _fallbackString[_fallbackIndex++];
}
else
{
return '\0';
}
}
public override bool MovePrevious()
{
if (_fallbackIndex > 0)
{
_fallbackIndex--;
return true;
}
return false;
}
}
For some reason the decoder fall back class is throwing an exception in the function public override bool Fallback
. It throws an exception because bytesunknown
only has 1 item in the array, but the index
parameter is 128 so its throwing an index out of range exception but I have no idea why.
I've tried changing ASCII to UTF-7 as Outlook sends the data in 7bit but it doesn't seem to make any difference.
Due to the HTML in the email I'm receiving, when I pass the email in, the formatting is wrong and sometimes I'll just get garbage in the email.
Update
Full email headers as requested
Message-ID: <[email protected]>
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="----=_NextPart_000_000E_01D0DC5A.6DD24AD0"
X-Mailer: Microsoft Outlook 15.0
Thread-Index: AdDcUeHbbPyOUTipQ462DEYroR+DWg==
Content-Language: en-gb
This is a multipart message in MIME format.
------=_NextPart_000_000E_01D0DC5A.6DD24AD0
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit
This is the content of the message
------=_NextPart_000_000E_01D0DC5A.6DD24AD0
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:schemas-microsoft-com:office:office" =
xmlns:w=3D"urn:schemas-microsoft-com:office:word" =
xmlns:m=3D"http://schemas.microsoft.com/office/2004/12/omml" =
xmlns=3D"http://www.w3.o
Quoted-printable and ASCII text with long lines and
=
The html attachment is encoded using quoted-printable encoding. Quoted-printable uses special 3 bytes sequences starting with
=
. Quoted printable encodes=
as=3D
. It is the only printable ascii character (33-126) that must be encoded.BTW
=
at end of line is also product ofquoted-printable
encoding. It "breaks" long lines.