summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/base/src/nsSpamSettings.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mailnews/base/src/nsSpamSettings.cpp')
-rw-r--r--comm/mailnews/base/src/nsSpamSettings.cpp806
1 files changed, 806 insertions, 0 deletions
diff --git a/comm/mailnews/base/src/nsSpamSettings.cpp b/comm/mailnews/base/src/nsSpamSettings.cpp
new file mode 100644
index 0000000000..61dc1e8f43
--- /dev/null
+++ b/comm/mailnews/base/src/nsSpamSettings.cpp
@@ -0,0 +1,806 @@
+/* -*- 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 "nsAppDirectoryServiceDefs.h"
+#include "nsIPrefService.h"
+#include "nsIPrefBranch.h"
+#include "nsIStringBundle.h"
+#include "mozilla/Components.h"
+#include "mozilla/mailnews/MimeHeaderParser.h"
+#include "nsMailDirServiceDefs.h"
+#include "nsDirectoryServiceUtils.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsISimpleEnumerator.h"
+#include "nsIAbCard.h"
+#include "nsIAbManager.h"
+#include "nsIMsgAccountManager.h"
+#include "mozilla/intl/AppDateTimeFormat.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;
+ mInhibitWhiteListingIdentityUser = false;
+ mInhibitWhiteListingIdentityDomain = false;
+ mUseWhiteList = false;
+ mUseServerFilter = false;
+
+ nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
+ getter_AddRefs(mLogFile));
+ if (NS_SUCCEEDED(rv)) mLogFile->Append(u"junklog.html"_ns);
+}
+
+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(nsACString& aWhiteListAbURI) {
+ aWhiteListAbURI = mWhiteListAbURI;
+ return NS_OK;
+}
+NS_IMETHODIMP nsSpamSettings::SetWhiteListAbURI(
+ const nsACString& aWhiteListAbURI) {
+ mWhiteListAbURI = aWhiteListAbURI;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSpamSettings::GetActionTargetAccount(
+ nsACString& aActionTargetAccount) {
+ aActionTargetAccount = mActionTargetAccount;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSpamSettings::SetActionTargetAccount(
+ const nsACString& aActionTargetAccount) {
+ mActionTargetAccount = aActionTargetAccount;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSpamSettings::GetActionTargetFolder(
+ nsACString& aActionTargetFolder) {
+ aActionTargetFolder = mActionTargetFolder;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSpamSettings::SetActionTargetFolder(
+ const nsACString& 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);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsString spamActionTargetFolder;
+ rv = aServer->GetUnicharValue("spamActionTargetFolder",
+ spamActionTargetFolder);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = SetActionTargetFolder(NS_ConvertUTF16toUTF8(spamActionTargetFolder));
+ 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);
+ 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", mTrustedMailDomains);
+
+ mWhiteListDirArray.Clear();
+ if (!mWhiteListAbURI.IsEmpty()) {
+ nsCOMPtr<nsIAbManager> abManager(
+ do_GetService("@mozilla.org/abmanager;1", &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("@mozilla.org/messenger/account-manager;1", &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();
+ nsTArray<RefPtr<nsIMsgAccount>> accounts;
+ // No sense scanning accounts if we've nothing to match.
+ if (account) {
+ rv = accountManager->GetAccounts(accounts);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ for (auto loopAccount : accounts) {
+ 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)) {
+ nsTArray<RefPtr<nsIMsgIdentity>> identities;
+ loopAccount->GetIdentities(identities);
+ for (auto identity : identities) {
+ 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(newJunkFolderURI);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!mCurrentJunkFolderURI.IsEmpty() &&
+ !mCurrentJunkFolderURI.Equals(newJunkFolderURI)) {
+ nsCOMPtr<nsIMsgFolder> oldJunkFolder;
+ rv = FindFolder(mCurrentJunkFolderURI, getter_AddRefs(oldJunkFolder));
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (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 = GetOrCreateJunkFolder(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(actionTargetAccount);
+ NS_ENSURE_SUCCESS(rv, rv);
+ mActionTargetAccount = actionTargetAccount;
+
+ nsCString actionTargetFolder;
+ rv = aSpamSettings->GetActionTargetFolder(actionTargetFolder);
+ NS_ENSURE_SUCCESS(rv, rv);
+ mActionTargetFolder = actionTargetFolder;
+
+ nsCString whiteListAbURI;
+ rv = aSpamSettings->GetWhiteListAbURI(whiteListAbURI);
+ NS_ENSURE_SUCCESS(rv, rv);
+ mWhiteListAbURI = whiteListAbURI;
+
+ aSpamSettings->GetServerFilterName(mServerFilterName);
+ aSpamSettings->GetServerFilterTrustFlags(&mServerFilterTrustFlags);
+
+ return rv;
+}
+
+NS_IMETHODIMP nsSpamSettings::GetSpamFolderURI(nsACString& 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(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<nsIMsgFolder> folder;
+ rv = GetOrCreateFolder(folderURI, getter_AddRefs(folder));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ 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.AppendLiteral("/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 = folderURI;
+ return NS_OK;
+}
+
+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.AppendLiteral(".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);
+
+ mozilla::intl::DateTimeFormat::StyleBag style;
+ style.date = mozilla::Some(mozilla::intl::DateTimeFormat::Style::Short);
+ style.time = mozilla::Some(mozilla::intl::DateTimeFormat::Style::Long);
+ mozilla::intl::AppDateTimeFormat::Format(style, &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.
+ buffer.SetCapacity(512);
+
+ nsCOMPtr<nsIStringBundleService> bundleService =
+ mozilla::components::StringBundle::Service();
+ 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);
+
+ AutoTArray<nsString, 3> junkLogDetectFormatStrings = {
+ authorValue, subjectValue, dateValue};
+ nsString junkLogDetectStr;
+ rv = bundle->FormatStringFromName(
+ "junkLogDetectStr", junkLogDetectFormatStrings, 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(junkFolderURI);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ AutoTArray<nsString, 2> logMoveFormatStrings;
+ CopyASCIItoUTF16(msgId, *logMoveFormatStrings.AppendElement());
+ CopyASCIItoUTF16(junkFolderURI, *logMoveFormatStrings.AppendElement());
+ nsString logMoveStr;
+ rv = bundle->FormatStringFromName("logMoveStr", logMoveFormatStrings,
+ 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);
+
+ mozilla::intl::DateTimeFormat::StyleBag style;
+ style.date = mozilla::Some(mozilla::intl::DateTimeFormat::Style::Short);
+ style.time = mozilla::Some(mozilla::intl::DateTimeFormat::Style::Long);
+ mozilla::intl::AppDateTimeFormat::Format(style, &exploded, dateValue);
+
+ nsCString timestampString(LOG_ENTRY_TIMESTAMP);
+ timestampString.ReplaceSubstring("$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>.
+ nsCString escapedBuffer;
+ nsAppendEscapedHTML(nsDependentCString(string), escapedBuffer);
+
+ uint32_t escapedBufferLen = escapedBuffer.Length();
+ rv = logStream->Write(escapedBuffer.get(), escapedBufferLen, &writeCount);
+ 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(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);
+
+ 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
+}