Dactyloidae/mailnews/base/prefs/content/accountcreation/createInBackend.js
Matt A. Tobin 1531d6498d Issue #1258 - Part 8: Ifdef MailNews OAuth2 Support
Use --disable-mailnews-oauth2 to exclude it. Confvars won't be respected.
2019-11-17 00:09:28 +08:00

337 lines
12 KiB
JavaScript

/* -*- Mode: Java; 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/. */
/**
* Takes an |AccountConfig| JS object and creates that account in the
* Thunderbird backend (which also writes it to prefs).
*
* @param config {AccountConfig} The account to create
*
* @return - the account created.
*/
Components.utils.import("resource:///modules/mailServices.js");
Components.utils.import("resource://gre/modules/Services.jsm");
function createAccountInBackend(config)
{
// incoming server
let inServer = MailServices.accounts.createIncomingServer(
config.incoming.username,
config.incoming.hostname,
sanitize.enum(config.incoming.type, ["pop3", "imap", "nntp"]));
inServer.port = config.incoming.port;
inServer.authMethod = config.incoming.auth;
inServer.password = config.incoming.password;
if (config.rememberPassword && config.incoming.password.length)
rememberPassword(inServer, config.incoming.password);
#ifdef MOZ_MAILNEWS_OAUTH2
if (inServer.authMethod == Ci.nsMsgAuthMethod.OAuth2) {
inServer.setCharValue("oauth2.scope", config.oauthSettings.scope);
inServer.setCharValue("oauth2.issuer", config.oauthSettings.issuer);
}
#endif
// SSL
if (config.incoming.socketType == 1) // plain
inServer.socketType = Ci.nsMsgSocketType.plain;
else if (config.incoming.socketType == 2) // SSL / TLS
inServer.socketType = Ci.nsMsgSocketType.SSL;
else if (config.incoming.socketType == 3) // STARTTLS
inServer.socketType = Ci.nsMsgSocketType.alwaysSTARTTLS;
//inServer.prettyName = config.displayName;
inServer.prettyName = config.identity.emailAddress;
inServer.doBiff = true;
inServer.biffMinutes = config.incoming.checkInterval;
const loginAtStartupPrefTemplate =
"mail.server.%serverkey%.login_at_startup";
var loginAtStartupPref =
loginAtStartupPrefTemplate.replace("%serverkey%", inServer.key);
Services.prefs.setBoolPref(loginAtStartupPref,
config.incoming.loginAtStartup);
if (config.incoming.type == "pop3")
{
const leaveOnServerPrefTemplate =
"mail.server.%serverkey%.leave_on_server";
const daysToLeaveOnServerPrefTemplate =
"mail.server.%serverkey%.num_days_to_leave_on_server";
const deleteFromServerPrefTemplate =
"mail.server.%serverkey%.delete_mail_left_on_server";
const deleteByAgeFromServerPrefTemplate =
"mail.server.%serverkey%.delete_by_age_from_server";
const downloadOnBiffPrefTemplate =
"mail.server.%serverkey%.download_on_biff";
var leaveOnServerPref =
leaveOnServerPrefTemplate.replace("%serverkey%", inServer.key);
var ageFromServerPref =
deleteByAgeFromServerPrefTemplate.replace("%serverkey%", inServer.key);
var daysToLeaveOnServerPref =
daysToLeaveOnServerPrefTemplate.replace("%serverkey%", inServer.key);
var deleteFromServerPref =
deleteFromServerPrefTemplate.replace("%serverkey%", inServer.key);
let downloadOnBiffPref =
downloadOnBiffPrefTemplate.replace("%serverkey%", inServer.key);
Services.prefs.setBoolPref(leaveOnServerPref,
config.incoming.leaveMessagesOnServer);
Services.prefs.setIntPref(daysToLeaveOnServerPref,
config.incoming.daysToLeaveMessagesOnServer);
Services.prefs.setBoolPref(deleteFromServerPref,
config.incoming.deleteOnServerWhenLocalDelete);
Services.prefs.setBoolPref(ageFromServerPref,
config.incoming.deleteByAgeFromServer);
Services.prefs.setBoolPref(downloadOnBiffPref,
config.incoming.downloadOnBiff);
}
inServer.valid = true;
let username = config.outgoing.auth > 1 ? config.outgoing.username : null;
let outServer = MailServices.smtp.findServer(username, config.outgoing.hostname);
assert(config.outgoing.addThisServer ||
config.outgoing.useGlobalPreferredServer ||
config.outgoing.existingServerKey,
"No SMTP server: inconsistent flags");
if (config.outgoing.addThisServer && !outServer)
{
outServer = MailServices.smtp.createServer();
outServer.hostname = config.outgoing.hostname;
outServer.port = config.outgoing.port;
outServer.authMethod = config.outgoing.auth;
if (config.outgoing.auth > 1)
{
outServer.username = username;
outServer.password = config.incoming.password;
if (config.rememberPassword && config.incoming.password.length)
rememberPassword(outServer, config.incoming.password);
}
#ifdef MOZ_MAILNEWS_OAUTH2
if (outServer.authMethod == Ci.nsMsgAuthMethod.OAuth2) {
let pref = "mail.smtpserver." + outServer.key + ".";
Services.prefs.setCharPref(pref + "oauth2.scope",
config.oauthSettings.scope);
Services.prefs.setCharPref(pref + "oauth2.issuer",
config.oauthSettings.issuer);
}
#endif
if (config.outgoing.socketType == 1) // no SSL
outServer.socketType = Ci.nsMsgSocketType.plain;
else if (config.outgoing.socketType == 2) // SSL / TLS
outServer.socketType = Ci.nsMsgSocketType.SSL;
else if (config.outgoing.socketType == 3) // STARTTLS
outServer.socketType = Ci.nsMsgSocketType.alwaysSTARTTLS;
// API problem: <http://mxr.mozilla.org/seamonkey/source/mailnews/compose/public/nsISmtpServer.idl#93>
outServer.description = config.displayName;
if (config.password)
outServer.password = config.outgoing.password;
// If this is the first SMTP server, set it as default
if (!MailServices.smtp.defaultServer ||
!MailServices.smtp.defaultServer.hostname)
MailServices.smtp.defaultServer = outServer;
}
// identity
// TODO accounts without identity?
let identity = MailServices.accounts.createIdentity();
identity.fullName = config.identity.realname;
identity.email = config.identity.emailAddress;
// for new accounts, default to replies being positioned above the quote
// if a default account is defined already, take its settings instead
if (config.incoming.type == "imap" || config.incoming.type == "pop3")
{
identity.replyOnTop = 1;
// identity.sigBottom = false; // don't set this until Bug 218346 is fixed
if (MailServices.accounts.accounts.length &&
MailServices.accounts.defaultAccount)
{
let defAccount = MailServices.accounts.defaultAccount;
let defIdentity = defAccount.defaultIdentity;
if (defAccount.incomingServer.canBeDefaultServer &&
defIdentity && defIdentity.valid)
{
identity.replyOnTop = defIdentity.replyOnTop;
identity.sigBottom = defIdentity.sigBottom;
}
}
}
// due to accepted conventions, news accounts should default to plain text
if (config.incoming.type == "nntp")
identity.composeHtml = false;
identity.valid = true;
if (config.outgoing.existingServerKey)
identity.smtpServerKey = config.outgoing.existingServerKey;
else if (!config.outgoing.useGlobalPreferredServer)
identity.smtpServerKey = outServer.key;
// account and hook up
// Note: Setting incomingServer will cause the AccountManager to refresh
// itself, which could be a problem if we came from it and we haven't set
// the identity (see bug 521955), so make sure everything else on the
// account is set up before you set the incomingServer.
let account = MailServices.accounts.createAccount();
account.addIdentity(identity);
account.incomingServer = inServer;
if (inServer.canBeDefaultServer && (!MailServices.accounts.defaultAccount ||
!MailServices.accounts.defaultAccount
.incomingServer.canBeDefaultServer))
MailServices.accounts.defaultAccount = account;
verifyLocalFoldersAccount(MailServices.accounts);
setFolders(identity, inServer);
// save
MailServices.accounts.saveAccountInfo();
try {
Services.prefs.savePrefFile(null);
} catch (ex) {
ddump("Could not write out prefs: " + ex);
}
return account;
}
function setFolders(identity, server)
{
// TODO: support for local folders for global inbox (or use smart search
// folder instead)
var baseURI = server.serverURI + "/";
// Names will be localized in UI, not in folder names on server/disk
// TODO allow to override these names in the XML config file,
// in case e.g. Google or AOL use different names?
// Workaround: Let user fix it :)
var fccName = "Sent";
var draftName = "Drafts";
var templatesName = "Templates";
identity.draftFolder = baseURI + draftName;
identity.stationeryFolder = baseURI + templatesName;
identity.fccFolder = baseURI + fccName;
identity.fccFolderPickerMode = 0;
identity.draftsFolderPickerMode = 0;
identity.tmplFolderPickerMode = 0;
}
function rememberPassword(server, password)
{
if (server instanceof Components.interfaces.nsIMsgIncomingServer)
var passwordURI = server.localStoreType + "://" + server.hostName;
else if (server instanceof Components.interfaces.nsISmtpServer)
var passwordURI = "smtp://" + server.hostname;
else
throw new NotReached("Server type not supported");
let login = Cc["@mozilla.org/login-manager/loginInfo;1"]
.createInstance(Ci.nsILoginInfo);
login.init(passwordURI, null, passwordURI, server.username, password, "", "");
try {
Services.logins.addLogin(login);
} catch (e) {
if (e.message.includes("This login already exists")) {
// TODO modify
} else {
throw e;
}
}
}
/**
* Check whether the user's setup already has an incoming server
* which matches (hostname, port, username) the primary one
* in the config.
* (We also check the email address as username.)
*
* @param config {AccountConfig} filled in (no placeholders)
* @return {nsIMsgIncomingServer} If it already exists, the server
* object is returned.
* If it's a new server, |null| is returned.
*/
function checkIncomingServerAlreadyExists(config)
{
assert(config instanceof AccountConfig);
let incoming = config.incoming;
let existing = MailServices.accounts.findRealServer(incoming.username,
incoming.hostname,
sanitize.enum(incoming.type, ["pop3", "imap", "nntp"]),
incoming.port);
// if username does not have an '@', also check the e-mail
// address form of the name.
if (!existing && !incoming.username.includes("@"))
existing = MailServices.accounts.findRealServer(config.identity.emailAddress,
incoming.hostname,
sanitize.enum(incoming.type, ["pop3", "imap", "nntp"]),
incoming.port);
return existing;
};
/**
* Check whether the user's setup already has an outgoing server
* which matches (hostname, port, username) the primary one
* in the config.
*
* @param config {AccountConfig} filled in (no placeholders)
* @return {nsISmtpServer} If it already exists, the server
* object is returned.
* If it's a new server, |null| is returned.
*/
function checkOutgoingServerAlreadyExists(config)
{
assert(config instanceof AccountConfig);
let smtpServers = MailServices.smtp.servers;
while (smtpServers.hasMoreElements())
{
let existingServer = smtpServers.getNext()
.QueryInterface(Ci.nsISmtpServer);
// TODO check username with full email address, too, like for incoming
if (existingServer.hostname == config.outgoing.hostname &&
existingServer.port == config.outgoing.port &&
existingServer.username == config.outgoing.username)
return existingServer;
}
return null;
};
/**
* Check if there already is a "Local Folders". If not, create it.
* Copied from AccountWizard.js with minor updates.
*/
function verifyLocalFoldersAccount(am)
{
let localMailServer;
try {
localMailServer = am.localFoldersServer;
}
catch (ex) {
localMailServer = null;
}
try {
if (!localMailServer)
{
// creates a copy of the identity you pass in
am.createLocalMailAccount();
try {
localMailServer = am.localFoldersServer;
}
catch (ex) {
ddump("Error! we should have found the local mail server " +
"after we created it.");
}
}
}
catch (ex) { ddump("Error in verifyLocalFoldersAccount " + ex); }
}