haraka / Haraka

A fast, highly extensible, and event driven SMTP server
https://haraka.github.io
MIT License
5.08k stars 661 forks source link

Attached emails are broken (stripped dots and \r\n issue) #2731

Open mitridatik opened 5 years ago

mitridatik commented 5 years ago

system info

Haraka Haraka.js — Version: 2.8.24
Node v10.16.0
OS Linux chd 4.4.0-159-generic #187-Ubuntu SMP Thu Aug 1 16:28:06 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
openssl OpenSSL 1.1.0h 27 Mar 2018 (Library: OpenSSL 1.1.1c 28 May 2019)

Expected behavior

Attached emails are broken after Haraka processing. Viewing them in MS Outlook show problems.

Observed behavior

Haraka changes \r\n to \n for attached email and removes first dot from email body. Attached email looks broken in MS Outlook.

Steps to reproduce

Create a plugin from this code

var plugin;

exports.register = function () {
    plugin = this;
};

exports.hook_rcpt_ok = function (next, connection) {
    connection.transaction.parse_body = true;

    connection.transaction.attachment_hooks(
        function (contentType, filename, body, stream) {

            var bufs = [];
            stream.on('data', function(d){
                bufs.push(d);
            });
            stream.on('end', function(){
              var buf = Buffer.concat(bufs);
              var bytes = [];
              for(var i = 0; i < 400; i++) {
                  bytes.push(buf[i].toString(16));
              }

              connection.loginfo(bytes.join(' '));
            });
        }
    );

    next();
};

Send this email

From: <support@example.com>
To: <to@example.com>
Subject: Email with email attach
Date: Fri, 25 Oct 2019 19:25:29 +0300
MIME-Version: 1.0
Content-Type: multipart/mixed;
    boundary="----=_NextPart_000_004B_01D58B69.F7719260"
X-Mailer: Microsoft Outlook 14.0
Thread-Index: AdWLUMXEiyuDnQtMQsyy4BTSiE9wTA==
Content-Language: en-us

This is a multipart message in MIME format.

------=_NextPart_000_004B_01D58B69.F7719260
Content-Type: multipart/alternative;
    boundary="----=_NextPart_001_004C_01D58B69.F7719260"

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

Hello,

Email with inline image attached.

------=_NextPart_001_004C_01D58B69.F7719260
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.org/TR/REC-html40"><head><META =
HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; =
charset=3Dus-ascii"><meta name=3DGenerator content=3D"Microsoft Word 14 =
(filtered medium)"><style><!--
/* Font Definitions */
@font-face
    {font-family:Calibri;
    panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
    {margin:0in;
    margin-bottom:.0001pt;
    font-size:11.0pt;
    font-family:"Calibri","sans-serif";
    mso-fareast-language:EN-US;}
a:link, span.MsoHyperlink
    {mso-style-priority:99;
    color:blue;
    text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
    {mso-style-priority:99;
    color:purple;
    text-decoration:underline;}
span.EmailStyle17
    {mso-style-type:personal-compose;
    font-family:"Calibri","sans-serif";
    color:windowtext;}
..MsoChpDefault
    {mso-style-type:export-only;
    font-family:"Calibri","sans-serif";
    mso-fareast-language:EN-US;}
@page WordSection1
    {size:8.5in 11.0in;
    margin:42.5pt 42.5pt 42.5pt 70.85pt;}
div.WordSection1
    {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext=3D"edit" spidmax=3D"1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext=3D"edit">
<o:idmap v:ext=3D"edit" data=3D"1" />
</o:shapelayout></xml><![endif]--></head><body lang=3DRU link=3Dblue =
vlink=3Dpurple><div class=3DWordSection1><p class=3DMsoNormal><span =
lang=3DEN-US>Hello,<o:p></o:p></span></p><p class=3DMsoNormal><span =
lang=3DEN-US><o:p>&nbsp;</o:p></span></p><p class=3DMsoNormal><span =
lang=3DEN-US>Email with inline image attached.<o:p></o:p></span></p><p =
class=3DMsoNormal><span lang=3DEN-US><o:p>&nbsp;</o:p></span></p><p =
class=3DMsoNormal><span lang=3DEN-US></span><span lang=3DEN-US =
style=3D'mso-fareast-language:RU'><o:p></o:p></span></p><p =
class=3DMsoNormal><span =
lang=3DEN-US><o:p>&nbsp;</o:p></span></p></div></body></html>
------=_NextPart_001_004C_01D58B69.F7719260--

------=_NextPart_000_004B_01D58B69.F7719260
Content-Type: message/rfc822
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment

From: <to@example.com>
To: <support@example.com>
Subject: Inline Image
Date: Fri, 25 Oct 2019 19:24:39 +0300
MIME-Version: 1.0
Content-Type: multipart/related;
    boundary="----=_NextPart_000_0046_01D58B69.F7716B50"
X-Mailer: Microsoft Outlook 14.0
Thread-Index: AQFrVQWRgfWxqO62bUCfRKlwlCB1Cw==
Content-Language: en-us

This is a multipart message in MIME format.

------=_NextPart_000_0046_01D58B69.F7716B50
Content-Type: multipart/alternative;
    boundary="----=_NextPart_001_0047_01D58B69.F7716B50"

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

Hello,

Inline image

------=_NextPart_001_0047_01D58B69.F7716B50
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.org/TR/REC-html40"><head><META =
HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; =
charset=3Dus-ascii"><meta name=3DGenerator content=3D"Microsoft Word 14 =
(filtered medium)"><!--[if !mso]><style>v\:* =
{behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
..shape {behavior:url(#default#VML);}
</style><![endif]--><style><!--
/* Font Definitions */
@font-face
    {font-family:Calibri;
    panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
    {font-family:Tahoma;
    panose-1:2 11 6 4 3 5 4 4 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
    {margin:0in;
    margin-bottom:.0001pt;
    font-size:11.0pt;
    font-family:"Calibri","sans-serif";
    mso-fareast-language:EN-US;}
a:link, span.MsoHyperlink
    {mso-style-priority:99;
    color:blue;
    text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
    {mso-style-priority:99;
    color:purple;
    text-decoration:underline;}
p.MsoAcetate, li.MsoAcetate, div.MsoAcetate
    {mso-style-priority:99;
    mso-style-link:"\0422\0435\043A\0441\0442 =
\0432\044B\043D\043E\0441\043A\0438 \0417\043D\0430\043A";
    margin:0in;
    margin-bottom:.0001pt;
    font-size:8.0pt;
    font-family:"Tahoma","sans-serif";
    mso-fareast-language:EN-US;}
span.EmailStyle17
    {mso-style-type:personal-compose;
    font-family:"Calibri","sans-serif";
    color:windowtext;}
span.a
    {mso-style-name:"\0422\0435\043A\0441\0442 =
\0432\044B\043D\043E\0441\043A\0438 \0417\043D\0430\043A";
    mso-style-priority:99;
    mso-style-link:"\0422\0435\043A\0441\0442 =
\0432\044B\043D\043E\0441\043A\0438";
    font-family:"Tahoma","sans-serif";}
..MsoChpDefault
    {mso-style-type:export-only;
    font-family:"Calibri","sans-serif";
    mso-fareast-language:EN-US;}
@page WordSection1
    {size:8.5in 11.0in;
    margin:42.5pt 42.5pt 42.5pt 70.85pt;}
div.WordSection1
    {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext=3D"edit" spidmax=3D"1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext=3D"edit">
<o:idmap v:ext=3D"edit" data=3D"1" />
</o:shapelayout></xml><![endif]--></head><body lang=3DRU link=3Dblue =
vlink=3Dpurple><div class=3DWordSection1><p class=3DMsoNormal><span =
lang=3DEN-US>Hello,<o:p></o:p></span></p><p class=3DMsoNormal><span =
lang=3DEN-US><o:p>&nbsp;</o:p></span></p><p class=3DMsoNormal><span =
lang=3DEN-US>Inline image<o:p></o:p></span></p><p =
class=3DMsoNormal><span style=3D'mso-fareast-language:RU'><img =
width=3D64 height=3D64 =
id=3D"&#1056;&#1080;&#1089;&#1091;&#1085;&#1086;&#1082;_x0020_1" =
src=3D"cid:image001.png@01D58B69.D8279F80"></span><span =
lang=3DEN-US><o:p></o:p></span></p><p class=3DMsoNormal><span =
lang=3DEN-US><o:p>&nbsp;</o:p></span></p><p class=3DMsoNormal><span =
lang=3DEN-US></span><span lang=3DEN-US =
style=3D'mso-fareast-language:RU'><o:p></o:p></span></p><p =
class=3DMsoNormal><o:p>&nbsp;</o:p></p></div></body></html>
------=_NextPart_001_0047_01D58B69.F7716B50--

------=_NextPart_000_0046_01D58B69.F7716B50
Content-Type: image/png;
    name="image001.png"
Content-Transfer-Encoding: base64
Content-ID: <image001.png@01D58B69.D8279F80>

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

------=_NextPart_000_0046_01D58B69.F7716B50--

------=_NextPart_000_004B_01D58B69.F7719260--

We will get this in HEX (\r removed):

[core] 46 72 6f 6d 3a 20 3c 74 6f 40 65 78 61 6d 70 6c 65 2e 63 6f 6d 3e a

We can also see that Haraka removes dots. In this example ..shape {behavior:url(#default#VML);} becomes .shape {behavior:url(#default#VML);}

celesteking commented 4 years ago

What if you try reading from attachment stream as explained in https://haraka.github.io/manual/Transaction.html , that is, via pipe mechanism? Will you get the same results?

mitridatik commented 4 years ago

Sorry, checked again and it still removes \r even if reading from stream through pipe as you suggested.