diff options
Diffstat (limited to 'mailnews/compose/src/nsSmtpService.cpp')
-rw-r--r-- | mailnews/compose/src/nsSmtpService.cpp | 772 |
1 files changed, 772 insertions, 0 deletions
diff --git a/mailnews/compose/src/nsSmtpService.cpp b/mailnews/compose/src/nsSmtpService.cpp new file mode 100644 index 000000000..9f9295934 --- /dev/null +++ b/mailnews/compose/src/nsSmtpService.cpp @@ -0,0 +1,772 @@ +/* -*- 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 "msgCore.h" // precompiled header... +#include "nsIPrefService.h" +#include "nsIPrefBranch.h" +#include "nsIIOService.h" +#include "nsIPipe.h" +#include "nsNetCID.h" +#include "nsMsgUtils.h" +#include "nsNetUtil.h" +#include "nsSmtpService.h" +#include "nsMsgBaseCID.h" +#include "nsMsgCompCID.h" +#include "nsArrayEnumerator.h" +#include "nsSmtpUrl.h" +#include "nsSmtpProtocol.h" +#include "nsCOMPtr.h" +#include "nsIMsgIdentity.h" +#include "nsIPrompt.h" +#include "nsIWindowWatcher.h" +#include "nsIUTF8ConverterService.h" +#include "nsUConvCID.h" +#include "nsAutoPtr.h" +#include "nsComposeStrings.h" +#include "nsIAsyncInputStream.h" +#include "nsIPrincipal.h" + +#define SERVER_DELIMITER ',' +#define APPEND_SERVERS_VERSION_PREF_NAME "append_preconfig_smtpservers.version" +#define MAIL_ROOT_PREF "mail." +#define PREF_MAIL_SMTPSERVERS "mail.smtpservers" +#define PREF_MAIL_SMTPSERVERS_APPEND_SERVERS "mail.smtpservers.appendsmtpservers" +#define PREF_MAIL_SMTP_DEFAULTSERVER "mail.smtp.defaultserver" + +typedef struct _findServerByKeyEntry { + const char *key; + nsISmtpServer *server; +} findServerByKeyEntry; + +typedef struct _findServerByHostnameEntry { + nsCString hostname; + nsCString username; + nsISmtpServer *server; +} findServerByHostnameEntry; + +static NS_DEFINE_CID(kCSmtpUrlCID, NS_SMTPURL_CID); +static NS_DEFINE_CID(kCMailtoUrlCID, NS_MAILTOURL_CID); + +// foward declarations... +nsresult +NS_MsgBuildSmtpUrl(nsIFile * aFilePath, + nsISmtpServer *aServer, + const char* aRecipients, + nsIMsgIdentity * aSenderIdentity, + nsIUrlListener * aUrlListener, + nsIMsgStatusFeedback *aStatusFeedback, + nsIInterfaceRequestor* aNotificationCallbacks, + nsIURI ** aUrl, + bool aRequestDSN); + +nsresult NS_MsgLoadSmtpUrl(nsIURI * aUrl, nsISupports * aConsumer, nsIRequest ** aRequest); + +nsSmtpService::nsSmtpService() : + mSmtpServersLoaded(false) +{ +} + +nsSmtpService::~nsSmtpService() +{ + // save the SMTP servers to disk + +} + +NS_IMPL_ISUPPORTS(nsSmtpService, nsISmtpService, nsIProtocolHandler) + + +NS_IMETHODIMP nsSmtpService::SendMailMessage(nsIFile * aFilePath, + const char * aRecipients, + nsIMsgIdentity * aSenderIdentity, + const char * aPassword, + nsIUrlListener * aUrlListener, + nsIMsgStatusFeedback *aStatusFeedback, + nsIInterfaceRequestor* aNotificationCallbacks, + bool aRequestDSN, + nsIURI ** aURL, + nsIRequest ** aRequest) +{ + nsIURI * urlToRun = nullptr; + nsresult rv = NS_OK; + + nsCOMPtr<nsISmtpServer> smtpServer; + rv = GetServerByIdentity(aSenderIdentity, getter_AddRefs(smtpServer)); + + if (NS_SUCCEEDED(rv) && smtpServer) + { + if (aPassword && *aPassword) + smtpServer->SetPassword(nsDependentCString(aPassword)); + + // this ref counts urlToRun + rv = NS_MsgBuildSmtpUrl(aFilePath, smtpServer, aRecipients, aSenderIdentity, + aUrlListener, aStatusFeedback, + aNotificationCallbacks, &urlToRun, aRequestDSN); + if (NS_SUCCEEDED(rv) && urlToRun) + rv = NS_MsgLoadSmtpUrl(urlToRun, nullptr, aRequest); + + if (aURL) // does the caller want a handle on the url? + *aURL = urlToRun; // transfer our ref count to the caller.... + else + NS_IF_RELEASE(urlToRun); + } + + return rv; +} + + +// The following are two convience functions I'm using to help expedite building and running a mail to url... + +// short cut function for creating a mailto url... +nsresult NS_MsgBuildSmtpUrl(nsIFile * aFilePath, + nsISmtpServer *aSmtpServer, + const char * aRecipients, + nsIMsgIdentity * aSenderIdentity, + nsIUrlListener * aUrlListener, + nsIMsgStatusFeedback *aStatusFeedback, + nsIInterfaceRequestor* aNotificationCallbacks, + nsIURI ** aUrl, + bool aRequestDSN) +{ + // mscott: this function is a convience hack until netlib actually dispatches + // smtp urls. in addition until we have a session to get a password, host and + // other stuff from, we need to use default values.... + // ..for testing purposes.... + + nsCString smtpHostName; + nsCString smtpUserName; + int32_t smtpPort; + int32_t socketType; + + aSmtpServer->GetHostname(smtpHostName); + aSmtpServer->GetUsername(smtpUserName); + aSmtpServer->GetPort(&smtpPort); + aSmtpServer->GetSocketType(&socketType); + + if (!smtpPort) + smtpPort = (socketType == nsMsgSocketType::SSL) ? + nsISmtpUrl::DEFAULT_SMTPS_PORT : nsISmtpUrl::DEFAULT_SMTP_PORT; + + nsresult rv; + nsCOMPtr<nsISmtpUrl> smtpUrl(do_CreateInstance(kCSmtpUrlCID, &rv)); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoCString urlSpec("smtp://"); + + if (!smtpUserName.IsEmpty()) + { + nsCString escapedUsername; + MsgEscapeString(smtpUserName, nsINetUtil::ESCAPE_XALPHAS, + escapedUsername); + urlSpec.Append(escapedUsername); + urlSpec.Append('@'); + } + + urlSpec.Append(smtpHostName); + if (smtpHostName.FindChar(':') == -1) + { + urlSpec.Append(':'); + urlSpec.AppendInt(smtpPort); + } + + nsCOMPtr<nsIMsgMailNewsUrl> url(do_QueryInterface(smtpUrl, &rv)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = url->SetSpec(urlSpec); + NS_ENSURE_SUCCESS(rv, rv); + + smtpUrl->SetRecipients(aRecipients); + smtpUrl->SetRequestDSN(aRequestDSN); + smtpUrl->SetPostMessageFile(aFilePath); + smtpUrl->SetSenderIdentity(aSenderIdentity); + if (aNotificationCallbacks) + smtpUrl->SetNotificationCallbacks(aNotificationCallbacks); + smtpUrl->SetSmtpServer(aSmtpServer); + + nsCOMPtr<nsIPrompt> smtpPrompt(do_GetInterface(aNotificationCallbacks)); + nsCOMPtr<nsIAuthPrompt> smtpAuthPrompt(do_GetInterface(aNotificationCallbacks)); + if (!smtpPrompt || !smtpAuthPrompt) + { + nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv)); + NS_ENSURE_SUCCESS(rv, rv); + + if (!smtpPrompt) + wwatch->GetNewPrompter(0, getter_AddRefs(smtpPrompt)); + if (!smtpAuthPrompt) + wwatch->GetNewAuthPrompter(0, getter_AddRefs(smtpAuthPrompt)); + } + + smtpUrl->SetPrompt(smtpPrompt); + smtpUrl->SetAuthPrompt(smtpAuthPrompt); + + if (aUrlListener) + url->RegisterListener(aUrlListener); + if (aStatusFeedback) + url->SetStatusFeedback(aStatusFeedback); + + return CallQueryInterface(smtpUrl, aUrl); +} + +nsresult NS_MsgLoadSmtpUrl(nsIURI * aUrl, nsISupports * aConsumer, nsIRequest ** aRequest) +{ + NS_ENSURE_ARG_POINTER(aUrl); + + // For now, assume the url is an smtp url and load it. + nsresult rv; + nsCOMPtr<nsISmtpUrl> smtpUrl(do_QueryInterface(aUrl, &rv)); + NS_ENSURE_SUCCESS(rv, rv); + + // Create a smtp protocol instance to run the url in. + RefPtr<nsSmtpProtocol> smtpProtocol = new nsSmtpProtocol(aUrl); + if (!smtpProtocol) + return NS_ERROR_OUT_OF_MEMORY; + + // Protocol will get destroyed when url is completed. + rv = smtpProtocol->LoadUrl(aUrl, aConsumer); + NS_ENSURE_SUCCESS(rv, rv); + + return CallQueryInterface(smtpProtocol.get(), aRequest); +} + +NS_IMETHODIMP nsSmtpService::VerifyLogon(nsISmtpServer *aServer, + nsIUrlListener *aUrlListener, + nsIMsgWindow *aMsgWindow, + nsIURI **aURL) +{ + NS_ENSURE_ARG_POINTER(aServer); + nsCString popHost; + nsCString popUser; + nsCOMPtr <nsIURI> urlToRun; + + nsresult rv = NS_MsgBuildSmtpUrl(nullptr, aServer, + nullptr, nullptr, aUrlListener, nullptr, + nullptr , getter_AddRefs(urlToRun), false); + if (NS_SUCCEEDED(rv) && urlToRun) + { + nsCOMPtr<nsIMsgMailNewsUrl> url(do_QueryInterface(urlToRun, &rv)); + NS_ENSURE_SUCCESS(rv, rv); + url->SetMsgWindow(aMsgWindow); + rv = NS_MsgLoadSmtpUrl(urlToRun, nullptr, nullptr /* aRequest */); + if (aURL) + urlToRun.forget(aURL); + } + return rv; +} + +NS_IMETHODIMP nsSmtpService::GetScheme(nsACString &aScheme) +{ + aScheme = "mailto"; + return NS_OK; +} + +NS_IMETHODIMP nsSmtpService::GetDefaultPort(int32_t *aDefaultPort) +{ + nsresult rv = NS_OK; + if (aDefaultPort) + *aDefaultPort = nsISmtpUrl::DEFAULT_SMTP_PORT; + else + rv = NS_ERROR_NULL_POINTER; + return rv; +} + +NS_IMETHODIMP +nsSmtpService::AllowPort(int32_t port, const char *scheme, bool *_retval) +{ + // allow smtp to run on any port + *_retval = true; + return NS_OK; +} + +NS_IMETHODIMP nsSmtpService::GetProtocolFlags(uint32_t *result) +{ + *result = URI_NORELATIVE | ALLOWS_PROXY | URI_LOADABLE_BY_ANYONE | + URI_NON_PERSISTABLE | URI_DOES_NOT_RETURN_DATA | + URI_FORBIDS_COOKIE_ACCESS; + return NS_OK; +} + +// the smtp service is also the protocol handler for mailto urls.... + +NS_IMETHODIMP nsSmtpService::NewURI(const nsACString &aSpec, + const char *aOriginCharset, + nsIURI *aBaseURI, + nsIURI **_retval) +{ + // get a new smtp url + nsresult rv; + nsCOMPtr<nsIURI> mailtoUrl = do_CreateInstance(kCMailtoUrlCID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoCString utf8Spec; + if (aOriginCharset) + { + nsCOMPtr<nsIUTF8ConverterService> + utf8Converter(do_GetService(NS_UTF8CONVERTERSERVICE_CONTRACTID, &rv)); + if (NS_SUCCEEDED(rv)) + rv = utf8Converter->ConvertURISpecToUTF8(aSpec, aOriginCharset, utf8Spec); + } + + // utf8Spec is filled up only when aOriginCharset is specified and + // the conversion is successful. Otherwise, fall back to aSpec. + if (aOriginCharset && NS_SUCCEEDED(rv)) + rv = mailtoUrl->SetSpec(utf8Spec); + else + rv = mailtoUrl->SetSpec(aSpec); + NS_ENSURE_SUCCESS(rv, rv); + + mailtoUrl.forget(_retval); + return NS_OK; +} + +NS_IMETHODIMP nsSmtpService::NewChannel(nsIURI *aURI, nsIChannel **_retval) +{ + return NewChannel2(aURI, nullptr, _retval); +} + +NS_IMETHODIMP nsSmtpService::NewChannel2(nsIURI *aURI, + nsILoadInfo* aLoadInfo, + nsIChannel **_retval) +{ + NS_ENSURE_ARG_POINTER(aURI); + // create an empty pipe for use with the input stream channel. + nsCOMPtr<nsIAsyncInputStream> pipeIn; + nsCOMPtr<nsIAsyncOutputStream> pipeOut; + nsCOMPtr<nsIPipe> pipe = do_CreateInstance("@mozilla.org/pipe;1"); + nsresult rv = pipe->Init(false, false, 0, 0); + NS_ENSURE_SUCCESS(rv, rv); + + // These always succeed because the pipe is initialized above. + MOZ_ALWAYS_SUCCEEDS(pipe->GetInputStream(getter_AddRefs(pipeIn))); + MOZ_ALWAYS_SUCCEEDS(pipe->GetOutputStream(getter_AddRefs(pipeOut))); + + pipeOut->Close(); + + if (aLoadInfo) { + return NS_NewInputStreamChannelInternal(_retval, + aURI, + pipeIn, + NS_LITERAL_CSTRING("application/x-mailto"), + EmptyCString(), + aLoadInfo); + } + + nsCOMPtr<nsIPrincipal> nullPrincipal = + do_CreateInstance("@mozilla.org/nullprincipal;1", &rv); + NS_ASSERTION(NS_SUCCEEDED(rv), "CreateInstance of nullprincipal failed."); + if (NS_FAILED(rv)) + return rv; + + return NS_NewInputStreamChannel(_retval, aURI, pipeIn, + nullPrincipal, nsILoadInfo::SEC_NORMAL, + nsIContentPolicy::TYPE_OTHER, + NS_LITERAL_CSTRING("application/x-mailto")); +} + +NS_IMETHODIMP +nsSmtpService::GetServers(nsISimpleEnumerator **aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + + // now read in the servers from prefs if necessary + uint32_t serverCount = mSmtpServers.Count(); + + if (serverCount <= 0) + loadSmtpServers(); + + return NS_NewArrayEnumerator(aResult, mSmtpServers); +} + +nsresult +nsSmtpService::loadSmtpServers() +{ + if (mSmtpServersLoaded) + return NS_OK; + + nsresult rv; + nsCOMPtr<nsIPrefService> prefService(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv)); + if (NS_FAILED(rv)) + return rv; + nsCOMPtr<nsIPrefBranch> prefRootBranch; + prefService->GetBranch(nullptr, getter_AddRefs(prefRootBranch)); + if (NS_FAILED(rv)) + return rv; + + nsCString serverList; + rv = prefRootBranch->GetCharPref(PREF_MAIL_SMTPSERVERS, getter_Copies(serverList)); + serverList.StripWhitespace(); + + nsTArray<nsCString> servers; + ParseString(serverList, SERVER_DELIMITER, servers); + + /** + * Check to see if we need to add pre-configured smtp servers. + * Following prefs are important to note in understanding the procedure here. + * + * 1. pref("mailnews.append_preconfig_smtpservers.version", version number); + * This pref registers the current version in the user prefs file. A default value + * is stored in mailnews.js file. If a given vendor needs to add more preconfigured + * smtp servers, the default version number can be increased. Comparing version + * number from user's prefs file and the default one from mailnews.js, we + * can add new smtp servers and any other version level changes that need to be done. + * + * 2. pref("mail.smtpservers.appendsmtpservers", <comma separated servers list>); + * This pref contains the list of pre-configured smp servers that ISP/Vendor wants to + * to add to the existing servers list. + */ + nsCOMPtr<nsIPrefBranch> defaultsPrefBranch; + rv = prefService->GetDefaultBranch(MAIL_ROOT_PREF, getter_AddRefs(defaultsPrefBranch)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr<nsIPrefBranch> prefBranch; + rv = prefService->GetBranch(MAIL_ROOT_PREF, getter_AddRefs(prefBranch)); + NS_ENSURE_SUCCESS(rv,rv); + + int32_t appendSmtpServersCurrentVersion = 0; + int32_t appendSmtpServersDefaultVersion = 0; + rv = prefBranch->GetIntPref(APPEND_SERVERS_VERSION_PREF_NAME, &appendSmtpServersCurrentVersion); + NS_ENSURE_SUCCESS(rv,rv); + + rv = defaultsPrefBranch->GetIntPref(APPEND_SERVERS_VERSION_PREF_NAME, &appendSmtpServersDefaultVersion); + NS_ENSURE_SUCCESS(rv,rv); + + // Update the smtp server list if needed + if (appendSmtpServersCurrentVersion <= appendSmtpServersDefaultVersion) { + // If there are pre-configured servers, add them to the existing server list + nsCString appendServerList; + rv = prefRootBranch->GetCharPref(PREF_MAIL_SMTPSERVERS_APPEND_SERVERS, getter_Copies(appendServerList)); + appendServerList.StripWhitespace(); + ParseString(appendServerList, SERVER_DELIMITER, servers); + + // Increase the version number so that updates will happen as and when needed + prefBranch->SetIntPref(APPEND_SERVERS_VERSION_PREF_NAME, appendSmtpServersCurrentVersion + 1); + } + + // use GetServerByKey to check if the key (pref) is already in + // in the list. If not it calls createKeyedServer directly. + + for (uint32_t i = 0; i < servers.Length(); i++) { + nsCOMPtr<nsISmtpServer> server; + GetServerByKey(servers[i].get(), getter_AddRefs(server)); + } + + saveKeyList(); + + mSmtpServersLoaded = true; + return NS_OK; +} + +// save the list of keys +nsresult +nsSmtpService::saveKeyList() +{ + nsresult rv; + nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv)); + if (NS_FAILED(rv)) return rv; + + return prefBranch->SetCharPref(PREF_MAIL_SMTPSERVERS, mServerKeyList.get()); +} + +nsresult +nsSmtpService::createKeyedServer(const char *key, nsISmtpServer** aResult) +{ + if (!key) return NS_ERROR_NULL_POINTER; + + nsresult rv; + nsCOMPtr<nsISmtpServer> server = do_CreateInstance(NS_SMTPSERVER_CONTRACTID, &rv); + if (NS_FAILED(rv)) return rv; + + server->SetKey(key); + mSmtpServers.AppendObject(server); + + if (mServerKeyList.IsEmpty()) + mServerKeyList = key; + else { + mServerKeyList.Append(','); + mServerKeyList += key; + } + + if (aResult) + server.swap(*aResult); + + return NS_OK; +} + +NS_IMETHODIMP +nsSmtpService::GetSessionDefaultServer(nsISmtpServer **aServer) +{ + NS_ENSURE_ARG_POINTER(aServer); + + if (!mSessionDefaultServer) + return GetDefaultServer(aServer); + + NS_ADDREF(*aServer = mSessionDefaultServer); + return NS_OK; +} + +NS_IMETHODIMP +nsSmtpService::SetSessionDefaultServer(nsISmtpServer *aServer) +{ + mSessionDefaultServer = aServer; + return NS_OK; +} + +NS_IMETHODIMP +nsSmtpService::GetDefaultServer(nsISmtpServer **aServer) +{ + NS_ENSURE_ARG_POINTER(aServer); + + loadSmtpServers(); + + *aServer = nullptr; + // always returns NS_OK, just leaving *aServer at nullptr + if (!mDefaultSmtpServer) { + nsresult rv; + nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv)); + if (NS_FAILED(rv)) return rv; + + // try to get it from the prefs + nsCString defaultServerKey; + rv = prefBranch->GetCharPref(PREF_MAIL_SMTP_DEFAULTSERVER, getter_Copies(defaultServerKey)); + if (NS_SUCCEEDED(rv) && + !defaultServerKey.IsEmpty()) { + + nsCOMPtr<nsISmtpServer> server; + rv = GetServerByKey(defaultServerKey.get(), + getter_AddRefs(mDefaultSmtpServer)); + } else { + // no pref set, so just return the first one, and set the pref + + // Ensure the list of servers is loaded + loadSmtpServers(); + + // nothing in the array, we had better create a new server + // (which will add it to the array & prefs anyway) + if (mSmtpServers.Count() == 0) + // if there are no smtp servers then don't create one for the default. + return NS_OK; + + mDefaultSmtpServer = mSmtpServers[0]; + NS_ENSURE_TRUE(mDefaultSmtpServer, NS_ERROR_NULL_POINTER); + + // now we have a default server, set the prefs correctly + nsCString serverKey; + mDefaultSmtpServer->GetKey(getter_Copies(serverKey)); + if (NS_SUCCEEDED(rv)) + prefBranch->SetCharPref(PREF_MAIL_SMTP_DEFAULTSERVER, serverKey.get()); + } + } + + // at this point: + // * mDefaultSmtpServer has a valid server + // * the key has been set in the prefs + + NS_IF_ADDREF(*aServer = mDefaultSmtpServer); + + return NS_OK; +} + +NS_IMETHODIMP +nsSmtpService::SetDefaultServer(nsISmtpServer *aServer) +{ + NS_ENSURE_ARG_POINTER(aServer); + + mDefaultSmtpServer = aServer; + + nsCString serverKey; + nsresult rv = aServer->GetKey(getter_Copies(serverKey)); + NS_ENSURE_SUCCESS(rv,rv); + + nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv)); + NS_ENSURE_SUCCESS(rv,rv); + prefBranch->SetCharPref(PREF_MAIL_SMTP_DEFAULTSERVER, serverKey.get()); + return NS_OK; +} + +bool +nsSmtpService::findServerByKey(nsISmtpServer *aServer, void *aData) +{ + findServerByKeyEntry *entry = (findServerByKeyEntry*) aData; + + nsCString key; + nsresult rv = aServer->GetKey(getter_Copies(key)); + if (NS_FAILED(rv)) + return true; + + if (key.Equals(entry->key)) + { + entry->server = aServer; + return false; + } + + return true; +} + +NS_IMETHODIMP +nsSmtpService::CreateServer(nsISmtpServer **aResult) +{ + if (!aResult) return NS_ERROR_NULL_POINTER; + + loadSmtpServers(); + nsresult rv; + int32_t i = 0; + bool unique = false; + + findServerByKeyEntry entry; + nsAutoCString key; + + do { + key = "smtp"; + key.AppendInt(++i); + entry.key = key.get(); + entry.server = nullptr; + + mSmtpServers.EnumerateForwards(findServerByKey, (void *)&entry); + if (!entry.server) unique=true; + + } while (!unique); + + rv = createKeyedServer(key.get(), aResult); + NS_ENSURE_SUCCESS(rv, rv); + return saveKeyList(); +} + + +nsresult +nsSmtpService::GetServerByKey(const char* aKey, nsISmtpServer **aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + + if (!aKey || !*aKey) + { + NS_ASSERTION(false, "bad key"); + return NS_ERROR_FAILURE; + } + findServerByKeyEntry entry; + entry.key = aKey; + entry.server = nullptr; + mSmtpServers.EnumerateForwards(findServerByKey, (void *)&entry); + + if (entry.server) { + NS_ADDREF(*aResult = entry.server); + return NS_OK; + } + + // not found in array, I guess we load it + return createKeyedServer(aKey, aResult); +} + +NS_IMETHODIMP +nsSmtpService::DeleteServer(nsISmtpServer *aServer) +{ + if (!aServer) return NS_OK; + + int32_t idx = mSmtpServers.IndexOf(aServer); + if (idx == -1) + return NS_OK; + + nsCString serverKey; + aServer->GetKey(getter_Copies(serverKey)); + + mSmtpServers.RemoveObjectAt(idx); + + if (mDefaultSmtpServer.get() == aServer) + mDefaultSmtpServer = nullptr; + if (mSessionDefaultServer.get() == aServer) + mSessionDefaultServer = nullptr; + + nsAutoCString newServerList; + nsCString tmpStr = mServerKeyList; + char *newStr = tmpStr.BeginWriting(); + char *token = NS_strtok(",", &newStr); + while (token) { + // only re-add the string if it's not the key + if (strcmp(token, serverKey.get()) != 0) { + if (newServerList.IsEmpty()) + newServerList = token; + else { + newServerList += ','; + newServerList += token; + } + } + token = NS_strtok(",", &newStr); + } + + // make sure the server clears out it's values.... + aServer->ClearAllValues(); + + mServerKeyList = newServerList; + saveKeyList(); + return NS_OK; +} + +bool +nsSmtpService::findServerByHostname(nsISmtpServer *aServer, void *aData) +{ + findServerByHostnameEntry *entry = (findServerByHostnameEntry*)aData; + + nsCString hostname; + nsresult rv = aServer->GetHostname(hostname); + if (NS_FAILED(rv)) + return true; + + nsCString username; + rv = aServer->GetUsername(username); + if (NS_FAILED(rv)) + return true; + + bool checkHostname = !entry->hostname.IsEmpty(); + bool checkUsername = !entry->username.IsEmpty(); + + if ((!checkHostname || + (entry->hostname.Equals(hostname, nsCaseInsensitiveCStringComparator()))) && + (!checkUsername || + entry->username.Equals(username, nsCaseInsensitiveCStringComparator()))) + { + entry->server = aServer; + return false; // stop when found + } + return true; +} + +NS_IMETHODIMP +nsSmtpService::FindServer(const char *aUsername, + const char *aHostname, nsISmtpServer ** aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + + findServerByHostnameEntry entry; + entry.server = nullptr; + entry.hostname = aHostname; + entry.username = aUsername; + + mSmtpServers.EnumerateForwards(findServerByHostname, (void *)&entry); + + // entry.server may be null, but that's ok. + // just return null if no server is found + NS_IF_ADDREF(*aResult = entry.server); + + return NS_OK; +} + +NS_IMETHODIMP +nsSmtpService::GetServerByIdentity(nsIMsgIdentity *aSenderIdentity, + nsISmtpServer **aSmtpServer) +{ + NS_ENSURE_ARG_POINTER(aSmtpServer); + nsresult rv = NS_ERROR_FAILURE; + + // First try the identity's preferred server + if (aSenderIdentity) + { + nsCString smtpServerKey; + rv = aSenderIdentity->GetSmtpServerKey(smtpServerKey); + if (NS_SUCCEEDED(rv) && !(smtpServerKey.IsEmpty())) + rv = GetServerByKey(smtpServerKey.get(), aSmtpServer); + } + + // Fallback to the default + if (NS_FAILED(rv) || !(*aSmtpServer)) + rv = GetDefaultServer(aSmtpServer); + return rv; +} |