Bug 1259534 - fix body search of base64 encoded bodies (incl. 10 new test cases). r=aceman

This commit is contained in:
Jorg K 2017-12-31 12:47:00 +01:00
Родитель 037e44335c
Коммит 4dcc9c1486
13 изменённых файлов: 476 добавлений и 41 удалений

Просмотреть файл

@ -88,20 +88,21 @@ protected:
// Transformations // Transformations
// With the exception of m_isMultipart, these all apply to the various parts // With the exception of m_isMultipart, these all apply to the various parts
bool m_stripHeaders; // true if we're supposed to strip of message headers bool m_stripHeaders; // true if we're supposed to strip of message headers
bool m_stripHtml; // true if we're supposed to strip off HTML tags bool m_stripHtml; // true if we're supposed to strip off HTML tags
bool m_pastHeaders; // true if we've already skipped over the headers bool m_pastMsgHeaders; // true if we've already skipped over the message headers
bool m_partIsHtml; // true if the Content-type header claims text/html bool m_pastPartHeaders; // true if we've already skipped over the part headers
bool m_base64part; // true if the current part is in base64 bool m_partIsHtml; // true if the Content-type header claims text/html
bool m_isMultipart; // true if the message is a multipart/* message bool m_base64part; // true if the current part is in base64
bool m_partIsText; // true if the current part is text/* bool m_isMultipart; // true if the message is a multipart/* message
bool m_partIsText; // true if the current part is text/*
nsCString boundary; // The boundary string to look for nsTArray<nsCString> m_boundaries; // The boundary strings to look for
// See implementation for comments // See implementation for comments
int32_t ApplyTransformations (const nsCString &line, int32_t length, int32_t ApplyTransformations (const nsCString &line, int32_t length,
bool &returnThisLine, nsCString &buf); bool &returnThisLine, nsCString &buf);
void SniffPossibleMIMEHeader (nsCString &line); void SniffPossibleMIMEHeader (const nsCString &line);
static void StripHtml (nsCString &buf); static void StripHtml (nsCString &buf);
static void Base64Decode (nsCString &buf); static void Base64Decode (nsCString &buf);
}; };

Просмотреть файл

@ -79,7 +79,8 @@ void nsMsgBodyHandler::Initialize()
m_base64part = false; m_base64part = false;
m_isMultipart = false; m_isMultipart = false;
m_partIsText = true; // default is text/plain m_partIsText = true; // default is text/plain
m_pastHeaders = false; m_pastMsgHeaders = false;
m_pastPartHeaders = false;
m_headerBytesRead = 0; m_headerBytesRead = 0;
} }
@ -186,7 +187,7 @@ int32_t nsMsgBodyHandler::GetNextLocalLine(nsCString &buf)
// I the line count is in body lines, only decrement once we have // I the line count is in body lines, only decrement once we have
// processed all the headers. Otherwise the line is not in body // processed all the headers. Otherwise the line is not in body
// lines and we want to decrement for every line. // lines and we want to decrement for every line.
if (m_pastHeaders || !m_lineCountInBodyLines) if (m_pastMsgHeaders || !m_lineCountInBodyLines)
m_numLocalLines--; m_numLocalLines--;
// do we need to check the return value here? // do we need to check the return value here?
if (m_fileLineStream) if (m_fileLineStream)
@ -206,13 +207,13 @@ int32_t nsMsgBodyHandler::GetNextLocalLine(nsCString &buf)
* *
* It applies the following sequences in order * It applies the following sequences in order
* * Removes headers if the searcher doesn't want them * * Removes headers if the searcher doesn't want them
* (sets m_pastHeaders) * (sets m_past*Headers)
* * Determines the current MIME type. * * Determines the current MIME type.
* (via SniffPossibleMIMEHeader) * (via SniffPossibleMIMEHeader)
* * Strips any HTML if the searcher doesn't want it * * Strips any HTML if the searcher doesn't want it
* * Strips non-text parts * * Strips non-text parts
* * Decodes any base64 part * * Decodes any base64 part
* (resetting part variables: m_base64part, m_pastHeaders, m_partIsHtml, * (resetting part variables: m_base64part, m_pastPartHeaders, m_partIsHtml,
* m_partIsText) * m_partIsText)
* *
* @param line (in) the current line * @param line (in) the current line
@ -229,7 +230,7 @@ int32_t nsMsgBodyHandler::ApplyTransformations (const nsCString &line, int32_t l
int32_t newLength = length; int32_t newLength = length;
eatThisLine = false; eatThisLine = false;
if (!m_pastHeaders) // line is a line from the message headers if (!m_pastPartHeaders) // line is a line from the part headers
{ {
if (m_stripHeaders) if (m_stripHeaders)
eatThisLine = true; eatThisLine = true;
@ -240,14 +241,29 @@ int32_t nsMsgBodyHandler::ApplyTransformations (const nsCString &line, int32_t l
SniffPossibleMIMEHeader(buf); SniffPossibleMIMEHeader(buf);
m_pastHeaders = buf.IsEmpty() || buf.First() == '\r' || m_pastPartHeaders = buf.IsEmpty() || buf.First() == '\r' ||
buf.First() == '\n'; buf.First() == '\n';
// We set m_pastMsgHeaders to 'true' only once.
if (m_pastPartHeaders)
m_pastMsgHeaders = true;
return length; return length;
} }
// Check to see if this is the boundary string // Check to see if this is one of our boundary strings.
if (m_isMultipart && StringBeginsWith(line, boundary)) bool matchedBoundary = false;
if (m_isMultipart && m_boundaries.Length() > 0) {
for (int32_t i = (int32_t)m_boundaries.Length() - 1; i >= 0; i--) {
if (StringBeginsWith(line, m_boundaries[i])) {
matchedBoundary = true;
// If we matched a boundary, we won't need the nested/later ones any more.
m_boundaries.SetLength(i+1);
break;
}
}
}
if (matchedBoundary)
{ {
if (m_base64part && m_partIsText) if (m_base64part && m_partIsText)
{ {
@ -260,7 +276,9 @@ int32_t nsMsgBodyHandler::ApplyTransformations (const nsCString &line, int32_t l
} }
else else
{ {
ApplyTransformations(buf, buf.Length(), eatThisLine, buf); // It is wrong to call ApplyTransformations() here since this will
// lead to the buffer being doubled-up at |buf.Append(line.get());| below.
// ApplyTransformations(buf, buf.Length(), eatThisLine, buf);
// Avoid spurious failures // Avoid spurious failures
eatThisLine = false; eatThisLine = false;
} }
@ -273,9 +291,13 @@ int32_t nsMsgBodyHandler::ApplyTransformations (const nsCString &line, int32_t l
// Reset all assumed headers // Reset all assumed headers
m_base64part = false; m_base64part = false;
m_pastHeaders = false; // Get ready to sniff new part headers, but do not reset m_pastMsgHeaders
// since it will screw the body line count.
m_pastPartHeaders = false;
m_partIsHtml = false; m_partIsHtml = false;
m_partIsText = true; // If we ever see a multipart message, each part needs to set 'm_partIsText',
// so no more defaulting to 'true' when the part is done.
m_partIsText = false;
return buf.Length(); return buf.Length();
} }
@ -342,7 +364,7 @@ void nsMsgBodyHandler::StripHtml (nsCString &pBufInOut)
* *
* @param line (in) a header line that may contain a MIME header * @param line (in) a header line that may contain a MIME header
*/ */
void nsMsgBodyHandler::SniffPossibleMIMEHeader(nsCString &line) void nsMsgBodyHandler::SniffPossibleMIMEHeader(const nsCString &line)
{ {
// Some parts of MIME are case-sensitive and other parts are case-insensitive; // Some parts of MIME are case-sensitive and other parts are case-insensitive;
// specifically, the headers are all case-insensitive and the values we care // specifically, the headers are all case-insensitive and the values we care
@ -354,7 +376,10 @@ void nsMsgBodyHandler::SniffPossibleMIMEHeader(nsCString &line)
if (StringBeginsWith(lowerCaseLine, NS_LITERAL_CSTRING("content-type:"))) if (StringBeginsWith(lowerCaseLine, NS_LITERAL_CSTRING("content-type:")))
{ {
if (lowerCaseLine.Find("text/html", /* ignoreCase = */ true) != -1) if (lowerCaseLine.Find("text/html", /* ignoreCase = */ true) != -1)
{
m_partIsText = true;
m_partIsHtml = true; m_partIsHtml = true;
}
// Strenuous edge case: a message/rfc822 is equivalent to the content type // Strenuous edge case: a message/rfc822 is equivalent to the content type
// of whatever the message is. Headers should be ignored here. Even more // of whatever the message is. Headers should be ignored here. Even more
// strenuous are message/partial and message/external-body, where the first // strenuous are message/partial and message/external-body, where the first
@ -369,20 +394,21 @@ void nsMsgBodyHandler::SniffPossibleMIMEHeader(nsCString &line)
{ {
if (m_isMultipart) if (m_isMultipart)
{ {
// This means we have a nested multipart tree. Since we currently only // Nested multipart, get ready for new headers.
// handle the first children, we are probably better off assuming that m_base64part = false;
// this nested part is going to have text/* children. After all, the m_pastPartHeaders = false;
// biggest usage that I've seen is multipart/signed. m_partIsHtml = false;
m_partIsText = true; m_partIsText = false;
} }
m_isMultipart = true; m_isMultipart = true;
} }
else if (lowerCaseLine.Find("text/", /* ignoreCase = */ true) != -1)
m_partIsText = true;
else if (lowerCaseLine.Find("text/", /* ignoreCase = */ true) == -1) else if (lowerCaseLine.Find("text/", /* ignoreCase = */ true) == -1)
m_partIsText = false; // We have disproved our assumption m_partIsText = false; // We have disproved our assumption
} }
// TODO: make this work for nested multiparts (requires some redesign) if (m_isMultipart &&
if (m_isMultipart && boundary.IsEmpty() &&
lowerCaseLine.Find("boundary=", /* ignoreCase = */ true) != -1) lowerCaseLine.Find("boundary=", /* ignoreCase = */ true) != -1)
{ {
int32_t start = lowerCaseLine.Find("boundary=", /* ignoreCase = */ true); int32_t start = lowerCaseLine.Find("boundary=", /* ignoreCase = */ true);
@ -393,8 +419,14 @@ void nsMsgBodyHandler::SniffPossibleMIMEHeader(nsCString &line)
if (end == -1) if (end == -1)
end = line.Length(); end = line.Length();
// Collect all boundaries. Since we only react to crossing a boundary,
// we can simply collect the boundaries instead of forming a tree
// structure from the message. Keep it simple ;-)
nsCString boundary;
boundary.AssignLiteral("--"); boundary.AssignLiteral("--");
boundary.Append(Substring(line,start,end-start)); boundary.Append(Substring(line,start,end-start));
if (!m_boundaries.Contains(boundary))
m_boundaries.AppendElement(boundary);
} }
if (StringBeginsWith(lowerCaseLine, if (StringBeginsWith(lowerCaseLine,

Просмотреть файл

@ -34,26 +34,49 @@ var Files =
"../../../data/base64-1", "../../../data/base64-1",
"../../../data/basic1", "../../../data/basic1",
"../../../data/multipart-base64-2", "../../../data/multipart-base64-2",
"../../../data/bug132340" "../../../data/bug132340",
"../../../data/01-plaintext.eml",
"../../../data/02-plaintext+attachment.eml",
"../../../data/03-HTML.eml",
"../../../data/04-HTML+attachment.eml",
"../../../data/05-HTML+embedded-image.eml",
"../../../data/06-plaintext+HMTL.eml",
"../../../data/07-plaintext+(HTML+embedded-image).eml",
"../../../data/08-plaintext+HTML+attachment.eml",
"../../../data/09-(HTML+embedded-image)+attachment.eml",
"../../../data/10-plaintext+(HTML+embedded-image)+attachment.eml"
] ]
var Tests = var Tests =
[ [
/* Translate Base64 messages */ /* Translate Base64 messages */
{ value: "World!", // "World!" is contained in three messages, but in bug132340 it's not in a text
op: Contains, // part and should be found.
count: 2 }, { value: "World!", op: Contains, count: 2 },
/* Don't match the base64 text */ /* Don't match the base64 text */
{ value: "DQp", { value: "DQp", op: Contains, count: 0 },
op: Contains,
count: 0 },
/* Nested multipart/mixed, don't match */ /* Nested multipart/mixed, don't match */
{ value: "PGh", { value: "PGh", op: Contains, count: 0 },
op: Contains,
count: 0 },
/* An encoded base-64 text/plain match */ /* An encoded base-64 text/plain match */
{ value: "base 64 text", { value: "base 64 text", op: Contains, count: 1 },
op: Contains,
count: 1 }, // Comprehensive test of various MIME structures, messages 01 to 10.
// Messages 01 to 10 contain "huhu" once.
{ value: "huhu", op: Contains, count: 10 },
// Messages 06, 07, 08, 10 contain "hihi" in the plaintext part.
{ value: "hihi", op: Contains, count: 4 },
// The base64 of embedded images and attachments contains "iVBORw" and we don't
// want to find that.
{ value: "iVBORw", op: Contains, count: 0 },
// The base64 of attachments contains "wMA005J0z" and we don't want to find that.
{ value: "wMA005J0z", op: Contains, count: 0 },
// The base64 of the plaintext and HTML parts contains "U2VhcmNoIGZ"
// and we don't want to find that.
{ value: "U2VhcmNoIGZ", op: Contains, count: 0 },
]; ];
function fixFile(file) { function fixFile(file) {

Просмотреть файл

@ -0,0 +1,14 @@
To: test@example.com
From: test@example.com
Subject: 1 plaintext
Message-ID: <8259dd8e-2293-8765-e720-61dfcd10a6f3@example.com>
Date: Sat, 30 Dec 2017 19:12:38 +0100
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101
Thunderbird/59.0a1
MIME-Version: 1.0
Content-Type: text/plain; charset=windows-1252; format=flowed
Content-Transfer-Encoding: base64
Content-Language: en-GB
U2VhcmNoIGZvciBodWh1

Просмотреть файл

@ -0,0 +1,32 @@
To: test@example.com
From: test@example.com
Subject: 2 plaintext + attachment
Message-ID: <9ec4f4cb-b14b-aed6-a042-58897d12e4a9@example.com>
Date: Sat, 30 Dec 2017 19:15:38 +0100
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101
Thunderbird/59.0a1
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="------------BC006DD22051247571F398E0"
Content-Language: en-GB
This is a multi-part message in MIME format.
--------------BC006DD22051247571F398E0
Content-Type: text/plain; charset=windows-1252; format=flowed
Content-Transfer-Encoding: base64
U2VhcmNoIGZvciBodWh1
--------------BC006DD22051247571F398E0
Content-Type: image/png;
name="attach.png"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="attach.png"
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAARnQU1B
AACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hv
dF5VCAUAAABpSURBVDhP3dA7EoAgDEXR7Ew+bgdx/018BEYyiICtb27FcCig3Z7Im6gK3ZxN
/RcQkb6aK8DjtuRMzMEAiNGvlFpgtyOdEjFz14xA10wA1pg5wLRZAthtVgEm5vGtA4DhvILa
O8A+AuYLy0U5xUUpL8kAAAAASUVORK5CYII=
--------------BC006DD22051247571F398E0--

Просмотреть файл

@ -0,0 +1,14 @@
To: test@example.com
From: test@example.com
Subject: 3 HTML
Message-ID: <8259dd8e-2293-8765-e720-61dfcd10a6f3@example.com>
Date: Sat, 30 Dec 2017 19:12:38 +0100
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101
Thunderbird/59.0a1
MIME-Version: 1.0
Content-Type: text/html; charset=windows-1252; format=flowed
Content-Transfer-Encoding: base64
Content-Language: en-GB
PGJvZHk+U2VhcmNoIGZvciA8Yj5odWh1PC9iPjwvYm9keT4=

Просмотреть файл

@ -0,0 +1,32 @@
To: test@example.com
From: test@example.com
Subject: 4 HTML + attachment
Message-ID: <9ec4f4cb-b14b-aed6-a042-58897d12e4a9@example.com>
Date: Sat, 30 Dec 2017 19:15:38 +0100
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101
Thunderbird/59.0a1
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="------------BC006DD22051247571F398E0"
Content-Language: en-GB
This is a multi-part message in MIME format.
--------------BC006DD22051247571F398E0
Content-Type: text/html; charset=windows-1252; format=flowed
Content-Transfer-Encoding: base64
PGJvZHk+U2VhcmNoIGZvciA8Yj5odWh1PC9iPjwvYm9keT4=
--------------BC006DD22051247571F398E0
Content-Type: image/png;
name="attach.png"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="attach.png"
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAARnQU1B
AACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hv
dF5VCAUAAABpSURBVDhP3dA7EoAgDEXR7Ew+bgdx/018BEYyiICtb27FcCig3Z7Im6gK3ZxN
/RcQkb6aK8DjtuRMzMEAiNGvlFpgtyOdEjFz14xA10wA1pg5wLRZAthtVgEm5vGtA4DhvILa
O8A+AuYLy0U5xUUpL8kAAAAASUVORK5CYII=
--------------BC006DD22051247571F398E0--

Просмотреть файл

@ -0,0 +1,38 @@
To: test@example.com
From: test@example.com
Subject: 5 HTML + embedded image
Message-ID: <c1ddcd5d-71c1-9c9d-1b81-e3b9abb99030@example.com>
Date: Sat, 30 Dec 2017 19:26:23 +0100
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101
Thunderbird/59.0a1
MIME-Version: 1.0
Content-Type: multipart/related;
boundary="------------B2BBD36A919AB2B2F84E2469"
Content-Language: en-GB
This is a multi-part message in MIME format.
--------------B2BBD36A919AB2B2F84E2469
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: base64
PGh0bWw+DQogIDxoZWFkPg0KDQogICAgPG1ldGEgaHR0cC1lcXVpdj0iY29udGVudC10eXBl
IiBjb250ZW50PSJ0ZXh0L2h0bWw7IGNoYXJzZXQ9d2luZG93cy0xMjUyIj4NCiAgPC9oZWFk
Pg0KICA8Ym9keSB0ZXh0PSIjMDAwMDAwIiBiZ2NvbG9yPSIjRkZGRkZGIj4NCiAgICA8cD48
dHQ+U2VhcmNoIGZvciBodWh1PC90dD48L3A+DQogICAgPHA+PGltZyBzcmM9ImNpZDpwYXJ0
MS44QzVFNkE4MS5EMEMxQjkxQUBqb3Jnay5jb20iIGFsdD0iIj48L3A+DQogIDwvYm9keT4N
CjwvaHRtbD4=
--------------B2BBD36A919AB2B2F84E2469
Content-Type: image/png;
name="kigaaldcbanejcbi.png"
Content-Transfer-Encoding: base64
Content-ID: <part1.8C5E6A81.D0C1B91A@jorgk.com>
Content-Disposition: inline;
filename="kigaaldcbanejcbi.png"
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAARnQU1B
AACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hv
dF5VCAUAAABpSURBVDhP3dA7EoAgDEXR7Ew+bgdx/018BEYyiICtb27FcCig3Z7Im6gK3ZxN
/RcQkb6aK8DjtuRMzMEAiNGvlFpgtyOdEjFz14xA10wA1pg5wLRZAthtVgEm5vGtA4DhvILa
O8A+AuYLy0U5xUUpL8kAAAAASUVORK5CYII=
--------------B2BBD36A919AB2B2F84E2469--

Просмотреть файл

@ -0,0 +1,27 @@
To: test@example.com
From: test@example.com
Subject: 6 plaintext + HMTL
Message-ID: <a30f750d-d56c-8a52-971c-f95a131e8332@example.com>
Date: Sat, 30 Dec 2017 19:31:21 +0100
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101
Thunderbird/59.0a1
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="------------FAB286B8794CC63C0A0FD1BB"
Content-Language: de-DE
This is a multi-part message in MIME format.
--------------FAB286B8794CC63C0A0FD1BB
Content-Type: text/plain; charset=windows-1252; format=flowed
Content-Transfer-Encoding: base64
U2VhcmNoIGZvciBoaWhp
--------------FAB286B8794CC63C0A0FD1BB
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: base64
PGJvZHk+U2VhcmNoIGZvciA8Yj5odWh1PC9iPjwvYm9keT4=
--------------FAB286B8794CC63C0A0FD1BB--

Просмотреть файл

@ -0,0 +1,52 @@
To: test@example.com
From: test@example.com
Subject: 7 plaintext + (HTML + embedded image)
Message-ID: <fd7a5d4a-6a3a-8b9b-b3e4-9e9391c3c703@example.com>
Date: Sat, 30 Dec 2017 19:36:00 +0100
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101
Thunderbird/59.0a1
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="------------77E82F0826A0A90EABD21FC3"
Content-Language: en-GB
This is a multi-part message in MIME format.
--------------77E82F0826A0A90EABD21FC3
Content-Type: text/plain; charset=windows-1252; format=flowed
Content-Transfer-Encoding: base64
U2VhcmNoIGZvciBoaWhp
--------------77E82F0826A0A90EABD21FC3
Content-Type: multipart/related;
boundary="------------D719681335F2A7D71D3761B1"
--------------D719681335F2A7D71D3761B1
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: base64
PGh0bWw+DQogIDxoZWFkPg0KDQogICAgPG1ldGEgaHR0cC1lcXVpdj0iY29udGVudC10eXBl
IiBjb250ZW50PSJ0ZXh0L2h0bWw7IGNoYXJzZXQ9d2luZG93cy0xMjUyIj4NCiAgPC9oZWFk
Pg0KICA8Ym9keSB0ZXh0PSIjMDAwMDAwIiBiZ2NvbG9yPSIjRkZGRkZGIj4NCiAgICA8cD48
dHQ+U2VhcmNoIGZvciBodWh1PC90dD48L3A+DQogICAgPHA+PGltZyBzcmM9ImNpZDpwYXJ0
MS44QzVFNkE4MS5EMEMxQjkxQUBqb3Jnay5jb20iIGFsdD0iIj48L3A+DQogIDwvYm9keT4N
CjwvaHRtbD4=
--------------D719681335F2A7D71D3761B1
Content-Type: image/png;
name="kigaaldcbanejcbi.png"
Content-Transfer-Encoding: base64
Content-ID: <part1.8C5E6A81.D0C1B91A@jorgk.com>
Content-Disposition: inline;
filename="kigaaldcbanejcbi.png"
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAARnQU1B
AACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hv
dF5VCAUAAABpSURBVDhP3dA7EoAgDEXR7Ew+bgdx/018BEYyiICtb27FcCig3Z7Im6gK3ZxN
/RcQkb6aK8DjtuRMzMEAiNGvlFpgtyOdEjFz14xA10wA1pg5wLRZAthtVgEm5vGtA4DhvILa
O8A+AuYLy0U5xUUpL8kAAAAASUVORK5CYII=
--------------D719681335F2A7D71D3761B1--
--------------77E82F0826A0A90EABD21FC3--

Просмотреть файл

@ -0,0 +1,46 @@
To: test@example.com
From: test@example.com
Subject: 8 plaintext + HTML + attachment
Message-ID: <b09c8682-a485-98ee-8f8e-edb89a1deec3@example.com>
Date: Sat, 30 Dec 2017 19:58:40 +0100
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101
Thunderbird/59.0a1
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="------------A1EC8071C6B86B871C9CB87F"
Content-Language: en-GB
This is a multi-part message in MIME format.
--------------A1EC8071C6B86B871C9CB87F
Content-Type: multipart/alternative;
boundary="------------9EC5D7C387C9839604A227BB"
--------------9EC5D7C387C9839604A227BB
Content-Type: text/plain; charset=windows-1252; format=flowed
Content-Transfer-Encoding: base64
U2VhcmNoIGZvciBoaWhp
--------------9EC5D7C387C9839604A227BB
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: base64
PGJvZHk+U2VhcmNoIGZvciA8Yj5odWh1PC9iPjwvYm9keT4=
--------------9EC5D7C387C9839604A227BB--
--------------A1EC8071C6B86B871C9CB87F
Content-Type: image/png;
name="attach.png"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="attach.png"
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAARnQU1B
AACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hv
dF5VCAUAAABpSURBVDhP3dA7EoAgDEXR7Ew+bgdx/018BEYyiICtb27FcCig3Z7Im6gK3ZxN
/RcQkb6aK8DjtuRMzMEAiNGvlFpgtyOdEjFz14xA10wA1pg5wLRZAthtVgEm5vGtA4DhvILa
O8A+AuYLy0U5xUUpL8kAAAAASUVORK5CYII=
--------------A1EC8071C6B86B871C9CB87F--

Просмотреть файл

@ -0,0 +1,55 @@
To: test@example.com
From: test@example.com
Subject: 9 (HTML + embedded image) + attachment
Message-ID: <cdf5bf44-03a4-4be1-c9c7-88cb4a5838ed@example.com>
Date: Sat, 30 Dec 2017 20:19:46 +0100
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101
Thunderbird/59.0a1
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="------------F5CEBCED9FC06ACB07B3D485"
Content-Language: en-GB
This is a multi-part message in MIME format.
--------------F5CEBCED9FC06ACB07B3D485
Content-Type: multipart/related;
boundary="------------1722706F2C203820A6CAA06F"
--------------1722706F2C203820A6CAA06F
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: base64
PGh0bWw+DQogIDxoZWFkPg0KDQogICAgPG1ldGEgaHR0cC1lcXVpdj0iY29udGVudC10eXBl
IiBjb250ZW50PSJ0ZXh0L2h0bWw7IGNoYXJzZXQ9d2luZG93cy0xMjUyIj4NCiAgPC9oZWFk
Pg0KICA8Ym9keSB0ZXh0PSIjMDAwMDAwIiBiZ2NvbG9yPSIjRkZGRkZGIj4NCiAgICA8cD48
dHQ+U2VhcmNoIGZvciBodWh1PC90dD48L3A+DQogICAgPHA+PGltZyBzcmM9ImNpZDpwYXJ0
MS44QzVFNkE4MS5EMEMxQjkxQUBqb3Jnay5jb20iIGFsdD0iIj48L3A+DQogIDwvYm9keT4N
CjwvaHRtbD4=
--------------1722706F2C203820A6CAA06F
Content-Type: image/png;
name="kigaaldcbanejcbi.png"
Content-Transfer-Encoding: base64
Content-ID: <part1.8C5E6A81.D0C1B91A@jorgk.com>
Content-Disposition: inline;
filename="kigaaldcbanejcbi.png"
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAARnQU1B
AACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hv
dF5VCAUAAABpSURBVDhP3dA7EoAgDEXR7Ew+bgdx/018BEYyiICtb27FcCig3Z7Im6gK3ZxN
/RcQkb6aK8DjtuRMzMEAiNGvlFpgtyOdEjFz14xA10wA1pg5wLRZAthtVgEm5vGtA4DhvILa
O8A+AuYLy0U5xUUpL8kAAAAASUVORK5CYII=
--------------1722706F2C203820A6CAA06F--
--------------F5CEBCED9FC06ACB07B3D485
Content-Type: image/png;
name="attach2.png"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="attach2.png"
iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAIAAACQKrqGAAAAAXNSR0IArs4c6QAAAARnQU1B
AACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hv
dF5VCAUAAAAVSURBVChTY/hPNBhVOqqUaKX//wMA005J0zvV0VsAAAAASUVORK5CYII=
--------------F5CEBCED9FC06ACB07B3D485--

Просмотреть файл

@ -0,0 +1,69 @@
To: test@example.com
From: test@example.com
Subject: 10 plaintext + (HTML + embedded image) + attachment
Message-ID: <1e58c8f2-3a15-96e7-76b7-046cf6e1ce1e@example.com>
Date: Sat, 30 Dec 2017 20:50:01 +0100
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101
Thunderbird/59.0a1
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="------------B94553864BC0A4472640622E"
Content-Language: en-GB
This is a multi-part message in MIME format.
--------------B94553864BC0A4472640622E
Content-Type: multipart/alternative;
boundary="------------B24EA868A72E5E6144485481"
--------------B24EA868A72E5E6144485481
Content-Type: text/plain; charset=windows-1252; format=flowed
Content-Transfer-Encoding: base64
U2VhcmNoIGZvciBoaWhp
--------------B24EA868A72E5E6144485481
Content-Type: multipart/related;
boundary="------------D1360749D11EBC0C64444B6C"
--------------D1360749D11EBC0C64444B6C
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: base64
PGh0bWw+DQogIDxoZWFkPg0KDQogICAgPG1ldGEgaHR0cC1lcXVpdj0iY29udGVudC10eXBl
IiBjb250ZW50PSJ0ZXh0L2h0bWw7IGNoYXJzZXQ9d2luZG93cy0xMjUyIj4NCiAgPC9oZWFk
Pg0KICA8Ym9keSB0ZXh0PSIjMDAwMDAwIiBiZ2NvbG9yPSIjRkZGRkZGIj4NCiAgICA8cD48
dHQ+U2VhcmNoIGZvciBodWh1PC90dD48L3A+DQogICAgPHA+PGltZyBzcmM9ImNpZDpwYXJ0
MS44QzVFNkE4MS5EMEMxQjkxQUBqb3Jnay5jb20iIGFsdD0iIj48L3A+DQogIDwvYm9keT4N
CjwvaHRtbD4=
--------------D1360749D11EBC0C64444B6C
Content-Type: image/png;
name="kigaaldcbanejcbi.png"
Content-Transfer-Encoding: base64
Content-ID: <part1.8C5E6A81.D0C1B91A@jorgk.com>
Content-Disposition: inline;
filename="kigaaldcbanejcbi.png"
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAARnQU1B
AACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hv
dF5VCAUAAABpSURBVDhP3dA7EoAgDEXR7Ew+bgdx/018BEYyiICtb27FcCig3Z7Im6gK3ZxN
/RcQkb6aK8DjtuRMzMEAiNGvlFpgtyOdEjFz14xA10wA1pg5wLRZAthtVgEm5vGtA4DhvILa
O8A+AuYLy0U5xUUpL8kAAAAASUVORK5CYII=
--------------D1360749D11EBC0C64444B6C--
--------------B24EA868A72E5E6144485481--
--------------B94553864BC0A4472640622E
Content-Type: image/png;
name="attach2.png"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="attach2.png"
iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAIAAACQKrqGAAAAAXNSR0IArs4c6QAAAARnQU1B
AACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASdEVYdFNvZnR3YXJlAEdyZWVuc2hv
dF5VCAUAAAAVSURBVChTY/hPNBhVOqqUaKX//wMA005J0zvV0VsAAAAASUVORK5CYII=
--------------B94553864BC0A4472640622E--