summaryrefslogtreecommitdiffstats
path: root/mailnews/base/src/nsSpamSettings.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mailnews/base/src/nsSpamSettings.cpp')
-rw-r--r--mailnews/base/src/nsSpamSettings.cpp892
1 files changed, 892 insertions, 0 deletions
diff --git a/mailnews/base/src/nsSpamSettings.cpp b/mailnews/base/src/nsSpamSettings.cpp
new file mode 100644
index 000000000..e8318b75a
--- /dev/null
+++ b/mailnews/base/src/nsSpamSettings.cpp
@@ -0,0 +1,892 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsSpamSettings.h"
+#include "nsIFile.h"
+#include "plstr.h"
+#include "prmem.h"
+#include "nsIMsgHdr.h"
+#include "nsNetUtil.h"
+#include "nsIMsgFolder.h"
+#include "nsMsgUtils.h"
+#include "nsMsgFolderFlags.h"
+#include "nsImapCore.h"
+#include "nsIImapIncomingServer.h"
+#include "nsIRDFService.h"
+#include "nsIRDFResource.h"
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsIPrefService.h"
+#include "nsIPrefBranch.h"
+#include "nsIStringBundle.h"
+#include "nsDateTimeFormatCID.h"
+#include "mozilla/Services.h"
+#include "mozilla/mailnews/MimeHeaderParser.h"
+#include "nsIArray.h"
+#include "nsArrayUtils.h"
+#include "nsMailDirServiceDefs.h"
+#include "nsDirectoryServiceUtils.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsISimpleEnumerator.h"
+#include "nsIDirectoryEnumerator.h"
+#include "nsAbBaseCID.h"
+#include "nsIAbManager.h"
+#include "nsIMsgAccountManager.h"
+#include "nsMsgBaseCID.h"
+
+using namespace mozilla::mailnews;
+
+nsSpamSettings::nsSpamSettings()
+{
+ mLevel = 0;
+ mMoveOnSpam = false;
+ mMoveTargetMode = nsISpamSettings::MOVE_TARGET_MODE_ACCOUNT;
+ mPurge = false;
+ mPurgeInterval = 14; // 14 days
+
+ mServerFilterTrustFlags = 0;
+
+ mUseWhiteList = false;
+ mUseServerFilter = false;
+
+ nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mLogFile));
+ if (NS_SUCCEEDED(rv))
+ mLogFile->Append(NS_LITERAL_STRING("junklog.html"));
+}
+
+nsSpamSettings::~nsSpamSettings()
+{
+}
+
+NS_IMPL_ISUPPORTS(nsSpamSettings, nsISpamSettings, nsIUrlListener)
+
+NS_IMETHODIMP
+nsSpamSettings::GetLevel(int32_t *aLevel)
+{
+ NS_ENSURE_ARG_POINTER(aLevel);
+ *aLevel = mLevel;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSpamSettings::SetLevel(int32_t aLevel)
+{
+ NS_ASSERTION((aLevel >= 0 && aLevel <= 100), "bad level");
+ mLevel = aLevel;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSpamSettings::GetMoveTargetMode(int32_t *aMoveTargetMode)
+{
+ NS_ENSURE_ARG_POINTER(aMoveTargetMode);
+ *aMoveTargetMode = mMoveTargetMode;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSpamSettings::SetMoveTargetMode(int32_t aMoveTargetMode)
+{
+ NS_ASSERTION((aMoveTargetMode == nsISpamSettings::MOVE_TARGET_MODE_FOLDER || aMoveTargetMode == nsISpamSettings::MOVE_TARGET_MODE_ACCOUNT), "bad move target mode");
+ mMoveTargetMode = aMoveTargetMode;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSpamSettings::GetManualMark(bool *aManualMark)
+{
+ NS_ENSURE_ARG_POINTER(aManualMark);
+ nsresult rv;
+ nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+ return prefBranch->GetBoolPref("mail.spam.manualMark", aManualMark);
+}
+
+NS_IMETHODIMP nsSpamSettings::GetManualMarkMode(int32_t *aManualMarkMode)
+{
+ NS_ENSURE_ARG_POINTER(aManualMarkMode);
+ nsresult rv;
+ nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+ return prefBranch->GetIntPref("mail.spam.manualMarkMode", aManualMarkMode);
+}
+
+NS_IMETHODIMP nsSpamSettings::GetLoggingEnabled(bool *aLoggingEnabled)
+{
+ NS_ENSURE_ARG_POINTER(aLoggingEnabled);
+ nsresult rv;
+ nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+ return prefBranch->GetBoolPref("mail.spam.logging.enabled", aLoggingEnabled);
+}
+
+NS_IMETHODIMP nsSpamSettings::GetMarkAsReadOnSpam(bool *aMarkAsReadOnSpam)
+{
+ NS_ENSURE_ARG_POINTER(aMarkAsReadOnSpam);
+ nsresult rv;
+ nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+ return prefBranch->GetBoolPref("mail.spam.markAsReadOnSpam", aMarkAsReadOnSpam);
+}
+
+NS_IMPL_GETSET(nsSpamSettings, MoveOnSpam, bool, mMoveOnSpam)
+NS_IMPL_GETSET(nsSpamSettings, Purge, bool, mPurge)
+NS_IMPL_GETSET(nsSpamSettings, UseWhiteList, bool, mUseWhiteList)
+NS_IMPL_GETSET(nsSpamSettings, UseServerFilter, bool, mUseServerFilter)
+
+NS_IMETHODIMP nsSpamSettings::GetWhiteListAbURI(char * *aWhiteListAbURI)
+{
+ NS_ENSURE_ARG_POINTER(aWhiteListAbURI);
+ *aWhiteListAbURI = ToNewCString(mWhiteListAbURI);
+ return NS_OK;
+}
+NS_IMETHODIMP nsSpamSettings::SetWhiteListAbURI(const char * aWhiteListAbURI)
+{
+ mWhiteListAbURI = aWhiteListAbURI;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSpamSettings::GetActionTargetAccount(char * *aActionTargetAccount)
+{
+ NS_ENSURE_ARG_POINTER(aActionTargetAccount);
+ *aActionTargetAccount = ToNewCString(mActionTargetAccount);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSpamSettings::SetActionTargetAccount(const char * aActionTargetAccount)
+{
+ mActionTargetAccount = aActionTargetAccount;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSpamSettings::GetActionTargetFolder(char * *aActionTargetFolder)
+{
+ NS_ENSURE_ARG_POINTER(aActionTargetFolder);
+ *aActionTargetFolder = ToNewCString(mActionTargetFolder);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSpamSettings::SetActionTargetFolder(const char * aActionTargetFolder)
+{
+ mActionTargetFolder = aActionTargetFolder;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSpamSettings::GetPurgeInterval(int32_t *aPurgeInterval)
+{
+ NS_ENSURE_ARG_POINTER(aPurgeInterval);
+ *aPurgeInterval = mPurgeInterval;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSpamSettings::SetPurgeInterval(int32_t aPurgeInterval)
+{
+ NS_ASSERTION(aPurgeInterval >= 0, "bad purge interval");
+ mPurgeInterval = aPurgeInterval;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSpamSettings::SetLogStream(nsIOutputStream *aLogStream)
+{
+ // if there is a log stream already, close it
+ if (mLogStream) {
+ // will flush
+ nsresult rv = mLogStream->Close();
+ NS_ENSURE_SUCCESS(rv,rv);
+ }
+
+ mLogStream = aLogStream;
+ return NS_OK;
+}
+
+#define LOG_HEADER "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<style type=\"text/css\">body{font-family:Consolas,\"Lucida Console\",Monaco,\"Courier New\",Courier,monospace;font-size:small}</style>\n</head>\n<body>\n"
+#define LOG_HEADER_LEN (strlen(LOG_HEADER))
+
+NS_IMETHODIMP
+nsSpamSettings::GetLogStream(nsIOutputStream **aLogStream)
+{
+ NS_ENSURE_ARG_POINTER(aLogStream);
+
+ nsresult rv;
+
+ if (!mLogStream) {
+ // append to the end of the log file
+ rv = MsgNewBufferedFileOutputStream(getter_AddRefs(mLogStream),
+ mLogFile,
+ PR_CREATE_FILE | PR_WRONLY | PR_APPEND,
+ 0600);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ int64_t fileSize;
+ rv = mLogFile->GetFileSize(&fileSize);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // write the header at the start
+ if (fileSize == 0)
+ {
+ uint32_t writeCount;
+
+ rv = mLogStream->Write(LOG_HEADER, LOG_HEADER_LEN, &writeCount);
+ NS_ENSURE_SUCCESS(rv, rv);
+ NS_ASSERTION(writeCount == LOG_HEADER_LEN, "failed to write out log header");
+ }
+ }
+
+ NS_ADDREF(*aLogStream = mLogStream);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSpamSettings::Initialize(nsIMsgIncomingServer *aServer)
+{
+ NS_ENSURE_ARG_POINTER(aServer);
+ nsresult rv;
+ int32_t spamLevel;
+ rv = aServer->GetIntValue("spamLevel", &spamLevel);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = SetLevel(spamLevel);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool moveOnSpam;
+ rv = aServer->GetBoolValue("moveOnSpam", &moveOnSpam);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = SetMoveOnSpam(moveOnSpam);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ int32_t moveTargetMode;
+ rv = aServer->GetIntValue("moveTargetMode", &moveTargetMode);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = SetMoveTargetMode(moveTargetMode);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCString spamActionTargetAccount;
+ rv = aServer->GetCharValue("spamActionTargetAccount", spamActionTargetAccount);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = SetActionTargetAccount(spamActionTargetAccount.get());
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCString spamActionTargetFolder;
+ rv = aServer->GetCharValue("spamActionTargetFolder", spamActionTargetFolder);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = SetActionTargetFolder(spamActionTargetFolder.get());
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool useWhiteList;
+ rv = aServer->GetBoolValue("useWhiteList", &useWhiteList);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = SetUseWhiteList(useWhiteList);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCString whiteListAbURI;
+ rv = aServer->GetCharValue("whiteListAbURI", whiteListAbURI);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = SetWhiteListAbURI(whiteListAbURI.get());
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool purgeSpam;
+ rv = aServer->GetBoolValue("purgeSpam", &purgeSpam);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = SetPurge(purgeSpam);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ int32_t purgeSpamInterval;
+ rv = aServer->GetIntValue("purgeSpamInterval", &purgeSpamInterval);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = SetPurgeInterval(purgeSpamInterval);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool useServerFilter;
+ rv = aServer->GetBoolValue("useServerFilter", &useServerFilter);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = SetUseServerFilter(useServerFilter);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCString serverFilterName;
+ rv = aServer->GetCharValue("serverFilterName", serverFilterName);
+ if (NS_SUCCEEDED(rv))
+ SetServerFilterName(serverFilterName);
+ int32_t serverFilterTrustFlags = 0;
+ rv = aServer->GetIntValue("serverFilterTrustFlags", &serverFilterTrustFlags);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = SetServerFilterTrustFlags(serverFilterTrustFlags);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
+ if (prefBranch)
+ prefBranch->GetCharPref("mail.trusteddomains",
+ getter_Copies(mTrustedMailDomains));
+
+ mWhiteListDirArray.Clear();
+ if (!mWhiteListAbURI.IsEmpty())
+ {
+ nsCOMPtr<nsIAbManager> abManager(do_GetService(NS_ABMANAGER_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsTArray<nsCString> whiteListArray;
+ ParseString(mWhiteListAbURI, ' ', whiteListArray);
+
+ for (uint32_t index = 0; index < whiteListArray.Length(); index++)
+ {
+ nsCOMPtr<nsIAbDirectory> directory;
+ rv = abManager->GetDirectory(whiteListArray[index],
+ getter_AddRefs(directory));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (directory)
+ mWhiteListDirArray.AppendObject(directory);
+ }
+ }
+
+ // the next two preferences affect whether we try to whitelist our own
+ // address or domain. Spammers send emails with spoofed from address matching
+ // either the email address of the recipient, or the recipient's domain,
+ // hoping to get whitelisted.
+ //
+ // The terms to describe this get wrapped up in chains of negatives. A full
+ // definition of the boolean inhibitWhiteListingIdentityUser is "Suppress address
+ // book whitelisting if the sender matches an identity's email address"
+
+ rv = aServer->GetBoolValue("inhibitWhiteListingIdentityUser",
+ &mInhibitWhiteListingIdentityUser);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = aServer->GetBoolValue("inhibitWhiteListingIdentityDomain",
+ &mInhibitWhiteListingIdentityDomain);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // collect lists of identity users if needed
+ if (mInhibitWhiteListingIdentityDomain || mInhibitWhiteListingIdentityUser)
+ {
+ nsCOMPtr<nsIMsgAccountManager>
+ accountManager(do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIMsgAccount> account;
+ rv = accountManager->FindAccountForServer(aServer, getter_AddRefs(account));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoCString accountKey;
+ if (account)
+ account->GetKey(accountKey);
+
+ // Loop through all accounts, adding emails from this account, as well as
+ // from any accounts that defer to this account.
+ mEmails.Clear();
+ nsCOMPtr<nsIArray> accounts;
+ rv = accountManager->GetAccounts(getter_AddRefs(accounts));
+ NS_ENSURE_SUCCESS(rv, rv);
+ uint32_t accountCount = 0;
+ if (account && accounts) // no sense scanning accounts if we've nothing to match
+ accounts->GetLength(&accountCount);
+
+ for (uint32_t i = 0; i < accountCount; i++)
+ {
+ nsCOMPtr<nsIMsgAccount> loopAccount(do_QueryElementAt(accounts, i));
+ if (!loopAccount)
+ continue;
+ nsAutoCString loopAccountKey;
+ loopAccount->GetKey(loopAccountKey);
+ nsCOMPtr<nsIMsgIncomingServer> loopServer;
+ loopAccount->GetIncomingServer(getter_AddRefs(loopServer));
+ nsAutoCString deferredToAccountKey;
+ if (loopServer)
+ loopServer->GetCharValue("deferred_to_account", deferredToAccountKey);
+
+ // Add the emails for any account that defers to this one, or for the
+ // account itself.
+ if (accountKey.Equals(deferredToAccountKey) || accountKey.Equals(loopAccountKey))
+ {
+ nsCOMPtr<nsIArray> identities;
+ loopAccount->GetIdentities(getter_AddRefs(identities));
+ if (!identities)
+ continue;
+ uint32_t identityCount = 0;
+ identities->GetLength(&identityCount);
+ for (uint32_t j = 0; j < identityCount; ++j)
+ {
+ nsCOMPtr<nsIMsgIdentity> identity(do_QueryElementAt(identities, j, &rv));
+ if (NS_FAILED(rv) || !identity)
+ continue;
+ nsAutoCString email;
+ identity->GetEmail(email);
+ if (!email.IsEmpty())
+ mEmails.AppendElement(email);
+ }
+ }
+ }
+ }
+
+ return UpdateJunkFolderState();
+}
+
+nsresult nsSpamSettings::UpdateJunkFolderState()
+{
+ nsresult rv;
+
+ // if the spam folder uri changed on us, we need to unset the junk flag
+ // on the old spam folder
+ nsCString newJunkFolderURI;
+ rv = GetSpamFolderURI(getter_Copies(newJunkFolderURI));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!mCurrentJunkFolderURI.IsEmpty() && !mCurrentJunkFolderURI.Equals(newJunkFolderURI))
+ {
+ nsCOMPtr<nsIMsgFolder> oldJunkFolder;
+ rv = GetExistingFolder(mCurrentJunkFolderURI, getter_AddRefs(oldJunkFolder));
+ if (NS_SUCCEEDED(rv) && oldJunkFolder)
+ {
+ // remove the nsMsgFolderFlags::Junk on the old junk folder
+ // XXX TODO
+ // JUNK MAIL RELATED
+ // (in ClearFlag?) we need to make sure that this folder
+ // is not the junk folder for another account
+ // the same goes for set flag. have fun with all that.
+ oldJunkFolder->ClearFlag(nsMsgFolderFlags::Junk);
+ }
+ }
+
+ mCurrentJunkFolderURI = newJunkFolderURI;
+
+ // only try to create the junk folder if we are moving junk
+ // and we have a non-empty uri
+ if (mMoveOnSpam && !mCurrentJunkFolderURI.IsEmpty()) {
+ // as the url listener, the spam settings will set the nsMsgFolderFlags::Junk folder flag
+ // on the junk mail folder, after it is created
+ rv = GetOrCreateFolder(mCurrentJunkFolderURI, this);
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP nsSpamSettings::Clone(nsISpamSettings *aSpamSettings)
+{
+ NS_ENSURE_ARG_POINTER(aSpamSettings);
+
+ nsresult rv = aSpamSettings->GetUseWhiteList(&mUseWhiteList);
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ (void)aSpamSettings->GetMoveOnSpam(&mMoveOnSpam);
+ (void)aSpamSettings->GetPurge(&mPurge);
+ (void)aSpamSettings->GetUseServerFilter(&mUseServerFilter);
+
+ rv = aSpamSettings->GetPurgeInterval(&mPurgeInterval);
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ rv = aSpamSettings->GetLevel(&mLevel);
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ rv = aSpamSettings->GetMoveTargetMode(&mMoveTargetMode);
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ nsCString actionTargetAccount;
+ rv = aSpamSettings->GetActionTargetAccount(getter_Copies(actionTargetAccount));
+ NS_ENSURE_SUCCESS(rv,rv);
+ mActionTargetAccount = actionTargetAccount;
+
+ nsCString actionTargetFolder;
+ rv = aSpamSettings->GetActionTargetFolder(getter_Copies(actionTargetFolder));
+ NS_ENSURE_SUCCESS(rv,rv);
+ mActionTargetFolder = actionTargetFolder;
+
+ nsCString whiteListAbURI;
+ rv = aSpamSettings->GetWhiteListAbURI(getter_Copies(whiteListAbURI));
+ NS_ENSURE_SUCCESS(rv,rv);
+ mWhiteListAbURI = whiteListAbURI;
+
+ aSpamSettings->GetServerFilterName(mServerFilterName);
+ aSpamSettings->GetServerFilterTrustFlags(&mServerFilterTrustFlags);
+
+ return rv;
+}
+
+NS_IMETHODIMP nsSpamSettings::GetSpamFolderURI(char **aSpamFolderURI)
+{
+ NS_ENSURE_ARG_POINTER(aSpamFolderURI);
+
+ if (mMoveTargetMode == nsISpamSettings::MOVE_TARGET_MODE_FOLDER)
+ return GetActionTargetFolder(aSpamFolderURI);
+
+ // if the mode is nsISpamSettings::MOVE_TARGET_MODE_ACCOUNT
+ // the spam folder URI = account uri + "/Junk"
+ nsCString folderURI;
+ nsresult rv = GetActionTargetAccount(getter_Copies(folderURI));
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ // we might be trying to get the old spam folder uri
+ // in order to clear the flag
+ // if we didn't have one, bail out.
+ if (folderURI.IsEmpty())
+ return NS_OK;
+
+ nsCOMPtr<nsIRDFService> rdf(do_GetService("@mozilla.org/rdf/rdf-service;1", &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIRDFResource> folderResource;
+ rv = rdf->GetResource(folderURI, getter_AddRefs(folderResource));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr <nsIMsgFolder> folder = do_QueryInterface(folderResource);
+ if (!folder)
+ return NS_ERROR_UNEXPECTED;
+
+ nsCOMPtr <nsIMsgIncomingServer> server;
+ rv = folder->GetServer(getter_AddRefs(server));
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ // see nsMsgFolder::SetPrettyName() for where the pretty name is set.
+
+ // Check for an existing junk folder - this will do a case-insensitive
+ // search by URI - if we find a junk folder, use its URI.
+ nsCOMPtr<nsIMsgFolder> junkFolder;
+ folderURI.Append("/Junk");
+ if (NS_SUCCEEDED(server->GetMsgFolderFromURI(nullptr, folderURI,
+ getter_AddRefs(junkFolder))) &&
+ junkFolder)
+ junkFolder->GetURI(folderURI);
+
+ // XXX todo
+ // better not to make base depend in imap
+ // but doing it here, like in nsMsgCopy.cpp
+ // one day, we'll fix this (and nsMsgCopy.cpp) to use GetMsgFolderFromURI()
+ nsCOMPtr<nsIImapIncomingServer> imapServer = do_QueryInterface(server);
+ if (imapServer) {
+ // Make sure an specific IMAP folder has correct personal namespace
+ // see bug #197043
+ nsCString folderUriWithNamespace;
+ (void)imapServer->GetUriWithNamespacePrefixIfNecessary(kPersonalNamespace, folderURI,
+ folderUriWithNamespace);
+ if (!folderUriWithNamespace.IsEmpty())
+ folderURI = folderUriWithNamespace;
+ }
+
+ *aSpamFolderURI = ToNewCString(folderURI);
+ if (!*aSpamFolderURI)
+ return NS_ERROR_OUT_OF_MEMORY;
+ else
+ return rv;
+}
+
+NS_IMETHODIMP nsSpamSettings::GetServerFilterName(nsACString &aFilterName)
+{
+ aFilterName = mServerFilterName;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSpamSettings::SetServerFilterName(const nsACString &aFilterName)
+{
+ mServerFilterName = aFilterName;
+ mServerFilterFile = nullptr; // clear out our stored location value
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSpamSettings::GetServerFilterFile(nsIFile ** aFile)
+{
+ NS_ENSURE_ARG_POINTER(aFile);
+ if (!mServerFilterFile)
+ {
+ nsresult rv;
+ nsAutoCString serverFilterFileName;
+ GetServerFilterName(serverFilterFileName);
+ serverFilterFileName.Append(".sfd");
+
+ nsCOMPtr<nsIProperties> dirSvc = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Walk through the list of isp directories
+ nsCOMPtr<nsISimpleEnumerator> ispDirectories;
+ rv = dirSvc->Get(ISP_DIRECTORY_LIST, NS_GET_IID(nsISimpleEnumerator), getter_AddRefs(ispDirectories));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool hasMore;
+ nsCOMPtr<nsIFile> file;
+ while (NS_SUCCEEDED(ispDirectories->HasMoreElements(&hasMore)) && hasMore)
+ {
+ nsCOMPtr<nsISupports> elem;
+ ispDirectories->GetNext(getter_AddRefs(elem));
+ file = do_QueryInterface(elem);
+
+ if (file)
+ {
+ // append our desired leaf name then test to see if the file exists. If it does, we've found
+ // mServerFilterFile.
+ file->AppendNative(serverFilterFileName);
+ bool exists;
+ if (NS_SUCCEEDED(file->Exists(&exists)) && exists)
+ {
+ file.swap(mServerFilterFile);
+ break;
+ }
+ } // if file
+ } // until we find the location of mServerFilterName
+ } // if we haven't already stored mServerFilterFile
+
+ NS_IF_ADDREF(*aFile = mServerFilterFile);
+ return NS_OK;
+}
+
+
+NS_IMPL_GETSET(nsSpamSettings, ServerFilterTrustFlags, int32_t, mServerFilterTrustFlags)
+
+#define LOG_ENTRY_START_TAG "<p>\n"
+#define LOG_ENTRY_START_TAG_LEN (strlen(LOG_ENTRY_START_TAG))
+#define LOG_ENTRY_END_TAG "</p>\n"
+#define LOG_ENTRY_END_TAG_LEN (strlen(LOG_ENTRY_END_TAG))
+// Does this need to be localizable?
+#define LOG_ENTRY_TIMESTAMP "[$S] "
+
+NS_IMETHODIMP nsSpamSettings::LogJunkHit(nsIMsgDBHdr *aMsgHdr, bool aMoveMessage)
+{
+ bool loggingEnabled;
+ nsresult rv = GetLoggingEnabled(&loggingEnabled);
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ if (!loggingEnabled)
+ return NS_OK;
+
+ PRTime date;
+
+ nsString authorValue;
+ nsString subjectValue;
+ nsString dateValue;
+
+ (void)aMsgHdr->GetDate(&date);
+ PRExplodedTime exploded;
+ PR_ExplodeTime(date, PR_LocalTimeParameters, &exploded);
+
+ if (!mDateFormatter)
+ {
+ mDateFormatter = do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!mDateFormatter)
+ {
+ return NS_ERROR_FAILURE;
+ }
+ }
+ mDateFormatter->FormatPRExplodedTime(nullptr, kDateFormatShort,
+ kTimeFormatSeconds, &exploded,
+ dateValue);
+
+ (void)aMsgHdr->GetMime2DecodedAuthor(authorValue);
+ (void)aMsgHdr->GetMime2DecodedSubject(subjectValue);
+
+ nsCString buffer;
+ // this is big enough to hold a log entry.
+ // do this so we avoid growing and copying as we append to the log.
+#ifdef MOZILLA_INTERNAL_API
+ buffer.SetCapacity(512);
+#endif
+
+ nsCOMPtr<nsIStringBundleService> bundleService =
+ mozilla::services::GetStringBundleService();
+ NS_ENSURE_TRUE(bundleService, NS_ERROR_UNEXPECTED);
+
+ nsCOMPtr<nsIStringBundle> bundle;
+ rv = bundleService->CreateBundle("chrome://messenger/locale/filter.properties",
+ getter_AddRefs(bundle));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ const char16_t *junkLogDetectFormatStrings[3] = { authorValue.get(), subjectValue.get(), dateValue.get() };
+ nsString junkLogDetectStr;
+ rv = bundle->FormatStringFromName(
+ u"junkLogDetectStr",
+ junkLogDetectFormatStrings, 3,
+ getter_Copies(junkLogDetectStr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ buffer += NS_ConvertUTF16toUTF8(junkLogDetectStr);
+ buffer += "\n";
+
+ if (aMoveMessage) {
+ nsCString msgId;
+ aMsgHdr->GetMessageId(getter_Copies(msgId));
+
+ nsCString junkFolderURI;
+ rv = GetSpamFolderURI(getter_Copies(junkFolderURI));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ NS_ConvertASCIItoUTF16 msgIdValue(msgId);
+ NS_ConvertASCIItoUTF16 junkFolderURIValue(junkFolderURI);
+
+ const char16_t *logMoveFormatStrings[2] = { msgIdValue.get(), junkFolderURIValue.get() };
+ nsString logMoveStr;
+ rv = bundle->FormatStringFromName(
+ u"logMoveStr",
+ logMoveFormatStrings, 2,
+ getter_Copies(logMoveStr));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ buffer += NS_ConvertUTF16toUTF8(logMoveStr);
+ buffer += "\n";
+ }
+
+ return LogJunkString(buffer.get());
+}
+
+NS_IMETHODIMP nsSpamSettings::LogJunkString(const char *string)
+{
+ bool loggingEnabled;
+ nsresult rv = GetLoggingEnabled(&loggingEnabled);
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ if (!loggingEnabled)
+ return NS_OK;
+
+ nsString dateValue;
+ PRExplodedTime exploded;
+ PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &exploded);
+
+ if (!mDateFormatter)
+ {
+ mDateFormatter = do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!mDateFormatter)
+ {
+ return NS_ERROR_FAILURE;
+ }
+ }
+ mDateFormatter->FormatPRExplodedTime(nullptr, kDateFormatShort,
+ kTimeFormatSeconds, &exploded,
+ dateValue);
+
+ nsCString timestampString(LOG_ENTRY_TIMESTAMP);
+ MsgReplaceSubstring(timestampString, "$S", NS_ConvertUTF16toUTF8(dateValue).get());
+
+ nsCOMPtr <nsIOutputStream> logStream;
+ rv = GetLogStream(getter_AddRefs(logStream));
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ uint32_t writeCount;
+
+ rv = logStream->Write(LOG_ENTRY_START_TAG, LOG_ENTRY_START_TAG_LEN, &writeCount);
+ NS_ENSURE_SUCCESS(rv,rv);
+ NS_ASSERTION(writeCount == LOG_ENTRY_START_TAG_LEN, "failed to write out start log tag");
+
+ rv = logStream->Write(timestampString.get(), timestampString.Length(), &writeCount);
+ NS_ENSURE_SUCCESS(rv,rv);
+ NS_ASSERTION(writeCount == timestampString.Length(), "failed to write out timestamp");
+
+ // HTML-escape the log for security reasons.
+ // We don't want someone to send us a message with a subject with
+ // HTML tags, especially <script>.
+ char *escapedBuffer = MsgEscapeHTML(string);
+ if (!escapedBuffer)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ uint32_t escapedBufferLen = strlen(escapedBuffer);
+ rv = logStream->Write(escapedBuffer, escapedBufferLen, &writeCount);
+ PR_Free(escapedBuffer);
+ NS_ENSURE_SUCCESS(rv,rv);
+ NS_ASSERTION(writeCount == escapedBufferLen, "failed to write out log hit");
+
+ rv = logStream->Write(LOG_ENTRY_END_TAG, LOG_ENTRY_END_TAG_LEN, &writeCount);
+ NS_ENSURE_SUCCESS(rv,rv);
+ NS_ASSERTION(writeCount == LOG_ENTRY_END_TAG_LEN, "failed to write out end log tag");
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSpamSettings::OnStartRunningUrl(nsIURI* aURL)
+{
+ // do nothing
+ // all the action happens in OnStopRunningUrl()
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSpamSettings::OnStopRunningUrl(nsIURI* aURL, nsresult exitCode)
+{
+ nsCString junkFolderURI;
+ nsresult rv = GetSpamFolderURI(getter_Copies(junkFolderURI));
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ if (junkFolderURI.IsEmpty())
+ return NS_ERROR_UNEXPECTED;
+
+ // when we get here, the folder should exist.
+ nsCOMPtr <nsIMsgFolder> junkFolder;
+ rv = GetExistingFolder(junkFolderURI, getter_AddRefs(junkFolder));
+ NS_ENSURE_SUCCESS(rv,rv);
+ if (!junkFolder)
+ return NS_ERROR_UNEXPECTED;
+
+ rv = junkFolder->SetFlag(nsMsgFolderFlags::Junk);
+ NS_ENSURE_SUCCESS(rv,rv);
+ return rv;
+}
+
+NS_IMETHODIMP nsSpamSettings::CheckWhiteList(nsIMsgDBHdr *aMsgHdr, bool *aResult)
+{
+ NS_ENSURE_ARG_POINTER(aMsgHdr);
+ NS_ENSURE_ARG_POINTER(aResult);
+ *aResult = false; // default in case of error or no whitelisting
+
+ if (!mUseWhiteList || (!mWhiteListDirArray.Count() &&
+ mTrustedMailDomains.IsEmpty()))
+ return NS_OK;
+
+ // do per-message processing
+
+ nsCString author;
+ aMsgHdr->GetAuthor(getter_Copies(author));
+
+ nsAutoCString authorEmailAddress;
+ ExtractEmail(EncodedHeader(author), authorEmailAddress);
+
+ if (authorEmailAddress.IsEmpty())
+ return NS_OK;
+
+ // should we skip whitelisting for the identity email?
+ if (mInhibitWhiteListingIdentityUser)
+ {
+ for (uint32_t i = 0; i < mEmails.Length(); ++i)
+ {
+ if (mEmails[i].Equals(authorEmailAddress, nsCaseInsensitiveCStringComparator()))
+ return NS_OK;
+ }
+ }
+
+ if (!mTrustedMailDomains.IsEmpty() || mInhibitWhiteListingIdentityDomain)
+ {
+ nsAutoCString domain;
+ int32_t atPos = authorEmailAddress.FindChar('@');
+ if (atPos >= 0)
+ domain = Substring(authorEmailAddress, atPos + 1);
+ if (!domain.IsEmpty())
+ {
+ if (!mTrustedMailDomains.IsEmpty() &&
+ MsgHostDomainIsTrusted(domain, mTrustedMailDomains))
+ {
+ *aResult = true;
+ return NS_OK;
+ }
+
+ if (mInhibitWhiteListingIdentityDomain)
+ {
+ for (uint32_t i = 0; i < mEmails.Length(); ++i)
+ {
+ nsAutoCString identityDomain;
+ int32_t atPos = mEmails[i].FindChar('@');
+ if (atPos >= 0)
+ {
+ identityDomain = Substring(mEmails[i], atPos + 1);
+ if (identityDomain.Equals(domain, nsCaseInsensitiveCStringComparator()))
+ return NS_OK; // don't whitelist
+ }
+ }
+ }
+ }
+ }
+
+ if (mWhiteListDirArray.Count())
+ {
+ nsCOMPtr<nsIAbCard> cardForAddress;
+ for (int32_t index = 0;
+ index < mWhiteListDirArray.Count() && !cardForAddress;
+ index++)
+ {
+ mWhiteListDirArray[index]->CardForEmailAddress(authorEmailAddress,
+ getter_AddRefs(cardForAddress));
+ }
+ if (cardForAddress)
+ {
+ *aResult = true;
+ return NS_OK;
+ }
+ }
+ return NS_OK; // default return is false
+}