mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-21 15:57:31 +09:00
772 lines
23 KiB
C++
772 lines
23 KiB
C++
|
|
/* -*- 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;
|
||
|
|
}
|