Bug 904458 - Filters that "Reply with Template" must add an Auto-Submitted header and prefix subject Auto:. r=irving, rkent
authorMagnus Melin <mkmelin+mozilla@iki.fi>
Sat, 19 Apr 2014 12:59:11 +0300
changeset 18757 a0e462249dc830c7e9779503a1ba2f9f2a28ab33
parent 18756 c4d4a986530e08676f10c989252dec6d5e1b0481
child 18758 79e74959cca26a343373399f5ad538dcefd65f82
push id11493
push usermkmelin@iki.fi
push dateSun, 13 Dec 2015 21:02:41 +0000
treeherdercomm-central@79e74959cca2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersirving, rkent
bugs904458
Bug 904458 - Filters that "Reply with Template" must add an Auto-Submitted header and prefix subject Auto:. r=irving, rkent Tests originally by Kent James
mailnews/compose/src/nsMsgComposeService.cpp
mailnews/compose/test/unit/test_autoReply.js
mailnews/compose/test/unit/xpcshell.ini
mailnews/test/resources/mailTestUtils.js
--- a/mailnews/compose/src/nsMsgComposeService.cpp
+++ b/mailnews/compose/src/nsMsgComposeService.cpp
@@ -954,39 +954,45 @@ NS_IMETHODIMP nsMsgTemplateReplyHelper::
   mHdrToReplyTo->GetStringProperty("replyTo", getter_Copies(replyTo));
   if (replyTo.IsEmpty())
     mHdrToReplyTo->GetAuthor(getter_Copies(replyTo));
   compFields->SetTo(NS_ConvertUTF8toUTF16(replyTo));
 
   nsString body;
   nsString templateSubject, replySubject;
 
+  mHdrToReplyTo->GetMime2DecodedSubject(replySubject);
   mTemplateHdr->GetMime2DecodedSubject(templateSubject);
-  mHdrToReplyTo->GetMime2DecodedSubject(replySubject);
+  nsString subject(NS_LITERAL_STRING("Auto: ")); // RFC 3834 3.1.5.
+  subject.Append(templateSubject);
   if (!replySubject.IsEmpty())
   {
-    templateSubject.Append(NS_LITERAL_STRING(" (was: "));
-    templateSubject.Append(replySubject);
-    templateSubject.Append(NS_LITERAL_STRING(")"));
+    subject.Append(NS_LITERAL_STRING(" (was: "));
+    subject.Append(replySubject);
+    subject.Append(NS_LITERAL_STRING(")"));
   }
-  compFields->SetSubject(templateSubject);
+
+  compFields->SetSubject(subject);
+  compFields->SetRawHeader("Auto-Submitted", NS_LITERAL_CSTRING("auto-replied"), nullptr);
+
   CopyASCIItoUTF16(mTemplateBody, body);
   compFields->SetBody(body);
 
   nsCString msgUri;
   nsCOMPtr <nsIMsgFolder> folder;
   mHdrToReplyTo->GetFolder(getter_AddRefs(folder));
   folder->GetUriForMsg(mHdrToReplyTo, msgUri);
   // populate the compose params
    // we use type new instead of reply - we might need to add a reply with template type.
   pMsgComposeParams->SetType(nsIMsgCompType::New);
   pMsgComposeParams->SetFormat(nsIMsgCompFormat::Default);
   pMsgComposeParams->SetIdentity(identity);
   pMsgComposeParams->SetComposeFields(compFields);
   pMsgComposeParams->SetOriginalMsgURI(msgUri.get());
+
   // create the nsIMsgCompose object to send the object
   nsCOMPtr<nsIMsgCompose> pMsgCompose (do_CreateInstance(NS_MSGCOMPOSE_CONTRACTID, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   /** initialize nsIMsgCompose, Send the message, wait for send completion response **/
 
   rv = pMsgCompose->Initialize(pMsgComposeParams, parentWindow, nullptr);
   NS_ENSURE_SUCCESS(rv,rv);
new file mode 100644
--- /dev/null
+++ b/mailnews/compose/test/unit/test_autoReply.js
@@ -0,0 +1,86 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Tests messages generated by ReplyWithTemplate.
+ */
+
+// make xpcshell-tests TEST_PATH=mailnews/compose/test/unit/test_autoReply.js
+
+Components.utils.import("resource://testing-common/mailnews/PromiseTestUtils.jsm");
+
+Components.utils.import("resource:///modules/mailServices.js");
+Components.utils.import("resource:///modules/mimeParser.jsm");
+
+load("../../../resources/logHelper.js"); // watch for errors in the error console
+
+const kSender = "from@foo.invalid";
+
+var gIncomingMailFile = do_get_file("../../../data/bugmail10"); // mail to reply to
+var gTemplateMailFile = do_get_file("../../../data/draft1"); // template
+var gTemplateFolder;
+
+function run_test() {
+  localAccountUtils.loadLocalMailAccount();
+  gTemplateFolder = localAccountUtils.rootFolder
+                                     .createLocalSubfolder("Templates");
+  run_next_test();
+}
+
+add_task(function* copySourceMessage() {
+  let promiseCopyListener = new PromiseTestUtils.PromiseCopyListener();
+  // Get the message to reply to into the inbox.
+  MailServices.copy.CopyFileMessage(gIncomingMailFile,
+    localAccountUtils.inboxFolder, null, false, 0, "",
+    promiseCopyListener, null);
+  yield promiseCopyListener.promise;
+});
+
+add_task(function* copyTemplateMessage() {
+  let promiseCopyListener = new PromiseTestUtils.PromiseCopyListener();
+  // Get a template message into the Templates folder.
+  MailServices.copy.CopyFileMessage(gTemplateMailFile,
+    gTemplateFolder, null, true, 0, "",
+    promiseCopyListener, null);
+  yield promiseCopyListener.promise;
+});
+
+add_task(function testReplyWithTemplate() {
+  testReply();
+});
+
+/// Test reply with template.
+function testReply() {
+  // fake smtp server setup
+  let server = setupServerDaemon();
+  let smtpServer = getBasicSmtpServer();
+  server.start();
+  smtpServer.port = server.port;
+
+  let identity = getSmtpIdentity(kSender, smtpServer);
+  localAccountUtils.msgAccount.addIdentity(identity);
+
+  let msgHdr = mailTestUtils.firstMsgHdr(localAccountUtils.inboxFolder);
+  let templateHdr = mailTestUtils.getMsgHdrN(gTemplateFolder, 0);
+
+  // See <method name="getTemplates"> in searchWidgets.xml
+  let msgTemplateUri = gTemplateFolder.URI +
+                       "?messageId=" + templateHdr.messageId +
+                       "&subject=" + templateHdr.mime2DecodedSubject;
+  MailServices.compose.replyWithTemplate(msgHdr, msgTemplateUri, null,
+    localAccountUtils.incomingServer);
+  server.performTest();
+  let headers = MimeParser.extractHeaders(server._daemon.post);
+  do_check_true(headers.get("Subject").startsWith("Auto: "));
+  do_check_eq(headers.get("Auto-submitted"), "auto-replied");;
+
+  // fake server cleanup
+  server.stop();
+
+  let thread = gThreadManager.currentThread;
+  while (thread.hasPendingEvents()) {
+    thread.processNextEvent(true);
+  }
+  do_test_finished();
+}
+
--- a/mailnews/compose/test/unit/xpcshell.ini
+++ b/mailnews/compose/test/unit/xpcshell.ini
@@ -1,15 +1,17 @@
 [DEFAULT]
 head = head_compose.js
 tail = tail_compose.js
 support-files = data/*
 
 [test_attachment.js]
 [test_attachment_intl.js]
+[test_autoReply.js]
+skip-if = os == 'mac'
 [test_bug155172.js]
 [test_bug235432.js]
 [test_bug474774.js]
 [test_detectAttachmentCharset.js]
 [test_expandMailingLists.js]
 [test_mailtoURL.js]
 [test_messageHeaders.js]
 [test_nsIMsgCompFields.js]
--- a/mailnews/test/resources/mailTestUtils.js
+++ b/mailnews/test/resources/mailTestUtils.js
@@ -112,25 +112,39 @@ var mailTestUtils = {
       }
       sstream.close();
     }
     stream.close();
 
     return data;
   },
 
-  // Gets the first message header in a folder.
+  /// Gets the first message header in a folder.
   firstMsgHdr: function(folder)
   {
     let enumerator = folder.msgDatabase.EnumerateMessages();
     if (enumerator.hasMoreElements())
       return enumerator.getNext().QueryInterface(Ci.nsIMsgDBHdr);
     return null;
   },
 
+  /// Gets message header number N (0 based index) in a folder.
+  getMsgHdrN: function(folder, n)
+  {
+    let i = 0;
+    let enumerator = folder.msgDatabase.EnumerateMessages();
+    while (enumerator.hasMoreElements()) {
+      let next = enumerator.getNext();
+      if (i == n)
+        return next.QueryInterface(Ci.nsIMsgDBHdr);
+      i++;
+    }
+    return null;
+  },
+
   /**
    * Returns the file system a particular file is on.
    * Currently supported on Windows only.
    *
    * @param aFile The file to get the file system for.
    * @return The file system a particular file is on, or 'null' if not on Windows.
    */
   get_file_system: function(aFile) {