Revision control
Copy as Markdown
Other Tools
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
/**
* Test that pop3 download code and message storage works correctly.
*/
const { PromiseTestUtils } = ChromeUtils.importESModule(
);
const [daemon, server, handler] = setupServerDaemon();
server.start();
registerCleanupFunction(() => {
server.stop();
});
/**
* Helper function to parse an RFC5322 message.
* Not totally comprehensive, but good enough for tests.
*
* For example:
* parseMessage("From: Alice\r\nTo: Bob\r\n\r\nHello there!\r\n")
*
* Returns:
* [{"From":["Alice"], "To": "Bob"}, "Hello there!\r\n"]
*
* NOTE: The returned header values are arrays because headers can repeat.
*
*/
function parseMessage(raw) {
// Mbox separators are more common than you'd like in test data.
// We'll tolerate and discard them.
raw = raw.replace("/^From .*\r?\n/", "");
// Split header block and body.
const headerBody = raw.match(/(.*?)\r?\n\r?\n(.*)/s);
const body = headerBody[2];
// Parse the headers.
const headers = {};
// Flatten any multi-line headers (delete any EOL followed by whitespace).
const rawHdrs = headerBody[1].replaceAll(/\r?\n(\s)/g, "$1");
const headerLines = rawHdrs.split(/\r?\n/);
for (const line of headerLines) {
// Split "name: value".
const m = line.match(/^([^\s:]+):\s+(.*)$/);
if (m == null) {
continue; // Uh-oh... Bad header.
}
const name = m[1];
// Headers can have multiple values.
headers[name] ??= [];
headers[name].push(m[2]);
}
return [headers, body];
}
Services.prefs.setBoolPref("mailnews.downloadToTempFile", false);
/**
* Test that messages download correctly, and have some of the basic headers
* correctly parsed.
*/
add_task(async function testDownloadMessages() {
const incomingServer = createPop3ServerAndLocalFolders(server.port);
const testMessages = [
"message1.eml",
"message_with_from_line.eml",
"message2.eml",
"message3.eml",
];
incomingServer.leaveMessagesOnServer = true;
// Read our original test messages directly from disk.
const expectRaw = [];
for (const filename of testMessages) {
const f = PathUtils.join(do_get_cwd().path, "data", filename);
expectRaw.push(await IOUtils.readUTF8(f));
}
// Inject test messages into POP3 server, and fetch them.
daemon.setMessages(testMessages);
const urlListener = new PromiseTestUtils.PromiseUrlListener();
MailServices.pop3.GetNewMail(
null,
urlListener,
localAccountUtils.inboxFolder,
incomingServer
);
await urlListener.promise;
// Collect the downloaded messages back out from the folder.
const gotMsgHdrs = [];
const gotRaw = [];
for (const msgHdr of localAccountUtils.inboxFolder.messages) {
const streamListener = new PromiseTestUtils.PromiseStreamListener();
const msgURI = msgHdr.folder.getUriForMsg(msgHdr);
MailServices.messageServiceFromURI(msgURI).streamMessage(
msgURI,
streamListener,
null,
null,
false,
"",
false
);
gotRaw.push(await streamListener.promise);
gotMsgHdrs.push(msgHdr);
}
// Check each downloaded message against what we're expecting.
// We're assuming the same ordering, which is a bit dodgy, but
// fine for our fake test server.
Assert.equal(
expectRaw.length,
gotRaw.length,
"Download correct number of messages"
);
// Some headers we want to strip out (because they are added by pop3 and
// the local message store):
const blacklist = [
// POP3 additions:
"X-UIDL",
"X-Account-Key",
// msgStore additions:
"X-Mozilla-Status",
"X-Mozilla-Status2",
"X-Mozilla-Keys",
];
// Check the downloaded messages against the expected data.
for (let i = 0; i < expectRaw.length; ++i) {
// Parse the message.
let [expectHeaders, expectBody] = parseMessage(expectRaw[i]);
let [gotHeaders, gotBody] = parseMessage(gotRaw[i]);
// Strip blacklisted headers.
for (const bad of blacklist) {
delete gotHeaders[bad];
delete expectHeaders[bad];
}
// Normalise EOLs and compare body.
expectBody = gotBody.replaceAll(/\r\n/gs, "\n");
gotBody = gotBody.replaceAll(/\r\n/gs, "\n");
Assert.equal(expectBody, gotBody, "Message bodies match");
// Compare headers (stripping out ones that might have added).
Assert.deepEqual(expectHeaders, gotHeaders, "Message headers match");
if ("Subject" in expectHeaders) {
Assert.equal(
gotMsgHdrs[i].subject,
expectHeaders.Subject.join(","),
"Parsed subject matches"
);
}
}
// Clean up.
MailServices.accounts.removeIncomingServer(incomingServer, false);
});