summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/compose/test/unit/test_sendMessageLater2.js
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mailnews/compose/test/unit/test_sendMessageLater2.js')
-rw-r--r--comm/mailnews/compose/test/unit/test_sendMessageLater2.js301
1 files changed, 301 insertions, 0 deletions
diff --git a/comm/mailnews/compose/test/unit/test_sendMessageLater2.js b/comm/mailnews/compose/test/unit/test_sendMessageLater2.js
new file mode 100644
index 0000000000..bd0b974400
--- /dev/null
+++ b/comm/mailnews/compose/test/unit/test_sendMessageLater2.js
@@ -0,0 +1,301 @@
+/* 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, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * Complex test for the send message later function - including sending multiple
+ * times in the same session.
+ *
+ * XXX: This test is intended to additionally test sending of multiple messages
+ * from one send later instance, however due to the fact we use one connection
+ * per message sent, it is very difficult to consistently get the fake server
+ * reconnected in time for the next connection. Thus, sending of multiple
+ * messages is currently disabled (but commented out for local testing if
+ * required), when we fix bug 136871 we should be able to enable the multiple
+ * messages option.
+ */
+
+var { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+var { PromiseTestUtils } = ChromeUtils.import(
+ "resource://testing-common/mailnews/PromiseTestUtils.jsm"
+);
+var { PromiseUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/PromiseUtils.sys.mjs"
+);
+
+var server = null;
+var smtpServer;
+var gSentFolder;
+var identity = null;
+var gMsgFile = [
+ do_get_file("data/message1.eml"),
+ do_get_file("data/429891_testcase.eml"),
+];
+var kTestFileSender = ["from_B@foo.invalid", "from_A@foo.invalid"];
+var kTestFileRecipient = ["to_B@foo.invalid", "to_A@foo.invalid"];
+
+var gMsgFileData = [];
+var gMsgOrder = [];
+var gLastSentMessage = 0;
+
+var kIdentityMail = "identity@foo.invalid";
+
+var msgSendLater = Cc["@mozilla.org/messengercompose/sendlater;1"].getService(
+ Ci.nsIMsgSendLater
+);
+
+var messageListener;
+var onStopCopyPromise = PromiseUtils.defer();
+
+/* exported OnStopCopy */
+// for head_compose.js
+// This function is used to find out when the copying of the message to the
+// unsent message folder is completed, and hence can fire off the actual
+// sending of the message.
+function OnStopCopy(aStatus) {
+ Assert.equal(aStatus, 0);
+
+ // Check this is false before we start sending.
+ Assert.equal(msgSendLater.sendingMessages, false);
+
+ // Check that the send later service thinks we have messages to send.
+ Assert.equal(msgSendLater.hasUnsentMessages(identity), true);
+
+ // Check we have a message in the unsent message folder.
+ Assert.equal(gSentFolder.getTotalMessages(false), gMsgOrder.length);
+
+ // Start the next step after a brief time so that functions can finish
+ // properly.
+ onStopCopyPromise.resolve();
+}
+
+add_setup(async function () {
+ // Load in the test files so we have a record of length and their data.
+ for (var i = 0; i < gMsgFile.length; ++i) {
+ gMsgFileData[i] = await IOUtils.readUTF8(gMsgFile[i].path);
+ }
+
+ // Ensure we have a local mail account, an normal account and appropriate
+ // servers and identities.
+ localAccountUtils.loadLocalMailAccount();
+
+ // Check that the send later service thinks we don't have messages to send.
+ Assert.equal(msgSendLater.hasUnsentMessages(identity), false);
+
+ MailServices.accounts.setSpecialFolders();
+
+ let account = MailServices.accounts.createAccount();
+ let incomingServer = MailServices.accounts.createIncomingServer(
+ "test",
+ "localhost",
+ "pop3"
+ );
+
+ smtpServer = getBasicSmtpServer(1);
+ identity = getSmtpIdentity(kIdentityMail, smtpServer);
+
+ account.addIdentity(identity);
+ account.defaultIdentity = identity;
+ account.incomingServer = incomingServer;
+ MailServices.accounts.defaultAccount = account;
+
+ localAccountUtils.rootFolder.createLocalSubfolder("Sent");
+
+ gSentFolder = msgSendLater.getUnsentMessagesFolder(identity);
+
+ // Don't copy messages to sent folder for this test.
+ identity.doFcc = false;
+
+ // Create and add a listener.
+ messageListener = new MsgSendLaterListener();
+
+ msgSendLater.addListener(messageListener);
+
+ // Set up the server.
+ server = setupServerDaemon();
+ server.setDebugLevel(fsDebugRecv);
+});
+
+add_task(async function test_sendMessageLater2_message1() {
+ // Copy Message from file to folder.
+ await sendMessageLater(0);
+
+ // Send unsent message.
+ await sendUnsentMessages();
+
+ // Check sent folder is now empty.
+ Assert.equal(gSentFolder.getTotalMessages(false), 0);
+
+ // Reset the server.
+ server.stop();
+ server.resetTest();
+
+ // Reset counts.
+ resetCounts();
+});
+
+add_task(async function test_sendMessageLater2_429891_testcase() {
+ // Copy more messages.
+ await sendMessageLater(1);
+
+ // XXX Only do one the second time round, as described at the start of the
+ // file.
+ // await sendMessageLater(0);
+
+ // Test send again.
+ await sendUnsentMessages();
+});
+
+async function sendMessageLater(aTestFileIndex) {
+ gMsgOrder.push(aTestFileIndex);
+
+ // Prepare to actually "send" the message later, i.e. dump it in the
+ // unsent messages folder.
+
+ var compFields = Cc[
+ "@mozilla.org/messengercompose/composefields;1"
+ ].createInstance(Ci.nsIMsgCompFields);
+
+ // Setting the compFields sender and recipient to any value is required to
+ // survive mime_sanity_check_fields in nsMsgCompUtils.cpp.
+ // Sender and recipient are required for sendMessageFile but SMTP
+ // transaction values will be used directly from mail body.
+ compFields.from = "irrelevant@foo.invalid";
+ compFields.to = "irrelevant@foo.invalid";
+
+ var msgSend = Cc["@mozilla.org/messengercompose/send;1"].createInstance(
+ Ci.nsIMsgSend
+ );
+
+ msgSend.sendMessageFile(
+ identity,
+ "",
+ compFields,
+ gMsgFile[aTestFileIndex],
+ false,
+ false,
+ Ci.nsIMsgSend.nsMsgQueueForLater,
+ null,
+ copyListener,
+ null,
+ null
+ );
+ await onStopCopyPromise.promise;
+ // Reset onStopCopyPromise.
+ onStopCopyPromise = PromiseUtils.defer();
+}
+
+function resetCounts() {
+ gMsgOrder = [];
+ gLastSentMessage = 0;
+}
+
+// This function does the actual send later.
+async function sendUnsentMessages() {
+ // Handle the server in a try/catch/finally loop so that we always will stop
+ // the server if something fails.
+ try {
+ // Start the fake SMTP server.
+ server.start();
+ smtpServer.port = server.port;
+
+ // Send the unsent message.
+ msgSendLater.sendUnsentMessages(identity);
+ } catch (e) {
+ throw new Error(e);
+ }
+ await messageListener.promise;
+ messageListener.deferPromise();
+}
+
+// This listener handles the post-sending of the actual message and checks the
+// sequence and ensures the data is correct.
+class MsgSendLaterListener {
+ constructor() {
+ this._deferredPromise = PromiseUtils.defer();
+ }
+
+ checkMessageSend(aCurrentMessage) {
+ do_check_transaction(server.playTransaction(), [
+ "EHLO test",
+ "MAIL FROM:<" +
+ kTestFileSender[gMsgOrder[aCurrentMessage - 1]] +
+ "> BODY=8BITMIME SIZE=" +
+ gMsgFileData[gMsgOrder[aCurrentMessage - 1]].length,
+ "RCPT TO:<" + kTestFileRecipient[gMsgOrder[aCurrentMessage - 1]] + ">",
+ "DATA",
+ ]);
+
+ // Compare data file to what the server received.
+ Assert.equal(
+ gMsgFileData[gMsgOrder[aCurrentMessage - 1]],
+ server._daemon.post
+ );
+ }
+
+ // nsIMsgSendLaterListener
+ onStartSending(aTotalMessageCount) {
+ Assert.equal(aTotalMessageCount, gMsgOrder.length);
+ Assert.equal(msgSendLater.sendingMessages, true);
+ }
+ onMessageStartSending(
+ aCurrentMessage,
+ aTotalMessageCount,
+ aMessageHeader,
+ aIdentity
+ ) {
+ if (gLastSentMessage > 0) {
+ this.checkMessageSend(aCurrentMessage);
+ }
+ Assert.equal(gLastSentMessage + 1, aCurrentMessage);
+ gLastSentMessage = aCurrentMessage;
+ }
+ onMessageSendProgress(
+ aCurrentMessage,
+ aTotalMessageCount,
+ aMessageSendPercent,
+ aMessageCopyPercent
+ ) {
+ Assert.equal(aTotalMessageCount, gMsgOrder.length);
+ Assert.equal(gLastSentMessage, aCurrentMessage);
+ Assert.equal(msgSendLater.sendingMessages, true);
+ }
+ onMessageSendError(aCurrentMessage, aMessageHeader, aStatus, aMsg) {
+ throw new Error(
+ "onMessageSendError should not have been called, status: " + aStatus
+ );
+ }
+ onStopSending(aStatus, aMsg, aTotalTried, aSuccessful) {
+ try {
+ Assert.equal(aStatus, 0);
+ Assert.equal(aTotalTried, aSuccessful);
+ Assert.equal(msgSendLater.sendingMessages, false);
+
+ // Check that the send later service now thinks we don't have messages to
+ // send.
+ Assert.equal(msgSendLater.hasUnsentMessages(identity), false);
+
+ this.checkMessageSend(gLastSentMessage);
+ } catch (e) {
+ throw new Error(e);
+ }
+ // The extra timeout here is to work around an issue where sometimes
+ // the sendUnsentMessages is completely synchronous up until onStopSending
+ // and sometimes it isn't. This protects us for the synchronous case to
+ // allow the sendUnsentMessages function to complete and exit before we
+ // resolve the promise.
+ PromiseTestUtils.promiseDelay(0).then(resolve => {
+ this._deferredPromise.resolve(true);
+ });
+ }
+
+ deferPromise() {
+ this._deferredPromise = PromiseUtils.defer();
+ }
+
+ get promise() {
+ return this._deferredPromise.promise;
+ }
+}