Work in progress changes for bayesian spam filter. sr=sspitzer, r=ducarroz
git-svn-id: svn://10.0.0.236/trunk@131019 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -327,7 +327,7 @@
|
||||
<!-- Settings for "FTP Panel" panel -->
|
||||
<SETTING><NAME>MWFTP_Post_hostName</NAME><VALUE></VALUE></SETTING>
|
||||
<SETTING><NAME>MWFTP_Post_username</NAME><VALUE></VALUE></SETTING>
|
||||
<SETTING><NAME>MWFTP_Post_password</NAME><VALUE>0</VALUE></SETTING>
|
||||
<SETTING><NAME>MWFTP_Post_password</NAME><VALUE>0ÿݸ</VALUE></SETTING>
|
||||
<SETTING><NAME>MWFTP_Post_remoteDir</NAME><VALUE></VALUE></SETTING>
|
||||
<SETTING><NAME>MWFTP_Post_ftp_PathVersion</NAME><VALUE>1</VALUE></SETTING>
|
||||
<SETTING><NAME>MWFTP_Post_ftp_PathType</NAME><VALUE>0</VALUE></SETTING>
|
||||
@@ -1136,6 +1136,13 @@
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIMsgFilterPlugin.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
</FILELIST>
|
||||
<LINKORDER>
|
||||
<FILEREF>
|
||||
@@ -1428,6 +1435,11 @@
|
||||
<PATH>nsISpamSettings.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIMsgFilterPlugin.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
</LINKORDER>
|
||||
</TARGET>
|
||||
<TARGET>
|
||||
@@ -1704,7 +1716,7 @@
|
||||
<!-- Settings for "FTP Panel" panel -->
|
||||
<SETTING><NAME>MWFTP_Post_hostName</NAME><VALUE></VALUE></SETTING>
|
||||
<SETTING><NAME>MWFTP_Post_username</NAME><VALUE></VALUE></SETTING>
|
||||
<SETTING><NAME>MWFTP_Post_password</NAME><VALUE>0</VALUE></SETTING>
|
||||
<SETTING><NAME>MWFTP_Post_password</NAME><VALUE>0ÿݸ</VALUE></SETTING>
|
||||
<SETTING><NAME>MWFTP_Post_remoteDir</NAME><VALUE></VALUE></SETTING>
|
||||
<SETTING><NAME>MWFTP_Post_ftp_PathVersion</NAME><VALUE>1</VALUE></SETTING>
|
||||
<SETTING><NAME>MWFTP_Post_ftp_PathType</NAME><VALUE>0</VALUE></SETTING>
|
||||
@@ -2513,6 +2525,13 @@
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIMsgFilterPlugin.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
</FILELIST>
|
||||
<LINKORDER>
|
||||
<FILEREF>
|
||||
@@ -2805,6 +2824,11 @@
|
||||
<PATH>nsISpamSettings.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIMsgFilterPlugin.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
</LINKORDER>
|
||||
</TARGET>
|
||||
</TARGETLIST>
|
||||
@@ -3102,6 +3126,12 @@
|
||||
<PATH>nsIMsgFilterList.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<TARGETNAME>headers</TARGETNAME>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIMsgFilterPlugin.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<TARGETNAME>headers</TARGETNAME>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
|
||||
@@ -429,44 +429,36 @@ function doHelpButton()
|
||||
|
||||
// XXX The following junkmail code might be going away or changing
|
||||
|
||||
const NS_BAYESIANFILTER_CONTRACTID = "@mozilla.org/messenger/filter-plugin;1?name=bayesianfilter";
|
||||
const nsIJunkMailPlugin = Components.interfaces.nsIJunkMailPlugin;
|
||||
|
||||
var gJunkmailComponent;
|
||||
|
||||
function getJunkmailComponent()
|
||||
{
|
||||
if (!gJunkmailComponent) {
|
||||
gJunkmailComponent = Components.classes['@mozilla.org/messenger/filter-plugin;1?name=junkmail']
|
||||
.getService(Components.interfaces.nsISupports).wrappedJSObject;
|
||||
gJunkmailComponent.initComponent();
|
||||
gJunkmailComponent = Components.classes[NS_BAYESIANFILTER_CONTRACTID].getService(nsIJunkMailPlugin);
|
||||
// gJunkmailComponent.initComponent();
|
||||
// who calls init method?
|
||||
}
|
||||
}
|
||||
|
||||
function analyze(aMessage, aNextFunction)
|
||||
{
|
||||
function callback(aScore) {
|
||||
}
|
||||
|
||||
callback.prototype =
|
||||
var listener = {
|
||||
onMessageClassified: function(aMsgURL, aClassification)
|
||||
{
|
||||
onMessageScored: function processNext(aScore)
|
||||
{
|
||||
if (aMessage) {
|
||||
//if (aScore == -1) debugger;
|
||||
if (aScore == 0) {
|
||||
aMessage.setStringProperty("score", "0");
|
||||
}
|
||||
else if (aScore == 1) {
|
||||
aMessage.setStringProperty("score", "100");
|
||||
}
|
||||
}
|
||||
aNextFunction();
|
||||
}
|
||||
};
|
||||
|
||||
dump(aMsgURL + ' is ' + (aClassification == nsIJunkMailPlugin.JUNK ? 'JUNK' : 'GOOD') + '\n');
|
||||
var score = (aClassification == nsIJunkMailPlugin.JUNK ? "100" : "0");
|
||||
aMessage.setStringProperty("score", score);
|
||||
aNextFunction();
|
||||
}
|
||||
};
|
||||
|
||||
// XXX TODO jumping through hoops here.
|
||||
var messageURI = aMessage.folder.generateMessageURI(aMessage.messageKey) + "?fetchCompleteMessage=true";
|
||||
var messageURL = mailSession.ConvertMsgURIToMsgURL(messageURI, msgWindow);
|
||||
gJunkmailComponent.calculate(messageURL, new callback);
|
||||
gJunkmailComponent.classifyMessage(messageURL, listener);
|
||||
}
|
||||
|
||||
function analyzeFolder()
|
||||
@@ -509,6 +501,7 @@ function analyzeMessages()
|
||||
++counter;
|
||||
while (!message.isRead) {
|
||||
if (counter == messages.length) {
|
||||
dump('[bayesian filter message analysis complete.]\n');
|
||||
gJunkmailComponent.mBatchUpdate = false;
|
||||
return;
|
||||
}
|
||||
@@ -519,6 +512,7 @@ function analyzeMessages()
|
||||
analyze(message, processNext);
|
||||
}
|
||||
else {
|
||||
dump('[bayesian filter message analysis complete.]\n');
|
||||
gJunkmailComponent.batchUpdate = false;
|
||||
}
|
||||
}
|
||||
@@ -527,6 +521,7 @@ function analyzeMessages()
|
||||
var messages = GetSelectedMessages();
|
||||
var counter = 0;
|
||||
gJunkmailComponent.batchUpdate = true;
|
||||
dump('[bayesian filter message analysis begins.]\n');
|
||||
processNext();
|
||||
}
|
||||
|
||||
@@ -541,38 +536,22 @@ function mark(aMessage, aSpam, aNextFunction)
|
||||
// XXX TODO jumping through hoops here.
|
||||
var score = aMessage.getStringProperty("score");
|
||||
|
||||
var action;
|
||||
if (aSpam) {
|
||||
if (score == "100") {
|
||||
// Marking a spam message as spam does nothing
|
||||
return;
|
||||
}
|
||||
|
||||
if (score == "0") {
|
||||
// Marking a non-spam message as spam
|
||||
action = Components.interfaces.nsIMsgFilterPlugin.hamToSpam;
|
||||
}
|
||||
else
|
||||
action = Components.interfaces.nsIMsgFilterPlugin.unknownToSpam;
|
||||
|
||||
}
|
||||
else {
|
||||
if (score == "0") {
|
||||
// Marking a non-spam message as non-spam does nothing
|
||||
return;
|
||||
}
|
||||
|
||||
if (score == "100") {
|
||||
// Marking a spam message as non-spam
|
||||
action = Components.interfaces.nsIMsgFilterPlugin.spamToHam;
|
||||
}
|
||||
else
|
||||
action = Components.interfaces.nsIMsgFilterPlugin.unknownToHam;
|
||||
}
|
||||
var oldClassification = ((score == "100") ? nsIJunkMailPlugin.JUNK :
|
||||
(score == "0") ? nsIJunkMailPlugin.GOOD : nsIJunkMailPlugin.UNCLASSIFIED);
|
||||
var newClassification = (aSpam ? nsIJunkMailPlugin.JUNK : nsIJunkMailPlugin.GOOD);
|
||||
|
||||
var messageURI = aMessage.folder.generateMessageURI(aMessage.messageKey) + "?fetchCompleteMessage=true";
|
||||
var messageURL = mailSession.ConvertMsgURIToMsgURL(messageURI, msgWindow);
|
||||
gJunkmailComponent.mark(messageURL, action, aNextFunction);
|
||||
|
||||
var listener = (aNextFunction == null ? null :
|
||||
{
|
||||
onMessageClassified: function(aMsgURL, aClassification)
|
||||
{
|
||||
aNextFunction();
|
||||
}
|
||||
});
|
||||
|
||||
gJunkmailComponent.setMessageClassification(messageURL, oldClassification, newClassification, listener);
|
||||
}
|
||||
|
||||
function JunkSelectedMessages(setAsJunk)
|
||||
@@ -620,6 +599,7 @@ function markFolderAsJunk(aSpam)
|
||||
message.setStringProperty("score","0");
|
||||
}
|
||||
else {
|
||||
dump('[folder marking complete.]\n');
|
||||
gJunkmailComponent.batchUpdate = false;
|
||||
}
|
||||
}
|
||||
@@ -628,5 +608,6 @@ function markFolderAsJunk(aSpam)
|
||||
var folder = GetFirstSelectedMsgFolder();
|
||||
var messages = folder.getMessages(msgWindow);
|
||||
gJunkmailComponent.batchUpdate = true;
|
||||
dump('[folder marking starting.]\n');
|
||||
processNext();
|
||||
}
|
||||
|
||||
@@ -47,11 +47,6 @@ interface nsIStreamListener;
|
||||
[scriptable, uuid(e2e56690-a676-11d6-80c9-00008646b737)]
|
||||
interface nsIMsgFilterPlugin : nsISupports
|
||||
{
|
||||
const long unknownToSpam = 0;
|
||||
const long unknownToHam = 1;
|
||||
const long hamToSpam = 2;
|
||||
const long spamToHam = 3;
|
||||
|
||||
/**
|
||||
* Initialize the plugin object.
|
||||
*
|
||||
@@ -61,8 +56,9 @@ interface nsIMsgFilterPlugin : nsISupports
|
||||
void init(in ACString aServerPrefsKey);
|
||||
|
||||
/**
|
||||
* Filter a message by headers.
|
||||
* Filter an email message by content or headers, your choice.
|
||||
*
|
||||
* @param aMsgURL URL to fetch full contents of this message.
|
||||
* @param aMsgHdr Can be used to set properties on the header of the
|
||||
* message (e.g. for attaching a score to it).
|
||||
*
|
||||
@@ -78,17 +74,12 @@ interface nsIMsgFilterPlugin : nsISupports
|
||||
*
|
||||
* @param aMsgWindow Passed back to the listener.
|
||||
*/
|
||||
void filterMsgByHeaders(in nsIMsgDBHdr aMsgHdr, in unsigned long aCount,
|
||||
[array, size_is(aCount)] in string aHeaders,
|
||||
in nsIMsgFilterHitNotify aListener,
|
||||
in nsIMsgWindow aMsgWindow);
|
||||
|
||||
/**
|
||||
* XXX |string| -- should really be a UTF8 String
|
||||
*/
|
||||
void filterMsg(in string aMessageURL,
|
||||
in nsIMsgDBHdr aMsgHdr,
|
||||
in nsIMsgFilterHitNotify aListener);
|
||||
void filterMessage(in string aMsgURL,
|
||||
in nsIMsgDBHdr aMsgHdr,
|
||||
in unsigned long aCount,
|
||||
[array, size_is(aCount)] in string aHeaders,
|
||||
in nsIMsgFilterHitNotify aListener,
|
||||
in nsIMsgWindow aMsgWindow);
|
||||
|
||||
/**
|
||||
* Do any necessary cleanup: flush and close any open files, etc.
|
||||
@@ -113,3 +104,44 @@ interface nsIMsgFilterPlugin : nsISupports
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Rather than passing low level details about scores and such, abstract
|
||||
* this away by informing a listener of a message's classification, which
|
||||
* can be one of 3 values: UNCLASSIFIED, GOOD, or JUNK.
|
||||
*/
|
||||
[scriptable, uuid(0243f3d6-d583-11d6-898a-00039310a47a)]
|
||||
interface nsIJunkMailClassificationListener : nsISupports
|
||||
{
|
||||
void onMessageClassified(in string aMsgURL, in long classification);
|
||||
};
|
||||
|
||||
[scriptable, uuid(caf3d467-d57c-11d6-96a9-00039310a47a)]
|
||||
interface nsIJunkMailPlugin : nsIMsgFilterPlugin
|
||||
{
|
||||
/**
|
||||
* Message classifications.
|
||||
*/
|
||||
const long UNCLASSIFIED = 0;
|
||||
const long GOOD = 1;
|
||||
const long JUNK = 2;
|
||||
|
||||
/**
|
||||
* Given a message URL, determine what its current classification is
|
||||
* according to the current training set.
|
||||
*/
|
||||
void classifyMessage(in string aMsgURL,
|
||||
in nsIJunkMailClassificationListener aListener);
|
||||
|
||||
void classifyMessages(in unsigned long aCount,
|
||||
[array, size_is(aCount)] in string aMsgURLs,
|
||||
in nsIJunkMailClassificationListener aListener);
|
||||
|
||||
/**
|
||||
* Called when a user forces the classification of a message. Should
|
||||
* cause the training set to be updated appropriately.
|
||||
*/
|
||||
void setMessageClassification(in string aMsgURL,
|
||||
in long aOldClassification,
|
||||
in long aNewClassification,
|
||||
in nsIJunkMailClassificationListener aListener);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user