store junk mail classification on imap servers that support user keywords, r/sr=sspitzer 180857

This commit is contained in:
bienvenu%netscape.com 2003-01-21 18:00:00 +00:00
Родитель 7e7ed390b5
Коммит 87aa6e6fe0
16 изменённых файлов: 244 добавлений и 12 удалений

Просмотреть файл

@ -2261,6 +2261,19 @@ nsMsgDBView::ApplyCommandToIndices(nsMsgViewCommandTypeValue command, nsMsgViewI
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;
}

Просмотреть файл

@ -86,7 +86,7 @@ interface nsIImapProtocol : nsIStreamListener {
void NotifyHdrsToDownload(out unsigned long keys, in unsigned long keyCount);
void NotifyBodysToDownload(out unsigned long keys, in unsigned long count);
// methods to get data from the imap parser flag state.
void GetFlagsForUID(in unsigned long uid, out boolean foundIt, out unsigned short flags);
void GetFlagsForUID(in unsigned long uid, out boolean foundIt, out unsigned short flags, out string customFlags);
void GetSupportedUserFlags(out unsigned short flags);
void GetRunningImapURL(out nsIImapUrl aImapUrl);

Просмотреть файл

@ -256,6 +256,13 @@ interface nsIImapService : nsISupports
in string aAttribute,
in string aMessageIdentifierList);
nsIURI storeCustomKeywords(in nsIEventQueue aClientEventQueue,
in nsIMsgFolder aMailFolder,
in nsIMsgWindow aMsgWindow,
in string flagsToAdd,
in string flagsToSubtract,
in string aMessageIdentifierList);
void getListOfFoldersOnServer(in nsIImapIncomingServer aServer, in nsIMsgWindow aMsgWindow);
void getListOfFoldersWithPath(in nsIImapIncomingServer aServer, in nsIMsgWindow aMsgWindow, in string folderPath);

Просмотреть файл

@ -87,6 +87,8 @@ interface nsIImapUrl : nsISupports
attribute string customAttributeResult;
readonly attribute string command;
attribute string customCommandResult;
readonly attribute string customAddFlags;
readonly attribute string customSubtractFlags;
void allocateCanonicalPath(in string aServerPath, in char aOnlineDelimiter, out string aAllocatedPath);
void allocateServerPath(in string aCanonicalPath, in char aOnlineDelimiter, out string aAllocatedPath);
string createServerSourceFolderPathString();
@ -189,6 +191,7 @@ interface nsIImapUrl : nsISupports
const long nsImapUserDefinedMsgCommand = 0x10000034;
const long nsImapUserDefinedFetchAttribute = 0x10000035;
const long nsImapMsgFetchPeek = 0x10000036;
const long nsImapMsgStoreCustomKeywords = 0x10000037;
};
%{C++

Просмотреть файл

@ -84,6 +84,12 @@ interface nsIMsgImapMailFolder : nsISupports {
// It assumes the command needs to be run in the selected state.
nsIURI issueCommandOnMsgs(in string command, in string uids, in nsIMsgWindow aWindow);
nsIURI fetchCustomMsgAttribute(in string msgAttribute, in string uids, in nsIMsgWindow aWindow);
nsIURI storeCustomKeywords(in nsIMsgWindow aMsgWindow,
in string aFlagsToAdd,
in string aFlagsToSubtract,
out nsMsgKey aKeysToStore,
in long aNumKeys);
attribute boolean verifiedAsOnlineFolder;
attribute boolean explicitlyVerify;
attribute wchar hierarchyDelimiter;

Просмотреть файл

@ -3526,7 +3526,9 @@ void nsImapMailFolder::TweakHeaderFlags(nsIImapProtocol* aProtocol, nsIMsgDBHdr
PRBool foundIt = PR_FALSE;
imapMessageFlagsType imap_flags;
nsresult res = aProtocol->GetFlagsForUID(m_curMsgUid, &foundIt, &imap_flags);
nsXPIDLCString customFlags;
nsresult res = aProtocol->GetFlagsForUID(m_curMsgUid, &foundIt, &imap_flags, getter_Copies(customFlags));
if (NS_SUCCEEDED(res) && foundIt)
{
// make a mask and clear these message flags
@ -3585,6 +3587,8 @@ void nsImapMailFolder::TweakHeaderFlags(nsIImapProtocol* aProtocol, nsIMsgDBHdr
if (newFlags)
tweakMe->OrFlags(newFlags, &dbHdrFlags);
if (!customFlags.IsEmpty())
(void) HandleCustomFlags(m_curMsgUid, tweakMe, customFlags);
}
}
}
@ -3941,6 +3945,28 @@ nsImapMailFolder::BeginMessageUpload()
return NS_ERROR_FAILURE;
}
nsresult nsImapMailFolder::HandleCustomFlags(nsMsgKey uidOfMessage, nsIMsgDBHdr *dbHdr, nsXPIDLCString &keywords)
{
PRBool messageClassified = PR_TRUE;
nsXPIDLCString::const_iterator b, e;
if (FindInReadable(NS_LITERAL_CSTRING("NonJunk"), keywords.BeginReading(b), keywords.EndReading(e)))
mDatabase->SetStringProperty(uidOfMessage, "junkscore", "0");
else if (FindInReadable(NS_LITERAL_CSTRING("Junk"), keywords.BeginReading(b), keywords.EndReading(e)))
mDatabase->SetStringProperty(uidOfMessage, "junkscore", "100");
else
messageClassified = PR_FALSE;
if (messageClassified)
{
// only set the junkscore origin if it wasn't set before. We assume plugin since we
// think that's the more common scenario.
nsXPIDLCString existingProperty;
dbHdr->GetStringProperty("junkscoreorigin", getter_Copies(existingProperty));
if (existingProperty.IsEmpty())
dbHdr->SetStringProperty("junkscoreorigin", "plugin");
}
return dbHdr->SetStringProperty("keywords", keywords);
}
// synchronize the message flags in the database with the server flags
nsresult nsImapMailFolder::SyncFlags(nsIImapFlagAndUidState *flagState)
{
@ -3979,7 +4005,7 @@ nsresult nsImapMailFolder::SyncFlags(nsIImapFlagAndUidState *flagState)
{
if (dbHdr && NS_SUCCEEDED(rv))
{
dbHdr->SetStringProperty("keywords", keywords);
HandleCustomFlags(uidOfMessage, dbHdr, keywords);
}
}
}
@ -7097,6 +7123,18 @@ nsImapMailFolder::SpamFilterClassifyMessages(const char **aURIArray, PRUint32 aU
return aJunkMailPlugin->ClassifyMessages(aURICount, aURIArray, aMsgWindow, this);
}
NS_IMETHODIMP
nsImapMailFolder::StoreCustomKeywords(nsIMsgWindow *aMsgWindow, const char *aFlagsToAdd,
const char *aFlagsToSubtract, nsMsgKey *aKeysToStore, PRInt32 aNumKeys, nsIURI **_retval)
{
nsresult rv;
nsCOMPtr<nsIImapService> imapService(do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString msgIds;
AllocateUidStringFromKeys(aKeysToStore, aNumKeys, msgIds);
return imapService->StoreCustomKeywords(m_eventQueue, this, aMsgWindow, aFlagsToAdd, aFlagsToSubtract, msgIds.get(), _retval);
}
NS_IMETHODIMP
nsImapMailFolder::OnMessageClassified(const char *aMsgURI, nsMsgJunkStatus aClassification)
@ -7116,6 +7154,13 @@ nsImapMailFolder::OnMessageClassified(const char *aMsgURI, nsMsgJunkStatus aClas
mDatabase->SetStringProperty(msgKey, "junkscore", (aClassification == nsIJunkMailPlugin::JUNK) ? "100" : "0");
mDatabase->SetStringProperty(msgKey, "junkscoreorigin", "plugin");
GetMoveCoalescer();
if (m_moveCoalescer)
{
nsMsgKeyArray *keysToClassify = m_moveCoalescer->GetKeyBucket((aClassification == nsIJunkMailPlugin::JUNK) ? 0 : 1);
if (keysToClassify)
keysToClassify->Add(msgKey);
}
if (aClassification == nsIJunkMailPlugin::JUNK)
{
nsCOMPtr<nsISpamSettings> spamSettings;
@ -7172,8 +7217,18 @@ nsImapMailFolder::OnMessageClassified(const char *aMsgURI, nsMsgJunkStatus aClas
rv = spamSettings->LogJunkHit(msgHdr, willMoveMessage);
NS_ENSURE_SUCCESS(rv,rv);
}
if (--m_numFilterClassifyRequests == 0 && m_moveCoalescer)
{
nsMsgKeyArray *junkKeysToClassify = m_moveCoalescer->GetKeyBucket(0);
nsMsgKeyArray *nonJunkKeysToClassify = m_moveCoalescer->GetKeyBucket(1);
if (--m_numFilterClassifyRequests == 0 && m_moveCoalescer) {
nsCOMPtr<nsIImapService> imapService(do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
if (junkKeysToClassify && junkKeysToClassify->GetSize() > 0)
StoreCustomKeywords(m_moveCoalescer->GetMsgWindow(), "Junk", "", junkKeysToClassify->GetArray(), junkKeysToClassify->GetSize(), nsnull);
if (nonJunkKeysToClassify && nonJunkKeysToClassify->GetSize() > 0)
StoreCustomKeywords(m_moveCoalescer->GetMsgWindow(), "NonJunk", "", nonJunkKeysToClassify->GetArray(), nonJunkKeysToClassify->GetSize(), nsnull);
m_moveCoalescer->PlaybackMoves();
}
return NS_OK;

Просмотреть файл

@ -364,7 +364,8 @@ protected:
void TweakHeaderFlags(nsIImapProtocol* aProtocol, nsIMsgDBHdr *tweakMe);
nsresult SyncFlags(nsIImapFlagAndUidState *flagState);
nsresult NotifyMessageFlagsFromHdr(nsIMsgDBHdr *dbHdr, nsMsgKey msgKey, PRUint32 flags);
nsresult HandleCustomFlags(nsMsgKey uidOfMessage, nsIMsgDBHdr *dbHdr, nsXPIDLCString &keywords);
nsresult NotifyMessageFlagsFromHdr(nsIMsgDBHdr *dbHdr, nsMsgKey msgKey, PRUint32 flags);
nsresult SetupHeaderParseStream(PRUint32 size, const char *content_type, nsIMailboxSpec *boxSpec);
nsresult ParseAdoptedHeaderLine(const char *messageLine, PRUint32 msgKey);

Просмотреть файл

@ -60,6 +60,11 @@ nsImapMoveCoalescer::~nsImapMoveCoalescer()
nsMsgKeyArray *keys = (nsMsgKeyArray *) m_sourceKeyArrays.ElementAt(i);
delete keys;
}
for (PRInt32 index = 0; index < m_keyBuckets.Count(); index++)
{
nsMsgKeyArray *keys = (nsMsgKeyArray *) m_keyBuckets.ElementAt(index);
delete keys;
}
}
nsresult nsImapMoveCoalescer::AddMove(nsIMsgFolder *folder, nsMsgKey key)
@ -167,3 +172,18 @@ nsresult nsImapMoveCoalescer::PlaybackMoves()
return rv;
}
nsMsgKeyArray *nsImapMoveCoalescer::GetKeyBucket(PRInt32 keyArrayIndex)
{
if (m_keyBuckets.Count() < keyArrayIndex + 1)
{
for (PRInt32 i = 0; i < keyArrayIndex + 1 - m_keyBuckets.Count(); i++)
{
nsMsgKeyArray *keysToAdd = new nsMsgKeyArray;
if (!keysToAdd)
return nsnull;
m_keyBuckets.AppendElement(keysToAdd);
}
}
return (nsMsgKeyArray *) m_keyBuckets.SafeElementAt(keyArrayIndex);
}

Просмотреть файл

@ -61,12 +61,17 @@ public:
nsresult AddMove(nsIMsgFolder *folder, nsMsgKey key);
nsresult PlaybackMoves();
// this lets the caller store keys in an arbitrary number of buckets. If the bucket
// for the passed in index doesn't exist, it will get created.
nsMsgKeyArray *GetKeyBucket(PRInt32 keyArrayIndex);
nsIMsgWindow *GetMsgWindow() {return m_msgWindow;}
protected:
// m_sourceKeySets and m_destFolders are parallel arrays.
// m_sourceKeyArrays and m_destFolders are parallel arrays.
nsVoidArray m_sourceKeyArrays;
nsCOMPtr <nsISupportsArray> m_destFolders;
nsCOMPtr <nsIMsgWindow> m_msgWindow;
nsCOMPtr <nsIMsgFolder> m_sourceFolder;
nsVoidArray m_keyBuckets;
};
#endif // _nsImapMoveCoalescer_H

Просмотреть файл

@ -2223,6 +2223,36 @@ void nsImapProtocol::ProcessSelectedStateURL()
FetchMsgAttribute(messageIdString, attribute);
}
break;
case nsIImapUrl::nsImapMsgStoreCustomKeywords:
{
// if the server doesn't support user defined flags, don't try to set them.
PRUint16 userFlags;
GetSupportedUserFlags(&userFlags);
if (! (userFlags & kImapMsgSupportUserFlag))
break;
nsXPIDLCString messageIdString;
nsXPIDLCString addFlags;
nsXPIDLCString subtractFlags;
m_runningUrl->CreateListOfMessageIdsString(getter_Copies(messageIdString));
m_runningUrl->GetCustomAddFlags(getter_Copies(addFlags));
m_runningUrl->GetCustomSubtractFlags(getter_Copies(subtractFlags));
if (addFlags.Length() > 0)
{
nsCAutoString storeString("+FLAGS (");
storeString.Append(addFlags);
storeString.Append(")");
Store(messageIdString, storeString.get(), PR_TRUE);
}
if (subtractFlags.Length() > 0)
{
nsCAutoString storeString("-FLAGS (");
storeString.Append(addFlags);
storeString.Append(")");
Store(messageIdString, storeString.get(), PR_TRUE);
}
}
break;
case nsIImapUrl::nsImapDeleteMsg:
{
nsXPIDLCString messageIdString;
@ -3577,13 +3607,17 @@ NS_IMETHODIMP nsImapProtocol::NotifyBodysToDownload(PRUint32 *keys, PRUint32 key
return NS_OK;
}
NS_IMETHODIMP nsImapProtocol::GetFlagsForUID(PRUint32 uid, PRBool *foundIt, imapMessageFlagsType *resultFlags)
NS_IMETHODIMP nsImapProtocol::GetFlagsForUID(PRUint32 uid, PRBool *foundIt, imapMessageFlagsType *resultFlags, char **customFlags)
{
PRInt32 i;
imapMessageFlagsType flags = m_flagState->GetMessageFlagsFromUID(uid, foundIt, &i);
if (*foundIt)
{
*resultFlags = flags;
if ((flags & kImapMsgCustomKeywordFlag) && customFlags)
m_flagState->GetCustomFlags(uid, customFlags);
}
return NS_OK;
}

Просмотреть файл

@ -191,7 +191,7 @@ public:
NS_IMETHOD NotifyHdrsToDownload(PRUint32 *keys, PRUint32 keyCount);
NS_IMETHOD NotifyBodysToDownload(PRUint32 *keys, PRUint32 keyCount);
NS_IMETHOD GetFlagsForUID(PRUint32 uid, PRBool *foundIt, imapMessageFlagsType *flags);
NS_IMETHOD GetFlagsForUID(PRUint32 uid, PRBool *foundIt, imapMessageFlagsType *flags, char **customFlags);
NS_IMETHOD GetSupportedUserFlags(PRUint16 *flags);
NS_IMETHOD GetRunningUrl(nsIURI **aUrl);

Просмотреть файл

@ -1286,7 +1286,12 @@ void nsImapServerResponseParser::msg_fetch()
{
if (CurrentResponseUID() && CurrentResponseUID() != nsMsgKey_None
&& fCurrentLineContainedFlagInfo && fFlagState)
{
fFlagState->AddUidFlagPair(CurrentResponseUID(), fSavedFlagInfo);
for (PRInt32 i = 0; i < fCustomFlags.Count(); i++)
fFlagState->AddUidCustomFlagPair(CurrentResponseUID(), fCustomFlags.CStringAt(i)->get());
fCustomFlags.Clear();
}
if (fFetchingAllFlags)
fCurrentLineContainedFlagInfo = PR_FALSE; // do not fire if in PostProcessEndOfLine
@ -1520,7 +1525,7 @@ void nsImapServerResponseParser::internal_date()
void nsImapServerResponseParser::flags()
{
imapMessageFlagsType messageFlags = kNoImapMsgFlag;
fCustomFlags.Clear();
// eat the opening '('
fNextToken++;
while (ContinueParse() && (*fNextToken != ')'))
@ -1620,7 +1625,10 @@ void nsImapServerResponseParser::flags()
if (parenIndex > 0)
flag.Truncate(parenIndex);
messageFlags |= kImapMsgCustomKeywordFlag;
fFlagState->AddUidCustomFlagPair(CurrentResponseUID(), flag.get());
if (CurrentResponseUID() != nsMsgKey_None)
fFlagState->AddUidCustomFlagPair(CurrentResponseUID(), flag.get());
else
fCustomFlags.AppendCString(flag);
}
if (PL_strcasestr(fNextToken, ")"))
{

Просмотреть файл

@ -232,7 +232,7 @@ private:
PRPackedBool fCurrentCommandIsSingleMessageFetch;
PRPackedBool fGotPermanentFlags;
imapMessageFlagsType fSavedFlagInfo;
nsCStringArray fCustomFlags;
PRUint16 fSupportsUserDefinedFlags;
PRUint16 fSettablePermanentFlags;

Просмотреть файл

@ -3920,6 +3920,60 @@ nsImapService::FetchCustomMsgAttribute(nsIEventQueue *aClientEventQueue,
return rv;
}
NS_IMETHODIMP
nsImapService::StoreCustomKeywords(nsIEventQueue *aClientEventQueue,
nsIMsgFolder *anImapFolder,
nsIMsgWindow *aMsgWindow,
const char *flagsToAdd,
const char *flagsToSubtract,
const char *uids,
nsIURI** aURL)
{
NS_ENSURE_ARG_POINTER(aClientEventQueue);
NS_ENSURE_ARG_POINTER(anImapFolder);
nsCOMPtr<nsIImapUrl> imapUrl;
nsCAutoString urlSpec;
nsresult rv;
PRUnichar hierarchySeparator = GetHierarchyDelimiter(anImapFolder);
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl), anImapFolder, nsnull, urlSpec, hierarchySeparator);
if (NS_SUCCEEDED(rv) && imapUrl)
{
// nsImapUrl::SetSpec() will set the imap action properly
rv = imapUrl->SetImapAction(nsIImapUrl::nsImapMsgStoreCustomKeywords);
nsCOMPtr <nsIMsgMailNewsUrl> mailNewsUrl = do_QueryInterface(imapUrl);
mailNewsUrl->SetMsgWindow(aMsgWindow);
mailNewsUrl->SetUpdatingFolder(PR_TRUE);
imapUrl->AddChannelToLoadGroup();
rv = SetImapUrlSink(anImapFolder, imapUrl);
if (NS_SUCCEEDED(rv))
{
nsXPIDLCString folderName;
GetFolderName(anImapFolder, getter_Copies(folderName));
urlSpec.Append("/customKeywords>UID>");
urlSpec.Append(char(hierarchySeparator));
urlSpec.Append((const char *) folderName);
urlSpec.Append(">");
urlSpec.Append(uids);
urlSpec.Append(">");
urlSpec.Append(flagsToAdd);
urlSpec.Append(">");
urlSpec.Append(flagsToSubtract);
rv = mailNewsUrl->SetSpec(urlSpec);
if (NS_SUCCEEDED(rv))
rv = GetImapConnectionAndLoadUrl(aClientEventQueue,
imapUrl,
nsnull,
aURL);
}
} // if we have a url to run....
return rv;
}
NS_IMETHODIMP
nsImapService::DownloadMessagesForOffline(const char *messageIds, nsIMsgFolder *aFolder, nsIUrlListener *aUrlListener, nsIMsgWindow *aMsgWindow)
{

Просмотреть файл

@ -425,6 +425,20 @@ NS_IMETHODIMP nsImapUrl::SetCustomCommandResult(const char *result)
return NS_OK;
}
NS_IMETHODIMP nsImapUrl::GetCustomAddFlags(char **aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = ToNewCString(m_customAddFlags);
return (*aResult) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
NS_IMETHODIMP nsImapUrl::GetCustomSubtractFlags(char **aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = ToNewCString(m_customSubtractFlags);
return (*aResult) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
NS_IMETHODIMP nsImapUrl::GetImapPartToFetch(char **result)
{
@ -781,11 +795,21 @@ void nsImapUrl::ParseImapPart(char *imapPartOfUrl)
ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
ParseListOfMessageIds();
}
else if (m_imapAction == nsIImapUrl::nsImapMsgStoreCustomKeywords)
{
ParseUidChoice();
ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
ParseListOfMessageIds();
char *flagsPtr = m_tokenPlaceHolder ? nsIMAPGenericParser::Imapstrtok_r(nsnull, IMAP_URL_TOKEN_SEPARATOR, &m_tokenPlaceHolder) : (char *)nsnull;
m_customAddFlags.Assign(flagsPtr);
flagsPtr = m_tokenPlaceHolder ? nsIMAPGenericParser::Imapstrtok_r(nsnull, IMAP_URL_TOKEN_SEPARATOR, &m_tokenPlaceHolder) : (char *)nsnull;
m_customSubtractFlags.Assign(flagsPtr);
}
else
{
m_validUrl = PR_FALSE;
}
}
}
}

Просмотреть файл

@ -115,6 +115,8 @@ protected:
nsCString m_msgFetchAttribute; // for fetching custom msg attributes
nsCString m_customAttributeResult; // for fetching custom msg attributes
nsCString m_customCommandResult; // custom command response
nsCString m_customAddFlags; // these two are for setting and clearing custom flags
nsCString m_customSubtractFlags;
PRPackedBool m_validUrl;
PRPackedBool m_runningUrl;
PRPackedBool m_idsAreUids;