/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* 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 "prmem.h" #include "plstr.h" #include "prprf.h" #include "nsCOMPtr.h" #include "nsIStringBundle.h" #include "nsIPop3IncomingServer.h" #include "nsPop3IncomingServer.h" #include "nsIPop3Service.h" #include "nsMsgBaseCID.h" #include "nsMsgLocalCID.h" #include "nsMsgFolderFlags.h" #include "nsPop3Protocol.h" #include "nsAutoPtr.h" #include "nsMsgKeyArray.h" #include "nsIMsgLocalMailFolder.h" #include "nsIMsgAccountManager.h" #include "nsIMsgMailNewsUrl.h" #include "nsServiceManagerUtils.h" #include "nsIMutableArray.h" #include "nsMsgUtils.h" #include "nsComponentManagerUtils.h" #include "mozilla/Likely.h" static NS_DEFINE_CID(kCPop3ServiceCID, NS_POP3SERVICE_CID); class nsPop3GetMailChainer final : public nsIUrlListener { public: NS_DECL_ISUPPORTS NS_DECL_NSIURLLISTENER nsPop3GetMailChainer(); nsresult GetNewMailForServers(nsIPop3IncomingServer** servers, uint32_t count, nsIMsgWindow *msgWindow, nsIMsgFolder *folderToDownloadTo, nsIUrlListener *listener); nsresult RunNextGetNewMail(); protected: ~nsPop3GetMailChainer(); nsCOMPtr m_folderToDownloadTo; nsCOMPtr m_downloadingMsgWindow; nsCOMArray m_serversToGetNewMailFor; nsCOMPtr m_listener; }; NS_IMPL_ISUPPORTS_INHERITED(nsPop3IncomingServer, nsMsgIncomingServer, nsIPop3IncomingServer, nsILocalMailIncomingServer) nsPop3IncomingServer::nsPop3IncomingServer() { m_capabilityFlags = POP3_AUTH_MECH_UNDEFINED | POP3_HAS_AUTH_USER | // should be always there POP3_GURL_UNDEFINED | POP3_UIDL_UNDEFINED | POP3_TOP_UNDEFINED | POP3_XTND_XLST_UNDEFINED; m_canHaveFilters = true; m_authenticated = false; } nsPop3IncomingServer::~nsPop3IncomingServer() { } NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingServer, LeaveMessagesOnServer, "leave_on_server") NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingServer, HeadersOnly, "headers_only") NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingServer, DeleteMailLeftOnServer, "delete_mail_left_on_server") NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingServer, DotFix, "dot_fix") NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingServer, DeleteByAgeFromServer, "delete_by_age_from_server") NS_IMPL_SERVERPREF_INT(nsPop3IncomingServer, NumDaysToLeaveOnServer, "num_days_to_leave_on_server") NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingServer, DeferGetNewMail, "defer_get_new_mail") NS_IMETHODIMP nsPop3IncomingServer::GetDeferredToAccount(nsACString& aRetVal) { nsresult rv = GetCharValue("deferred_to_account", aRetVal); if (aRetVal.IsEmpty()) return rv; // We need to repair broken profiles that defer to hidden or invalid servers, // so find out if the deferred to account has a valid non-hidden server, and // if not, defer to the local folders inbox. nsCOMPtr acctMgr = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID); bool invalidAccount = true; if (acctMgr) { nsCOMPtr account; nsCOMPtr server; rv = acctMgr->GetAccount(aRetVal, getter_AddRefs(account)); if (account) { account->GetIncomingServer(getter_AddRefs(server)); if (server) server->GetHidden(&invalidAccount); } if (invalidAccount) { nsCOMPtr localServer; nsCOMPtr localAccount; rv = acctMgr->GetLocalFoldersServer(getter_AddRefs(localServer)); NS_ENSURE_SUCCESS(rv, rv); // Try to copy any folders that have been stranded in the hidden account // into the local folders account. if (server) { nsCOMPtr hiddenRootFolder; nsCOMPtr localFoldersRoot; server->GetRootFolder(getter_AddRefs(hiddenRootFolder)); localServer->GetRootFolder(getter_AddRefs(localFoldersRoot)); if (hiddenRootFolder && localFoldersRoot) { // We're going to iterate over the folders in Local Folders-1, // though I suspect only the Inbox will have messages. I don't // think Sent Mail could end up here, but if any folders have // messages, might as well copy them to the real Local Folders // account. nsCOMPtr enumerator; rv = hiddenRootFolder->GetSubFolders(getter_AddRefs(enumerator)); if (NS_SUCCEEDED(rv)) { bool hasMore; while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore) { nsCOMPtr item; enumerator->GetNext(getter_AddRefs(item)); nsCOMPtr subFolder(do_QueryInterface(item)); if (subFolder) { nsCOMPtr subFolderDB; subFolder->GetMsgDatabase(getter_AddRefs(subFolderDB)); if (subFolderDB) { // Copy any messages in this sub-folder of the hidden // account to the corresponding folder in Local Folders. RefPtr keys = new nsMsgKeyArray; rv = subFolderDB->ListAllKeys(keys); nsCOMPtr hdrsToCopy(do_CreateInstance(NS_ARRAY_CONTRACTID)); MsgGetHeadersFromKeys(subFolderDB, keys->m_keys, hdrsToCopy); uint32_t numHdrs = 0; if (hdrsToCopy) hdrsToCopy->GetLength(&numHdrs); if (numHdrs) { // Look for a folder with the same name in Local Folders. nsCOMPtr dest; nsString folderName; subFolder->GetName(folderName); localFoldersRoot->GetChildNamed(folderName, getter_AddRefs(dest)); if (dest) dest->CopyMessages(subFolder, hdrsToCopy, false, nullptr, nullptr, false,false); // Should we copy the folder if the dest doesn't exist? } } } } } } } rv = acctMgr->FindAccountForServer(localServer, getter_AddRefs(localAccount)); NS_ENSURE_SUCCESS(rv, rv); if (!localAccount) return NS_ERROR_NOT_AVAILABLE; localAccount->GetKey(aRetVal); // Can't call SetDeferredToAccount because it calls GetDeferredToAccount. return SetCharValue("deferred_to_account", aRetVal); } } return rv; } NS_IMETHODIMP nsPop3IncomingServer::SetDeferredToAccount(const nsACString& aAccountKey) { nsCString deferredToAccount; GetDeferredToAccount(deferredToAccount); m_rootMsgFolder = nullptr; // clear this so we'll recalculate it on demand. //Notify listeners who listen to every folder nsresult rv = SetCharValue("deferred_to_account", aAccountKey); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr folderListenerManager = do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) { nsCOMPtr rootFolder; // use GetRootFolder, because that returns the real // root, not the deferred to root. rv = GetRootFolder(getter_AddRefs(rootFolder)); if (rootFolder) { // if isDeferred state has changed, send notification if (aAccountKey.IsEmpty() != deferredToAccount.IsEmpty()) { nsCOMPtr deferAtom = MsgGetAtom("isDeferred"); nsCOMPtr canFileAtom = MsgGetAtom("CanFileMessages"); folderListenerManager->OnItemBoolPropertyChanged(rootFolder, deferAtom, !deferredToAccount.IsEmpty(), deferredToAccount.IsEmpty()); folderListenerManager->OnItemBoolPropertyChanged(rootFolder, canFileAtom, deferredToAccount.IsEmpty(), !deferredToAccount.IsEmpty()); // this hack causes the account manager ds to send notifications to the // xul content builder that make the changed acct appear or disappear // from the folder pane and related menus. nsCOMPtr acctMgr = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID); if (acctMgr) { acctMgr->NotifyServerUnloaded(this); acctMgr->NotifyServerLoaded(this); // check if this newly deferred to account is the local folders account // and needs to have a newly created INBOX. if (!aAccountKey.IsEmpty()) { nsCOMPtr account; acctMgr->GetAccount(aAccountKey, getter_AddRefs(account)); if (account) { nsCOMPtr server; account->GetIncomingServer(getter_AddRefs(server)); if (server) { nsCOMPtr incomingLocalServer = do_QueryInterface(server); if (incomingLocalServer) { nsCOMPtr rootFolder; rv = server->GetRootFolder(getter_AddRefs(rootFolder)); NS_ENSURE_SUCCESS(rv, rv); // this will fail if it already exists, which is fine. rootFolder->CreateSubfolder(NS_LITERAL_STRING("Inbox"), nullptr); } } } } } } } } return rv; } //NS_IMPL_GETSET(nsPop3IncomingServer, Authenticated, bool, m_authenticated); NS_IMETHODIMP nsPop3IncomingServer::GetAuthenticated(bool *aAuthenticated) { NS_ENSURE_ARG_POINTER(aAuthenticated); *aAuthenticated = m_authenticated; return NS_OK; } NS_IMETHODIMP nsPop3IncomingServer::SetAuthenticated(bool aAuthenticated) { m_authenticated = aAuthenticated; return NS_OK; } nsresult nsPop3IncomingServer::GetPop3CapabilityFlags(uint32_t *flags) { *flags = m_capabilityFlags; return NS_OK; } nsresult nsPop3IncomingServer::SetPop3CapabilityFlags(uint32_t flags) { m_capabilityFlags = flags; return NS_OK; } NS_IMETHODIMP nsPop3IncomingServer::GetRootMsgFolder(nsIMsgFolder **aRootMsgFolder) { NS_ENSURE_ARG_POINTER(aRootMsgFolder); nsresult rv = NS_OK; if (!m_rootMsgFolder) { nsCString deferredToAccount; GetDeferredToAccount(deferredToAccount); if (deferredToAccount.IsEmpty()) { rv = CreateRootFolder(); m_rootMsgFolder = m_rootFolder; } else { nsCOMPtr accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv,rv); nsCOMPtr account; rv = accountManager->GetAccount(deferredToAccount, getter_AddRefs(account)); NS_ENSURE_SUCCESS(rv,rv); if (account) { nsCOMPtr incomingServer; rv = account->GetIncomingServer(getter_AddRefs(incomingServer)); NS_ENSURE_SUCCESS(rv,rv); // make sure we're not deferred to ourself... if (incomingServer && incomingServer != this) rv = incomingServer->GetRootMsgFolder(getter_AddRefs(m_rootMsgFolder)); else rv = NS_ERROR_FAILURE; } } } NS_IF_ADDREF(*aRootMsgFolder = m_rootMsgFolder); return m_rootMsgFolder ? rv : NS_ERROR_FAILURE; } nsresult nsPop3IncomingServer::GetInbox(nsIMsgWindow *msgWindow, nsIMsgFolder **inbox) { NS_ENSURE_ARG_POINTER(inbox); nsCOMPtr rootFolder; nsresult rv = GetRootMsgFolder(getter_AddRefs(rootFolder)); if(NS_SUCCEEDED(rv) && rootFolder) { rootFolder->GetFolderWithFlags(nsMsgFolderFlags::Inbox, inbox); } nsCOMPtr localInbox = do_QueryInterface(*inbox, &rv); if (NS_SUCCEEDED(rv) && localInbox) { nsCOMPtr db; rv = (*inbox)->GetMsgDatabase(getter_AddRefs(db)); if (NS_FAILED(rv)) { (*inbox)->SetMsgDatabase(nullptr); (void) localInbox->SetCheckForNewMessagesAfterParsing(true); // this will cause a reparse of the mail folder. localInbox->GetDatabaseWithReparse(nullptr, msgWindow, getter_AddRefs(db)); rv = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE; } } return rv; } NS_IMETHODIMP nsPop3IncomingServer::PerformBiff(nsIMsgWindow *aMsgWindow) { nsresult rv; nsCOMPtr pop3Service(do_GetService(kCPop3ServiceCID, &rv)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr inbox; nsCOMPtr rootMsgFolder; nsCOMPtr urlListener; rv = GetRootMsgFolder(getter_AddRefs(rootMsgFolder)); NS_ENSURE_TRUE(rootMsgFolder, NS_ERROR_FAILURE); rootMsgFolder->GetFolderWithFlags(nsMsgFolderFlags::Inbox, getter_AddRefs(inbox)); if (!inbox) return NS_ERROR_FAILURE; nsCOMPtr server; inbox->GetServer(getter_AddRefs(server)); server->SetPerformingBiff(true); urlListener = do_QueryInterface(inbox); bool downloadOnBiff = false; rv = GetDownloadOnBiff(&downloadOnBiff); if (downloadOnBiff) { nsCOMPtr localInbox = do_QueryInterface(inbox, &rv); if (localInbox && NS_SUCCEEDED(rv)) { bool valid = false; nsCOMPtr db; rv = inbox->GetMsgDatabase(getter_AddRefs(db)); if (NS_SUCCEEDED(rv) && db) rv = db->GetSummaryValid(&valid); if (NS_SUCCEEDED(rv) && valid) rv = pop3Service->GetNewMail(aMsgWindow, urlListener, inbox, this, nullptr); else { bool isLocked; inbox->GetLocked(&isLocked); if (!isLocked) rv = localInbox->GetDatabaseWithReparse(urlListener, aMsgWindow, getter_AddRefs(db)); if (NS_SUCCEEDED(rv)) rv = localInbox->SetCheckForNewMessagesAfterParsing(true); } } } else rv = pop3Service->CheckForNewMail(aMsgWindow, urlListener, inbox, this, nullptr); return NS_OK; } NS_IMETHODIMP nsPop3IncomingServer::SetFlagsOnDefaultMailboxes() { nsCOMPtr rootFolder; nsresult rv = GetRootFolder(getter_AddRefs(rootFolder)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr localFolder = do_QueryInterface(rootFolder, &rv); NS_ENSURE_SUCCESS(rv, rv); // pop3 gets an inbox, but no queue (unsent messages) localFolder->SetFlagsOnDefaultMailboxes(nsMsgFolderFlags::SpecialUse & ~nsMsgFolderFlags::Queue); return NS_OK; } NS_IMETHODIMP nsPop3IncomingServer::CreateDefaultMailboxes() { nsresult rv = CreateLocalFolder(NS_LITERAL_STRING("Inbox")); NS_ENSURE_SUCCESS(rv, rv); return CreateLocalFolder(NS_LITERAL_STRING("Trash")); } // override this so we can say that deferred accounts can't have messages // filed to them, which will remove them as targets of all the move/copy // menu items. NS_IMETHODIMP nsPop3IncomingServer::GetCanFileMessagesOnServer(bool *aCanFileMessagesOnServer) { NS_ENSURE_ARG_POINTER(aCanFileMessagesOnServer); nsCString deferredToAccount; GetDeferredToAccount(deferredToAccount); *aCanFileMessagesOnServer = deferredToAccount.IsEmpty(); return NS_OK; } NS_IMETHODIMP nsPop3IncomingServer::GetCanCreateFoldersOnServer(bool *aCanCreateFoldersOnServer) { NS_ENSURE_ARG_POINTER(aCanCreateFoldersOnServer); nsCString deferredToAccount; GetDeferredToAccount(deferredToAccount); *aCanCreateFoldersOnServer = deferredToAccount.IsEmpty(); return NS_OK; } NS_IMETHODIMP nsPop3IncomingServer::VerifyLogon(nsIUrlListener *aUrlListener, nsIMsgWindow *aMsgWindow, nsIURI **aURL) { nsresult rv; nsCOMPtr pop3Service = do_GetService(kCPop3ServiceCID, &rv); NS_ENSURE_SUCCESS(rv,rv); return pop3Service->VerifyLogon(this, aUrlListener, aMsgWindow, aURL); } NS_IMETHODIMP nsPop3IncomingServer::DownloadMailFromServers(nsIPop3IncomingServer** aServers, uint32_t aCount, nsIMsgWindow *aMsgWindow, nsIMsgFolder *aFolder, nsIUrlListener *aUrlListener) { nsPop3GetMailChainer *getMailChainer = new nsPop3GetMailChainer; NS_ENSURE_TRUE(getMailChainer, NS_ERROR_OUT_OF_MEMORY); getMailChainer->AddRef(); // this object owns itself and releases when done. return getMailChainer->GetNewMailForServers(aServers, aCount, aMsgWindow, aFolder, aUrlListener); } NS_IMETHODIMP nsPop3IncomingServer::GetNewMail(nsIMsgWindow *aMsgWindow, nsIUrlListener *aUrlListener, nsIMsgFolder *aInbox, nsIURI **aResult) { nsresult rv; nsCOMPtr pop3Service = do_GetService(kCPop3ServiceCID, &rv); NS_ENSURE_SUCCESS(rv,rv); return pop3Service->GetNewMail(aMsgWindow, aUrlListener, aInbox, this, aResult); } // user has clicked get new messages on this server. If other servers defer to this server, // we need to get new mail for them. But if this server defers to an other server, // I think we only get new mail for this server. NS_IMETHODIMP nsPop3IncomingServer::GetNewMessages(nsIMsgFolder *aFolder, nsIMsgWindow *aMsgWindow, nsIUrlListener *aUrlListener) { nsresult rv; nsCOMPtr pop3Service = do_GetService(kCPop3ServiceCID, &rv); NS_ENSURE_SUCCESS(rv,rv); nsCOMPtr inbox; rv = GetInbox(aMsgWindow, getter_AddRefs(inbox)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr url; nsCOMPtr server; nsCOMArray deferredServers; nsCString deferredToAccount; GetDeferredToAccount(deferredToAccount); if (deferredToAccount.IsEmpty()) { aFolder->GetServer(getter_AddRefs(server)); GetDeferredServers(server, deferredServers); } if (deferredToAccount.IsEmpty() && !deferredServers.IsEmpty()) { nsPop3GetMailChainer *getMailChainer = new nsPop3GetMailChainer; NS_ENSURE_TRUE(getMailChainer, NS_ERROR_OUT_OF_MEMORY); getMailChainer->AddRef(); // this object owns itself and releases when done. deferredServers.InsertElementAt(0, this); return getMailChainer->GetNewMailForServers(deferredServers.Elements(), deferredServers.Length(), aMsgWindow, inbox, aUrlListener); } if (m_runningProtocol) return NS_MSG_FOLDER_BUSY; return pop3Service->GetNewMail(aMsgWindow, aUrlListener, inbox, this, getter_AddRefs(url)); } NS_IMETHODIMP nsPop3IncomingServer::GetDownloadMessagesAtStartup(bool *getMessagesAtStartup) { NS_ENSURE_ARG_POINTER(getMessagesAtStartup); // GetMessages is not automatically done for pop servers at startup. // We need to trigger that action. Return true. *getMessagesAtStartup = true; return NS_OK; } NS_IMETHODIMP nsPop3IncomingServer::GetCanBeDefaultServer(bool *canBeDefaultServer) { NS_ENSURE_ARG_POINTER(canBeDefaultServer); *canBeDefaultServer = true; return NS_OK; } NS_IMETHODIMP nsPop3IncomingServer::GetCanSearchMessages(bool *canSearchMessages) { // this will return false if this server is deferred, which is what we want. return GetCanFileMessagesOnServer(canSearchMessages); } NS_IMETHODIMP nsPop3IncomingServer::CloseCachedConnections() { nsCOMPtr channel = do_QueryInterface(m_runningProtocol); if (channel) channel->Cancel(NS_ERROR_ABORT); return NS_OK; } NS_IMETHODIMP nsPop3IncomingServer::GetOfflineSupportLevel(int32_t *aSupportLevel) { NS_ENSURE_ARG_POINTER(aSupportLevel); nsresult rv; rv = GetIntValue("offline_support_level", aSupportLevel); if (*aSupportLevel != OFFLINE_SUPPORT_LEVEL_UNDEFINED) return rv; // set default value *aSupportLevel = OFFLINE_SUPPORT_LEVEL_NONE; return NS_OK; } NS_IMETHODIMP nsPop3IncomingServer::SetRunningProtocol(nsIPop3Protocol *aProtocol) { NS_ASSERTION(!aProtocol || !m_runningProtocol, "overriding running protocol"); m_runningProtocol = aProtocol; return NS_OK; } NS_IMETHODIMP nsPop3IncomingServer::GetRunningProtocol(nsIPop3Protocol **aProtocol) { NS_ENSURE_ARG_POINTER(aProtocol); NS_IF_ADDREF(*aProtocol = m_runningProtocol); return NS_OK; } NS_IMETHODIMP nsPop3IncomingServer::AddUidlToMark(const char *aUidl, int32_t aMark) { NS_ENSURE_ARG_POINTER(aUidl); Pop3UidlEntry *uidlEntry = PR_NEWZAP(Pop3UidlEntry); NS_ENSURE_TRUE(uidlEntry, NS_ERROR_OUT_OF_MEMORY); uidlEntry->uidl = strdup(aUidl); if (MOZ_UNLIKELY(!uidlEntry->uidl)) { PR_Free(uidlEntry); return NS_ERROR_OUT_OF_MEMORY; } uidlEntry->status = (aMark == POP3_DELETE) ? DELETE_CHAR : (aMark == POP3_FETCH_BODY) ? FETCH_BODY : KEEP; m_uidlsToMark.AppendElement(uidlEntry); return NS_OK; } NS_IMETHODIMP nsPop3IncomingServer::MarkMessages() { nsresult rv; if (m_runningProtocol) rv = m_runningProtocol->MarkMessages(&m_uidlsToMark); else { nsCString hostName; nsCString userName; nsCOMPtr localPath; GetLocalPath(getter_AddRefs(localPath)); GetHostName(hostName); GetUsername(userName); // do it all in one fell swoop rv = nsPop3Protocol::MarkMsgForHost(hostName.get(), userName.get(), localPath, m_uidlsToMark); } uint32_t count = m_uidlsToMark.Length(); for (uint32_t i = 0; i < count; i++) { Pop3UidlEntry *ue = m_uidlsToMark[i]; PR_Free(ue->uidl); PR_Free(ue); } m_uidlsToMark.Clear(); return rv; } NS_IMPL_ISUPPORTS(nsPop3GetMailChainer, nsIUrlListener) nsPop3GetMailChainer::nsPop3GetMailChainer() { } nsPop3GetMailChainer::~nsPop3GetMailChainer() { } nsresult nsPop3GetMailChainer::GetNewMailForServers(nsIPop3IncomingServer** servers, uint32_t count, nsIMsgWindow *msgWindow, nsIMsgFolder *folderToDownloadTo, nsIUrlListener *listener) { NS_ENSURE_ARG_POINTER(folderToDownloadTo); m_serversToGetNewMailFor.AppendElements(servers, count); m_folderToDownloadTo = folderToDownloadTo; m_downloadingMsgWindow = msgWindow; m_listener = listener; nsCOMPtr destFolderDB; nsresult rv = folderToDownloadTo->GetMsgDatabase(getter_AddRefs(destFolderDB)); if (NS_FAILED(rv) || !destFolderDB) { nsCOMPtr localFolder = do_QueryInterface(folderToDownloadTo); if (localFolder) { localFolder->GetDatabaseWithReparse(this, msgWindow, getter_AddRefs(destFolderDB)); return NS_OK; } } return RunNextGetNewMail(); } NS_IMETHODIMP nsPop3GetMailChainer::OnStartRunningUrl(nsIURI *url) { return NS_OK; } NS_IMETHODIMP nsPop3GetMailChainer::OnStopRunningUrl(nsIURI *aUrl, nsresult aExitCode) { return RunNextGetNewMail(); } nsresult nsPop3GetMailChainer::RunNextGetNewMail() { nsresult rv; uint32_t numServersLeft = m_serversToGetNewMailFor.Count(); for (; numServersLeft > 0;) { nsCOMPtr popServer(m_serversToGetNewMailFor[0]); m_serversToGetNewMailFor.RemoveObjectAt(0); numServersLeft--; if (popServer) { bool deferGetNewMail = false; nsCOMPtr downloadingToServer; m_folderToDownloadTo->GetServer(getter_AddRefs(downloadingToServer)); popServer->GetDeferGetNewMail(&deferGetNewMail); nsCOMPtr server = do_QueryInterface(popServer); nsCOMPtr protocol; popServer->GetRunningProtocol(getter_AddRefs(protocol)); if ((deferGetNewMail || downloadingToServer == server) && !protocol) { // have to call routine that just gets mail for one server, // and ignores deferred servers... if (server) { nsCOMPtr url; nsCOMPtr pop3Service = do_GetService(kCPop3ServiceCID, &rv); NS_ENSURE_SUCCESS(rv,rv); return pop3Service->GetNewMail(m_downloadingMsgWindow, this, m_folderToDownloadTo, popServer, getter_AddRefs(url)); } } } } rv = m_listener ? m_listener->OnStopRunningUrl(nullptr, NS_OK) : NS_OK; Release(); // release ref to ourself. return rv; }