summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/local/src/Pop3IncomingServer.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mailnews/local/src/Pop3IncomingServer.jsm')
-rw-r--r--comm/mailnews/local/src/Pop3IncomingServer.jsm308
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}"
+);