summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/compose/test/unit/test_longLines.js
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mailnews/compose/test/unit/test_longLines.js')
-rw-r--r--comm/mailnews/compose/test/unit/test_longLines.js232
1 files changed, 232 insertions, 0 deletions
diff --git a/comm/mailnews/compose/test/unit/test_longLines.js b/comm/mailnews/compose/test/unit/test_longLines.js
new file mode 100644
index 0000000000..cd75e75d38
--- /dev/null
+++ b/comm/mailnews/compose/test/unit/test_longLines.js
@@ -0,0 +1,232 @@
+/*
+ * Test ensuring that messages with "long lines" are transmitted correctly.
+ * Most of this test was copied from test_messageHeaders.js.
+ */
+
+const { MimeParser } = ChromeUtils.import("resource:///modules/mimeParser.jsm");
+
+var CompFields = CC(
+ "@mozilla.org/messengercompose/composefields;1",
+ Ci.nsIMsgCompFields
+);
+
+// Copied from jsmime.js.
+function stringToTypedArray(buffer) {
+ var typedarray = new Uint8Array(buffer.length);
+ for (var i = 0; i < buffer.length; i++) {
+ typedarray[i] = buffer.charCodeAt(i);
+ }
+ return typedarray;
+}
+
+function checkDraftHeadersAndBody(
+ expectedHeaders,
+ expectedBody,
+ charset = "UTF-8"
+) {
+ let msgData = mailTestUtils.loadMessageToString(
+ gDraftFolder,
+ mailTestUtils.firstMsgHdr(gDraftFolder)
+ );
+ checkMessageHeaders(msgData, expectedHeaders);
+
+ // Get the message body, decode from base64 and check.
+ let endOfHeaders = msgData.indexOf("\r\n\r\n");
+ let body = msgData.slice(endOfHeaders + 4);
+ let endOfBody = body.indexOf("\r\n\r\n");
+
+ if (endOfBody > 0) {
+ body = body.slice(0, endOfBody);
+ } else {
+ body = body.slice(0, body.length);
+ }
+
+ // Remove line breaks and decode from base64 if required.
+ if (expectedHeaders["Content-Transfer-Encoding"] == "base64") {
+ body = atob(body.replace(/\r\n/g, ""));
+ }
+
+ if (charset == "UTF-8") {
+ let expectedBinary = String.fromCharCode.apply(
+ undefined,
+ new TextEncoder("UTF-8").encode(expectedBody)
+ );
+ Assert.equal(body, expectedBinary);
+ } else {
+ let strView = stringToTypedArray(body);
+ let decodedBody = new TextDecoder(charset).decode(strView);
+ Assert.equal(decodedBody, expectedBody);
+ }
+}
+
+function checkMessageHeaders(msgData, expectedHeaders, partNum = "") {
+ let seen = false;
+ let handler = {
+ startPart(part, headers) {
+ if (part != partNum) {
+ return;
+ }
+ seen = true;
+ for (let header in expectedHeaders) {
+ let expected = expectedHeaders[header];
+ if (expected === undefined) {
+ Assert.ok(!headers.has(header));
+ } else {
+ let value = headers.getRawHeader(header);
+ Assert.equal(value.length, 1);
+ value[0] = value[0].replace(/boundary=[^;]*(;|$)/, "boundary=.");
+ Assert.equal(value[0], expected);
+ }
+ }
+ },
+ };
+ MimeParser.parseSync(msgData, handler, {
+ onerror(e) {
+ throw e;
+ },
+ });
+ Assert.ok(seen);
+}
+
+// Create a line with 600 letters 'a' with acute accent, encoded as
+// two bytes c3a1 in UTF-8.
+let longMultibyteLine = "\u00E1".repeat(600);
+
+// And here a line with a Korean character, encoded as three bytes
+// ec9588 in UTF-8.
+let longMultibyteLineCJK = "안".repeat(400);
+
+// And some Japanese.
+let longMultibyteLineJapanese = "語".repeat(450);
+
+async function testBodyWithLongLine() {
+ // Lines in the message body are split by CRLF according to RFC 5322, should
+ // be independent of the system.
+ let newline = "\r\n";
+
+ let fields = new CompFields();
+ let identity = getSmtpIdentity(
+ "from@tinderbox.invalid",
+ getBasicSmtpServer()
+ );
+ identity.fullName = "Me";
+ identity.organization = "World Destruction Committee";
+ fields.from = "Nobody <nobody@tinderbox.invalid>";
+ fields.to = "Nobody <nobody@tinderbox.invalid>";
+ fields.subject = "Message with 1200 byte line in body";
+ let htmlMessage =
+ "<html><head>" +
+ '<meta http-equiv="content-type" content="text/html; charset=utf-8">' +
+ "</head><body>" +
+ longMultibyteLine +
+ "</body></html>\r\n\r\n";
+ fields.body = htmlMessage;
+ await richCreateMessage(fields, [], identity);
+ checkDraftHeadersAndBody(
+ {
+ "Content-Type": "text/html; charset=UTF-8",
+ "Content-Transfer-Encoding": "base64",
+ },
+ htmlMessage
+ );
+
+ // Again, but this time as plain text.
+ fields.body = htmlMessage;
+ fields.forcePlainText = true;
+ fields.useMultipartAlternative = false;
+ await richCreateMessage(fields, [], identity);
+ checkDraftHeadersAndBody(
+ {
+ "Content-Type": "text/plain; charset=UTF-8; format=flowed",
+ "Content-Transfer-Encoding": "base64",
+ },
+ longMultibyteLine + " " + newline + newline // Expected body: The message without the tags.
+ );
+
+ // Now CJK.
+ fields.forcePlainText = false;
+ htmlMessage =
+ "<html><head>" +
+ '<meta http-equiv="content-type" content="text/html; charset=utf-8">' +
+ "</head><body>" +
+ longMultibyteLineCJK +
+ "</body></html>\r\n\r\n";
+ fields.body = htmlMessage;
+ await richCreateMessage(fields, [], identity);
+ checkDraftHeadersAndBody(
+ {
+ "Content-Type": "text/html; charset=UTF-8",
+ "Content-Transfer-Encoding": "base64",
+ },
+ htmlMessage
+ );
+
+ // Again, but this time as plain text.
+ fields.body = htmlMessage;
+ fields.forcePlainText = true;
+ fields.useMultipartAlternative = false;
+ await richCreateMessage(fields, [], identity);
+ checkDraftHeadersAndBody(
+ {
+ "Content-Type": "text/plain; charset=UTF-8; format=flowed",
+ "Content-Transfer-Encoding": "base64",
+ },
+ longMultibyteLineCJK + " " + newline + newline // Expected body: The message without the tags.
+ );
+
+ // Now a test for ISO-2022-JP.
+ fields.forcePlainText = false;
+ htmlMessage =
+ "<html><head>" +
+ '<meta http-equiv="content-type" content="text/html; charset=ISO-2022-JP">' +
+ "</head><body>" +
+ longMultibyteLineJapanese +
+ "</body></html>\r\n\r\n";
+ fields.body = htmlMessage;
+ await richCreateMessage(fields, [], identity);
+ checkDraftHeadersAndBody(
+ {
+ "Content-Type": "text/html; charset=UTF-8",
+ "Content-Transfer-Encoding": "base64",
+ },
+ htmlMessage
+ );
+
+ // Again, but this time as plain text.
+ fields.body = htmlMessage;
+ fields.forcePlainText = true;
+ fields.useMultipartAlternative = false;
+ await richCreateMessage(fields, [], identity);
+
+ let expectedBody = longMultibyteLineJapanese + " " + newline + newline;
+
+ checkDraftHeadersAndBody(
+ {
+ "Content-Type": "text/plain; charset=UTF-8; format=flowed",
+ "Content-Transfer-Encoding": "base64",
+ },
+ expectedBody
+ );
+
+ // Again, but this time not flowed.
+ fields.body = htmlMessage;
+ Services.prefs.setBoolPref("mailnews.send_plaintext_flowed", false);
+
+ await richCreateMessage(fields, [], identity);
+ checkDraftHeadersAndBody(
+ {
+ "Content-Type": "text/plain; charset=UTF-8",
+ "Content-Transfer-Encoding": "base64",
+ },
+ expectedBody.replace(/ /g, "") // No spaces expected this time.
+ );
+}
+
+var tests = [testBodyWithLongLine];
+
+function run_test() {
+ // Ensure we have at least one mail account
+ localAccountUtils.loadLocalMailAccount();
+ tests.forEach(x => add_task(x));
+ run_next_test();
+}