summaryrefslogtreecommitdiffstats
path: root/comm/mail/components/about-support/content/accounts.js
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mail/components/about-support/content/accounts.js')
-rw-r--r--comm/mail/components/about-support/content/accounts.js339
1 files changed, 339 insertions, 0 deletions
diff --git a/comm/mail/components/about-support/content/accounts.js b/comm/mail/components/about-support/content/accounts.js
new file mode 100644
index 0000000000..33633f4a15
--- /dev/null
+++ b/comm/mail/components/about-support/content/accounts.js
@@ -0,0 +1,339 @@
+/* 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/. */
+
+/* globals CLASS_DATA_PRIVATE, CLASS_DATA_PUBLIC */
+
+"use strict";
+
+var { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+
+// Platform-specific includes
+var AboutSupportPlatform;
+if ("@mozilla.org/windows-registry-key;1" in Cc) {
+ let temp = ChromeUtils.import("resource:///modules/AboutSupportWin32.jsm");
+ AboutSupportPlatform = temp.AboutSupportPlatform;
+} else if ("nsILocalFileMac" in Ci) {
+ let temp = ChromeUtils.import("resource:///modules/AboutSupportMac.jsm");
+ AboutSupportPlatform = temp.AboutSupportPlatform;
+} else {
+ let temp = ChromeUtils.import("resource:///modules/AboutSupportUnix.jsm");
+ AboutSupportPlatform = temp.AboutSupportPlatform;
+}
+
+var gMessengerBundle = Services.strings.createBundle(
+ "chrome://messenger/locale/messenger.properties"
+);
+
+var gSocketTypes = {};
+for (let [str, index] of Object.entries(Ci.nsMsgSocketType)) {
+ gSocketTypes[index] = str;
+}
+
+var gAuthMethods = {};
+for (let [str, index] of Object.entries(Ci.nsMsgAuthMethod)) {
+ gAuthMethods[index] = str;
+}
+
+// l10n properties in messenger.properties corresponding to each auth method
+var gAuthMethodProperties = new Map([
+ [0, "authNo"], // Special value defined to be invalid.
+ // Some accounts without auth report this.
+ [Ci.nsMsgAuthMethod.none, "authNo"],
+ [Ci.nsMsgAuthMethod.old, "authOld"],
+ [Ci.nsMsgAuthMethod.passwordCleartext, "authPasswordCleartextViaSSL"],
+ [Ci.nsMsgAuthMethod.passwordEncrypted, "authPasswordEncrypted"],
+ [Ci.nsMsgAuthMethod.GSSAPI, "authKerberos"],
+ [Ci.nsMsgAuthMethod.NTLM, "authNTLM"],
+ [Ci.nsMsgAuthMethod.External, "authExternal"],
+ [Ci.nsMsgAuthMethod.secure, "authAnySecure"],
+ [Ci.nsMsgAuthMethod.anything, "authAny"],
+ [Ci.nsMsgAuthMethod.OAuth2, "authOAuth2"],
+]);
+
+var AboutSupport = {
+ /**
+ * Gets details about SMTP servers for a given nsIMsgAccount.
+ *
+ * @returns An array of records, each record containing the name and other details
+ * about one SMTP server.
+ */
+ _getSMTPDetails(aAccount) {
+ let defaultIdentity = aAccount.defaultIdentity;
+ let smtpDetails = [];
+
+ for (let identity of aAccount.identities) {
+ let isDefault = identity == defaultIdentity;
+ let smtpServer = MailServices.smtp.getServerByIdentity(identity);
+ if (!smtpServer) {
+ continue;
+ }
+ smtpDetails.push({
+ identityName: identity.identityName,
+ name: smtpServer.displayname,
+ authMethod: smtpServer.authMethod,
+ socketType: smtpServer.socketType,
+ isDefault,
+ });
+ }
+
+ return smtpDetails;
+ },
+
+ /**
+ * Returns account details as an array of records.
+ */
+ getAccountDetails() {
+ let accountDetails = [];
+
+ for (let account of MailServices.accounts.accounts) {
+ let server = account.incomingServer;
+ accountDetails.push({
+ key: account.key,
+ name: server.prettyName,
+ hostDetails:
+ "(" +
+ server.type +
+ ") " +
+ server.hostName +
+ (server.port != -1 ? ":" + server.port : ""),
+ socketType: server.socketType,
+ authMethod: server.authMethod,
+ smtpServers: this._getSMTPDetails(account),
+ });
+ }
+
+ function idCompare(accountA, accountB) {
+ let regex = /^account([0-9]+)$/;
+ let regexA = regex.exec(accountA.key);
+ let regexB = regex.exec(accountB.key);
+ // There's an off chance that the account ID isn't in the standard
+ // accountN form. If so, use the standard string compare against a fixed
+ // string ("account") to avoid correctness issues.
+ if (!regexA || !regexB) {
+ let keyA = regexA ? "account" : accountA.key;
+ let keyB = regexB ? "account" : accountB.key;
+ return keyA.localeCompare(keyB);
+ }
+ let idA = parseInt(regexA[1]);
+ let idB = parseInt(regexB[1]);
+ return idA - idB;
+ }
+
+ // Sort accountDetails by account ID.
+ accountDetails.sort(idCompare);
+ return accountDetails;
+ },
+
+ /**
+ * Returns the corresponding text for a given socket type index. The text is
+ * returned as a record with "localized" and "neutral" entries.
+ */
+ getSocketTypeText(aIndex) {
+ let plainSocketType =
+ aIndex in gSocketTypes ? gSocketTypes[aIndex] : aIndex;
+ let prettySocketType;
+ try {
+ prettySocketType = gMessengerBundle.GetStringFromName(
+ "smtpServer-ConnectionSecurityType-" + aIndex
+ );
+ } catch (e) {
+ if (e.result == Cr.NS_ERROR_FAILURE) {
+ // The string wasn't found in the bundle. Make do without it.
+ prettySocketType = plainSocketType;
+ } else {
+ throw e;
+ }
+ }
+ return { localized: prettySocketType, neutral: plainSocketType };
+ },
+
+ /**
+ * Returns the corresponding text for a given authentication method index. The
+ * text is returned as a record with "localized" and "neutral" entries.
+ */
+ getAuthMethodText(aIndex) {
+ let prettyAuthMethod;
+ let plainAuthMethod =
+ aIndex in gAuthMethods ? gAuthMethods[aIndex] : aIndex;
+ if (gAuthMethodProperties.has(parseInt(aIndex))) {
+ prettyAuthMethod = gMessengerBundle.GetStringFromName(
+ gAuthMethodProperties.get(parseInt(aIndex))
+ );
+ } else {
+ prettyAuthMethod = plainAuthMethod;
+ }
+ return { localized: prettyAuthMethod, neutral: plainAuthMethod };
+ },
+};
+
+function createParentElement(tagName, childElems) {
+ let elem = document.createElement(tagName);
+ appendChildren(elem, childElems);
+ return elem;
+}
+
+function createElement(tagName, textContent, opt_attributes, opt_copyData) {
+ if (opt_attributes == null) {
+ opt_attributes = {};
+ }
+ let elem = document.createElement(tagName);
+ elem.textContent = textContent;
+ for (let key in opt_attributes) {
+ elem.setAttribute(key, "" + opt_attributes[key]);
+ }
+
+ if (opt_copyData != null) {
+ elem.dataset.copyData = opt_copyData;
+ }
+
+ return elem;
+}
+
+function appendChildren(parentElem, children) {
+ for (let i = 0; i < children.length; i++) {
+ parentElem.appendChild(children[i]);
+ }
+}
+
+/**
+ * Coerces x into a string.
+ */
+function toStr(x) {
+ return "" + x;
+}
+
+/**
+ * Marks x as private (see below).
+ */
+function toPrivate(x) {
+ return { localized: x, neutral: x, isPrivate: true };
+}
+
+/**
+ * A list of fields for the incoming server of an account. Each element of the
+ * list is a pair of [property name, transforming function]. The transforming
+ * function should take the property and return either a string or an object
+ * with the following properties:
+ * - localized: the data in (possibly) localized form
+ * - neutral: the data in language-neutral form
+ * - isPrivate (optional): true if the data is private-only, false if public-only,
+ * not stated otherwise
+ */
+var gIncomingDetails = [
+ ["key", toStr],
+ ["name", toPrivate],
+ ["hostDetails", toStr],
+ ["socketType", AboutSupport.getSocketTypeText.bind(AboutSupport)],
+ ["authMethod", AboutSupport.getAuthMethodText.bind(AboutSupport)],
+];
+
+/**
+ * A list of fields for the outgoing servers associated with an account. This is
+ * similar to gIncomingDetails above.
+ */
+var gOutgoingDetails = [
+ ["identityName", toPrivate],
+ ["name", toStr],
+ ["socketType", AboutSupport.getSocketTypeText.bind(AboutSupport)],
+ ["authMethod", AboutSupport.getAuthMethodText.bind(AboutSupport)],
+ ["isDefault", toStr],
+];
+
+/**
+ * A list of account details.
+ */
+var gAccountDetails = AboutSupport.getAccountDetails();
+
+function populateAccountsSection() {
+ let trAccounts = [];
+
+ function createTD(data, rowSpan) {
+ let text = typeof data == "string" ? data : data.localized;
+ let copyData = typeof data == "string" ? null : data.neutral;
+ let attributes = { rowspan: rowSpan };
+ if (typeof data == "object" && "isPrivate" in data) {
+ attributes.class = data.isPrivate
+ ? CLASS_DATA_PRIVATE
+ : CLASS_DATA_PUBLIC;
+ }
+
+ return createElement("td", text, attributes, copyData);
+ }
+
+ for (let account of gAccountDetails) {
+ // We want a minimum rowspan of 1
+ let rowSpan = account.smtpServers.length || 1;
+ // incomingTDs is an array of TDs
+ let incomingTDs = gIncomingDetails.map(([prop, fn]) =>
+ createTD(fn(account[prop]), rowSpan)
+ );
+ // outgoingTDs is an array of arrays of TDs
+ let outgoingTDs = [];
+ for (let smtp of account.smtpServers) {
+ outgoingTDs.push(
+ gOutgoingDetails.map(([prop, fn]) => createTD(fn(smtp[prop]), 1))
+ );
+ }
+
+ // If there are no SMTP servers, add a dummy element to make life easier below
+ if (outgoingTDs.length == 0) {
+ outgoingTDs = [[]];
+ }
+
+ // Add the first SMTP server to this tr.
+ let tr = createParentElement("tr", incomingTDs.concat(outgoingTDs[0]));
+ trAccounts.push(tr);
+ // Add the remaining SMTP servers as separate trs
+ for (let tds of outgoingTDs.slice(1)) {
+ trAccounts.push(createParentElement("tr", tds));
+ }
+ }
+
+ appendChildren(document.getElementById("accounts-tbody"), trAccounts);
+}
+
+/**
+ * Returns a plaintext representation of the accounts data.
+ */
+function getAccountsText(aHidePrivateData, aIndent) {
+ let accumulator = [];
+
+ // Given a string or object, converts it into a language-neutral form
+ function neutralizer(data) {
+ if (typeof data == "string") {
+ return data;
+ }
+ if ("isPrivate" in data && aHidePrivateData == data.isPrivate) {
+ return "";
+ }
+ return data.neutral;
+ }
+
+ for (let account of gAccountDetails) {
+ accumulator.push(aIndent + account.key + ":");
+ // incomingData is an array of strings
+ let incomingData = gIncomingDetails.map(([prop, fn]) =>
+ neutralizer(fn(account[prop]))
+ );
+ accumulator.push(aIndent + " INCOMING: " + incomingData.join(", "));
+
+ // outgoingData is an array of arrays of strings
+ let outgoingData = [];
+ for (let smtp of account.smtpServers) {
+ outgoingData.push(
+ gOutgoingDetails.map(([prop, fn]) => neutralizer(fn(smtp[prop])))
+ );
+ }
+
+ for (let data of outgoingData) {
+ accumulator.push(aIndent + " OUTGOING: " + data.join(", "));
+ }
+
+ accumulator.push("");
+ }
+
+ return accumulator.join("\n");
+}