Bug 368415 - if you only download message headers, mails which are recognised as junk (spam) lose their "junk" status if you download their content [r/sr/a=bienvenu]
authorKent James <kent@caspia.com>
Wed, 21 Oct 2009 11:13:02 -0700
changeset 4212 e747fcd384775c940de3a752539f85996adcc855
parent 4211 83e8ff7342e8e960dbb13b1d9f19b4e671eb6fa8
child 4213 520db1c594d996707391a5e0a656774ff5f29c7d
push idunknown
push userunknown
push dateunknown
bugs368415
Bug 368415 - if you only download message headers, mails which are recognised as junk (spam) lose their "junk" status if you download their content [r/sr/a=bienvenu]
mailnews/local/public/nsIMsgLocalMailFolder.idl
mailnews/local/public/nsIPop3Sink.idl
mailnews/local/src/nsLocalMailFolder.cpp
mailnews/local/src/nsPop3Sink.cpp
mailnews/local/src/nsPop3Sink.h
--- a/mailnews/local/public/nsIMsgLocalMailFolder.idl
+++ b/mailnews/local/public/nsIMsgLocalMailFolder.idl
@@ -51,17 +51,17 @@ interface nsIMsgCopyServiceListener;
 #define POP3_NONE 0
 #define POP3_DELETE 1
 #define POP3_FETCH_BODY 2
 #define POP3_FORCE_DEL 3
 
 struct nsLocalFolderScanState;
 %}
 
-[scriptable, uuid(dd95a709-3996-4573-84a8-aa936d0dc00c)]
+[scriptable, uuid(6AA1A91E-F51A-4a94-A5F7-90489D1DE826)]
 interface nsIMsgLocalMailFolder : nsISupports {
   /**
    * set the default flags on the subfolders of this folder, such as
    * Drafts, Templates, etc
    * you should bitwise OR all the flags all mailboxes you want to flag,
    * this function will be smart and find the right names.
    * like nsMsgFolderFlags::Inbox | nsMsgFolderFlags::Drafts | etc
    */
@@ -100,9 +100,18 @@ interface nsIMsgLocalMailFolder : nsISup
   /**
    * functions for grubbing thru a folder to find the Uidl for a
    * given msgDBHdr
    */
   [noscript] void getFolderScanState(in nsLocalFolderScanState aState);
   [noscript] void getUidlFromFolder(in nsLocalFolderScanState aState, in nsIMsgDBHdr aMsgHdr);
 
   boolean warnIfLocalFileTooBig(in nsIMsgWindow aWindow);
+
+  /**
+   * Update properties on a new header from an old header, for cases where
+   * a partial message will be replaced with a full message.
+   *
+   * @param   aOldHdr  message header used as properties source
+   * @param   aNewHdr  message header used as properties destination
+   */
+  void updateNewMsgHdr(in nsIMsgDBHdr aOldHdr, in nsIMsgDBHdr aNewHdr);
 };
--- a/mailnews/local/public/nsIPop3Sink.idl
+++ b/mailnews/local/public/nsIPop3Sink.idl
@@ -36,25 +36,28 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 #include "nsIPop3IncomingServer.idl"
 #include "nsIMsgFolder.idl"
 
 interface nsIURI;
 
-[scriptable, uuid(EC54D490-BB00-11D2-AB5E-00805F8AC968)]
+[scriptable, uuid(29F76AC4-51FF-4081-A268-B43CACDF4BFF)]
 interface nsIPop3Sink : nsISupports {
 
   attribute boolean userAuthenticated;
   attribute string mailAccountURL;
   attribute boolean buildMessageUri;
   attribute string messageUri;
   attribute string baseMessageUri;
 
+  /// message uri for header-only message version
+  attribute ACString origMessageUri;
+
   boolean BeginMailDelivery(in boolean uidlDownload, in nsIMsgWindow msgWindow);
   void endMailDelivery(in nsIPop3Protocol protocol);
   void AbortMailDelivery(in nsIPop3Protocol protocol);
 
   /* returns a closure ? */
   [noscript] voidPtr IncorporateBegin(in string uidlString, in nsIURI aURL,
                                       in unsigned long flags);
 
--- a/mailnews/local/src/nsLocalMailFolder.cpp
+++ b/mailnews/local/src/nsLocalMailFolder.cpp
@@ -3160,16 +3160,19 @@ NS_IMETHODIMP nsMsgLocalMailFolder::Dele
       msgDBHdr->GetMessageId(&oldMsgId);
 
       // Delete the first match and remove it from the array
       if (!PL_strcmp(newMsgId, oldMsgId))
       {
         rv = GetDatabase();
         if (!mDatabase)
           return rv;
+
+        UpdateNewMsgHdr(msgDBHdr, aMsgHdr);
+
 #if DOWNLOAD_NOTIFY_STYLE == DOWNLOAD_NOTIFY_LAST
         msgDBHdr->GetMessageKey(&mDownloadOldKey);
         msgDBHdr->GetThreadParent(&mDownloadOldParent);
         msgDBHdr->GetFlags(&mDownloadOldFlags);
         mDatabase->DeleteHeader(msgDBHdr, nsnull, PR_FALSE, PR_FALSE);
         // Tell caller we want to select this message
         if (aDoSelect)
           *aDoSelect = PR_TRUE;
@@ -3329,17 +3332,22 @@ nsMsgLocalMailFolder::OnStartRunningUrl(
   {
     nsCAutoString aSpec;
     aUrl->GetSpec(aSpec);
     if (strstr(aSpec.get(), "uidl="))
     {
       nsCOMPtr<nsIPop3Sink> popsink;
       rv = popurl->GetPop3Sink(getter_AddRefs(popsink));
       if (NS_SUCCEEDED(rv))
+      {
         popsink->SetBaseMessageUri(mBaseMessageURI.get());
+        nsCString messageuri;
+        popurl->GetMessageUri(getter_Copies(messageuri));
+        popsink->SetOrigMessageUri(messageuri);
+      }
     }
   }
   return nsMsgDBFolder::OnStartRunningUrl(aUrl);
 }
 
 NS_IMETHODIMP
 nsMsgLocalMailFolder::OnStopRunningUrl(nsIURI * aUrl, nsresult aExitCode)
 {
@@ -4060,8 +4068,30 @@ nsresult nsMsgLocalMailFolder::ChangeKey
   }
   return rv;
 }
 
 NS_IMETHODIMP nsMsgLocalMailFolder::RemoveKeywordsFromMessages(nsIArray *aMessages, const nsACString& aKeywords)
 {
   return ChangeKeywordForMessages(aMessages, aKeywords, PR_FALSE /* remove */);
 }
+
+NS_IMETHODIMP nsMsgLocalMailFolder::UpdateNewMsgHdr(nsIMsgDBHdr* aOldHdr, nsIMsgDBHdr* aNewHdr)
+{
+  NS_ENSURE_ARG_POINTER(aOldHdr);
+  NS_ENSURE_ARG_POINTER(aNewHdr);
+  // Preserve any properties set on the message.
+  CopyPropertiesToMsgHdr(aNewHdr, aOldHdr, PR_TRUE);
+
+  // Preserve keywords manually, since they are set as don't preserve.
+  nsCString keywordString;
+  aOldHdr->GetStringProperty("keywords", getter_Copies(keywordString));
+  aNewHdr->SetStringProperty("keywords", keywordString.get());
+
+  // If the junk score was set by the plugin, remove junkscore to force a new
+  // junk analysis, this time using the body.
+  nsCString junkScoreOrigin;
+  aOldHdr->GetStringProperty("junkscoreorigin", getter_Copies(junkScoreOrigin));
+  if (junkScoreOrigin.EqualsLiteral("plugin"))
+    aNewHdr->SetStringProperty("junkscore", "");
+
+  return NS_OK;
+}
--- a/mailnews/local/src/nsPop3Sink.cpp
+++ b/mailnews/local/src/nsPop3Sink.cpp
@@ -805,16 +805,27 @@ nsPop3Sink::IncorporateComplete(nsIMsgWi
     nsCOMPtr<nsIMsgLocalMailFolder> localFolder = do_QueryInterface(m_folder);
     PRBool doSelect = PR_FALSE;
 
     // aSize is only set for partial messages. For full messages,
     // check to see if we're replacing an old partial message.
     if (!aSize && localFolder)
       (void) localFolder->DeleteDownloadMsg(hdr, &doSelect);
 
+    // If a header already exists for this message (for example, when
+    // getting a complete message when a partial exists), then update the new
+    // header from the old.
+    if (!m_origMessageUri.IsEmpty() && localFolder)
+    {
+      nsCOMPtr <nsIMsgDBHdr> oldMsgHdr;
+      rv = GetMsgDBHdrFromURI(m_origMessageUri.get(), getter_AddRefs(oldMsgHdr));
+      if (NS_SUCCEEDED(rv) && oldMsgHdr)
+        localFolder->UpdateNewMsgHdr(oldMsgHdr, hdr);
+    }
+
     if (m_downloadingToTempFile)
     {
       PRBool moved = PR_FALSE;
       // close file to give virus checkers a chance to do their thing...
       m_outFileStream->Flush();
       m_outFileStream->Close();
       m_newMailParser->FinishHeader();
       // need to re-open the inbox file stream.
@@ -1029,8 +1040,22 @@ nsPop3Sink::GetBaseMessageUri(char ** ba
 
 NS_IMETHODIMP
 nsPop3Sink::SetBaseMessageUri(const char *baseMessageUri)
 {
   NS_ENSURE_ARG_POINTER(baseMessageUri);
   m_baseMessageUri = baseMessageUri;
   return NS_OK;
 }
+
+NS_IMETHODIMP
+nsPop3Sink::GetOrigMessageUri(nsACString& aOrigMessageUri)
+{
+  aOrigMessageUri.Assign(m_origMessageUri);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPop3Sink::SetOrigMessageUri(const nsACString& aOrigMessageUri)
+{
+  m_origMessageUri.Assign(aOrigMessageUri);
+  return NS_OK;
+}
--- a/mailnews/local/src/nsPop3Sink.h
+++ b/mailnews/local/src/nsPop3Sink.h
@@ -87,13 +87,14 @@ protected:
     PRInt32 m_fileCounter;
 #endif
     nsCOMPtr <nsIOutputStream> m_outFileStream;
     PRBool m_buildMessageUri;
     PRBool m_downloadingToTempFile;
     nsCOMPtr <nsILocalFile> m_tmpDownloadFile;
     nsCString m_messageUri;
     nsCString m_baseMessageUri;
+    nsCString m_origMessageUri;
     nsCString m_accountKey;
     nsVoidArray m_partialMsgsArray;
 };
 
 #endif