diff options
Diffstat (limited to 'comm/mailnews/local/src/Pop3IncomingServer.jsm')
-rw-r--r-- | comm/mailnews/local/src/Pop3IncomingServer.jsm | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/comm/mailnews/local/src/Pop3IncomingServer.jsm b/comm/mailnews/local/src/Pop3IncomingServer.jsm new file mode 100644 index 0000000000..b8c147a022 --- /dev/null +++ b/comm/mailnews/local/src/Pop3IncomingServer.jsm @@ -0,0 +1,308 @@ +/* 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/. */ + +const EXPORTED_SYMBOLS = ["Pop3IncomingServer"]; + +var { MsgIncomingServer } = ChromeUtils.import( + "resource:///modules/MsgIncomingServer.jsm" +); +const { MailServices } = ChromeUtils.import( + "resource:///modules/MailServices.jsm" +); +const { XPCOMUtils } = ChromeUtils.importESModule( + "resource://gre/modules/XPCOMUtils.sys.mjs" +); + +const lazy = {}; + +XPCOMUtils.defineLazyModuleGetters(lazy, { + Pop3Client: "resource:///modules/Pop3Client.jsm", +}); + +/** + * @implements {nsIPop3IncomingServer} + * @implements {nsILocalMailIncomingServer} + * @implements {nsIMsgIncomingServer} + * @implements {nsISupportsWeakReference} + */ +class Pop3IncomingServer extends MsgIncomingServer { + QueryInterface = ChromeUtils.generateQI([ + "nsIPop3IncomingServer", + "nsILocalMailIncomingServer", + "nsIMsgIncomingServer", + "nsISupportsWeakReference", + ]); + + constructor() { + super(); + + // nsIMsgIncomingServer attributes. + this.localStoreType = "mailbox"; + this.localDatabaseType = "mailbox"; + this.downloadMessagesAtStartup = true; + this.canBeDefaultServer = true; + + Object.defineProperty(this, "canCreateFoldersOnServer", { + get: () => !this.deferredToAccount, + }); + Object.defineProperty(this, "canFileMessagesOnServer", { + get: () => !this.deferredToAccount, + }); + + // nsIPop3IncomingServer attributes that map directly to pref values. + this._mapAttrsToPrefs([ + ["Bool", "leaveMessagesOnServer", "leave_on_server"], + ["Bool", "headersOnly", "headers_only"], + ["Bool", "deleteMailLeftOnServer", "delete_mail_left_on_server"], + ["Bool", "deleteByAgeFromServer", "delete_by_age_from_server"], + ["Bool", "deferGetNewMail", "defer_get_new_mail"], + ["Int", "numDaysToLeaveOnServer", "num_days_to_leave_on_server"], + ]); + + // @type {Map<string,string>} - A map from uidl to status. + this._uidlsToMark = new Map(); + } + + /** @see nsIMsgIncomingServer */ + get rootMsgFolder() { + if (this._rootMsgFolder) { + return this._rootMsgFolder; + } + + if (!this.deferredToAccount) { + this._rootMsgFolder = this.rootFolder; + return this._rootMsgFolder; + } + + let incomingServer = MailServices.accounts.getAccount( + this.deferredToAccount + ).incomingServer; + if (incomingServer.equals(this)) { + // Make sure we're not deferred to ourself. + throw Components.Exception( + `${incomingServer.prettyName} cannot be deferred to itself`, + Cr.NS_ERROR_FAILURE + ); + } + + this._rootMsgFolder = incomingServer.rootMsgFolder; + return this._rootMsgFolder; + } + + get canSearchMessages() { + return this.canFileMessagesOnServer; + } + + getNewMessages(folder, msgWindow, urlListener) { + let inbox = this.rootMsgFolder.getFolderWithFlags( + Ci.nsMsgFolderFlags.Inbox + ); + if (!this.deferredToAccount) { + let deferredServers = this._getDeferedServers(folder.server); + if (deferredServers.length) { + // If other servers are deferred to this server, get new mail for them + // as well. + return this.downloadMailFromServers( + [...deferredServers, this], + msgWindow, + inbox, + urlListener + ); + } + } + return MailServices.pop3.GetNewMail(msgWindow, urlListener, inbox, this); + } + + verifyLogon(urlListener, msgWindow) { + return MailServices.pop3.verifyLogon(this, urlListener, msgWindow); + } + + performBiff(msgWindow) { + this.performingBiff = true; + let inbox = this.rootMsgFolder.getFolderWithFlags( + Ci.nsMsgFolderFlags.Inbox + ); + let urlListener = inbox.QueryInterface(Ci.nsIUrlListener); + if (this.downloadOnBiff) { + MailServices.pop3.GetNewMail(msgWindow, urlListener, inbox, this); + } else { + MailServices.pop3.CheckForNewMail(msgWindow, urlListener, inbox, this); + } + } + + /** @see nsILocalMailIncomingServer */ + createDefaultMailboxes() { + for (let name of ["Inbox", "Trash"]) { + let folderUri = this.rootFolder.URI + "/" + name; + // Check by URI instead of by name, because folder name can be localized. + if (!this.rootFolder.getChildWithURI(folderUri, false, false)) { + this.msgStore.createFolder(this.rootFolder, name); + } + } + } + + setFlagsOnDefaultMailboxes() { + this.rootFolder + .QueryInterface(Ci.nsIMsgLocalMailFolder) + // POP3 account gets an inbox, but no queue (unsent messages). + .setFlagsOnDefaultMailboxes( + Ci.nsMsgFolderFlags.SpecialUse & ~Ci.nsMsgFolderFlags.Queue + ); + } + + getNewMail(msgWindow, urlListener, inbox) { + return MailServices.pop3.GetNewMail(msgWindow, urlListener, inbox, this); + } + + /** @see nsIPop3IncomingServer */ + get deferredToAccount() { + let accountKey = this.getCharValue("deferred_to_account"); + if (!accountKey) { + return ""; + } + + let account = MailServices.accounts.getAccount(accountKey); + // If currently deferred to an invalid or hidden server, change to defer to + // the local folders inbox. + if (!account || !account.incomingServer || account.incomingServer.hidden) { + let localAccount; + try { + localAccount = MailServices.accounts.FindAccountForServer( + MailServices.accounts.localFoldersServer + ); + } catch (e) { + // MailServices.accounts.localFoldersServer throws if no Local Folders. + return ""; + } + accountKey = localAccount.key; + this.setCharValue("deferred_to_account", accountKey); + } + + return accountKey; + } + + set deferredToAccount(accountKey) { + this._rootMsgFolder = null; + + let wasDeferred = Boolean(this.deferredToAccount); + this.setCharValue("deferred_to_account", accountKey); + + // If isDeferred state has changed, send notification. + if (Boolean(accountKey) != wasDeferred) { + let folderListenerManager = MailServices.mailSession.QueryInterface( + Ci.nsIFolderListener + ); + folderListenerManager.onFolderBoolPropertyChanged( + this.rootFolder, + "isDeferred", + wasDeferred, + !wasDeferred + ); + folderListenerManager.onFolderBoolPropertyChanged( + this.rootFolder, + "CanFileMessages", + !wasDeferred, + wasDeferred + ); + } + + if (!accountKey) { + return; + } + // Check if we are deferred to the local folders, and create INBOX if needed. + let server = MailServices.accounts.getAccount(accountKey).incomingServer; + if (server instanceof Ci.nsILocalMailIncomingServer) { + // Check by URI instead of by name, because folder name can be localized. + if ( + !this.rootFolder.getChildWithURI( + `${this.rootFolder.URI}/Inbox`, + false, + false + ) + ) { + server.rootFolder.createSubfolder("Inbox", null); + } + } + } + + addUidlToMark(uidl, mark) { + // @see nsIMsgLocalMailFolder + const POP3_DELETE = 1; + const POP3_FETCH_BODY = 2; + let status = "k"; + if (mark == POP3_DELETE) { + status = "d"; + } else if (mark == POP3_FETCH_BODY) { + status = "f"; + } + this._uidlsToMark.set(uidl, status); + } + + markMessages() { + if (!this._uidlsToMark.size) { + return; + } + + let client = this.runningClient || new lazy.Pop3Client(this); + // Pass a clone of this._uidlsToMark to client.markMessages, because + // this._uidlsToMark may be changed before markMessages finishes. + client.markMessages(new Map(this._uidlsToMark)); + this._uidlsToMark = new Map(); + } + + downloadMailFromServers(servers, msgWindow, folder, urlListener) { + let server = servers.shift(); + if (!server) { + urlListener?.OnStopRunningUrl(null, Cr.NS_OK); + return; + } + + // If server != folder.server, it means server is deferred to folder.server, + // so if server.deferGetNewMail is false, no need to call GetNewMail. + if (server == folder.server || server.deferGetNewMail) { + MailServices.pop3.GetNewMail( + msgWindow, + { + OnStartRunningUrl() {}, + OnStopRunningUrl: () => { + // Call GetNewMail for the next server only after it is finished for + // the current server. + this.downloadMailFromServers( + servers, + msgWindow, + folder, + urlListener + ); + }, + }, + folder, + server + ); + return; + } + this.downloadMailFromServers(servers, msgWindow, folder, urlListener); + } + + /** + * Get all the servers that defer to the passed in server. + * + * @param {nsIMsgIncomingServer} dstServer - The server that others servers + * are deferred to. + */ + _getDeferedServers(dstServer) { + let dstAccount = MailServices.accounts.FindAccountForServer(dstServer); + if (!dstAccount) { + return []; + } + return MailServices.accounts.allServers.filter( + server => + server instanceof Ci.nsIPop3IncomingServer && + server.deferredToAccount == dstAccount.key + ); + } +} + +Pop3IncomingServer.prototype.classID = Components.ID( + "{f99fdbf7-2e79-4ce3-9d94-7af3763b82fc}" +); |