diff --git a/mozilla/mailnews/base/public/nsISpamSettings.idl b/mozilla/mailnews/base/public/nsISpamSettings.idl
index d1b8513e820..8dd574c0f0f 100644
--- a/mozilla/mailnews/base/public/nsISpamSettings.idl
+++ b/mozilla/mailnews/base/public/nsISpamSettings.idl
@@ -55,6 +55,7 @@ interface nsISpamSettings: nsISupports {
attribute long level;
attribute boolean moveOnSpam;
+ attribute boolean markAsReadOnSpam;
/**
* Most consumers will just use spamFolderURI rather than accessing any of
diff --git a/mozilla/mailnews/base/resources/content/junkMail.js b/mozilla/mailnews/base/resources/content/junkMail.js
index 9d59205598c..74fdb1b0c41 100644
--- a/mozilla/mailnews/base/resources/content/junkMail.js
+++ b/mozilla/mailnews/base/resources/content/junkMail.js
@@ -115,6 +115,9 @@ function setupForAccountFromFolder(aURI)
document.getElementById("moveOnSpam").checked = obj.settings.moveOnSpam;
document.getElementById("moveTargetMode").selectedItem = document.getElementById("moveTargetMode" + obj.settings.moveTargetMode);
+ // set up the 'mark as read' checkbox
+ document.getElementById("markAsReadOnSpam").checked = obj.settings.markAsReadOnSpam;
+
// the default account should be the current account
// unless you can't create a folder on that server
// or search on that account (for purge)
@@ -177,6 +180,7 @@ function onAccept()
function storeSettings(aSettings, aLoggingEnabled)
{
aSettings.level = document.getElementById("level").checked ? 100 : 0;
+ aSettings.markAsReadOnSpam = document.getElementById("markAsReadOnSpam").checked;
aSettings.moveOnSpam = document.getElementById("moveOnSpam").checked;
aSettings.moveTargetMode = document.getElementById("moveTargetMode").value;
aSettings.actionTargetAccount = document.getElementById("actionTargetAccount").getAttribute("uri");
@@ -206,6 +210,7 @@ function conditionallyEnableUI(id)
document.getElementById("useWhiteList").disabled = true;
document.getElementById("whiteListAbURI").disabled = true;
document.getElementById("moveOnSpam").disabled = true;
+ document.getElementById("markAsReadOnSpam").disabled = true;
document.getElementById("moveTargetMode").disabled = true;
document.getElementById("actionTargetAccount").disabled = true;
@@ -222,6 +227,7 @@ function conditionallyEnableUI(id)
document.getElementById("useWhiteList").disabled = false;
document.getElementById("moveOnSpam").disabled = false;
+ document.getElementById("markAsReadOnSpam").disabled = false;
document.getElementById("manualMark").disabled = false;
var enabled;
diff --git a/mozilla/mailnews/base/resources/content/junkMail.xul b/mozilla/mailnews/base/resources/content/junkMail.xul
index fa7a5e0ee56..d9a9f3b7163 100644
--- a/mozilla/mailnews/base/resources/content/junkMail.xul
+++ b/mozilla/mailnews/base/resources/content/junkMail.xul
@@ -150,6 +150,8 @@
+
+
diff --git a/mozilla/mailnews/base/resources/content/mail3PaneWindowCommands.js b/mozilla/mailnews/base/resources/content/mail3PaneWindowCommands.js
index 85d7c4a404a..41ed95044b4 100644
--- a/mozilla/mailnews/base/resources/content/mail3PaneWindowCommands.js
+++ b/mozilla/mailnews/base/resources/content/mail3PaneWindowCommands.js
@@ -611,7 +611,7 @@ var DefaultController =
MsgApplyFilters(null);
return;
case "cmd_runJunkControls":
- analyzeFolderForJunk();
+ filterFolderForJunk();
return;
case "cmd_deleteJunk":
deleteJunkInFolder();
diff --git a/mozilla/mailnews/base/resources/content/mailCommands.js b/mozilla/mailnews/base/resources/content/mailCommands.js
index ecd54ef7104..e77aed40d6d 100644
--- a/mozilla/mailnews/base/resources/content/mailCommands.js
+++ b/mozilla/mailnews/base/resources/content/mailCommands.js
@@ -480,68 +480,71 @@ const nsIJunkMailPlugin = Components.interfaces.nsIJunkMailPlugin;
const nsIMsgDBHdr = Components.interfaces.nsIMsgDBHdr;
var gJunkmailComponent;
-var gJunkKeys = [];
-var gJunkTargetFolder;
-function saveJunkMsgForAction(aServer, aMsgURI, aClassification)
+function determineActionsForJunkMsgs(aView, aIndices, aActionParams)
{
- // we only care when the message gets marked as junk
- if (aClassification == nsIJunkMailPlugin.GOOD)
+
+ // we use some arbitrary message to determine the
+ // message server
+ var msgURI = aView.getURIForViewIndex(aIndices[0]);
+ var msgHdr = messenger.messageServiceFromURI(msgURI).messageURIToMsgHdr(msgURI);
+ var server = msgHdr.folder.server;
+
+ var spamSettings = server.spamSettings;
+
+ // note we will do moves/marking as read even if the spam
+ // feature is disabled, since the user has asked to use it
+ // despite the disabling
+
+ // note also that we will only act on messages which
+ // _the_current_run_ of the classifier has classified as
+ // junk, rather than on all junk messages in the folder
+
+ aActionParams.markRead = spamSettings.markAsReadOnSpam;
+ aActionParams.junkTargetFolder = null;
+
+ if (!spamSettings.moveOnSpam)
return;
- var spamSettings = aServer.spamSettings
-
- // if the spam feature is disabled,
- // or if the move functionality is turned off, bail out.
- // the user could still run the JMC manually,
- // but let's not move in that scenario
- if (!spamSettings.level || !spamSettings.moveOnSpam)
- return;
-
- var msgHdr = messenger.messageServiceFromURI(aMsgURI).messageURIToMsgHdr(aMsgURI);
-
// don't move if we are already in the junk folder
if (msgHdr.folder.flags & MSG_FOLDER_FLAG_JUNK)
return;
var spamFolderURI = spamSettings.spamFolderURI;
if (!spamFolderURI)
- return;
-
- var spamFolder = GetMsgFolderFromUri(spamFolderURI);
-
- if (spamFolder)
{
- gJunkKeys[gJunkKeys.length] = msgHdr.messageKey;
- gJunkTargetFolder = spamFolder;
+ dump('no spam folder!');
+ return;
}
+
+ aActionParams.junkTargetFolder = GetMsgFolderFromUri(spamFolderURI);
}
-function performActionOnJunkMsgs()
+function performActionsOnJunkMsgs(aIndices)
{
- if (!gJunkKeys.length)
- {
- gJunkTargetFolder = [];
- return;
- }
-
- var indices = new Array(gJunkKeys.length);
- for (var i=0;i
+
diff --git a/mozilla/mailnews/base/src/nsMsgDBView.cpp b/mozilla/mailnews/base/src/nsMsgDBView.cpp
index b5807437341..aa66afc4288 100644
--- a/mozilla/mailnews/base/src/nsMsgDBView.cpp
+++ b/mozilla/mailnews/base/src/nsMsgDBView.cpp
@@ -141,8 +141,9 @@ nsMsgDBView::nsMsgDBView()
mIsNews = PR_FALSE;
mDeleteModel = nsMsgImapDeleteModels::MoveToTrash;
m_deletingRows = PR_FALSE;
- mOutstandingJunkBatches = 0;
-
+ mJunkIndices = nsnull;
+ mNumJunkIndices = 0;
+
/* mCommandsNeedDisablingBecauseOffline - A boolean that tell us if we needed to disable commands because we're offline w/o a downloaded msg select */
mCommandsNeedDisablingBecauseOffline = PR_FALSE;
@@ -2229,185 +2230,206 @@ nsresult
nsMsgDBView::ApplyCommandToIndices(nsMsgViewCommandTypeValue command, nsMsgViewIndex* indices,
PRInt32 numIndices)
{
- nsresult rv = NS_OK;
- nsMsgKeyArray imapUids;
-
- // if numIndices == 0, return quietly, just in case
- if (numIndices == 0)
- return NS_OK;
-
NS_ASSERTION(numIndices >= 0, "nsMsgDBView::ApplyCommandToIndices(): "
"numIndices is negative!");
- nsCOMPtr imapFolder = do_QueryInterface(m_folder);
- PRBool thisIsImapFolder = (imapFolder != nsnull);
+ if (numIndices == 0)
+ return NS_OK; // return quietly, just in case
if (command == nsMsgViewCommandType::deleteMsg)
- rv = DeleteMessages(mMsgWindow, indices, numIndices, PR_FALSE);
- else if (command == nsMsgViewCommandType::deleteNoTrash)
- rv = DeleteMessages(mMsgWindow, indices, numIndices, PR_TRUE);
- else
+ return DeleteMessages(mMsgWindow, indices, numIndices, PR_FALSE);
+ if (command == nsMsgViewCommandType::deleteNoTrash)
+ return DeleteMessages(mMsgWindow, indices, numIndices, PR_TRUE);
+
+ nsMsgKeyArray imapUids;
+ nsresult rv = NS_OK;
+ nsCOMPtr imapFolder = do_QueryInterface(m_folder);
+ PRBool thisIsImapFolder = (imapFolder != nsnull);
+ nsCOMPtr junkPlugin;
+
+ // if this is a junk command, start a batch.
+ //
+ if ( command == nsMsgViewCommandType::junk
+ || command == nsMsgViewCommandType::unjunk )
{
- nsCOMPtr junkPlugin;
+ // get the folder from the first item; we assume that
+ // all messages in the view are from the same folder (no
+ // more junk status column in the 'search messages' dialog
+ // like in earlier versions...)
+ //
+ nsCOMPtr folder;
+ rv = GetFolderForViewIndex(indices[0], getter_AddRefs(folder));
+ NS_ENSURE_SUCCESS(rv, rv);
- // if this is a junk command, start a batch. The batch will be ended
- // in the last callback.
- //
- if ( command == nsMsgViewCommandType::junk
- || command == nsMsgViewCommandType::unjunk )
+ nsCOMPtr server;
+ rv = folder->GetServer(getter_AddRefs(server));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (command == nsMsgViewCommandType::junk)
{
-
- // get the folder from the first item (if it's the search view,
- // only one item can be touched at a time; if a regular folder view,
- // all items will have the same folder).
- //
- nsCOMPtr folder;
- rv = GetFolderForViewIndex(indices[0], getter_AddRefs(folder));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr server;
- rv = folder->GetServer(getter_AddRefs(server));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr filterPlugin;
- rv = server->GetSpamFilterPlugin(getter_AddRefs(filterPlugin));
- NS_ENSURE_SUCCESS(rv, rv);
-
- junkPlugin = do_QueryInterface(filterPlugin, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = junkPlugin->StartBatch();
- NS_ENSURE_SUCCESS(rv, rv);
-
- mOutstandingJunkBatches++;
+ // append this batch of junk message indices to the
+ // array of junk message indices to be acted upon
+ // once OnMessageClassified() is run for the last message
+ //
+ // note: although message classification is done
+ // asynchronously, it is not done in a different thread,
+ // so the manipulations of mJunkIndices here and in
+ // OnMessageClassified() cannot interrupt each other
+ //
+ mNumJunkIndices += numIndices;
+ mJunkIndices = (nsMsgViewIndex *)nsMemory::Realloc(mJunkIndices, mNumJunkIndices * sizeof(nsMsgViewIndex));
+ memcpy(mJunkIndices + (mNumJunkIndices - numIndices), indices, numIndices * sizeof(nsMsgViewIndex));
+
+ // save the last URI, so that OnMessageClassified()
+ // will know when the classification it runs after
+ // is the last one; if the classification of previously-marked
+ // messages has not been completed, we replace here the
+ // previous 'last URI' with a new 'last URI',
+ // causing the batches to be coalesced
+ //
+ rv = GetURIForViewIndex(indices[numIndices-1], getter_Copies(mLastJunkURIInBatch));
+ NS_ENSURE_SUCCESS(rv, rv);
}
-
- m_folder->EnableNotifications(nsIMsgFolder::allMessageCountNotifications, PR_FALSE, PR_TRUE /*dbBatching*/);
+
+ nsCOMPtr filterPlugin;
+ rv = server->GetSpamFilterPlugin(getter_AddRefs(filterPlugin));
+ NS_ENSURE_SUCCESS(rv, rv);
- for (int32 i = 0; i < numIndices; i++)
+ junkPlugin = do_QueryInterface(filterPlugin, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = junkPlugin->StartBatch();
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ m_folder->EnableNotifications(nsIMsgFolder::allMessageCountNotifications, PR_FALSE, PR_TRUE /*dbBatching*/);
+
+ for (int32 i = 0; i < numIndices; i++)
+ {
+ if (thisIsImapFolder && command != nsMsgViewCommandType::markThreadRead)
+ imapUids.Add(GetAt(indices[i]));
+
+ switch (command)
{
- if (thisIsImapFolder && command != nsMsgViewCommandType::markThreadRead)
- imapUids.Add(GetAt(indices[i]));
-
- switch (command)
- {
- case nsMsgViewCommandType::markMessagesRead:
- rv = SetReadByIndex(indices[i], PR_TRUE);
- break;
- case nsMsgViewCommandType::markMessagesUnread:
- rv = SetReadByIndex(indices[i], PR_FALSE);
- break;
- case nsMsgViewCommandType::toggleMessageRead:
- rv = ToggleReadByIndex(indices[i]);
- break;
- case nsMsgViewCommandType::flagMessages:
- rv = SetFlaggedByIndex(indices[i], PR_TRUE);
- break;
- case nsMsgViewCommandType::unflagMessages:
- rv = SetFlaggedByIndex(indices[i], PR_FALSE);
- break;
- case nsMsgViewCommandType::markThreadRead:
- rv = SetThreadOfMsgReadByIndex(indices[i], imapUids, PR_TRUE);
- break;
- case nsMsgViewCommandType::label0:
- case nsMsgViewCommandType::label1:
- case nsMsgViewCommandType::label2:
- case nsMsgViewCommandType::label3:
- case nsMsgViewCommandType::label4:
- case nsMsgViewCommandType::label5:
- rv = SetLabelByIndex(indices[i], (command - nsMsgViewCommandType::label0));
- break;
- case nsMsgViewCommandType::junk:
- rv = SetJunkScoreByIndex(junkPlugin.get(), indices[i],
- nsIJunkMailPlugin::JUNK, (i == numIndices-1));
- break;
- case nsMsgViewCommandType::unjunk:
- rv = SetJunkScoreByIndex(junkPlugin.get(), indices[i],
- nsIJunkMailPlugin::GOOD, (i == numIndices-1));
- break;
- case nsMsgViewCommandType::undeleteMsg:
- break; // this is completely handled in the imap code below.
- default:
- NS_ASSERTION(PR_FALSE, "unhandled command");
- break;
- }
- }
- m_folder->EnableNotifications(nsIMsgFolder::allMessageCountNotifications, PR_TRUE, PR_TRUE /*dbBatching*/);
-
- if (thisIsImapFolder)
- {
- imapMessageFlagsType flags = kNoImapMsgFlag;
- PRBool commandIsLabelSet = PR_FALSE;
- PRBool addFlags = PR_FALSE;
- PRBool isRead = PR_FALSE;
-
- switch (command)
- {
- case nsMsgViewCommandType::markThreadRead:
- case nsMsgViewCommandType::markMessagesRead:
- flags |= kImapMsgSeenFlag;
- addFlags = PR_TRUE;
- break;
- case nsMsgViewCommandType::markMessagesUnread:
- flags |= kImapMsgSeenFlag;
- addFlags = PR_FALSE;
- break;
- case nsMsgViewCommandType::toggleMessageRead:
- {
- flags |= kImapMsgSeenFlag;
- m_db->IsRead(GetAt(indices[0]), &isRead);
- if (isRead)
- addFlags = PR_TRUE;
- else
- addFlags = PR_FALSE;
- }
- break;
- case nsMsgViewCommandType::flagMessages:
- flags |= kImapMsgFlaggedFlag;
- addFlags = PR_TRUE;
- break;
- case nsMsgViewCommandType::unflagMessages:
- flags |= kImapMsgFlaggedFlag;
- addFlags = PR_FALSE;
- break;
- case nsMsgViewCommandType::label0:
- case nsMsgViewCommandType::label1:
- case nsMsgViewCommandType::label2:
- case nsMsgViewCommandType::label3:
- case nsMsgViewCommandType::label4:
- case nsMsgViewCommandType::label5:
- flags |= ((command - nsMsgViewCommandType::label0) << 9);
- addFlags = (command != nsMsgViewCommandType::label0);
- commandIsLabelSet = PR_TRUE;
- break;
- case nsMsgViewCommandType::undeleteMsg:
- flags = kImapMsgDeletedFlag;
- addFlags = PR_FALSE;
- break;
- case nsMsgViewCommandType::junk:
- return imapFolder->StoreCustomKeywords(mMsgWindow,
- "Junk",
- "NonJunk",
- imapUids.GetArray(), imapUids.GetSize(),
- nsnull);
- case nsMsgViewCommandType::unjunk:
- return imapFolder->StoreCustomKeywords(mMsgWindow,
- "NonJunk",
- "Junk",
- imapUids.GetArray(), imapUids.GetSize(),
- nsnull);
-
- default:
- break;
- }
-
- if (flags != kNoImapMsgFlag || commandIsLabelSet) // can't get here without thisIsImapThreadPane == TRUE
- imapFolder->StoreImapFlags(flags, addFlags, imapUids.GetArray(), imapUids.GetSize());
-
+ case nsMsgViewCommandType::markMessagesRead:
+ rv = SetReadByIndex(indices[i], PR_TRUE);
+ break;
+ case nsMsgViewCommandType::markMessagesUnread:
+ rv = SetReadByIndex(indices[i], PR_FALSE);
+ break;
+ case nsMsgViewCommandType::toggleMessageRead:
+ rv = ToggleReadByIndex(indices[i]);
+ break;
+ case nsMsgViewCommandType::flagMessages:
+ rv = SetFlaggedByIndex(indices[i], PR_TRUE);
+ break;
+ case nsMsgViewCommandType::unflagMessages:
+ rv = SetFlaggedByIndex(indices[i], PR_FALSE);
+ break;
+ case nsMsgViewCommandType::markThreadRead:
+ rv = SetThreadOfMsgReadByIndex(indices[i], imapUids, PR_TRUE);
+ break;
+ case nsMsgViewCommandType::label0:
+ case nsMsgViewCommandType::label1:
+ case nsMsgViewCommandType::label2:
+ case nsMsgViewCommandType::label3:
+ case nsMsgViewCommandType::label4:
+ case nsMsgViewCommandType::label5:
+ rv = SetLabelByIndex(indices[i], (command - nsMsgViewCommandType::label0));
+ break;
+ case nsMsgViewCommandType::junk:
+ rv = SetAsJunkByIndex(junkPlugin.get(), indices[i],
+ nsIJunkMailPlugin::JUNK);
+ break;
+ case nsMsgViewCommandType::unjunk:
+ rv = SetAsJunkByIndex(junkPlugin.get(), indices[i],
+ nsIJunkMailPlugin::GOOD);
+ break;
+ case nsMsgViewCommandType::undeleteMsg:
+ break; // this is completely handled in the imap code below.
+ default:
+ NS_ASSERTION(PR_FALSE, "unhandled command");
+ break;
}
}
+
+ m_folder->EnableNotifications(nsIMsgFolder::allMessageCountNotifications, PR_TRUE, PR_TRUE /*dbBatching*/);
+
+ if (thisIsImapFolder)
+ {
+ imapMessageFlagsType flags = kNoImapMsgFlag;
+ PRBool commandIsLabelSet = PR_FALSE;
+ PRBool addFlags = PR_FALSE;
+ PRBool isRead = PR_FALSE;
+
+ switch (command)
+ {
+ case nsMsgViewCommandType::markThreadRead:
+ case nsMsgViewCommandType::markMessagesRead:
+ flags |= kImapMsgSeenFlag;
+ addFlags = PR_TRUE;
+ break;
+ case nsMsgViewCommandType::markMessagesUnread:
+ flags |= kImapMsgSeenFlag;
+ addFlags = PR_FALSE;
+ break;
+ case nsMsgViewCommandType::toggleMessageRead:
+ {
+ flags |= kImapMsgSeenFlag;
+ m_db->IsRead(GetAt(indices[0]), &isRead);
+ if (isRead)
+ addFlags = PR_TRUE;
+ else
+ addFlags = PR_FALSE;
+ }
+ break;
+ case nsMsgViewCommandType::flagMessages:
+ flags |= kImapMsgFlaggedFlag;
+ addFlags = PR_TRUE;
+ break;
+ case nsMsgViewCommandType::unflagMessages:
+ flags |= kImapMsgFlaggedFlag;
+ addFlags = PR_FALSE;
+ break;
+ case nsMsgViewCommandType::label0:
+ case nsMsgViewCommandType::label1:
+ case nsMsgViewCommandType::label2:
+ case nsMsgViewCommandType::label3:
+ case nsMsgViewCommandType::label4:
+ case nsMsgViewCommandType::label5:
+ flags |= ((command - nsMsgViewCommandType::label0) << 9);
+ addFlags = (command != nsMsgViewCommandType::label0);
+ commandIsLabelSet = PR_TRUE;
+ break;
+ case nsMsgViewCommandType::undeleteMsg:
+ flags = kImapMsgDeletedFlag;
+ addFlags = PR_FALSE;
+ break;
+ case nsMsgViewCommandType::junk:
+ return imapFolder->StoreCustomKeywords(mMsgWindow,
+ "Junk",
+ "NonJunk",
+ imapUids.GetArray(), imapUids.GetSize(),
+ nsnull);
+ case nsMsgViewCommandType::unjunk:
+ return imapFolder->StoreCustomKeywords(mMsgWindow,
+ "NonJunk",
+ "Junk",
+ imapUids.GetArray(), imapUids.GetSize(),
+ nsnull);
+
+ default:
+ break;
+ }
+
+ if (flags != kNoImapMsgFlag || commandIsLabelSet) // can't get here without thisIsImapThreadPane == TRUE
+ imapFolder->StoreImapFlags(flags, addFlags, imapUids.GetArray(), imapUids.GetSize());
+
+ }
+
return rv;
}
+
// view modifications methods by index
// This method just removes the specified line from the view. It does
@@ -2621,12 +2643,10 @@ nsresult nsMsgDBView::SetStringPropertyByIndex(nsMsgViewIndex index, const char
return rv;
}
-nsresult nsMsgDBView::SetJunkScoreByIndex(nsIJunkMailPlugin *aJunkPlugin,
+nsresult nsMsgDBView::SetAsJunkByIndex(nsIJunkMailPlugin *aJunkPlugin,
nsMsgViewIndex aIndex,
- nsMsgJunkStatus aNewClassification,
- PRBool aIsLastInBatch)
+ nsMsgJunkStatus aNewClassification)
{
-
// get the message header (need this to get string properties)
//
nsCOMPtr msgHdr;
@@ -2667,13 +2687,6 @@ nsresult nsMsgDBView::SetJunkScoreByIndex(nsIJunkMailPlugin *aJunkPlugin,
rv = GetURIForViewIndex(aIndex, getter_Copies(uri));
NS_ENSURE_SUCCESS(rv, rv);
- if ( aIsLastInBatch ) {
- // if there's already a batch in progress, just replace the URI,
- // thus causing the batches to be coalesced
- //
- mLastJunkUriInBatch = uri;
- }
-
// tell the plugin about this change, so that it can (potentially)
// adjust its database appropriately
//
@@ -2709,106 +2722,185 @@ NS_IMETHODIMP
nsMsgDBView::OnMessageClassified(const char *aMsgURI,
nsMsgJunkStatus aClassification)
{
- // we can't just use m_folder
- // as this might be from a cross folder search
- // see bug #180477
- nsCOMPtr folder;
- nsresult rv = GetFolderFromMsgURI(aMsgURI, getter_AddRefs(folder));
- NS_ENSURE_SUCCESS(rv,rv);
+ // Note: we know all messages in a batch have the same
+ // classification, since unlike OnMessageClassified
+ // methods in other classes (such as nsLocalMailFolder
+ // and nsImapMailFolder), this class, nsMsgDBView, currently
+ // only triggers message classifications due to a command to
+ // mark some of the messages in the view as junk, or as not
+ // junk - so the classification is dictated to the filter,
+ // not suggested by it.
+ //
+ // for this reason the only thing we (may) have to do is
+ // perform the action on all of the junk messages
+ //
+
+ // this check is necessary because it is theoretically
+ // possible for a message to be flagged as non-junk,
+ // and before the classifier can finish with it, for it
+ // to be again classified as junk, and thus to have
+ // mLastJunkURIInBatch set with its URI - and it should
+ // not be considered the last junk messages during
+ // the first call of this function
+ if (aClassification == nsIJunkMailPlugin::GOOD)
+ return NS_OK;
+
+ NS_ASSERTION(mJunkIndices != nsnull, "the classification of a manually-marked junk message has been classified as junk, yet there seem to be no such outstanding messages");
- nsCOMPtr server;
- rv = folder->GetServer(getter_AddRefs(server));
- NS_ENSURE_SUCCESS(rv, rv);
+ if ( mLastJunkURIInBatch.Equals(aMsgURI) )
+ {
+ nsCOMPtr folder;
+ nsresult rv = GetFolderForViewIndex(mJunkIndices[0], getter_AddRefs(folder));
+ NS_ENSURE_SUCCESS(rv, rv);
- // save off the msg hdr, if we need to
- rv = SaveJunkMsgForAction(server, aMsgURI, aClassification);
- NS_ENSURE_SUCCESS(rv,rv);
+ // it seems EndBatch must be called here, rather
+ // than after the last message has been dispatched for
+ // classification. One would think when the UI tells the
+ // classifier "I am done with sending you this batch of
+ // messages" the classifer should say "ok, now as soon
+ // as I finish classification I should flush my data file"
+ // ... but that's not the way it works. If that were
+ // to change you could move the EndBatch() call to
+ // ApplyCommandToIndices and avoid the redundant
+ // lines of code which get the pointer to the junk plugin
+ // object.
+
+ nsCOMPtr server;
+ rv = folder->GetServer(getter_AddRefs(server));
+ NS_ENSURE_SUCCESS(rv, rv);
- // is this the last url in the batch?
- if (mLastJunkUriInBatch.Equals(aMsgURI))
- {
- // get the filter, and QI to the interface we want
nsCOMPtr filterPlugin;
rv = server->GetSpamFilterPlugin(getter_AddRefs(filterPlugin));
NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr junkPlugin = do_QueryInterface(filterPlugin, &rv);
+
+ nsCOMPtr junkPlugin;
+ junkPlugin = do_QueryInterface(filterPlugin, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = junkPlugin->EndBatch();
NS_ENSURE_SUCCESS(rv, rv);
- // close out existing coalesced junk batches
- for ( ; mOutstandingJunkBatches > 0 ; --mOutstandingJunkBatches )
- {
- // tell the plugin that all outstanding batches from us
- // have finished.
- rv = junkPlugin->EndBatch();
- NS_ENSURE_SUCCESS(rv, rv);
+ if ( mNumJunkIndices > 0 )
+ {
+ PerformActionsOnJunkMsgs();
+ nsMemory::Free(mJunkIndices);
+ mJunkIndices = nsnull;
+ mNumJunkIndices = 0;
+ mLastJunkURIInBatch.Truncate();
}
- rv = PerformActionOnJunkMsgs();
- NS_ENSURE_SUCCESS(rv,rv);
}
return NS_OK;
}
nsresult
-nsMsgDBView::PerformActionOnJunkMsgs()
+nsMsgDBView::PerformActionsOnJunkMsgs()
{
- PRUint32 numIndices = mJunkKeys.GetSize();
- // nothing to do, bail out
- if (!numIndices)
- {
- mJunkTargetFolder = nsnull; // just to be safe
- return NS_OK;
- }
+ PRBool movingJunkMessages,markingJunkMessagesRead;
+ nsCOMPtr junkTargetFolder;
- nsMsgViewIndex *indices = (nsMsgViewIndex *)nsMemory::Alloc(numIndices * sizeof(nsMsgViewIndex));
- if (!indices)
- return NS_ERROR_OUT_OF_MEMORY;
-
- for (PRUint32 i=0;iUpdateNextMessageAfterDelete();
- NS_ENSURE_SUCCESS(rv,rv);
+ // question: is it possible for the junk mail move/mark as read
+ // options to change after we've handled some of the batches but
+ // before we've handled the last one? if so, we can decide when
+ // handling each batch whether to save its indices or forget
+ // them, and then perform the known action when handling the
+ // last batch; however if the options can change between batches
+ // we may have to remember in separate arrays the indices to
+ // mark as read and the indices to move
+ //
+ // for now, we assume the options do not change between batches
+ //
- if (numIndices > 1)
- NS_QuickSort(indices, numIndices, sizeof(nsMsgViewIndex), CompareViewIndices, nsnull);
- NoteStartChange(nsMsgViewNotificationCode::none, 0, 0);
- if (mJunkTargetFolder)
- rv = ApplyCommandToIndicesWithFolder(nsMsgViewCommandType::moveMessages, indices, numIndices, mJunkTargetFolder);
- else
- rv = ApplyCommandToIndices(nsMsgViewCommandType::deleteMsg, indices, numIndices);
- NoteEndChange(nsMsgViewNotificationCode::none, 0, 0);
+ nsresult rv = DetermineActionsForJunkMsgs(&movingJunkMessages, &markingJunkMessagesRead, getter_AddRefs(junkTargetFolder));
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ // nothing to do, bail out
+ if (!(movingJunkMessages || markingJunkMessagesRead))
+ return NS_OK;
- mJunkKeys.RemoveAll();
- mJunkTargetFolder = nsnull;
- nsMemory::Free(indices);
+ NS_ASSERTION( (mNumJunkIndices > 0), "no indices of marked-as-junk messages to act on");
- NS_ASSERTION(NS_SUCCEEDED(rv), "move or delete failed");
+ if (mNumJunkIndices > 1)
+ NS_QuickSort(mJunkIndices, mNumJunkIndices, sizeof(nsMsgViewIndex), CompareViewIndices, nsnull);
+
+ if (markingJunkMessagesRead)
+ {
+ // notes on marking junk as read:
+ // 1. there are 2 occasions on which junk messages are marked as
+ // read: here (after a manual marking) as well as after automatic
+ // marking by the bayesian filter (see code for local mail folders
+ // and for imap mail folders); it is perhaps worth considering
+ // making these two separate options... but for now they are
+ // controlled by a single preference
+ // 2. even though move/delete on manual mark may be
+ // turned off, we might still need to mark as read
+
+ NoteStartChange(nsMsgViewNotificationCode::none, 0, 0);
+ rv = ApplyCommandToIndices(nsMsgViewCommandType::markMessagesRead, mJunkIndices, mNumJunkIndices);
+ NoteEndChange(nsMsgViewNotificationCode::none, 0, 0);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "marking marked-as-junk messages as read failed");
+ }
+ if (movingJunkMessages)
+ {
+ // tell the FE to call SetNextMessageAfterDelete() because a delete is coming
+ rv = mCommandUpdater->UpdateNextMessageAfterDelete();
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ NoteStartChange(nsMsgViewNotificationCode::none, 0, 0);
+ if (junkTargetFolder)
+ rv = ApplyCommandToIndicesWithFolder(nsMsgViewCommandType::moveMessages, mJunkIndices, mNumJunkIndices, junkTargetFolder);
+ else
+ rv = ApplyCommandToIndices(nsMsgViewCommandType::deleteMsg, mJunkIndices, mNumJunkIndices);
+ NoteEndChange(nsMsgViewNotificationCode::none, 0, 0);
+
+ NS_ASSERTION(NS_SUCCEEDED(rv), "move or deletion of marked-as-junk messages failed");
+ }
return rv;
}
nsresult
-nsMsgDBView::SaveJunkMsgForAction(nsIMsgIncomingServer *aServer, const char *aMsgURI, nsMsgJunkStatus aClassification)
+nsMsgDBView::DetermineActionsForJunkMsgs(PRBool* movingJunkMessages, PRBool* markingJunkMessagesRead, nsIMsgFolder** junkTargetFolder)
{
- // we only care when the message gets marked as junk
- if (aClassification == nsIJunkMailPlugin::GOOD)
- return NS_OK;
+ // there are two possible actions which may be performed
+ // on messages marked as spam: marking as read and moving
+ // somewhere...
+
+ *movingJunkMessages = false;
+ *markingJunkMessagesRead = false;
+
+ // ... the 'somewhere', junkTargetFolder, can be a folder,
+ // but if it remains null we'll delete the messages
+
+ *junkTargetFolder = nsnull;
+
+ nsCOMPtr folder;
+ nsresult rv = GetFolderForViewIndex(mJunkIndices[0], getter_AddRefs(folder));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr server;
+ rv = folder->GetServer(getter_AddRefs(server));
+ NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr spamSettings;
- nsresult rv = aServer->GetSpamSettings(getter_AddRefs(spamSettings));
+ rv = server->GetSpamSettings(getter_AddRefs(spamSettings));
NS_ENSURE_SUCCESS(rv, rv);
- // if the spam feature is disabled, do nothing
- // the user could still manually mark spam if the feature is disabled
- // but let's not move or delete in that scenario
+ // if the spam system is completely disabled we won't do anything
+ // question: is this a valid choice?
PRInt32 spamLevel;
(void)spamSettings->GetLevel(&spamLevel);
if (!spamLevel)
return NS_OK;
- // if the manual mark functionality is turned off, bail out.
+ // now let's determine whether we'll be taking the first action,
+ // marking as read
+
+ (void)spamSettings->GetMarkAsReadOnSpam(markingJunkMessagesRead);
+
+
+ // now let's determine whether we'll be taking the second action,
+ // the move / deletion (and also determine which of these two)
+
PRBool manualMark;
(void)spamSettings->GetManualMark(&manualMark);
if (!manualMark)
@@ -2816,28 +2908,14 @@ nsMsgDBView::SaveJunkMsgForAction(nsIMsgIncomingServer *aServer, const char *aMs
PRInt32 manualMarkMode;
(void)spamSettings->GetManualMarkMode(&manualMarkMode);
+ NS_ASSERTION(manualMarkMode == nsISpamSettings::MANUAL_MARK_MODE_MOVE
+ || manualMarkMode == nsISpamSettings::MANUAL_MARK_MODE_DELETE,
+ "bad manual mark mode");
- nsCOMPtr msgMessageService;
- rv = GetMessageServiceFromURI(aMsgURI, getter_AddRefs(msgMessageService));
- NS_ENSURE_SUCCESS(rv,rv);
-
- nsCOMPtr msgHdr;
- rv = msgMessageService->MessageURIToMsgHdr(aMsgURI, getter_AddRefs(msgHdr));
- NS_ENSURE_SUCCESS(rv,rv);
-
- nsCOMPtr srcFolder;
- rv = msgHdr->GetFolder(getter_AddRefs(srcFolder));
- NS_ENSURE_SUCCESS(rv,rv);
-
- nsMsgKey msgKey;
- rv = msgHdr->GetMessageKey(&msgKey);
- NS_ENSURE_SUCCESS(rv,rv);
-
- // we can execute the move or delete
+ // the folder must allow us to execute the move (or the deletion)
PRUint32 folderFlags;
- srcFolder->GetFlags(&folderFlags);
+ folder->GetFlags(&folderFlags);
- NS_ASSERTION(manualMarkMode == nsISpamSettings::MANUAL_MARK_MODE_MOVE || manualMarkMode == nsISpamSettings::MANUAL_MARK_MODE_DELETE, "bad mode");
if (manualMarkMode == nsISpamSettings::MANUAL_MARK_MODE_MOVE)
{
PRBool moveOnSpam;
@@ -2856,48 +2934,25 @@ nsMsgDBView::SaveJunkMsgForAction(nsIMsgIncomingServer *aServer, const char *aMs
rv = spamSettings->GetSpamFolderURI(getter_Copies(spamFolderURI));
NS_ENSURE_SUCCESS(rv,rv);
- NS_ASSERTION(!spamFolderURI.IsEmpty(), "spam folder is empty, can't move");
+ NS_ASSERTION(!spamFolderURI.IsEmpty(), "spam folder URI is empty, can't move");
if (!spamFolderURI.IsEmpty())
{
- nsCOMPtr destFolder;
- rv = GetExistingFolder(spamFolderURI.get(), getter_AddRefs(destFolder));
- if (NS_SUCCEEDED(rv) && destFolder)
- {
-#ifdef DEBUG
- // double check the assumptions
- if (mJunkKeys.GetSize())
- {
- NS_ASSERTION(mJunkTargetFolder, "should have a junk folder at this point");
- NS_ASSERTION(mJunkTargetFolder.get() == destFolder.get(), "junk folder doesn't match");
- }
- else
- NS_ASSERTION(mJunkTargetFolder == nsnull, "junk folder should be null, no keys yet");
-#endif
- // save off msg key and folder
- mJunkKeys.Add(msgKey);
- if (!mJunkTargetFolder)
- mJunkTargetFolder = destFolder;
- }
+ //nsCOMPtr destFolder;
+ rv = GetExistingFolder(spamFolderURI.get(), junkTargetFolder);
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ *movingJunkMessages = true;
}
+ return NS_OK;
}
- else // manualMarkMode == nsISpamSettings::MANUAL_MARK_MODE_DELETE)
- {
- // if this is in the trash, don't delete?
- if (folderFlags & MSG_FOLDER_FLAG_TRASH)
- return NS_OK;
-
- // we can't delete, bail out
- PRBool canDelete;
- (void)srcFolder->GetCanDeleteMessages(&canDelete);
- if (!canDelete)
- return NS_OK;
-
- // save off msg key
- mJunkKeys.Add(msgKey);
- NS_ASSERTION(mJunkTargetFolder == nsnull, "should be null");
- mJunkTargetFolder = nsnull; // should already be null
- }
- return NS_OK;
+
+ // at this point manualMarkMode == nsISpamSettings::MANUAL_MARK_MODE_DELETE)
+
+ // if this is in the trash, let's not delete
+ if (folderFlags & MSG_FOLDER_FLAG_TRASH)
+ return NS_OK;
+
+ return folder->GetCanDeleteMessages(movingJunkMessages);
}
// reversing threads involves reversing the threads but leaving the
diff --git a/mozilla/mailnews/base/src/nsMsgDBView.h b/mozilla/mailnews/base/src/nsMsgDBView.h
index b6f8f7055bf..a9b6c221610 100644
--- a/mozilla/mailnews/base/src/nsMsgDBView.h
+++ b/mozilla/mailnews/base/src/nsMsgDBView.h
@@ -250,10 +250,9 @@ protected:
virtual nsresult CopyMessages(nsIMsgWindow *window, nsMsgViewIndex *indices, PRInt32 numIndices, PRBool isMove, nsIMsgFolder *destFolder);
virtual nsresult DeleteMessages(nsIMsgWindow *window, nsMsgViewIndex *indices, PRInt32 numIndices, PRBool deleteStorage);
nsresult SetStringPropertyByIndex(nsMsgViewIndex index, const char *aProperty, const char *aValue);
- nsresult SetJunkScoreByIndex(nsIJunkMailPlugin *aJunkPlugin,
+ nsresult SetAsJunkByIndex(nsIJunkMailPlugin *aJunkPlugin,
nsMsgViewIndex aIndex,
- nsMsgJunkStatus aNewClassification,
- PRBool aIsLastInBatch);
+ nsMsgJunkStatus aNewClassification);
nsresult ToggleReadByIndex(nsMsgViewIndex index);
nsresult SetReadByIndex(nsMsgViewIndex index, PRBool read);
nsresult SetThreadOfMsgReadByIndex(nsMsgViewIndex index, nsMsgKeyArray &keysMarkedRead, PRBool read);
@@ -360,12 +359,21 @@ protected:
// used to cache the atoms created for each color to be displayed
static nsIAtom* mLabelPrefColorAtoms[PREF_LABELS_MAX];
- // used to know to finish out the junk mail classification batch when the
- // last classification callback happens
- nsCString mLastJunkUriInBatch;
- PRUint8 mOutstandingJunkBatches;
+ // comparing against this value, the classifier
+ // callback function, OnMessageClassified(), can know
+ // when the classified message is the last one in the
+ // batch/series of batches (in which case the
+ // appropriate action is taken for all the messages)
+ nsXPIDLCString mLastJunkURIInBatch;
+ // these are the indices of the messages in the current
+ // batch/series of batches of messages manually marked
+ // as junk
+ nsMsgViewIndex *mJunkIndices;
+ PRUint32 mNumJunkIndices;
+
nsUInt32Array mIndicesToNoteChange;
+
protected:
static nsresult InitDisplayFormats();
@@ -375,10 +383,8 @@ private:
static nsDateFormatSelector m_dateFormatToday;
PRBool ServerSupportsFilterAfterTheFact();
- nsMsgKeyArray mJunkKeys;
- nsCOMPtr mJunkTargetFolder;
- nsresult PerformActionOnJunkMsgs();
- nsresult SaveJunkMsgForAction(nsIMsgIncomingServer *aServer, const char *aMsgURI, nsMsgJunkStatus aClassification);
+ nsresult PerformActionsOnJunkMsgs();
+ nsresult DetermineActionsForJunkMsgs(PRBool* movingJunkMessages, PRBool* markingJunkMessagesRead, nsIMsgFolder** junkTargetFolder);
};
diff --git a/mozilla/mailnews/base/src/nsSpamSettings.cpp b/mozilla/mailnews/base/src/nsSpamSettings.cpp
index e9cc109e8e4..e7c8e2265aa 100644
--- a/mozilla/mailnews/base/src/nsSpamSettings.cpp
+++ b/mozilla/mailnews/base/src/nsSpamSettings.cpp
@@ -58,6 +58,7 @@ nsSpamSettings::nsSpamSettings()
{
mLevel = 0;
mMoveOnSpam = PR_FALSE;
+ mMarkAsReadOnSpam = PR_FALSE;
mMoveTargetMode = nsISpamSettings::MOVE_TARGET_MODE_ACCOUNT;
mPurge = PR_FALSE;
mPurgeInterval = 14; // 14 days
@@ -123,6 +124,7 @@ NS_IMETHODIMP nsSpamSettings::SetManualMarkMode(PRInt32 aManualMarkMode)
NS_IMPL_GETSET(nsSpamSettings, LoggingEnabled, PRBool, mLoggingEnabled)
NS_IMPL_GETSET(nsSpamSettings, MoveOnSpam, PRBool, mMoveOnSpam)
+NS_IMPL_GETSET(nsSpamSettings, MarkAsReadOnSpam, PRBool, mMarkAsReadOnSpam)
NS_IMPL_GETSET(nsSpamSettings, Purge, PRBool, mPurge)
NS_IMPL_GETSET(nsSpamSettings, UseWhiteList, PRBool, mUseWhiteList)
NS_IMPL_GETSET(nsSpamSettings, ManualMark, PRBool, mManualMark)
@@ -349,6 +351,7 @@ NS_IMETHODIMP nsSpamSettings::Clone(nsISpamSettings *aSpamSettings)
NS_ENSURE_SUCCESS(rv,rv);
(void)aSpamSettings->GetMoveOnSpam(&mMoveOnSpam);
+ (void)aSpamSettings->GetMarkAsReadOnSpam(&mMarkAsReadOnSpam);
(void)aSpamSettings->GetManualMark(&mManualMark);
(void)aSpamSettings->GetManualMarkMode(&mManualMarkMode);
(void)aSpamSettings->GetPurge(&mPurge);
diff --git a/mozilla/mailnews/base/src/nsSpamSettings.h b/mozilla/mailnews/base/src/nsSpamSettings.h
index 618d809873f..70ca97a3341 100644
--- a/mozilla/mailnews/base/src/nsSpamSettings.h
+++ b/mozilla/mailnews/base/src/nsSpamSettings.h
@@ -72,6 +72,7 @@ private:
PRBool mPurge;
PRBool mUseWhiteList;
PRBool mMoveOnSpam;
+ PRBool mMarkAsReadOnSpam;
nsCString mActionTargetAccount;
nsCString mActionTargetFolder;
diff --git a/mozilla/mailnews/base/util/nsMsgIncomingServer.cpp b/mozilla/mailnews/base/util/nsMsgIncomingServer.cpp
index 82d7f589a5d..1b4451ce7aa 100644
--- a/mozilla/mailnews/base/util/nsMsgIncomingServer.cpp
+++ b/mozilla/mailnews/base/util/nsMsgIncomingServer.cpp
@@ -2101,6 +2101,10 @@ nsMsgIncomingServer::SetSpamSettings(nsISpamSettings *aSpamSettings)
(void)mSpamSettings->GetMoveOnSpam(&moveOnSpam);
(void)SetBoolValue("moveOnSpam", moveOnSpam);
+ PRBool markAsReadOnSpam;
+ (void)mSpamSettings->GetMarkAsReadOnSpam(&markAsReadOnSpam);
+ (void)SetBoolValue("markAsReadOnSpam", markAsReadOnSpam);
+
PRInt32 moveTargetMode;
(void)mSpamSettings->GetMoveTargetMode(&moveTargetMode);
(void)SetIntValue("moveTargetMode", moveTargetMode);
@@ -2213,6 +2217,12 @@ nsMsgIncomingServer::GetSpamSettings(nsISpamSettings **aSpamSettings)
rv = mSpamSettings->SetMoveOnSpam(moveOnSpam);
NS_ENSURE_SUCCESS(rv,rv);
+ PRBool markAsReadOnSpam;
+ rv = GetBoolValue("markAsReadOnSpam", &markAsReadOnSpam);
+ NS_ENSURE_SUCCESS(rv,rv);
+ rv = mSpamSettings->SetMarkAsReadOnSpam(markAsReadOnSpam);
+ NS_ENSURE_SUCCESS(rv,rv);
+
PRInt32 moveTargetMode;
rv = GetIntValue("moveTargetMode", &moveTargetMode);
NS_ENSURE_SUCCESS(rv,rv);
diff --git a/mozilla/mailnews/imap/src/nsImapMailFolder.cpp b/mozilla/mailnews/imap/src/nsImapMailFolder.cpp
index c8376c9e1be..25f49f0eef6 100644
--- a/mozilla/mailnews/imap/src/nsImapMailFolder.cpp
+++ b/mozilla/mailnews/imap/src/nsImapMailFolder.cpp
@@ -7512,6 +7512,15 @@ nsImapMailFolder::OnMessageClassified(const char *aMsgURI, nsMsgJunkStatus aClas
rv = server->GetSpamSettings(getter_AddRefs(spamSettings));
NS_ENSURE_SUCCESS(rv, rv);
+ PRBool markAsReadOnSpam;
+ (void)spamSettings->GetMarkAsReadOnSpam(&markAsReadOnSpam);
+ if (markAsReadOnSpam)
+ {
+ if (!m_junkMessagesToMarkAsRead)
+ NS_NewISupportsArray(getter_AddRefs(m_junkMessagesToMarkAsRead));
+ m_junkMessagesToMarkAsRead->AppendElement(msgHdr);
+ }
+
PRBool willMoveMessage = PR_FALSE;
// don't do the move when we are opening up
@@ -7562,6 +7571,17 @@ nsImapMailFolder::OnMessageClassified(const char *aMsgURI, nsMsgJunkStatus aClas
}
if (--m_numFilterClassifyRequests == 0)
{
+ if (m_junkMessagesToMarkAsRead)
+ {
+ PRUint32 count;
+ m_junkMessagesToMarkAsRead->Count(&count);
+ if (count > 0)
+ {
+ rv = MarkMessagesRead(m_junkMessagesToMarkAsRead, true);
+ NS_ENSURE_SUCCESS(rv,rv);
+ m_junkMessagesToMarkAsRead->SizeTo(0);
+ }
+ }
PlaybackCoalescedOperations();
// If we are performing biff for this folder, tell the server object
if (m_performingBiff)
diff --git a/mozilla/mailnews/imap/src/nsImapMailFolder.h b/mozilla/mailnews/imap/src/nsImapMailFolder.h
index 75ccd61f475..91c3da538ff 100644
--- a/mozilla/mailnews/imap/src/nsImapMailFolder.h
+++ b/mozilla/mailnews/imap/src/nsImapMailFolder.h
@@ -447,6 +447,7 @@ protected:
PRInt32 m_numFilterClassifyRequests;
PRBool m_msgMovedByFilter;
nsImapMoveCoalescer *m_moveCoalescer; // strictly owned by the nsImapMailFolder
+ nsCOMPtr m_junkMessagesToMarkAsRead;
nsMsgKey m_curMsgUid;
PRUint32 m_uidValidity;
PRInt32 m_numStatusRecentMessages; // used to store counts from Status command
diff --git a/mozilla/mailnews/local/src/nsLocalMailFolder.cpp b/mozilla/mailnews/local/src/nsLocalMailFolder.cpp
index c5ea725492d..93dfc2d274b 100644
--- a/mozilla/mailnews/local/src/nsLocalMailFolder.cpp
+++ b/mozilla/mailnews/local/src/nsLocalMailFolder.cpp
@@ -3429,6 +3429,15 @@ nsMsgLocalMailFolder::OnMessageClassified(const char *aMsgURI, nsMsgJunkStatus a
if (aClassification == nsIJunkMailPlugin::JUNK)
{
+ PRBool markAsReadOnSpam;
+ (void)spamSettings->GetMarkAsReadOnSpam(&markAsReadOnSpam);
+ if (markAsReadOnSpam)
+ {
+ rv = mDatabase->MarkRead(msgKey, true, this);
+ if (!NS_SUCCEEDED(rv))
+ NS_WARNING("failed marking spam message as read");
+ }
+
PRBool willMoveMessage = PR_FALSE;
// don't do the move when we are opening up
diff --git a/mozilla/mailnews/mailnews.js b/mozilla/mailnews/mailnews.js
index 9b7eb0ef1c2..e349e6587ed 100644
--- a/mozilla/mailnews/mailnews.js
+++ b/mozilla/mailnews/mailnews.js
@@ -378,6 +378,7 @@ pref("mail.server.default.use_idle", true);
// for spam
pref("mail.server.default.spamLevel",100); // 0 off, 100 on. not doing bool since we might have real levels one day.
pref("mail.server.default.moveOnSpam",false);
+pref("mail.server.default.markAsReadOnSpam",false);
pref("mail.server.default.moveTargetMode",0); // 0 == "Junk" on server, 1 == specific folder
pref("mail.server.default.spamActionTargetAccount","");
pref("mail.server.default.spamActionTargetFolder","");