Bug 640371 - Prevent POP3 inbox folder to grow past the mailstore limit when getting mail. r=irving AURORA_BASE_20130513
authoraceman <acelists@atlas.sk>
Mon, 13 May 2013 17:51:10 +0200
changeset 15527 cc6213af0ce8a32093186c2548dc8db20d5a6139
parent 15526 9242d22c0ce2fceb8497d07df34b7f863d21ab45
child 15528 f386a43e6138e5e6c27c1705bdf38c62f5368ffe
push id920
push userbugzilla@standard8.plus.com
push dateMon, 24 Jun 2013 19:03:14 +0000
treeherdercomm-beta@936bfe9d120b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersirving
bugs640371
Bug 640371 - Prevent POP3 inbox folder to grow past the mailstore limit when getting mail. r=irving
mailnews/local/src/nsPop3Protocol.cpp
mailnews/local/test/unit/test_over4GBMailboxes.js
mailnews/test/resources/POP3pump.js
mailnews/test/resources/messageGenerator.js
--- a/mailnews/local/src/nsPop3Protocol.cpp
+++ b/mailnews/local/src/nsPop3Protocol.cpp
@@ -25,33 +25,32 @@
 #include "nspr.h"
 #include "plbase64.h"
 #include "nsIMsgMailNewsUrl.h"
 #include "nsPop3Protocol.h"
 #include "MailNewsTypes.h"
 #include "nsStringGlue.h"
 #include "nsIPrompt.h"
 #include "nsIMsgIncomingServer.h"
+#include "nsIMsgPluggableStore.h"
 #include "nsTextFormatter.h"
 #include "nsCOMPtr.h"
 #include "nsIMsgWindow.h"
 #include "nsIMsgFolder.h" // TO include biffState enum. Change to bool later...
 #include "nsIDocShell.h"
 #include "nsMsgUtils.h"
 #include "nsISocketTransport.h"
 #include "nsISSLSocketControl.h"
 #include "nsILineInputStream.h"
 #include "nsLocalStrings.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsMsgMessageFlags.h"
 #include "nsMsgBaseCID.h"
 #include "mozilla/Services.h"
 
-#define EXTRA_SAFETY_SPACE 3096
-
 PRLogModuleInfo *POP3LOGMODULE = nullptr;
 
 
 static int
 net_pop3_remove_messages_marked_delete(PLHashEntry* he,
                                        int msgindex,
                                        void *arg)
 {
@@ -2926,70 +2925,38 @@ int32_t nsPop3Protocol::GetMsg()
       m_pop3ConData->next_state = POP3_SEND_QUIT;
       return(0);
     }
     /* get the amount of available space on the drive
      * and make sure there is enough
      */
     if (m_totalDownloadSize > 0) // skip all this if there aren't any messages
     {
-      nsresult rv;
-      int64_t mailboxSpaceLeft = 0;
-      nsCOMPtr <nsIMsgFolder> folder;
-      nsCOMPtr <nsIFile> path;
-
-      // Get the path to the current mailbox
-      //
+      nsCOMPtr<nsIMsgFolder> folder;
+
+      // Get the current mailbox folder
       NS_ENSURE_TRUE(m_nsIPop3Sink, -1);
-      rv = m_nsIPop3Sink->GetFolder(getter_AddRefs(folder));
-      if (NS_FAILED(rv))
-        return -1;
-      rv = folder->GetFilePath(getter_AddRefs(path));
+      nsresult rv = m_nsIPop3Sink->GetFolder(getter_AddRefs(folder));
       if (NS_FAILED(rv))
         return -1;
 
-      // call GetDiskSpaceAvailable on the directory
-      nsCOMPtr <nsIFile> parent;
-      path->GetParent(getter_AddRefs(parent));
-      rv = parent->GetDiskSpaceAvailable(&mailboxSpaceLeft);
-      if (NS_FAILED(rv))
-      {
-        // The call to GetDiskSpaceAvailable FAILED!
-        // This will happen on certain platforms where GetDiskSpaceAvailable
-        // is not implemented. Since people on those platforms still need
-        // to check mail, we will simply bypass the disk-space check.
-        //
-        // We'll leave a debug message to warn people.
-
-#ifdef DEBUG
-        printf("Call to GetDiskSpaceAvailable FAILED! \n");
-#endif
-      }
-      else
-      {
+      nsCOMPtr<nsIMsgPluggableStore> msgStore;
+      rv = folder->GetMsgStore(getter_AddRefs(msgStore));
+      NS_ENSURE_SUCCESS(rv, -1);
+
+      bool spaceAvailable;
+      // check if we have a reasonable amount of space left
+      rv = msgStore->HasSpaceAvailable(folder, m_totalDownloadSize, &spaceAvailable);
+      if (NS_FAILED(rv) || !spaceAvailable) {
 #ifdef DEBUG
-        printf("GetDiskSpaceAvailable returned: %lld bytes\n", mailboxSpaceLeft);
+        printf("Not enough disk space! Raising error!\n");
 #endif
-
-        /* When checking for disk space available, take into consideration
-        * possible database
-        * changes, therefore ask for a little more than what the message
-        * size is. Also, due to disk sector sizes, allocation blocks,
-        * etc. The space "available" may be greater than the actual space
-        * usable. */
-
-        if (m_totalDownloadSize + int64_t(EXTRA_SAFETY_SPACE) > mailboxSpaceLeft)
-        {
-          // Not enough disk space!
-#ifdef DEBUG
-          printf("Not enough disk space! Raising error! \n");
-#endif
-          return (Error(MK_POP3_OUT_OF_DISK_SPACE));
-        }
+        return (Error(MK_POP3_OUT_OF_DISK_SPACE));
       }
+
       // Here we know how many messages we're going to download, so let
       // the pop3 sink know.
       rv = m_nsIPop3Sink->SetMsgsToDownload(m_pop3ConData->really_new_messages);
     }
   }
 
   /* Look at this message, and decide whether to ignore it, get it, just get
   the TOP of it, or delete it. */
--- a/mailnews/local/test/unit/test_over4GBMailboxes.js
+++ b/mailnews/local/test/unit/test_over4GBMailboxes.js
@@ -1,176 +1,307 @@
 /* -*- Mode: JavaScript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
- * Test to ensure that copyFileMessageInLocalFolder checks for over 4 GiB local folder, and that
- * we can parse and compact folders over 4 GiB to allow users to get them under
- * 4 GiB.
+ * Test to ensure that operations around the 4GiB folder size boundary work correctly.
+ * This test only works for mbox format mail folders.
+ * Some of the tests will be removed when support for over 4GiB folders is enabled by default.
+ * The test functions are executed in this order:
+ * - run_test
+ * -  ParseListener1
+ * - downloadUnder4GiB
+ * -  ParseListener2
+ * - downloadOver4GiB
+ * - growOver4GiB
+ * -  ParseListener3
+ * - copyIntoOver4GiB
+ * - compactUnder4GiB
+ * -  CompactListener2
  */
 
 load("../../../resources/mailTestUtils.js");
 load("../../../resources/asyncTestUtils.js");
 load("../../../resources/alertTestUtils.js");
+load("../../../resources/messageGenerator.js");
+load("../../../resources/POP3pump.js");
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-load("../../../resources/messageGenerator.js");
 
 Services.prefs.setCharPref("mail.serverDefaultStoreContractID",
                            "@mozilla.org/msgstore/berkeleystore;1");
 
 // If we're running out of memory parsing the folder, lowering the
 // block size might help, though it will slow the test down and consume
 // more disk space.
 const kSparseBlockSize = 102400000;
+const kSizeLimit = 0x100000000; // 4GiB
+const kNearLimit = kSizeLimit - 0x1000000; // -16MiB
 
 var gGotAlert = false;
-var gLocalInboxSize;
+var gInboxFile = null;
 
 // This alert() is triggered when file size becomes close (enough) to or
 // exceeds 4 GiB.
 // See hardcoded value in nsMsgBrkMBoxStore::HasSpaceAvailable().
 function alert(aDialogTitle, aText) {
   // See "/*/locales/en-US/chrome/*/messenger.properties > mailboxTooLarge".
   do_check_true(aText.startsWith("The folder Inbox is full, and can't hold any more messages."));
   gGotAlert = true;
 }
 
+/**
+ * Grow local inbox folder to the wanted size using direct appending
+ * to the underlying file. The folder is filled with copies of a dummy
+ * message with kSparseBlockSize bytes in size.
+ * The file is marked as sparse in the filesystem so that it does not
+ * really take 4GiB and working with it is faster.
+ */
+function growInbox(aWantedSize) {
+  // Put a single message in the Inbox.
+  let messageGenerator = new MessageGenerator();
+  let message = messageGenerator.makeMessage();
+
+  // Refresh 'gInboxFile'.
+  gInboxFile = gLocalInboxFolder.filePath;
+
+  let mboxString = message.toMboxString();
+  let plugStore = gLocalInboxFolder.msgStore;
+  // Grow local inbox to our wished size that is below the max limit.
+  do {
+    let nextOffset = gInboxFile.fileSize +
+      Math.min(kSparseBlockSize + mboxString.length,
+               aWantedSize - gInboxFile.fileSize) - 2;
+
+    // Get stream to write a new message.
+    let reusable = new Object;
+    let newMsgHdr = new Object;
+    let outputStream = plugStore.getNewMsgOutputStream(gLocalInboxFolder,
+                                                       newMsgHdr, reusable)
+                                .QueryInterface(Ci.nsISeekableStream);
+    // Write message header.
+    outputStream.write(mboxString, mboxString.length);
+
+    // "Add" a new (empty) sparse block at the end of the file.
+    mark_file_region_sparse(gInboxFile, gInboxFile.fileSize + mboxString.length,
+                            nextOffset - (gInboxFile.fileSize + mboxString.length));
+
+    // Skip to the wished end of the message.
+    outputStream.seek(0, nextOffset);
+    // Add a CR+LF to terminate the message.
+    outputStream.write("\r\n", 2);
+    outputStream.close();
+    plugStore.finishNewMessage(outputStream, newMsgHdr);
+
+    // Refresh 'gInboxFile'.
+    gInboxFile = gLocalInboxFolder.filePath;
+  }
+  while (gInboxFile.fileSize < aWantedSize);
+
+  do_print("Local inbox size = " + gInboxFile.fileSize + "bytes = " +
+           gInboxFile.fileSize / 1024 / 1024 + "MiB");
+}
+
 function run_test()
 {
   loadLocalMailAccount();
 
   // "Master" do_test_pending(), paired with a do_test_finished() at the end of
   // all the operations.
   do_test_pending();
 
-  let inboxFile = gLocalInboxFolder.filePath;
+  gInboxFile = gLocalInboxFolder.filePath;
 
-  let neededFreeSpace = 0x110000000;
+  let neededFreeSpace = kSizeLimit + 0x10000000; // +256MiB
   // On Windows, check whether the drive is NTFS. If it is, mark the file as
   // sparse. If it isn't, then bail out now, because in all probability it is
-  // FAT32, which doesn't support file sizes greater than 4 GB.
+  // FAT32, which doesn't support file sizes greater than 4 GiB.
   if ("@mozilla.org/windows-registry-key;1" in Cc &&
-      get_file_system(inboxFile) != "NTFS")
+      get_file_system(gInboxFile) != "NTFS")
   {
     dump("On Windows, this test only works on NTFS volumes.\n");
 
     endTest();
     return;
   }
 
-  let freeDiskSpace = inboxFile.diskSpaceAvailable;
+  let freeDiskSpace = gInboxFile.diskSpaceAvailable;
   do_print("Free disk space = " + toMiBString(freeDiskSpace));
   if (freeDiskSpace < neededFreeSpace) {
     do_print("This test needs " + toMiBString(neededFreeSpace) +
              " free space to run. Aborting.");
     todo_check_true(false);
 
     endTest();
     return;
   }
 
-  // Put a single message in the Inbox.
-  let messageGenerator = new MessageGenerator();
-  let message = messageGenerator.makeMessage();
-  let localInbox = gLocalInboxFolder.QueryInterface(Ci.nsIMsgLocalMailFolder);
-  localInbox.addMessage(message.toMboxString());
+  // Grow inbox to size near the max limit.
+  growInbox(kNearLimit);
+
+  // Force the db closed, so that getDatabaseWithReparse will notice
+  // that it's out of date.
+  gLocalInboxFolder.msgDatabase.ForceClosed();
+  gLocalInboxFolder.msgDatabase = null;
+  try {
+    gLocalInboxFolder.getDatabaseWithReparse(ParseListener1, gDummyMsgWindow);
+  } catch (ex) {
+    do_check_eq(ex.result, Cr.NS_ERROR_NOT_INITIALIZED);
+  }
+  // Execution continues in downloadUnder4GiB() when done.
+}
 
-  // Refresh 'inboxFile'.
-  inboxFile = gLocalInboxFolder.filePath;
+/**
+ * Check we can download new mail when we are near 4GiB limit but do not cross it.
+ */
+function downloadUnder4GiB()
+{
+  // Check fake POP3 server is ready.
+  do_check_neq(gPOP3Pump.fakeServer, null);
 
-  // Grow local inbox to over 4 GiB.
-  let plugStore = gLocalInboxFolder.msgStore;
-  do {
-    let nextOffset = inboxFile.fileSize + kSparseBlockSize;
-    // "Add" a new (empty) sparse block at the end of the file.
-    mark_file_region_sparse(inboxFile, inboxFile.fileSize,
-                            kSparseBlockSize);
+  // Download a file that still fits into the limit.
+  let bigFile = do_get_file("../../../data/mime-torture");
+  do_check_true(bigFile.fileSize >= 1024 * 1024);
+  do_check_true(bigFile.fileSize <= 1024 * 1024 * 2);
+
+  gPOP3Pump.files = ["../../../data/mime-torture"];
+  gPOP3Pump.onDone = downloadOver4GiB;
+  // It must succeed.
+  gPOP3Pump.run(0);
+  // Execution continues in downloadOver4GiB() when done.
+}
 
-    let reusable = new Object;
-    let newMsgHdr = new Object;
-    let outputStream = plugStore.getNewMsgOutputStream(gLocalInboxFolder,
-                                                       newMsgHdr, reusable)
-                                .QueryInterface(Ci.nsISeekableStream);
-    // Skip directly to the new end of the file.
-    outputStream.seek(0, nextOffset);
-    // Add a CR+LF at end of previous message then
-    // write the (same) message another time.
-    let mboxString = "\r\n" + message.toMboxString();
-    outputStream.write(mboxString, mboxString.length);
-    outputStream.close();
-    plugStore.finishNewMessage(outputStream, newMsgHdr);
+/**
+ * Bug 640371
+ * Check we will not cross the 4GiB limit when downloading new mail.
+ */
+function downloadOver4GiB()
+{
+  let localInboxSize = gInboxFile.fileSize;
+  do_check_true(localInboxSize > kNearLimit);
+  do_check_true(localInboxSize < kSizeLimit);
+  // The big file is between 1 and 2 MiB. Append it 16 times to attempt to cross the 4GiB limit.
+  gPOP3Pump.files = ["../../../data/mime-torture", "../../../data/mime-torture",
+                     "../../../data/mime-torture", "../../../data/mime-torture",
+                     "../../../data/mime-torture", "../../../data/mime-torture",
+                     "../../../data/mime-torture", "../../../data/mime-torture",
+                     "../../../data/mime-torture", "../../../data/mime-torture",
+                     "../../../data/mime-torture", "../../../data/mime-torture",
+                     "../../../data/mime-torture", "../../../data/mime-torture",
+                     "../../../data/mime-torture", "../../../data/mime-torture"];
+  gPOP3Pump.onDone = growOver4GiB;
+  // The download must fail.
+  gPOP3Pump.run(2147500037);
+  // Execution continues in growOver4GiB() when done.
+}
 
-    // Refresh 'inboxFile'.
-    inboxFile = gLocalInboxFolder.filePath;
-  }
-  while (inboxFile.fileSize < 0x100000000)
+/**
+ * Bug 608449
+ * Check we can parse a folder if it is above 4GiB.
+ */
+function growOver4GiB()
+{
+  gPOP3Pump = null;
+
+  // Grow inbox to size greater than the max limit (+16 MiB).
+  growInbox(kSizeLimit + 0x1000000);
+  do_check_true(gInboxFile.fileSize > kSizeLimit);
 
+  // Force the db closed, so that getDatabaseWithReparse will notice
+  // that it's out of date.
+  gLocalInboxFolder.msgDatabase.ForceClosed();
+  gLocalInboxFolder.msgDatabase = null;
+  try {
+    gLocalInboxFolder.getDatabaseWithReparse(ParseListener2, gDummyMsgWindow);
+  } catch (ex) {
+    do_check_eq(ex.result, Cr.NS_ERROR_NOT_INITIALIZED);
+  }
+  // Execution continues in copyOver4GiB() when done.
+}
+
+/**
+ * Bug 598104
+ * Check that copy operation does not allow to grow a local folder above 4 GiB.
+ */
+function copyIntoOver4GiB()
+{
   // Save initial file size.
-  gLocalInboxSize = inboxFile.fileSize;
+  let localInboxSize = gInboxFile.fileSize;
   do_print("Local inbox size (before copyFileMessageInLocalFolder()) = " +
-           gLocalInboxSize);
+           localInboxSize);
 
   // Use copyFileMessageInLocalFolder() to (try to) append another message
-  //  to local inbox.
+  // to local inbox.
   let file = do_get_file("../../../data/multipart-complex2");
   copyFileMessageInLocalFolder(file, 0, "", gDummyMsgWindow,
                                function(aMessageHeadersKeys, aStatus) {
     do_check_false(Components.isSuccessCode(aStatus));
   });
   do_check_true(gGotAlert);
 
   // Make sure inbox file did not grow (i.e., no data were appended).
-  let localInboxSize = gLocalInboxFolder.filePath.fileSize;
+  let newLocalInboxSize = gLocalInboxFolder.filePath.fileSize;
   do_print("Local inbox size (after copyFileMessageInLocalFolder()) = " +
-           localInboxSize);
-  do_check_eq(localInboxSize, gLocalInboxSize);
+           newLocalInboxSize);
+  do_check_eq(newLocalInboxSize, localInboxSize);
 
-  // Force the db closed, so that getDatabaseWithReparse will notice
-  // that it's out of date.
-  gLocalInboxFolder.msgDatabase.ForceClosed();
-  gLocalInboxFolder.msgDatabase = null;
-  try {
-    gLocalInboxFolder.getDatabaseWithReparse(ParseListener, gDummyMsgWindow);
-  } catch (ex) {
-    do_check_eq(ex.result, Cr.NS_ERROR_NOT_INITIALIZED);
-  }
+  do_timeout(0, compactUnder4GiB);
 }
 
-function testCompact()
+/**
+ * Bug 608449
+ * Check we compact a folder to get it under 4 GiB.
+ */
+function compactUnder4GiB()
 {
+  do_check_true(gInboxFile.fileSize > kSizeLimit);
   // Very first header in msgDB is retained,
   // then all other headers are marked as deleted.
   let msgDB = gLocalInboxFolder.msgDatabase;
   let enumerator = msgDB.EnumerateMessages();
   let firstHdr = true;
   let messages = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
   while (enumerator.hasMoreElements()) {
     let header = enumerator.getNext();
     if (header instanceof Components.interfaces.nsIMsgDBHdr && !firstHdr)
       messages.appendElement(header, false);
     firstHdr = false;
   }
   gLocalInboxFolder.deleteMessages(messages, null, true, false, null, false);
 
   // Note: compact() will also add 'X-Mozilla-Status' and 'X-Mozilla-Status2'
   // lines to message(s).
-  gLocalInboxFolder.compact(CompactListener, null);
+  gLocalInboxFolder.compact(CompactListener2, null);
+  // Test ends after compaction is done.
 }
 
-var ParseListener =
+var ParseListener1 =
 {
   OnStartRunningUrl: function (aUrl) {},
   OnStopRunningUrl: function (aUrl, aExitCode) {
     // Check: reparse successful
     do_check_eq(aExitCode, 0);
+    do_check_neq(gLocalInboxFolder.msgDatabase, null);
     do_check_true(gLocalInboxFolder.msgDatabase.summaryValid);
 
-    testCompact();
+    downloadUnder4GiB();
   }
 };
 
-var CompactListener =
+var ParseListener2 =
+{
+  OnStartRunningUrl: function (aUrl) {},
+  OnStopRunningUrl: function (aUrl, aExitCode) {
+    // Check: reparse successful
+    do_check_eq(aExitCode, 0);
+    do_check_neq(gLocalInboxFolder.msgDatabase, null);
+    do_check_true(gLocalInboxFolder.msgDatabase.summaryValid);
+
+    copyIntoOver4GiB();
+  }
+};
+
+var CompactListener2 =
 {
   OnStartRunningUrl: function (aUrl) {},
   OnStopRunningUrl: function (aUrl, aExitCode) {
     // Check: message successfully copied.
     do_check_eq(aExitCode, 0);
     do_check_true(gLocalInboxFolder.msgDatabase.summaryValid);
 
     // Check that folder size isn't much bigger than our sparse block size, ...
--- a/mailnews/test/resources/POP3pump.js
+++ b/mailnews/test/resources/POP3pump.js
@@ -45,38 +45,34 @@ function POP3Pump()
   this.kPOP3_PORT = 1024 + 110;
   this._server = null;
   this._daemon = null;
   this._incomingServer = null;
   this._pop3Service = null;
   this._firstFile = true;
   this._tests = [];
   this._finalCleanup = false;
-
+  this._expectedResult = 0;
 }
 
 POP3Pump.prototype._urlListener =
 {
   OnStartRunningUrl: function OnStartRunningUrl(url) {},
   OnStopRunningUrl: function OnStopRunningUrl(aUrl, aResult)
   {
-    try
+    if (aResult != 0)
     {
-      do_check_eq(aResult, 0);
-    }
-    catch (e)
-    {
-      // If we have an error, clean up nicely before we throw it.
-      this._server.stop();
+      // If we have an error, clean up nicely.
+      gPOP3Pump._server.stop();
 
       var thread = gThreadManager.currentThread;
       while (thread.hasPendingEvents())
         thread.processNextEvent(true);
-      do_throw(e);
     }
+    do_check_eq(aResult, gPOP3Pump._expectedResult);
 
     // Let OnStopRunningUrl return cleanly before doing anything else.
     do_timeout(0, _checkPumpBusy);
   }
 };
 
 // Setup the daemon and server
 // If the debugOption is set, then it will be applied to the server.
@@ -181,32 +177,35 @@ POP3Pump.prototype._testNext = function 
   } finally
   {
     var thread = gThreadManager.currentThread;
     while (thread.hasPendingEvents())
       thread.processNextEvent(true);
   }
 };
 
-POP3Pump.prototype.run = function run()
+POP3Pump.prototype.run = function run(aExpectedResult)
 {
   do_test_pending();
   // Disable new mail notifications
   Services.prefs.setBoolPref("mail.biff.play_sound", false);
   Services.prefs.setBoolPref("mail.biff.show_alert", false);
   Services.prefs.setBoolPref("mail.biff.show_tray_icon", false);
   Services.prefs.setBoolPref("mail.biff.animate_dock_icon", false);
 
   this._server = this._setupServerDaemon();
   this._daemon = this._server[0];
   this._server = this._server[1];
 
   this._firstFile = true;
   this._finalCleanup = false;
 
+  if (aExpectedResult)
+    this._expectedResult = aExpectedResult;
+
   // In the default configuration, only a single test is accepted
   // by this routine. But the infrastructure exists to support
   // multiple tests, as this was in the original files. We leave that
   // infrastructure in place, so that if desired this routine could
   // be easily copied and modified to make multiple passes through
   // a POP3 server.
 
   this._tests[0] = this.files;
--- a/mailnews/test/resources/messageGenerator.js
+++ b/mailnews/test/resources/messageGenerator.js
@@ -710,17 +710,17 @@ MessageGenerator.prototype = {
    * @returns The unique name corresponding to the name mail address.
    */
   makeMailAddress: function(aNameNumber) {
     let iFirst = aNameNumber % FIRST_NAMES.length;
     let iLast = (iFirst + Math.floor(aNameNumber / FIRST_NAMES.length)) %
                 LAST_NAMES.length;
 
     return FIRST_NAMES[iFirst].toLowerCase() + "@" +
-           LAST_NAMES[iLast].toLowerCase() + ".nul";
+           LAST_NAMES[iLast].toLowerCase() + ".invalid";
   },
 
   /**
    * Generate a pair of name and e-mail address.
    *
    * @param aNameNumber The optional 'number' of the name and mail address you
    *     want.  If you do not provide a value, we will increment an internal
    *     counter to ensure that a new name is allocated and that will not be
@@ -784,17 +784,17 @@ MessageGenerator.prototype = {
    *  message id to the server that theoretically might be sending it.  Or some
    *  such.
    *
    * @param The synthetic message you would like us to make up a message-id for.
    *     We don't set the message-id on the message, that's up to you.
    * @returns a Message-id suitable for the given message.
    */
   makeMessageId: function(aSynthMessage) {
-    let msgId = this._nextMessageIdNum + "@made.up";
+    let msgId = this._nextMessageIdNum + "@made.up.invalid";
     this._nextMessageIdNum++;
     return msgId;
   },
 
   /**
    * Generates a valid date which is after all previously issued dates by this
    *  method, ensuring an apparent ordering of time consistent with the order
    *  in which code is executed / messages are generated.