зеркало из https://github.com/mozilla/pjs.git
Bug 193625 Option to mark incoming junk mail as read p=eyalroz@technion.ac.il r=me sr=bienvenu
This commit is contained in:
Родитель
9d2e5b35dc
Коммит
ffbd23982c
|
@ -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
|
||||
|
|
|
@ -1,266 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Seth Spitzer <sspitzer@netscape.com>
|
||||
* Dan Mosedale <dmose@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
var gSpamSettings = {};
|
||||
var gCurrentServer;
|
||||
var gMessengerBundle;
|
||||
|
||||
const kJunkOnLocalFolderURI = "mailbox://nobody@Local%20Folders/Junk";
|
||||
|
||||
function onJunkMailLoad()
|
||||
{
|
||||
gMessengerBundle = document.getElementById("bundle_messenger");
|
||||
if (window.arguments && window.arguments[0]) {
|
||||
setupForAccountFromFolder(window.arguments[0].folder ? window.arguments[0].folder.URI : null);
|
||||
}
|
||||
}
|
||||
|
||||
function onServerClick(event)
|
||||
{
|
||||
if (gCurrentServer.serverURI == event.target.id)
|
||||
return;
|
||||
|
||||
// before we set the UI for the new server,
|
||||
// save off the old one
|
||||
storeSettings(gSpamSettings[gCurrentServer.key].settings, gCurrentServer.spamSettings.loggingEnabled);
|
||||
|
||||
// set up the UI for the server
|
||||
setupForAccountFromFolder(event.target.id);
|
||||
}
|
||||
|
||||
function setupForAccountFromFolder(aURI)
|
||||
{
|
||||
try {
|
||||
if (!aURI)
|
||||
throw "this can happen if no folder is selected in the folder pane"
|
||||
var msgFolder = GetMsgFolderFromUri(aURI, false);
|
||||
gCurrentServer = msgFolder.server;
|
||||
|
||||
if (gCurrentServer.type == "nntp")
|
||||
throw "this can happen if the selected folder (or account) doesn't have junk controls (news)"
|
||||
}
|
||||
catch (ex) {
|
||||
// get server for default account
|
||||
// XXX TODO
|
||||
// edge cases to worry about later:
|
||||
// what if there is no default account?
|
||||
// what if default account is of a type where canGetIncomingMessages == true?
|
||||
// what if no accounts are of a type where canGetIncomingMessages == true?
|
||||
var accountManager = Components.classes["@mozilla.org/messenger/account-manager;1"]
|
||||
.getService(Components.interfaces.nsIMsgAccountManager);
|
||||
var account = accountManager.defaultAccount;
|
||||
gCurrentServer = account.incomingServer;
|
||||
}
|
||||
|
||||
var obj;
|
||||
var key = gCurrentServer.key;
|
||||
|
||||
if (key in gSpamSettings) {
|
||||
obj = gSpamSettings[key];
|
||||
}
|
||||
else {
|
||||
// get and clone spam settings for this server
|
||||
// we clone because if the users cancels we are going to throw away the changes
|
||||
var settings = Components.classes["@mozilla.org/messenger/spamsettings;1"].createInstance(Components.interfaces.nsISpamSettings);
|
||||
settings.clone(gCurrentServer.spamSettings);
|
||||
obj = {server: gCurrentServer, settings: settings};
|
||||
gSpamSettings[key] = obj;
|
||||
}
|
||||
|
||||
// select server in the menulist
|
||||
var serverList = document.getElementById("server");
|
||||
var menuitems = serverList.getElementsByAttribute("id", obj.server.serverURI);
|
||||
serverList.selectedItem = menuitems[0];
|
||||
|
||||
// set up the UI for this server
|
||||
// set up the level checkbox
|
||||
document.getElementById("level").checked = (obj.settings.level > 0);
|
||||
|
||||
// set up the junk mail folder picker
|
||||
document.getElementById("moveOnSpam").checked = obj.settings.moveOnSpam;
|
||||
document.getElementById("moveTargetMode").selectedItem = document.getElementById("moveTargetMode" + obj.settings.moveTargetMode);
|
||||
|
||||
// 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)
|
||||
// in which case, use Local Folders
|
||||
var defaultAccountURI = obj.server.canCreateFoldersOnServer && obj.server.canSearchMessages ? obj.server.serverURI : "mailbox://nobody@Local%20Folders";
|
||||
// if there is a target account, use it, else use the default account
|
||||
SetFolderPicker(obj.settings.actionTargetAccount ? obj.settings.actionTargetAccount : defaultAccountURI, "actionTargetAccount");
|
||||
|
||||
// if there is a target account, use it, else use Junk on Local Folders
|
||||
if (obj.settings.actionTargetFolder)
|
||||
SetFolderPicker(obj.settings.actionTargetFolder, "actionTargetFolder");
|
||||
else {
|
||||
// note, this folder might not exist, but better this than ""
|
||||
// and, we'll create it if we try to use it.
|
||||
SetFolderPicker(kJunkOnLocalFolderURI, "actionTargetFolder");
|
||||
}
|
||||
|
||||
// set up the purge UI
|
||||
document.getElementById("purge").checked = obj.settings.purge;
|
||||
document.getElementById("purgeInterval").value = obj.settings.purgeInterval;
|
||||
|
||||
// set up the whitelist UI
|
||||
document.getElementById("useWhiteList").checked = obj.settings.useWhiteList;
|
||||
var abList = document.getElementById("whiteListAbURI");
|
||||
menuitems = abList.getElementsByAttribute("id", obj.settings.whiteListAbURI);
|
||||
abList.selectedItem = menuitems[0];
|
||||
|
||||
// set up the manual mark UI
|
||||
document.getElementById("manualMark").checked = obj.settings.manualMark;
|
||||
document.getElementById("manualMarkMode").selectedItem = document.getElementById("manualMarkMode" + obj.settings.manualMarkMode);
|
||||
|
||||
conditionallyEnableUI(null);
|
||||
}
|
||||
|
||||
function junkLog()
|
||||
{
|
||||
// pass in the "real" spam settings, as it's the one with the logStream
|
||||
var args = {spamSettings: gCurrentServer.spamSettings};
|
||||
window.openDialog("chrome://messenger/content/junkLog.xul", "junkLog", "chrome,modal,titlebar,resizable,centerscreen", args);
|
||||
}
|
||||
|
||||
function onAccept()
|
||||
{
|
||||
// store the current changes
|
||||
storeSettings(gSpamSettings[gCurrentServer.key].settings, gCurrentServer.spamSettings.loggingEnabled);
|
||||
|
||||
for (var key in gSpamSettings) {
|
||||
try {
|
||||
// if they hit ok, set the "real" server's spam settings.
|
||||
// this will set prefs.
|
||||
gSpamSettings[key].server.spamSettings = gSpamSettings[key].settings;
|
||||
}
|
||||
catch (ex) {
|
||||
dump("spam setting not saved: " + ex);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function storeSettings(aSettings, aLoggingEnabled)
|
||||
{
|
||||
aSettings.level = document.getElementById("level").checked ? 100 : 0;
|
||||
aSettings.moveOnSpam = document.getElementById("moveOnSpam").checked;
|
||||
aSettings.moveTargetMode = document.getElementById("moveTargetMode").value;
|
||||
aSettings.actionTargetAccount = document.getElementById("actionTargetAccount").getAttribute("uri");
|
||||
var targetFolderURI = document.getElementById("actionTargetFolder").getAttribute("uri");
|
||||
if (targetFolderURI)
|
||||
aSettings.actionTargetFolder = targetFolderURI;
|
||||
else {
|
||||
// note, this folder might not exist, but better this than ""
|
||||
// and, we'll create it if we try to use it.
|
||||
aSettings.actionTargetFolder = kJunkOnLocalFolderURI;
|
||||
}
|
||||
|
||||
aSettings.purge = document.getElementById("purge").checked;
|
||||
aSettings.purgeInterval = document.getElementById("purgeInterval").value;
|
||||
|
||||
aSettings.useWhiteList = document.getElementById("useWhiteList").checked;
|
||||
aSettings.whiteListAbURI = document.getElementById("whiteListAbURI").selectedItem.getAttribute("id");
|
||||
aSettings.loggingEnabled = aLoggingEnabled;
|
||||
|
||||
aSettings.manualMark = document.getElementById("manualMark").checked;
|
||||
aSettings.manualMarkMode = document.getElementById("manualMarkMode").value;
|
||||
}
|
||||
|
||||
function conditionallyEnableUI(id)
|
||||
{
|
||||
if (!document.getElementById("level").checked) {
|
||||
document.getElementById("useWhiteList").disabled = true;
|
||||
document.getElementById("whiteListAbURI").disabled = true;
|
||||
document.getElementById("moveOnSpam").disabled = true;
|
||||
|
||||
document.getElementById("moveTargetMode").disabled = true;
|
||||
document.getElementById("actionTargetAccount").disabled = true;
|
||||
document.getElementById("actionTargetFolder").disabled = true;
|
||||
|
||||
document.getElementById("purge").disabled = true;
|
||||
document.getElementById("purgeInterval").disabled = true;
|
||||
document.getElementById("purgeLabel").disabled = true;
|
||||
|
||||
document.getElementById("manualMark").disabled = true;
|
||||
document.getElementById("manualMarkMode").disabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
document.getElementById("useWhiteList").disabled = false;
|
||||
document.getElementById("moveOnSpam").disabled = false;
|
||||
document.getElementById("manualMark").disabled = false;
|
||||
|
||||
var enabled;
|
||||
|
||||
if (!id || id == "manualMark") {
|
||||
enabled = document.getElementById("manualMark").checked;
|
||||
// need to enable manualMarkMode before we enable manualMarkMode0
|
||||
document.getElementById("manualMarkMode").disabled = !enabled;
|
||||
}
|
||||
|
||||
if (!id || id == "moveOnSpam") {
|
||||
enabled = document.getElementById("moveOnSpam").checked;
|
||||
var choice = document.getElementById("moveTargetMode").value;
|
||||
|
||||
document.getElementById("moveTargetMode").disabled = !enabled;
|
||||
document.getElementById("actionTargetAccount").disabled = !enabled || (choice == 1);
|
||||
document.getElementById("actionTargetFolder").disabled = !enabled || (choice == 0);
|
||||
|
||||
var checked = document.getElementById("purge").checked;
|
||||
document.getElementById("purge").disabled = !enabled;
|
||||
document.getElementById("purgeInterval").disabled = !enabled || !checked;
|
||||
document.getElementById("purgeLabel").disabled = !enabled;
|
||||
|
||||
if (!document.getElementById("manualMarkMode").disabled)
|
||||
document.getElementById("manualMarkMode0").disabled = !enabled;
|
||||
}
|
||||
|
||||
if (id == "purge") {
|
||||
enabled = document.getElementById("purge").checked;
|
||||
document.getElementById("purgeInterval").disabled = !enabled;
|
||||
}
|
||||
|
||||
if (!id || id == "useWhiteList") {
|
||||
enabled = document.getElementById("useWhiteList").checked;
|
||||
document.getElementById("whiteListAbURI").disabled = !enabled;
|
||||
}
|
||||
}
|
||||
|
||||
function doHelpButton()
|
||||
{
|
||||
openHelp("mail-junk-controls");
|
||||
}
|
|
@ -150,6 +150,8 @@
|
|||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<checkbox id="markAsReadOnSpam" oncommand="conditionallyEnableUI('markAsReadOnSpam')" label="&markAsReadOnSpam.label;"/>
|
||||
|
||||
<vbox align="start">
|
||||
<checkbox id="manualMark" oncommand="conditionallyEnableUI('manualMark')" label="&manualMark.label;"/>
|
||||
<hbox>
|
||||
|
|
|
@ -611,7 +611,7 @@ var DefaultController =
|
|||
MsgApplyFilters(null);
|
||||
return;
|
||||
case "cmd_runJunkControls":
|
||||
analyzeFolderForJunk();
|
||||
filterFolderForJunk();
|
||||
return;
|
||||
case "cmd_deleteJunk":
|
||||
deleteJunkInFolder();
|
||||
|
|
|
@ -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<gJunkKeys.length;i++)
|
||||
indices[i] = gDBView.findIndexFromKey(gJunkKeys[i], true /* expand */);
|
||||
|
||||
var treeView = gDBView.QueryInterface(Components.interfaces.nsITreeView);
|
||||
var actionParams = { markRead: false, junkTargetFolder: null };
|
||||
determineActionsForJunkMsgs(treeView,aIndices,actionParams);
|
||||
|
||||
if (!aIndices.length)
|
||||
return;
|
||||
|
||||
var treeSelection = treeView.selection;
|
||||
treeSelection.clearSelection();
|
||||
|
||||
// select the messages
|
||||
for (i=0;i<indices.length;i++)
|
||||
treeSelection.rangedSelect(indices[i], indices[i], true /* augment */);
|
||||
for (i=0;i<aIndices.length;i++)
|
||||
treeSelection.rangedSelect(aIndices[i], aIndices[i], true /* augment */);
|
||||
|
||||
SetNextMessageAfterDelete();
|
||||
gDBView.doCommandWithFolder(nsMsgViewCommandType.moveMessages, gJunkTargetFolder);
|
||||
|
||||
gJunkKeys = [];
|
||||
gJunkTargetFolder = null;
|
||||
if (actionParams.markRead)
|
||||
MarkSelectedMessagesRead(true);
|
||||
|
||||
if (actionParams.junkTargetFolder)
|
||||
{
|
||||
SetNextMessageAfterDelete();
|
||||
gDBView.doCommandWithFolder(nsMsgViewCommandType.moveMessages, actionParams.junkTargetFolder);
|
||||
}
|
||||
treeSelection.clearSelection();
|
||||
}
|
||||
|
||||
function getJunkmailComponent()
|
||||
|
@ -551,19 +554,19 @@ function getJunkmailComponent()
|
|||
}
|
||||
}
|
||||
|
||||
function analyze(aMsgHdr, aNextFunction)
|
||||
function analyzeMessageForJunk(aMsgHdr, aMsgIndex, aJunkMsgIndices, aLastMessage, aWhiteListDirectory)
|
||||
{
|
||||
var listener = {
|
||||
onMessageClassified: function(aMsgURI, aClassification)
|
||||
onMessageClassified: function(aClassifiedMsgURI, aClassification)
|
||||
{
|
||||
// XXX todo
|
||||
// XXX TODO
|
||||
// update status bar, or a progress dialog
|
||||
// running junk mail controls manually, on a large folder
|
||||
// can take a while, and the user doesn't know when we are done.
|
||||
dump(aMsgURI + ' is '
|
||||
+ (aClassification == nsIJunkMailPlugin.JUNK
|
||||
? 'JUNK' : 'GOOD') + '\n');
|
||||
// XXX TODO, make the cut off 50, like in nsMsgSearchTerm.cpp
|
||||
|
||||
// XXX TODO
|
||||
// make the cut off 50, like in nsMsgSearchTerm.cpp
|
||||
|
||||
var score =
|
||||
aClassification == nsIJunkMailPlugin.JUNK ? "100" : "0";
|
||||
|
||||
|
@ -574,26 +577,28 @@ function analyze(aMsgHdr, aNextFunction)
|
|||
db.setStringProperty(aMsgHdr.messageKey, "junkscore", score);
|
||||
db.setStringProperty(aMsgHdr.messageKey, "junkscoreorigin",
|
||||
"plugin");
|
||||
saveJunkMsgForAction(aMsgHdr.folder.server, aMsgURI, aClassification);
|
||||
aNextFunction();
|
||||
|
||||
if (aClassification == nsIJunkMailPlugin.JUNK)
|
||||
aJunkMsgIndices.push(aMsgIndex);
|
||||
|
||||
if (aLastMessage)
|
||||
{
|
||||
gJunkmailComponent.endBatch();
|
||||
performActionsOnJunkMsgs(aJunkMsgIndices);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// if we are whitelisting, check if the email address is in the whitelist addressbook.
|
||||
var spamSettings = aMsgHdr.folder.server.spamSettings;
|
||||
if (spamSettings.useWhiteList && spamSettings.whiteListAbURI)
|
||||
if (aWhiteListDirectory)
|
||||
{
|
||||
var whiteListDirectory = RDF.GetResource(spamSettings.whiteListAbURI).QueryInterface(Components.interfaces.nsIAbMDBDirectory);
|
||||
var headerParser = Components.classes["@mozilla.org/messenger/headerparser;1"].getService(Components.interfaces.nsIMsgHeaderParser);
|
||||
var authorEmailAddress = headerParser.extractHeaderAddressMailboxes(null, aMsgHdr.author);
|
||||
if (whiteListDirectory.hasCardForEmailAddress(authorEmailAddress))
|
||||
{
|
||||
if (aWhiteListDirectory.hasCardForEmailAddress(authorEmailAddress))
|
||||
// skip over this message, like we do on incoming mail
|
||||
// the difference is it could be marked as junk from previous analysis
|
||||
// or from being manually marked by the user.
|
||||
aNextFunction();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var messageURI = aMsgHdr.folder.generateMessageURI(aMsgHdr.messageKey)
|
||||
|
@ -601,7 +606,7 @@ function analyze(aMsgHdr, aNextFunction)
|
|||
gJunkmailComponent.classifyMessage(messageURI, msgWindow, listener);
|
||||
}
|
||||
|
||||
function analyzeFolderForJunk()
|
||||
function filterFolderForJunk()
|
||||
{
|
||||
MsgJunkMailInfo(true);
|
||||
var view = GetDBView();
|
||||
|
@ -614,42 +619,24 @@ function analyzeFolderForJunk()
|
|||
if (!count)
|
||||
return;
|
||||
|
||||
var messages = new Array(count)
|
||||
var junkMsgsArray = new Array;
|
||||
|
||||
var tmpMsgURI = view.getURIForViewIndex(0);
|
||||
var tmpMsgHdr = messenger.messageServiceFromURI(tmpMsgURI).messageURIToMsgHdr(tmpMsgURI);
|
||||
var spamSettings = tmpMsgHdr.folder.server.spamSettings;
|
||||
var whiteListDirectory;
|
||||
if (spamSettings.useWhiteList && spamSettings.whiteListAbURI)
|
||||
whiteListDirectory = RDF.GetResource(spamSettings.whiteListAbURI).QueryInterface(Components.interfaces.nsIAbMDBDirectory);
|
||||
|
||||
getJunkmailComponent();
|
||||
gJunkmailComponent.startBatch();
|
||||
|
||||
for (var i = 0; i < count; i++) {
|
||||
messages[i] = view.getURIForViewIndex(i);
|
||||
var msgIndex = i;
|
||||
var msgURI = view.getURIForViewIndex(i);
|
||||
var msgHdr = messenger.messageServiceFromURI(msgURI).messageURIToMsgHdr(msgURI);
|
||||
analyzeMessageForJunk(msgHdr,msgIndex,junkMsgsArray,(i == count-1),whiteListDirectory);
|
||||
}
|
||||
analyzeMessages(messages);
|
||||
}
|
||||
|
||||
// not used yet, but soon
|
||||
function analyzeMessagesForJunk()
|
||||
{
|
||||
var messages = GetSelectedMessages();
|
||||
analyzeMessages(messages);
|
||||
}
|
||||
|
||||
function analyzeMessages(messages)
|
||||
{
|
||||
function processNext()
|
||||
{
|
||||
if (counter < messages.length) {
|
||||
var messageUri = messages[counter];
|
||||
var message = messenger.messageServiceFromURI(messageUri).messageURIToMsgHdr(messageUri);
|
||||
++counter;
|
||||
analyze(message, processNext);
|
||||
}
|
||||
else {
|
||||
dump('[bayesian filter message analysis complete.]\n');
|
||||
gJunkmailComponent.endBatch();
|
||||
performActionOnJunkMsgs();
|
||||
}
|
||||
}
|
||||
|
||||
getJunkmailComponent();
|
||||
var counter = 0;
|
||||
gJunkmailComponent.startBatch();
|
||||
dump('[bayesian filter message analysis begins.]\n');
|
||||
processNext();
|
||||
}
|
||||
|
||||
function JunkSelectedMessages(setAsJunk)
|
||||
|
@ -657,6 +644,9 @@ function JunkSelectedMessages(setAsJunk)
|
|||
MsgJunkMailInfo(true);
|
||||
gDBView.doCommand(setAsJunk ? nsMsgViewCommandType.junk
|
||||
: nsMsgViewCommandType.unjunk);
|
||||
// XXX TODO
|
||||
// consider whether these messages should be
|
||||
// marked as read (if markAsReadOnSpam is set)
|
||||
}
|
||||
|
||||
function deleteJunkInFolder()
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
<!ENTITY window.title "Junk Mail Controls">
|
||||
<!ENTITY account.label "Account:">
|
||||
<!ENTITY account.accesskey "A">
|
||||
<!ENTITY viewLog.label "Junk Mail Log">
|
||||
<!ENTITY viewLog.accesskey "j">
|
||||
<!ENTITY info1.label "Junk mail controls evaluate your incoming messages and identify those that are most likely to be junk mail, or unsolicited mail. A junk icon is displayed if the message is identified as junk mail.">
|
||||
<!ENTITY info2.label "Junk mail controls can be fine-tuned by using the Junk Mail toolbar button to mark junk messages appropriately.">
|
||||
<!ENTITY level.label "Enable junk mail controls">
|
||||
<!ENTITY level.accesskey "E">
|
||||
<!ENTITY move.label "Move incoming messages determined to be junk mail to:">
|
||||
<!ENTITY otherFolder.label "Other:">
|
||||
<!ENTITY junkFolderOn.label ""Junk" folder on:">
|
||||
<!ENTITY purge1.label "Automatically delete junk messages older than">
|
||||
<!ENTITY purge1.accesskey "u">
|
||||
<!ENTITY purge2.label "days from this folder">
|
||||
<!ENTITY whitelist.label "Do not mark messages as junk mail if the sender is in my address book:">
|
||||
<!ENTITY whitelist.accesskey "D">
|
||||
<!ENTITY manualMark.label "When I manually mark messages as Junk:">
|
||||
<!ENTITY manualMarkModeMove.label "Move them to the "Junk" folder">
|
||||
<!ENTITY manualMarkModeDelete.label "Delete them">
|
|
@ -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 <nsIMsgImapMailFolder> 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 <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(m_folder);
|
||||
PRBool thisIsImapFolder = (imapFolder != nsnull);
|
||||
nsCOMPtr<nsIJunkMailPlugin> junkPlugin;
|
||||
|
||||
// if this is a junk command, start a batch.
|
||||
//
|
||||
if ( command == nsMsgViewCommandType::junk
|
||||
|| command == nsMsgViewCommandType::unjunk )
|
||||
{
|
||||
nsCOMPtr<nsIJunkMailPlugin> 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<nsIMsgFolder> 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<nsIMsgIncomingServer> 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<nsIMsgFolder> folder;
|
||||
rv = GetFolderForViewIndex(indices[0], getter_AddRefs(folder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIMsgIncomingServer> server;
|
||||
rv = folder->GetServer(getter_AddRefs(server));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIMsgFilterPlugin> 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<nsIMsgFilterPlugin> 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 <nsIMsgDBHdr> 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 <nsIMsgFolder> 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<nsIMsgIncomingServer> server;
|
||||
rv = folder->GetServer(getter_AddRefs(server));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if ( mLastJunkURIInBatch.Equals(aMsgURI) )
|
||||
{
|
||||
nsCOMPtr<nsIMsgFolder> 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<nsIMsgIncomingServer> 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<nsIMsgFilterPlugin> filterPlugin;
|
||||
rv = server->GetSpamFilterPlugin(getter_AddRefs(filterPlugin));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIJunkMailPlugin> junkPlugin = do_QueryInterface(filterPlugin, &rv);
|
||||
|
||||
nsCOMPtr<nsIJunkMailPlugin> 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 <nsIMsgFolder> junkTargetFolder;
|
||||
|
||||
nsMsgViewIndex *indices = (nsMsgViewIndex *)nsMemory::Alloc(numIndices * sizeof(nsMsgViewIndex));
|
||||
if (!indices)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
for (PRUint32 i=0;i<numIndices;i++)
|
||||
indices[i] = FindKey(mJunkKeys.GetAt(i), PR_TRUE /* expand */); // what if we don't find the index?
|
||||
|
||||
// tell the FE to call SetNextMessageAfterDelete() because a delete is coming
|
||||
nsresult rv = mCommandUpdater->UpdateNextMessageAfterDelete();
|
||||
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<nsIMsgFolder> folder;
|
||||
nsresult rv = GetFolderForViewIndex(mJunkIndices[0], getter_AddRefs(folder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIMsgIncomingServer> server;
|
||||
rv = folder->GetServer(getter_AddRefs(server));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr <nsISpamSettings> 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 <nsIMsgMessageService> msgMessageService;
|
||||
rv = GetMessageServiceFromURI(aMsgURI, getter_AddRefs(msgMessageService));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
nsCOMPtr <nsIMsgDBHdr> msgHdr;
|
||||
rv = msgMessageService->MessageURIToMsgHdr(aMsgURI, getter_AddRefs(msgHdr));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
nsCOMPtr <nsIMsgFolder> 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<nsIMsgFolder> 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<nsIMsgFolder> 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
|
||||
|
|
|
@ -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 <nsIMsgFolder> mJunkTargetFolder;
|
||||
nsresult PerformActionOnJunkMsgs();
|
||||
nsresult SaveJunkMsgForAction(nsIMsgIncomingServer *aServer, const char *aMsgURI, nsMsgJunkStatus aClassification);
|
||||
nsresult PerformActionsOnJunkMsgs();
|
||||
nsresult DetermineActionsForJunkMsgs(PRBool* movingJunkMessages, PRBool* markingJunkMessagesRead, nsIMsgFolder** junkTargetFolder);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -72,6 +72,7 @@ private:
|
|||
PRBool mPurge;
|
||||
PRBool mUseWhiteList;
|
||||
PRBool mMoveOnSpam;
|
||||
PRBool mMarkAsReadOnSpam;
|
||||
|
||||
nsCString mActionTargetAccount;
|
||||
nsCString mActionTargetFolder;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -447,6 +447,7 @@ protected:
|
|||
PRInt32 m_numFilterClassifyRequests;
|
||||
PRBool m_msgMovedByFilter;
|
||||
nsImapMoveCoalescer *m_moveCoalescer; // strictly owned by the nsImapMailFolder
|
||||
nsCOMPtr <nsISupportsArray> m_junkMessagesToMarkAsRead;
|
||||
nsMsgKey m_curMsgUid;
|
||||
PRUint32 m_uidValidity;
|
||||
PRInt32 m_numStatusRecentMessages; // used to store counts from Status command
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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","");
|
||||
|
|
Загрузка…
Ссылка в новой задаче