mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-27 02:47:31 +09:00
Issue #1258 - Part 1: Import mailnews, ldap, and mork from comm-esr52.9.1
This commit is contained in:
parent
23e0d82436
commit
e400f4130a
1564 changed files with 510348 additions and 0 deletions
1628
mailnews/base/prefs/content/AccountManager.js
Normal file
1628
mailnews/base/prefs/content/AccountManager.js
Normal file
File diff suppressed because it is too large
Load diff
92
mailnews/base/prefs/content/AccountManager.xul
Normal file
92
mailnews/base/prefs/content/AccountManager.xul
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/folderPane.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/accountManage.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE dialog SYSTEM "chrome://messenger/locale/AccountManager.dtd">
|
||||
<dialog id="accountManager"
|
||||
windowtype="mailnews:accountmanager"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&accountManagerTitle.label;"
|
||||
style="&accountManager.size;"
|
||||
persist="width height screenX screenY"
|
||||
buttons="accept,cancel"
|
||||
onload="onLoad(event);"
|
||||
onunload="onUnload();"
|
||||
ondialogaccept="return onAccept(true);">
|
||||
<stringbundle id="bundle_brand" src="chrome://branding/locale/brand.properties"/>
|
||||
<stringbundle id="bundle_prefs" src="chrome://messenger/locale/prefs.properties"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/accountUtils.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/am-prefs.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/AccountManager.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/am-help.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/amUtils.js"/>
|
||||
|
||||
<hbox flex="1">
|
||||
<vbox style="&accountTree.width;">
|
||||
<tree flex="1" onselect="onAccountTreeSelect(null, null);" id="accounttree"
|
||||
seltype="single" hidecolumnpicker="true">
|
||||
<treecols>
|
||||
<treecol id="AccountCol" flex="1" primary="true" hideheader="true"/>
|
||||
</treecols>
|
||||
<treechildren id="account-tree-children"/>
|
||||
</tree>
|
||||
|
||||
#ifdef MOZ_THUNDERBIRD
|
||||
<button id="accountActionsButton" type="menu"
|
||||
label="&accountActionsButton.label;"
|
||||
accesskey="&accountActionsButton.accesskey;">
|
||||
<menupopup id="accountActionsDropdown"
|
||||
onpopupshowing="initAccountActionsButtons(this);">
|
||||
<menuitem id="accountActionsAddMailAccount"
|
||||
label="&addMailAccountButton.label;"
|
||||
accesskey="&addMailAccountButton.accesskey;"
|
||||
prefstring="mail.disable_new_account_addition"
|
||||
oncommand="AddMailAccount(event); event.stopPropagation();"/>
|
||||
<menuitem id="accountActionsAddIMAccount"
|
||||
label="&addIMAccountButton.label;"
|
||||
accesskey="&addIMAccountButton.accesskey;"
|
||||
prefstring="mail.disable_new_account_addition"
|
||||
oncommand="AddIMAccount(event); event.stopPropagation();"/>
|
||||
<menuitem id="accountActionsAddFeedAccount"
|
||||
label="&addFeedAccountButton.label;"
|
||||
accesskey="&addFeedAccountButton.accesskey;"
|
||||
prefstring="mail.disable_new_account_addition"
|
||||
oncommand="AddFeedAccount(event); event.stopPropagation();"/>
|
||||
<menuitem id="accountActionsAddOtherAccount"
|
||||
label="&addOtherAccountButton.label;"
|
||||
accesskey="&addOtherAccountButton.accesskey;"
|
||||
prefstring="mail.disable_new_account_addition"
|
||||
oncommand="onAddAccount(event); event.stopPropagation();"/>
|
||||
<menuseparator id="accountActionsDropdownSep1"/>
|
||||
<menuitem id="accountActionsDropdownSetDefault"
|
||||
label="&setDefaultButton.label;"
|
||||
accesskey="&setDefaultButton.accesskey;"
|
||||
prefstring="mail.disable_button.set_default_account"
|
||||
oncommand="onSetDefault(event); event.stopPropagation();"/>
|
||||
<menuitem id="accountActionsDropdownRemove"
|
||||
label="&removeButton.label;"
|
||||
accesskey="&removeButton.accesskey;"
|
||||
prefstring="mail.disable_button.delete_account"
|
||||
oncommand="onRemoveAccount(event); event.stopPropagation();"/>
|
||||
</menupopup>
|
||||
</button>
|
||||
#else
|
||||
<button label="&addAccountButton.label;" oncommand="onAddAccount(event);" id="addAccountButton"
|
||||
prefstring="mail.disable_new_account_addition"
|
||||
accesskey="&addAccountButton.accesskey;"/>
|
||||
<button label="&setDefaultButton.label;" oncommand="onSetDefault(event);" disabled="true" id="setDefaultButton"
|
||||
prefstring="mail.disable_button.set_default_account"
|
||||
accesskey="&setDefaultButton.accesskey;"/>
|
||||
<button disabled="true" label="&removeButton.label;" oncommand="onRemoveAccount(event);" id="removeButton"
|
||||
prefstring="mail.disable_button.delete_account"
|
||||
accesskey="&removeButton.accesskey;"/>
|
||||
#endif
|
||||
</vbox>
|
||||
|
||||
<iframe id="contentFrame" name="contentFrame" flex="1"/>
|
||||
</hbox>
|
||||
</dialog>
|
||||
992
mailnews/base/prefs/content/AccountWizard.js
Normal file
992
mailnews/base/prefs/content/AccountWizard.js
Normal file
|
|
@ -0,0 +1,992 @@
|
|||
/* -*- Mode: Java; 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/. */
|
||||
|
||||
/* the okCallback is used for sending a callback for the parent window */
|
||||
var okCallback = null;
|
||||
/* The account wizard creates new accounts */
|
||||
|
||||
/*
|
||||
data flow into the account wizard like this:
|
||||
|
||||
For new accounts:
|
||||
* pageData -> Array -> createAccount -> finishAccount
|
||||
|
||||
For accounts coming from the ISP setup:
|
||||
* RDF -> Array -> pageData -> Array -> createAccount -> finishAccount
|
||||
|
||||
for "unfinished accounts"
|
||||
* account -> Array -> pageData -> Array -> finishAccount
|
||||
|
||||
Where:
|
||||
pageData - the actual pages coming out of the Widget State Manager
|
||||
RDF - the ISP datasource
|
||||
Array - associative array of attributes, that very closely
|
||||
resembles the nsIMsgAccount/nsIMsgIncomingServer/nsIMsgIdentity
|
||||
structure
|
||||
createAccount() - creates an account from the above Array
|
||||
finishAccount() - fills an existing account with data from the above Array
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
the account wizard path is something like:
|
||||
|
||||
accounttype -> identity -> server -> login -> accname -> done
|
||||
\-> newsserver ----/
|
||||
|
||||
where the accounttype determines which path to take
|
||||
(server vs. newsserver)
|
||||
*/
|
||||
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
|
||||
var contentWindow;
|
||||
|
||||
var gPageData;
|
||||
|
||||
var nsIMsgIdentity = Components.interfaces.nsIMsgIdentity;
|
||||
var nsIMsgIncomingServer = Components.interfaces.nsIMsgIncomingServer;
|
||||
var gPrefsBundle, gMessengerBundle;
|
||||
|
||||
// the current nsIMsgAccount
|
||||
var gCurrentAccount;
|
||||
|
||||
// default account
|
||||
var gDefaultAccount;
|
||||
|
||||
// the current associative array that
|
||||
// will eventually be dumped into the account
|
||||
var gCurrentAccountData;
|
||||
|
||||
// default picker mode for copies and folders
|
||||
var gDefaultSpecialFolderPickerMode = "0";
|
||||
|
||||
// event handlers
|
||||
function onAccountWizardLoad() {
|
||||
gPrefsBundle = document.getElementById("bundle_prefs");
|
||||
gMessengerBundle = document.getElementById("bundle_messenger");
|
||||
|
||||
if ("testingIspServices" in this) {
|
||||
if ("SetCustomizedWizardDimensions" in this && testingIspServices()) {
|
||||
SetCustomizedWizardDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
/* We are checking here for the callback argument */
|
||||
if (window.arguments && window.arguments[0]) {
|
||||
if(window.arguments[0].okCallback )
|
||||
{
|
||||
//dump("There is okCallback");
|
||||
top.okCallback = window.arguments[0].okCallback;
|
||||
}
|
||||
}
|
||||
|
||||
checkForInvalidAccounts();
|
||||
|
||||
try {
|
||||
gDefaultAccount = MailServices.accounts.defaultAccount;
|
||||
}
|
||||
catch (ex) {
|
||||
// no default account, this is expected the first time you launch mail
|
||||
// on a new profile
|
||||
gDefaultAccount = null;
|
||||
}
|
||||
|
||||
// Set default value for global inbox checkbox
|
||||
var checkGlobalInbox = document.getElementById("deferStorage");
|
||||
try {
|
||||
checkGlobalInbox.checked = Services.prefs.getBoolPref("mail.accountwizard.deferstorage");
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
function onCancel()
|
||||
{
|
||||
if ("ActivationOnCancel" in this && ActivationOnCancel())
|
||||
return false;
|
||||
var firstInvalidAccount = getFirstInvalidAccount();
|
||||
var closeWizard = true;
|
||||
|
||||
// if the user cancels the the wizard when it pops up because of
|
||||
// an invalid account (example, a webmail account that activation started)
|
||||
// we just force create it by setting some values and calling the FinishAccount()
|
||||
// see bug #47521 for the full discussion
|
||||
if (firstInvalidAccount) {
|
||||
var pageData = GetPageData();
|
||||
// set the fullName if it doesn't exist
|
||||
if (!pageData.identity.fullName || !pageData.identity.fullName.value) {
|
||||
setPageData(pageData, "identity", "fullName", "");
|
||||
}
|
||||
|
||||
// set the email if it doesn't exist
|
||||
if (!pageData.identity.email || !pageData.identity.email.value) {
|
||||
setPageData(pageData, "identity", "email", "user@domain.invalid");
|
||||
}
|
||||
|
||||
// call FinishAccount() and not onFinish(), since the "finish"
|
||||
// button may be disabled
|
||||
FinishAccount();
|
||||
}
|
||||
else {
|
||||
// since this is not an invalid account
|
||||
// really cancel if the user hits the "cancel" button
|
||||
// if the length of the account list is less than 1, there are no accounts
|
||||
if (MailServices.accounts.accounts.length < 1) {
|
||||
let confirmMsg = gPrefsBundle.getString("cancelWizard");
|
||||
let confirmTitle = gPrefsBundle.getString("accountWizard");
|
||||
let result = Services.prompt.confirmEx(window, confirmTitle, confirmMsg,
|
||||
(Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_0) +
|
||||
(Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_1),
|
||||
gPrefsBundle.getString('WizardExit'),
|
||||
gPrefsBundle.getString('WizardContinue'),
|
||||
null, null, {value:0});
|
||||
|
||||
if (result == 1)
|
||||
closeWizard = false;
|
||||
}
|
||||
|
||||
if(top.okCallback && closeWizard) {
|
||||
var state = false;
|
||||
top.okCallback(state);
|
||||
}
|
||||
}
|
||||
return closeWizard;
|
||||
}
|
||||
|
||||
function FinishAccount()
|
||||
{
|
||||
try {
|
||||
var pageData = GetPageData();
|
||||
|
||||
var accountData= gCurrentAccountData;
|
||||
|
||||
if (!accountData)
|
||||
{
|
||||
accountData = new Object;
|
||||
// Time to set the smtpRequiresUsername attribute
|
||||
if (!serverIsNntp(pageData))
|
||||
accountData.smtpRequiresUsername = true;
|
||||
}
|
||||
|
||||
// we may need local folders before account is "Finished"
|
||||
// if it's a pop3 account which defers to Local Folders.
|
||||
verifyLocalFoldersAccount();
|
||||
|
||||
PageDataToAccountData(pageData, accountData);
|
||||
|
||||
FixupAccountDataForIsp(accountData);
|
||||
|
||||
// we might be simply finishing another account
|
||||
if (!gCurrentAccount)
|
||||
gCurrentAccount = createAccount(accountData);
|
||||
|
||||
// transfer all attributes from the accountdata
|
||||
finishAccount(gCurrentAccount, accountData);
|
||||
|
||||
setupCopiesAndFoldersServer(gCurrentAccount, getCurrentServerIsDeferred(pageData), accountData);
|
||||
|
||||
if (gCurrentAccount.incomingServer.canBeDefaultServer)
|
||||
EnableCheckMailAtStartUpIfNeeded(gCurrentAccount);
|
||||
|
||||
if (!document.getElementById("downloadMsgs").hidden) {
|
||||
// skip the default biff, we will load messages manually if needed
|
||||
window.opener.gLoadStartFolder = false;
|
||||
if (document.getElementById("downloadMsgs").checked) {
|
||||
window.opener.gNewAccountToLoad = gCurrentAccount; // load messages for new POP account
|
||||
}
|
||||
}
|
||||
|
||||
// in case we crash, force us a save of the prefs file NOW
|
||||
try {
|
||||
MailServices.accounts.saveAccountInfo();
|
||||
}
|
||||
catch (ex) {
|
||||
dump("Error saving account info: " + ex + "\n");
|
||||
}
|
||||
window.close();
|
||||
if(top.okCallback)
|
||||
{
|
||||
var state = true;
|
||||
//dump("finish callback");
|
||||
top.okCallback(state);
|
||||
}
|
||||
}
|
||||
catch(ex) {
|
||||
dump("FinishAccount failed, " + ex +"\n");
|
||||
}
|
||||
}
|
||||
|
||||
// prepopulate pageData with stuff from accountData
|
||||
// use: to prepopulate the wizard with account information
|
||||
function AccountDataToPageData(accountData, pageData)
|
||||
{
|
||||
if (!accountData) {
|
||||
dump("null account data! clearing..\n");
|
||||
// handle null accountData as if it were an empty object
|
||||
// so that we clear-out any old pagedata from a
|
||||
// previous accountdata. The trick is that
|
||||
// with an empty object, accountData.identity.slot is undefined,
|
||||
// so this will clear out the prefill data in setPageData
|
||||
|
||||
accountData = new Object;
|
||||
accountData.incomingServer = new Object;
|
||||
accountData.identity = new Object;
|
||||
accountData.smtp = new Object;
|
||||
}
|
||||
|
||||
var server = accountData.incomingServer;
|
||||
|
||||
if (server.type == undefined) {
|
||||
// clear out the old server data
|
||||
//setPageData(pageData, "accounttype", "mailaccount", undefined);
|
||||
// setPageData(pageData, "accounttype", "newsaccount", undefined);
|
||||
setPageData(pageData, "server", "servertype", undefined);
|
||||
setPageData(pageData, "server", "hostname", undefined);
|
||||
|
||||
}
|
||||
else {
|
||||
if (server.type == "nntp") {
|
||||
setPageData(pageData, "accounttype", "newsaccount", true);
|
||||
setPageData(pageData, "accounttype", "mailaccount", false);
|
||||
setPageData(pageData, "newsserver", "hostname", server.hostName);
|
||||
}
|
||||
else {
|
||||
setPageData(pageData, "accounttype", "mailaccount", true);
|
||||
setPageData(pageData, "accounttype", "newsaccount", false);
|
||||
setPageData(pageData, "server", "servertype", server.type);
|
||||
setPageData(pageData, "server", "hostname", server.hostName);
|
||||
}
|
||||
setPageData(pageData, "accounttype", "otheraccount", false);
|
||||
}
|
||||
|
||||
setPageData(pageData, "login", "username", server.username || "");
|
||||
setPageData(pageData, "login", "password", server.password || "");
|
||||
setPageData(pageData, "accname", "prettyName", server.prettyName || "");
|
||||
setPageData(pageData, "accname", "userset", false);
|
||||
setPageData(pageData, "ispdata", "supplied", false);
|
||||
|
||||
var identity;
|
||||
|
||||
if (accountData.identity) {
|
||||
dump("This is an accountdata\n");
|
||||
identity = accountData.identity;
|
||||
}
|
||||
else if (accountData.identities) {
|
||||
identity = accountData.identities.queryElementAt(0, Components.interfaces.nsIMsgIdentity);
|
||||
dump("this is an account, id= " + identity + "\n");
|
||||
}
|
||||
|
||||
setPageData(pageData, "identity", "email", identity.email || "");
|
||||
setPageData(pageData, "identity", "fullName", identity.fullName || "");
|
||||
|
||||
var smtp;
|
||||
|
||||
if (accountData.smtp) {
|
||||
smtp = accountData.smtp;
|
||||
setPageData(pageData, "server", "smtphostname", smtp.hostname);
|
||||
setPageData(pageData, "login", "smtpusername", smtp.username);
|
||||
}
|
||||
}
|
||||
|
||||
// take data from each page of pageData and dump it into accountData
|
||||
// use: to put results of wizard into a account-oriented object
|
||||
function PageDataToAccountData(pageData, accountData)
|
||||
{
|
||||
if (!accountData.identity)
|
||||
accountData.identity = new Object;
|
||||
if (!accountData.incomingServer)
|
||||
accountData.incomingServer = new Object;
|
||||
if (!accountData.smtp)
|
||||
accountData.smtp = new Object;
|
||||
if (!accountData.pop3)
|
||||
accountData.pop3 = new Object;
|
||||
if (!accountData.imap)
|
||||
accountData.imap = new Object;
|
||||
|
||||
var identity = accountData.identity;
|
||||
var server = accountData.incomingServer;
|
||||
var smtp = accountData.smtp;
|
||||
var pop3 = accountData.pop3;
|
||||
var imap = accountData.imap;
|
||||
|
||||
if (pageData.identity.email)
|
||||
identity.email = pageData.identity.email.value;
|
||||
if (pageData.identity.fullName)
|
||||
identity.fullName = pageData.identity.fullName.value;
|
||||
|
||||
server.type = getCurrentServerType(pageData);
|
||||
server.hostName = getCurrentHostname(pageData);
|
||||
if (getCurrentServerIsDeferred(pageData))
|
||||
{
|
||||
try
|
||||
{
|
||||
let localFoldersServer = MailServices.accounts.localFoldersServer;
|
||||
let localFoldersAccount = MailServices.accounts.FindAccountForServer(localFoldersServer);
|
||||
pop3.deferredToAccount = localFoldersAccount.key;
|
||||
pop3.deferGetNewMail = true;
|
||||
server["ServerType-pop3"] = pop3;
|
||||
}
|
||||
catch (ex) {dump ("exception setting up deferred account" + ex);}
|
||||
}
|
||||
if (serverIsNntp(pageData)) {
|
||||
// this stuff probably not relevant
|
||||
dump("not setting username/password/etc\n");
|
||||
}
|
||||
else {
|
||||
if (pageData.login) {
|
||||
if (pageData.login.username)
|
||||
server.username = pageData.login.username.value;
|
||||
if (pageData.login.password)
|
||||
server.password = pageData.login.password.value;
|
||||
if (pageData.login.smtpusername)
|
||||
smtp.username = pageData.login.smtpusername.value;
|
||||
}
|
||||
|
||||
dump("pageData.server = " + pageData.server + "\n");
|
||||
if (pageData.server) {
|
||||
dump("pageData.server.smtphostname.value = " + pageData.server.smtphostname + "\n");
|
||||
if (pageData.server.smtphostname &&
|
||||
pageData.server.smtphostname.value)
|
||||
smtp.hostname = pageData.server.smtphostname.value;
|
||||
}
|
||||
if (pageData.identity && pageData.identity.smtpServerKey)
|
||||
identity.smtpServerKey = pageData.identity.smtpServerKey.value;
|
||||
|
||||
if (pageData.server.port &&
|
||||
pageData.server.port.value)
|
||||
{
|
||||
if (server.type == 'imap')
|
||||
{
|
||||
imap.port = pageData.server.port.value;
|
||||
server["ServerType-imap"] = imap;
|
||||
}
|
||||
else if (server.type == 'pop3')
|
||||
{
|
||||
pop3.port = pageData.server.port.value;
|
||||
server["ServerType-pop3"] = pop3;
|
||||
}
|
||||
}
|
||||
|
||||
if (pageData.server.leaveMessagesOnServer &&
|
||||
pageData.server.leaveMessagesOnServer.value)
|
||||
{
|
||||
pop3.leaveMessagesOnServer = pageData.server.leaveMessagesOnServer.value;
|
||||
server["ServerType-pop3"] = pop3;
|
||||
}
|
||||
}
|
||||
|
||||
if (pageData.accname) {
|
||||
if (pageData.accname.prettyName)
|
||||
server.prettyName = pageData.accname.prettyName.value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// given an accountData structure, create an account
|
||||
// (but don't fill in any fields, that's for finishAccount()
|
||||
function createAccount(accountData)
|
||||
{
|
||||
// Retrieve the server (data) from the account data.
|
||||
var server = accountData.incomingServer;
|
||||
|
||||
// for news, username is always null
|
||||
var username = (server.type == "nntp") ? null : server.username;
|
||||
dump("MailServices.accounts.createIncomingServer(" +
|
||||
username + ", " + server.hostName + ", " + server.type + ")\n");
|
||||
// Create a (actual) server.
|
||||
server = MailServices.accounts.createIncomingServer(username, server.hostName, server.type);
|
||||
|
||||
dump("MailServices.accounts.createAccount()\n");
|
||||
// Create an account.
|
||||
let account = MailServices.accounts.createAccount();
|
||||
|
||||
// only create an identity for this account if we really have one
|
||||
// (use the email address as a check)
|
||||
if (accountData.identity && accountData.identity.email)
|
||||
{
|
||||
dump("MailServices.accounts.createIdentity()\n");
|
||||
// Create an identity.
|
||||
let identity = MailServices.accounts.createIdentity();
|
||||
|
||||
// New nntp identities should use plain text by default;
|
||||
// we want that GNKSA (The Good Net-Keeping Seal of Approval).
|
||||
if (server.type == "nntp")
|
||||
identity.composeHtml = false;
|
||||
|
||||
account.addIdentity(identity);
|
||||
}
|
||||
|
||||
// we mark the server as invalid so that the account manager won't
|
||||
// tell RDF about the new server - it's not quite finished getting
|
||||
// set up yet, in particular, the deferred storage pref hasn't been set.
|
||||
server.valid = false;
|
||||
// Set the new account to use the new server.
|
||||
account.incomingServer = server;
|
||||
server.valid = true;
|
||||
return account;
|
||||
}
|
||||
|
||||
// given an accountData structure, copy the data into the
|
||||
// given account, incoming server, and so forth
|
||||
function finishAccount(account, accountData)
|
||||
{
|
||||
if (accountData.incomingServer) {
|
||||
|
||||
var destServer = account.incomingServer;
|
||||
var srcServer = accountData.incomingServer;
|
||||
copyObjectToInterface(destServer, srcServer, true);
|
||||
|
||||
// see if there are any protocol-specific attributes
|
||||
// if so, we use the type to get the IID, QueryInterface
|
||||
// as appropriate, then copy the data over
|
||||
dump("srcServer.ServerType-" + srcServer.type + " = " +
|
||||
srcServer["ServerType-" + srcServer.type] + "\n");
|
||||
if (srcServer["ServerType-" + srcServer.type]) {
|
||||
// handle server-specific stuff
|
||||
var IID;
|
||||
try {
|
||||
IID = destServer.protocolInfo.serverIID;
|
||||
} catch (ex) {
|
||||
Components.utils.reportError("Could not get IID for " + srcServer.type + ": " + ex);
|
||||
}
|
||||
|
||||
if (IID) {
|
||||
destProtocolServer = destServer.QueryInterface(IID);
|
||||
srcProtocolServer = srcServer["ServerType-" + srcServer.type];
|
||||
|
||||
dump("Copying over " + srcServer.type + "-specific data\n");
|
||||
copyObjectToInterface(destProtocolServer, srcProtocolServer, false);
|
||||
}
|
||||
}
|
||||
|
||||
account.incomingServer.valid=true;
|
||||
// hack to cause an account loaded notification now the server is valid
|
||||
account.incomingServer = account.incomingServer;
|
||||
}
|
||||
|
||||
// copy identity info
|
||||
var destIdentity = account.identities.length ?
|
||||
account.identities.queryElementAt(0, nsIMsgIdentity) :
|
||||
null;
|
||||
|
||||
if (destIdentity) // does this account have an identity?
|
||||
{
|
||||
if (accountData.identity && accountData.identity.email) {
|
||||
// fixup the email address if we have a default domain
|
||||
var emailArray = accountData.identity.email.split('@');
|
||||
if (emailArray.length < 2 && accountData.domain) {
|
||||
accountData.identity.email += '@' + accountData.domain;
|
||||
}
|
||||
|
||||
copyObjectToInterface(destIdentity, accountData.identity, true);
|
||||
destIdentity.valid=true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If signature file need to be set, get the path to the signature file.
|
||||
* Signature files, if exist, are placed under default location. Get
|
||||
* default files location for messenger using directory service. Signature
|
||||
* file name should be extracted from the account data to build the complete
|
||||
* path for signature file. Once the path is built, set the identity's signature pref.
|
||||
*/
|
||||
if (destIdentity.attachSignature)
|
||||
{
|
||||
var sigFileName = accountData.signatureFileName;
|
||||
let sigFile = MailServices.mailSession.getDataFilesDir("messenger");
|
||||
sigFile.append(sigFileName);
|
||||
destIdentity.signature = sigFile;
|
||||
}
|
||||
|
||||
if (accountData.smtp.hostname && !destIdentity.smtpServerKey)
|
||||
{
|
||||
// hostname + no key => create a new SMTP server.
|
||||
|
||||
let smtpServer = MailServices.smtp.createServer();
|
||||
var isDefaultSmtpServer;
|
||||
if (!MailServices.smtp.defaultServer.hostname) {
|
||||
MailServices.smtp.defaultServer = smtpServer;
|
||||
isDefaultSmtpServer = true;
|
||||
}
|
||||
|
||||
copyObjectToInterface(smtpServer, accountData.smtp, false);
|
||||
|
||||
// If it's the default server we created, make the identity use
|
||||
// "Use Default" by default.
|
||||
destIdentity.smtpServerKey =
|
||||
(isDefaultSmtpServer) ? "" : smtpServer.key;
|
||||
}
|
||||
} // if the account has an identity...
|
||||
|
||||
if (this.FinishAccountHook != undefined) {
|
||||
FinishAccountHook(accountData.domain);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method used by copyObjectToInterface which attempts to set dest[attribute] as a generic
|
||||
// attribute on the xpconnect object, src.
|
||||
// This routine skips any attribute that begins with ServerType-
|
||||
function setGenericAttribute(dest, src, attribute)
|
||||
{
|
||||
if (!(attribute.toLowerCase().startsWith("servertype-")) && src[attribute])
|
||||
{
|
||||
switch (typeof src[attribute])
|
||||
{
|
||||
case "string":
|
||||
dest.setUnicharAttribute(attribute, src[attribute]);
|
||||
break;
|
||||
case "boolean":
|
||||
dest.setBoolAttribute(attribute, src[attribute]);
|
||||
break;
|
||||
case "number":
|
||||
dest.setIntAttribute(attribute, src[attribute]);
|
||||
break;
|
||||
default:
|
||||
dump("Error: No Generic attribute " + attribute + " found for: " + dest + "\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// copy over all attributes from dest into src that already exist in src
|
||||
// the assumption is that src is an XPConnect interface full of attributes
|
||||
// @param useGenericFallback if we can't set an attribute directly on src, then fall back
|
||||
// and try setting it generically. This assumes that src supports setIntAttribute, setUnicharAttribute
|
||||
// and setBoolAttribute.
|
||||
function copyObjectToInterface(dest, src, useGenericFallback)
|
||||
{
|
||||
if (!dest) return;
|
||||
if (!src) return;
|
||||
|
||||
var attribute;
|
||||
for (attribute in src)
|
||||
{
|
||||
if (dest.__lookupSetter__(attribute))
|
||||
{
|
||||
if (dest[attribute] != src[attribute])
|
||||
dest[attribute] = src[attribute];
|
||||
}
|
||||
else if (useGenericFallback) // fall back to setting the attribute generically
|
||||
setGenericAttribute(dest, src, attribute);
|
||||
} // for each attribute in src we want to copy
|
||||
}
|
||||
|
||||
// check if there already is a "Local Folders"
|
||||
// if not, create it.
|
||||
function verifyLocalFoldersAccount()
|
||||
{
|
||||
var localMailServer = null;
|
||||
try {
|
||||
localMailServer = MailServices.accounts.localFoldersServer;
|
||||
}
|
||||
catch (ex) {
|
||||
// dump("exception in findserver: " + ex + "\n");
|
||||
localMailServer = null;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!localMailServer)
|
||||
{
|
||||
// dump("Creating local mail account\n");
|
||||
// creates a copy of the identity you pass in
|
||||
MailServices.accounts.createLocalMailAccount();
|
||||
try {
|
||||
localMailServer = MailServices.accounts.localFoldersServer;
|
||||
}
|
||||
catch (ex) {
|
||||
dump("error! we should have found the local mail server after we created it.\n");
|
||||
localMailServer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ex) {dump("Error in verifyLocalFoldersAccount" + ex + "\n"); }
|
||||
|
||||
}
|
||||
|
||||
function setupCopiesAndFoldersServer(account, accountIsDeferred, accountData)
|
||||
{
|
||||
try {
|
||||
var server = account.incomingServer;
|
||||
|
||||
// This function sets up the default send preferences. The send preferences
|
||||
// go on identities, so there is no need to continue without any identities.
|
||||
if (server.type == "rss" || account.identities.length == 0)
|
||||
return false;
|
||||
let identity = account.identities.queryElementAt(0, Components.interfaces.nsIMsgIdentity);
|
||||
// For this server, do we default the folder prefs to this server, or to the "Local Folders" server
|
||||
// If it's deferred, we use the local folders account.
|
||||
var defaultCopiesAndFoldersPrefsToServer = !accountIsDeferred && server.defaultCopiesAndFoldersPrefsToServer;
|
||||
|
||||
var copiesAndFoldersServer = null;
|
||||
if (defaultCopiesAndFoldersPrefsToServer)
|
||||
{
|
||||
copiesAndFoldersServer = server;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!MailServices.accounts.localFoldersServer)
|
||||
{
|
||||
dump("error! we should have a local mail server at this point\n");
|
||||
return false;
|
||||
}
|
||||
copiesAndFoldersServer = MailServices.accounts.localFoldersServer;
|
||||
}
|
||||
|
||||
setDefaultCopiesAndFoldersPrefs(identity, copiesAndFoldersServer, accountData);
|
||||
|
||||
} catch (ex) {
|
||||
// return false (meaning we did not setupCopiesAndFoldersServer)
|
||||
// on any error
|
||||
dump("Error in setupCopiesAndFoldersServer: " + ex + "\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function setDefaultCopiesAndFoldersPrefs(identity, server, accountData)
|
||||
{
|
||||
var rootFolder = server.rootFolder;
|
||||
|
||||
// we need to do this or it is possible that the server's draft,
|
||||
// stationery fcc folder will not be in rdf
|
||||
//
|
||||
// this can happen in a couple cases
|
||||
// 1) the first account we create, creates the local mail. since
|
||||
// local mail was just created, it obviously hasn't been opened,
|
||||
// or in rdf..
|
||||
// 2) the account we created is of a type where
|
||||
// defaultCopiesAndFoldersPrefsToServer is true
|
||||
// this since we are creating the server, it obviously hasn't been
|
||||
// opened, or in rdf.
|
||||
//
|
||||
// this makes the assumption that the server's draft, stationery fcc folder
|
||||
// are at the top level (ie subfolders of the root folder.) this works
|
||||
// because we happen to be doing things that way, and if the user changes
|
||||
// that, it will work because to change the folder, it must be in rdf,
|
||||
// coming from the folder cache, in the worst case.
|
||||
var msgFolder = rootFolder.QueryInterface(Components.interfaces.nsIMsgFolder);
|
||||
|
||||
/**
|
||||
* When a new account is created, folders 'Sent', 'Drafts'
|
||||
* and 'Templates' are not created then, but created on demand at runtime.
|
||||
* But we do need to present them as possible choices in the Copies and Folders
|
||||
* UI. To do that, folder URIs have to be created and stored in the prefs file.
|
||||
* So, if there is a need to build special folders, append the special folder
|
||||
* names and create right URIs.
|
||||
*/
|
||||
var folderDelim = "/";
|
||||
|
||||
/* we use internal names known to everyone like Sent, Templates and Drafts */
|
||||
/* if folder names were already given in isp rdf, we use them,
|
||||
otherwise we use internal names known to everyone like Sent, Templates and Drafts */
|
||||
|
||||
// Note the capital F, D and S!
|
||||
var draftFolder = (accountData.identity && accountData.identity.DraftFolder ?
|
||||
accountData.identity.DraftFolder : "Drafts");
|
||||
var stationeryFolder = (accountData.identity && accountData.identity.StationeryFolder ?
|
||||
accountData.identity.StationeryFolder : "Templates");
|
||||
var fccFolder = (accountData.identity && accountData.identity.FccFolder ?
|
||||
accountData.identity.FccFolder : "Sent");
|
||||
|
||||
identity.draftFolder = msgFolder.server.serverURI+ folderDelim + draftFolder;
|
||||
identity.stationeryFolder = msgFolder.server.serverURI+ folderDelim + stationeryFolder;
|
||||
identity.fccFolder = msgFolder.server.serverURI+ folderDelim + fccFolder;
|
||||
|
||||
// Note the capital F, D and S!
|
||||
identity.fccFolderPickerMode = (accountData.identity &&
|
||||
accountData.identity.FccFolder ? 1 : gDefaultSpecialFolderPickerMode);
|
||||
identity.draftsFolderPickerMode = (accountData.identity &&
|
||||
accountData.identity.DraftFolder ? 1 : gDefaultSpecialFolderPickerMode);
|
||||
identity.tmplFolderPickerMode = (accountData.identity &&
|
||||
accountData.identity.StationeryFolder ? 1 : gDefaultSpecialFolderPickerMode);
|
||||
}
|
||||
|
||||
function AccountExists(userName, hostName, serverType)
|
||||
{
|
||||
return MailServices.accounts.findRealServer(userName, hostName, serverType, 0);
|
||||
}
|
||||
|
||||
function getFirstInvalidAccount()
|
||||
{
|
||||
let invalidAccounts = getInvalidAccounts(MailServices.accounts.accounts);
|
||||
|
||||
if (invalidAccounts.length > 0)
|
||||
return invalidAccounts[0];
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
function checkForInvalidAccounts()
|
||||
{
|
||||
var firstInvalidAccount = getFirstInvalidAccount();
|
||||
|
||||
if (firstInvalidAccount) {
|
||||
var pageData = GetPageData();
|
||||
dump("We have an invalid account, " + firstInvalidAccount + ", let's use that!\n");
|
||||
gCurrentAccount = firstInvalidAccount;
|
||||
|
||||
// there's a possibility that the invalid account has ISP defaults
|
||||
// as well.. so first pre-fill accountData with ISP info, then
|
||||
// overwrite it with the account data
|
||||
|
||||
|
||||
var identity =
|
||||
firstInvalidAccount.identities.queryElementAt(0, nsIMsgIdentity);
|
||||
|
||||
var accountData = null;
|
||||
// If there is a email address already provided, try to get to other ISP defaults.
|
||||
// If not, get pre-configured data, if any.
|
||||
if (identity.email) {
|
||||
dump("Invalid account: trying to get ISP data for " + identity.email + "\n");
|
||||
accountData = getIspDefaultsForEmail(identity.email);
|
||||
dump("Invalid account: Got " + accountData + "\n");
|
||||
|
||||
// account -> accountData -> pageData
|
||||
accountData = AccountToAccountData(firstInvalidAccount, accountData);
|
||||
}
|
||||
else {
|
||||
accountData = getPreConfigDataForAccount(firstInvalidAccount);
|
||||
}
|
||||
|
||||
AccountDataToPageData(accountData, pageData);
|
||||
|
||||
gCurrentAccountData = accountData;
|
||||
|
||||
setupWizardPanels();
|
||||
// Set the page index to identity page.
|
||||
document.documentElement.pageIndex = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Transfer all invalid account information to AccountData. Also, get those special
|
||||
// preferences (not associated with any interfaces but preconfigurable via prefs or rdf files)
|
||||
// like whether not the smtp server associated with this account requires
|
||||
// a user name (mail.identity.<id_key>.smtpRequiresUsername) and the choice of skipping
|
||||
// panels (mail.identity.<id_key>.wizardSkipPanels).
|
||||
function getPreConfigDataForAccount(account)
|
||||
{
|
||||
var accountData = new Object;
|
||||
accountData = new Object;
|
||||
accountData.incomingServer = new Object;
|
||||
accountData.identity = new Object;
|
||||
accountData.smtp = new Object;
|
||||
|
||||
accountData = AccountToAccountData(account, null);
|
||||
|
||||
let identity = account.identities.queryElementAt(0, nsIMsgIdentity);
|
||||
|
||||
try {
|
||||
var skipPanelsPrefStr = "mail.identity." + identity.key + ".wizardSkipPanels";
|
||||
accountData.wizardSkipPanels = Services.prefs.getCharPref(skipPanelsPrefStr);
|
||||
|
||||
if (identity.smtpServerKey) {
|
||||
let smtpServer = MailServices.smtp.getServerByKey(identity.smtpServerKey);
|
||||
accountData.smtp = smtpServer;
|
||||
|
||||
var smtpRequiresUsername = false;
|
||||
var smtpRequiresPrefStr = "mail.identity." + identity.key + ".smtpRequiresUsername";
|
||||
smtpRequiresUsername = Services.prefs.getBoolPref(smtpRequiresPrefStr);
|
||||
accountData.smtpRequiresUsername = smtpRequiresUsername;
|
||||
}
|
||||
}
|
||||
catch(ex) {
|
||||
// reached here as special identity pre-configuration prefs
|
||||
// (wizardSkipPanels, smtpRequiresUsername) are not defined.
|
||||
}
|
||||
|
||||
return accountData;
|
||||
}
|
||||
|
||||
function AccountToAccountData(account, defaultAccountData)
|
||||
{
|
||||
dump("AccountToAccountData(" + account + ", " +
|
||||
defaultAccountData + ")\n");
|
||||
var accountData = defaultAccountData;
|
||||
if (!accountData)
|
||||
accountData = new Object;
|
||||
|
||||
accountData.incomingServer = account.incomingServer;
|
||||
accountData.identity = account.identities.queryElementAt(0, nsIMsgIdentity);
|
||||
accountData.smtp = MailServices.smtp.defaultServer;
|
||||
|
||||
return accountData;
|
||||
}
|
||||
|
||||
// sets the page data, automatically creating the arrays as necessary
|
||||
function setPageData(pageData, tag, slot, value) {
|
||||
if (!pageData[tag]) pageData[tag] = [];
|
||||
|
||||
if (value == undefined) {
|
||||
// clear out this slot
|
||||
if (pageData[tag][slot]) delete pageData[tag][slot];
|
||||
}
|
||||
else {
|
||||
// pre-fill this slot
|
||||
if (!pageData[tag][slot]) pageData[tag][slot] = [];
|
||||
pageData[tag][slot].id = slot;
|
||||
pageData[tag][slot].value = value;
|
||||
}
|
||||
}
|
||||
|
||||
// value of checkbox on the first page
|
||||
function serverIsNntp(pageData) {
|
||||
if (pageData.accounttype.newsaccount)
|
||||
return pageData.accounttype.newsaccount.value;
|
||||
return false;
|
||||
}
|
||||
|
||||
function getUsernameFromEmail(aEmail, aEnsureDomain)
|
||||
{
|
||||
var username = aEmail.substr(0, aEmail.indexOf("@"));
|
||||
if (aEnsureDomain && gCurrentAccountData && gCurrentAccountData.domain)
|
||||
username += '@' + gCurrentAccountData.domain;
|
||||
return username;
|
||||
}
|
||||
|
||||
function getCurrentUserName(pageData)
|
||||
{
|
||||
var userName = "";
|
||||
|
||||
if (pageData.login) {
|
||||
if (pageData.login.username) {
|
||||
userName = pageData.login.username.value;
|
||||
}
|
||||
}
|
||||
if (userName == "") {
|
||||
var email = pageData.identity.email.value;
|
||||
userName = getUsernameFromEmail(email, false);
|
||||
}
|
||||
return userName;
|
||||
}
|
||||
|
||||
function getCurrentServerType(pageData) {
|
||||
var servertype = "pop3"; // hopefully don't resort to default!
|
||||
if (serverIsNntp(pageData))
|
||||
servertype = "nntp";
|
||||
else if (pageData.server && pageData.server.servertype)
|
||||
servertype = pageData.server.servertype.value;
|
||||
return servertype;
|
||||
}
|
||||
|
||||
function getCurrentServerIsDeferred(pageData) {
|
||||
var serverDeferred = false;
|
||||
if (getCurrentServerType(pageData) == "pop3" && pageData.server && pageData.server.deferStorage)
|
||||
serverDeferred = pageData.server.deferStorage.value;
|
||||
|
||||
return serverDeferred;
|
||||
}
|
||||
|
||||
function getCurrentHostname(pageData) {
|
||||
if (serverIsNntp(pageData))
|
||||
return pageData.newsserver.hostname.value;
|
||||
else
|
||||
return pageData.server.hostname.value;
|
||||
}
|
||||
|
||||
function GetPageData()
|
||||
{
|
||||
if (!gPageData)
|
||||
gPageData = new Object;
|
||||
|
||||
return gPageData;
|
||||
}
|
||||
|
||||
function PrefillAccountForIsp(ispName)
|
||||
{
|
||||
dump("AccountWizard.prefillAccountForIsp(" + ispName + ")\n");
|
||||
|
||||
var ispData = getIspDefaultsForUri(ispName);
|
||||
|
||||
var pageData = GetPageData();
|
||||
|
||||
if (!ispData) {
|
||||
SetCurrentAccountData(null);
|
||||
return;
|
||||
}
|
||||
|
||||
// prefill the rest of the wizard
|
||||
dump("PrefillAccountForISP: filling with " + ispData + "\n");
|
||||
SetCurrentAccountData(ispData);
|
||||
AccountDataToPageData(ispData, pageData);
|
||||
|
||||
setPageData(pageData, "ispdata", "supplied", true);
|
||||
}
|
||||
|
||||
// does any cleanup work for the the account data
|
||||
// - sets the username from the email address if it's not already set
|
||||
// - anything else?
|
||||
function FixupAccountDataForIsp(accountData)
|
||||
{
|
||||
// no fixup for news
|
||||
// setting the username does bad things
|
||||
// see bugs #42105 and #154213
|
||||
if (accountData.incomingServer.type == "nntp")
|
||||
return;
|
||||
|
||||
var email = accountData.identity.email;
|
||||
|
||||
// The identity might not have an email address, which is what the rest of
|
||||
// this function is looking for.
|
||||
if (!email)
|
||||
return;
|
||||
|
||||
// fix up the username
|
||||
if (!accountData.incomingServer.username)
|
||||
accountData.incomingServer.username =
|
||||
getUsernameFromEmail(email, accountData.incomingServerUserNameRequiresDomain);
|
||||
|
||||
if (!accountData.smtp.username &&
|
||||
accountData.smtpRequiresUsername) {
|
||||
// fix for bug #107953
|
||||
// if incoming hostname is same as smtp hostname
|
||||
// use the server username (instead of the email username)
|
||||
if (accountData.smtp.hostname == accountData.incomingServer.hostName &&
|
||||
accountData.smtpUserNameRequiresDomain == accountData.incomingServerUserNameRequiresDomain)
|
||||
accountData.smtp.username = accountData.incomingServer.username;
|
||||
else
|
||||
accountData.smtp.username = getUsernameFromEmail(email, accountData.smtpUserNameRequiresDomain);
|
||||
}
|
||||
}
|
||||
|
||||
function SetCurrentAccountData(accountData)
|
||||
{
|
||||
// dump("Setting current account data (" + gCurrentAccountData + ") to " + accountData + "\n");
|
||||
gCurrentAccountData = accountData;
|
||||
}
|
||||
|
||||
// flush the XUL cache - just for debugging purposes - not called
|
||||
function onFlush() {
|
||||
Services.prefs.setBoolPref("nglayout.debug.disable_xul_cache", true);
|
||||
Services.prefs.setBoolPref("nglayout.debug.disable_xul_cache", false);
|
||||
}
|
||||
|
||||
/** If there are no default accounts..
|
||||
* this is will be the new default, so enable
|
||||
* check for mail at startup
|
||||
*/
|
||||
function EnableCheckMailAtStartUpIfNeeded(newAccount)
|
||||
{
|
||||
// Check if default account exists and if that account is alllowed to be
|
||||
// a default account. If no such account, make this one as the default account
|
||||
// and turn on the new mail check at startup for the current account
|
||||
if (!(gDefaultAccount && gDefaultAccount.incomingServer.canBeDefaultServer)) {
|
||||
MailServices.accounts.defaultAccount = newAccount;
|
||||
newAccount.incomingServer.loginAtStartUp = true;
|
||||
newAccount.incomingServer.downloadOnBiff = true;
|
||||
}
|
||||
}
|
||||
|
||||
function SetSmtpRequiresUsernameAttribute(accountData)
|
||||
{
|
||||
// If this is the default server, time to set the smtp user name
|
||||
// Set the generic attribute for requiring user name for smtp to true.
|
||||
// ISPs can override the pref via rdf files.
|
||||
if (!(gDefaultAccount && gDefaultAccount.incomingServer.canBeDefaultServer)) {
|
||||
accountData.smtpRequiresUsername = true;
|
||||
}
|
||||
}
|
||||
|
||||
function setNextPage(currentPageId, nextPageId) {
|
||||
var currentPage = document.getElementById(currentPageId);
|
||||
currentPage.next = nextPageId;
|
||||
}
|
||||
371
mailnews/base/prefs/content/AccountWizard.xul
Normal file
371
mailnews/base/prefs/content/AccountWizard.xul
Normal file
|
|
@ -0,0 +1,371 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/accountWizard.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE wizard SYSTEM "chrome://messenger/locale/AccountWizard.dtd">
|
||||
|
||||
<wizard id="AccountWizard" title="&windowTitle.label;"
|
||||
onwizardcancel="return onCancel();"
|
||||
onwizardfinish="return FinishAccount();"
|
||||
#ifdef MOZ_THUNDERBIRD
|
||||
onload="onAccountWizardLoad(); initAccountWizardTB(window.arguments);"
|
||||
#else
|
||||
onload="onAccountWizardLoad();"
|
||||
#endif
|
||||
style="&accountWizard.size;"
|
||||
xmlns:nc="http://home.netscape.com/NC-rdf#"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<stringbundle id="bundle_prefs" src="chrome://messenger/locale/prefs.properties"/>
|
||||
<stringbundle id="bundle_messenger" src="chrome://messenger/locale/messenger.properties"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/accountUtils.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/amUtils.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/AccountWizard.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/ispUtils.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/aw-accounttype.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/aw-identity.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/aw-incoming.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/aw-outgoing.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/aw-accname.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/aw-done.js"/>
|
||||
|
||||
<!-- Account Type page : Displays choices of mail and news accounts that user can create -->
|
||||
<wizardpage id="accounttype" pageid="accounttype"
|
||||
label="&accountTypeTitle.label;"
|
||||
onpageshow="document.documentElement.canAdvance = true;"
|
||||
onpageadvanced="return acctTypePageUnload();">
|
||||
<vbox flex="1">
|
||||
<description>&accountSetupInfo2.label;</description>
|
||||
<description>&accountTypeDesc2.label;</description>
|
||||
<label control="acctyperadio">&accountTypeDirections.label;</label>
|
||||
<separator/>
|
||||
<radiogroup id="acctyperadio" >
|
||||
#ifndef MOZ_THUNDERBIRD
|
||||
<radio id="mailaccount" value="mailaccount"
|
||||
label="&accountTypeMail.label;" accesskey="&accountTypeMail.accesskey;"
|
||||
selected="true"/>
|
||||
#endif
|
||||
<vbox datasources="rdf:ispdefaults"
|
||||
containment="http://home.netscape.com/NC-rdf#providers"
|
||||
id="ispBox"
|
||||
ref="NC:ispinfo">
|
||||
<template>
|
||||
<rule nc:wizardShow="true">
|
||||
<radio uri="..."
|
||||
value="rdf:http://home.netscape.com/NC-rdf#wizardShortName"
|
||||
label="rdf:http://home.netscape.com/NC-rdf#wizardLongName"
|
||||
accesskey="rdf:http://home.netscape.com/NC-rdf#wizardLongNameAccesskey"/>
|
||||
</rule>
|
||||
</template>
|
||||
</vbox>
|
||||
<radio id="newsaccount" value="newsaccount"
|
||||
label="&accountTypeNews.label;" accesskey="&accountTypeNews.accesskey;"/>
|
||||
</radiogroup>
|
||||
</vbox>
|
||||
</wizardpage>
|
||||
|
||||
<!-- Identity page : Collects user's full name and email address -->
|
||||
<wizardpage id="identitypage" pageid="identitypage"
|
||||
label="&identityTitle.label;"
|
||||
onpageshow="return identityPageInit();"
|
||||
onpageadvanced="return identityPageUnload();">
|
||||
<vbox flex="1">
|
||||
<description>&identityDesc.label;</description>
|
||||
<separator/>
|
||||
<description>&fullnameDesc.label; &fullnameExample.label;</description>
|
||||
<separator class="thin"/>
|
||||
<hbox align="center">
|
||||
<label class="awIdentityLabel" value="&fullnameLabel.label;"
|
||||
accesskey="&fullnameLabel.accesskey;" control="fullName"/>
|
||||
<textbox mailtype="identity" wsm_persist="true" name="fullName" id="fullName" flex="1" oninput="identityPageValidate();"/>
|
||||
</hbox>
|
||||
<separator/>
|
||||
<grid>
|
||||
<columns>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row>
|
||||
<description id="emailDescText"/>
|
||||
</row>
|
||||
<separator class="thin"/>
|
||||
<row>
|
||||
<hbox align="center">
|
||||
<label class="awIdentityLabel" id="emailFieldLabel" value="&emailLabel.label;"
|
||||
accesskey="&emailLabel.accesskey;" control="email"/>
|
||||
<hbox class="uri-element" align="center" flex="1">
|
||||
<textbox wsm_persist="true" mailtype="identity" name="email"
|
||||
oninput="identityPageValidate();"
|
||||
id="email" flex="6" class="uri-element"/>
|
||||
<label id="postEmailText"/>
|
||||
</hbox>
|
||||
</hbox>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</vbox>
|
||||
</wizardpage>
|
||||
|
||||
<!-- Incoming page : User can choose to create mail account of his choice, POP3 or IMAP -->
|
||||
<!-- Collects incoming server name and login name. -->
|
||||
<!-- Login name is prefilled with user id from the email address provided in identity page -->
|
||||
<!-- User can enter a login name here if it is different from the user id of his/her email address -->
|
||||
<wizardpage id="incomingpage" pageid="incomingpage"
|
||||
label="&incomingTitle.label;"
|
||||
onpageshow="return incomingPageInit();"
|
||||
onpageadvanced="return incomingPageUnload();">
|
||||
<vbox flex="1">
|
||||
<vbox id="serverTypeBox">
|
||||
<label control="servertype">&incomingServerTypeDesc.label;</label>
|
||||
<separator class="thin"/>
|
||||
<hbox align="center" class="serverDataBox">
|
||||
<!-- The initial value for the servertype radiogroup is set in onInit() -->
|
||||
<radiogroup id="servertype" wsm_persist="true" orient="horizontal">
|
||||
<radio group="servertype" value="pop3" id="pop3" label="&popType.label;"
|
||||
wsm_persist="true" oncommand="setServerType();" accesskey="&popType.accesskey;"/>
|
||||
<radio group="servertype" value="imap" id="imap" label="&imapType.label;"
|
||||
wsm_persist="true" oncommand="setServerType();" accesskey="&imapType.accesskey;"/>
|
||||
</radiogroup>
|
||||
<label id="serverPortLabel" control="serverPort"
|
||||
accesskey="&portNum.accesskey;"
|
||||
value="&portNum.label;"/>
|
||||
<textbox id="serverPort" type="number" size="3" max="65535"/>
|
||||
<label id="defaultPortLabel" value="&defaultPortLabel.label;"/>
|
||||
<label id="defaultPortValue" value="&defaultPortValue.label;"/>
|
||||
</hbox>
|
||||
<separator/>
|
||||
</vbox>
|
||||
|
||||
<vbox id="incomingServerbox">
|
||||
<description>&incomingServer.description;</description>
|
||||
<hbox align="center" class="serverDataBox">
|
||||
<label class="label, serverLabel"
|
||||
value="&incomingServer.label;"
|
||||
accesskey="&incomingServer.accesskey;"
|
||||
control="incomingServer"/>
|
||||
<textbox wsm_persist="true"
|
||||
id="incomingServer"
|
||||
flex="1"
|
||||
class="uri-element"
|
||||
oninput="incomingPageValidate();"/>
|
||||
</hbox>
|
||||
<hbox id="leaveMsgsOnSrvrBox" class="indent">
|
||||
<checkbox id="leaveMessagesOnServer"
|
||||
label="&leaveMsgsOnSrvr.label;"
|
||||
accesskey="&leaveMsgsOnSrvr.accesskey;"
|
||||
wsm_persist="true"
|
||||
oncommand="setServerPrefs(this);"
|
||||
checked="true"/>
|
||||
</hbox>
|
||||
<separator/>
|
||||
</vbox>
|
||||
<description>&incomingUsername.description;</description>
|
||||
<separator class="thin"/>
|
||||
<hbox align="center">
|
||||
<label class="label"
|
||||
value="&incomingUsername.label;"
|
||||
style="width: 8em;"
|
||||
accesskey="&incomingUsername.accesskey;"
|
||||
control="username"/>
|
||||
<textbox id="username"
|
||||
wsm_persist="true"
|
||||
flex="1"
|
||||
oninput="incomingPageValidate();"/>
|
||||
</hbox>
|
||||
<vbox id="deferStorageBox">
|
||||
<separator class="groove"/>
|
||||
<description> &deferStorageDesc.label;</description>
|
||||
<hbox>
|
||||
<checkbox id="deferStorage"
|
||||
label="&deferStorage.label;"
|
||||
accesskey="&deferStorage.accesskey;"
|
||||
checked="true"
|
||||
wsm_persist="true"
|
||||
oncommand="setServerPrefs(this);"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</vbox>
|
||||
</wizardpage>
|
||||
|
||||
<!-- Outgoing page : Collects outgoing server name and login name. -->
|
||||
<!-- Outgoing server name is collected if there isn't one already -->
|
||||
<!-- Login name is prefilled with user id from the email address provided in identity page -->
|
||||
<!-- User can enter a login name here if it is different from the user id of his/her email address -->
|
||||
<wizardpage id="outgoingpage" pageid="outgoingpage"
|
||||
label="&outgoingTitle.label;"
|
||||
onpageshow="return outgoingPageInit();"
|
||||
onpageadvanced="return outgoingPageUnload();">
|
||||
<vbox flex="1">
|
||||
<vbox id="noSmtp">
|
||||
<description>&outgoingServer.description;</description>
|
||||
<hbox align="center" class="serverDataBox">
|
||||
<label class="label, serverLabel"
|
||||
value="&outgoingServer.label;"
|
||||
accesskey="&outgoingServer.accesskey;"
|
||||
control="smtphostname"/>
|
||||
<textbox id="smtphostname"
|
||||
wsm_persist="true"
|
||||
flex="1"
|
||||
class="uri-element"
|
||||
oninput="outgoingPageValidate();"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<vbox id="haveSmtp">
|
||||
<description id="smtpStaticText1"
|
||||
style="width: 200px;"
|
||||
prefix="&haveSmtp1.prefix;"
|
||||
suffix="&haveSmtp1.suffix3; &modifyOutgoing.suffix;">*</description>
|
||||
</vbox>
|
||||
|
||||
<vbox id="loginSet1">
|
||||
<description>&outgoingUsername.description;</description>
|
||||
<separator class="thin"/>
|
||||
<hbox align="center">
|
||||
<label class="label"
|
||||
value="&outgoingUsername.label;"
|
||||
style="width: 8em;"
|
||||
accesskey="&outgoingUsername.accesskey;"
|
||||
control="smtpusername"/>
|
||||
<textbox id="smtpusername" wsm_persist="true" flex="1"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<vbox id="loginSet2" hidden="true">
|
||||
<description id="smtpStaticText2" style="width: 200px;" prefix="&haveSmtp2.prefix;"
|
||||
suffix="&haveSmtp2.suffix3; &modifyOutgoing.suffix;">*</description>
|
||||
</vbox>
|
||||
|
||||
<vbox id="loginSet3" hidden="true">
|
||||
<description id="smtpStaticText3" style="width: 200px;" prefix="&haveSmtp3.prefix;"
|
||||
suffix="&haveSmtp3.suffix3; &modifyOutgoing.suffix;">*</description>
|
||||
</vbox>
|
||||
|
||||
</vbox>
|
||||
</wizardpage>
|
||||
|
||||
<!-- News Server page : Collects the News groups server name -->
|
||||
<wizardpage id="newsserver" pageid="newsserver"
|
||||
label="&incomingTitle.label;"
|
||||
onpageshow="return incomingPageInit();"
|
||||
onpageadvanced="return incomingPageUnload();">
|
||||
<vbox flex="1">
|
||||
<description>&newsServerNameDesc.label;</description>
|
||||
<separator class="thin"/>
|
||||
<hbox align="center">
|
||||
<label control="newsServer" value="&newsServerLabel.label;" accesskey="&newsServerLabel.accesskey;" style="width: 8em;"/>
|
||||
<textbox id="newsServer"
|
||||
wsm_persist="true"
|
||||
flex="1"
|
||||
class="uri-element"
|
||||
oninput="incomingPageValidate();"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</wizardpage>
|
||||
|
||||
<!-- Account name page : User gets a choice to enter a pretty name for the account -->
|
||||
<!-- Defaults : Mail account -> Email address, Newsgroup account -> Newsgroup server name -->
|
||||
<wizardpage id="accnamepage" pageid="accnamepage"
|
||||
label="&accnameTitle.label;"
|
||||
onpageshow="return acctNamePageInit();"
|
||||
onpageadvanced="return acctNamePageUnload();">
|
||||
<vbox flex="1">
|
||||
<description>&accnameDesc.label;</description>
|
||||
<separator class="thin"/>
|
||||
<hbox align="center">
|
||||
<label class="label" value="&accnameLabel.label;" style="width: 8em;"
|
||||
accesskey="&accnameLabel.accesskey;" control="prettyName"/>
|
||||
<textbox id="prettyName" size="40" wsm_persist="true" flex="1" oninput="acctNamePageValidate();"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</wizardpage>
|
||||
|
||||
<!-- Done page : this page summarizes information collected to create a mail/news account -->
|
||||
<wizardpage id="done" pageid="done"
|
||||
label="&completionTitle.label;"
|
||||
onpageshow="return donePageInit();">
|
||||
<vbox flex="1">
|
||||
<description>&completionText.label;</description>
|
||||
<separator class="thin"/>
|
||||
<grid>
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center" id="account.name">
|
||||
<label class="label" flex="1" id="account.name.label" value="&accnameLabel.label;"/>
|
||||
<label class="label" id="account.name.text"/>
|
||||
</row>
|
||||
<row align="center" id="identity.email">
|
||||
<label class="label" flex="1" id="identity.email.label" value="&emailLabel.label;"/>
|
||||
<label class="label" id="identity.email.text"/>
|
||||
</row>
|
||||
<row align="center" id="server.username">
|
||||
<label class="label" flex="1" id="server.username.label" value="&incomingUsername.label;"/>
|
||||
<label class="label" id="server.username.text"/>
|
||||
</row>
|
||||
<row align="center" id="server.name">
|
||||
<label class="label" flex="1" id="server.name.label" value="&serverNamePrefix.label;"/>
|
||||
<label class="label" id="server.name.text"/>
|
||||
</row>
|
||||
<row align="center" id="server.type">
|
||||
<label class="label" flex="1" id="server.type.label" value="&serverTypePrefix.label;"/>
|
||||
<label class="label" id="server.type.text"/>
|
||||
</row>
|
||||
<row align="center" id="server.port">
|
||||
<label class="label" id="server.port.label" flex="1" value="&portNum.label;"/>
|
||||
<label class="label" id="server.port.text"/>
|
||||
</row>
|
||||
<row align="center" id="newsServer.name">
|
||||
<label class="label" flex="1" id="newsServer.name.label" value="&newsServerNamePrefix.label;"/>
|
||||
<label class="label" id="newsServer.name.text"/>
|
||||
</row>
|
||||
<row align="center" id="smtpServer.username">
|
||||
<label class="label" flex="1" id="smtpServer.username.label" value="&outgoingUsername.label;"/>
|
||||
<label class="label" id="smtpServer.username.text"/>
|
||||
</row>
|
||||
<row align="center" id="smtpServer.name">
|
||||
<label class="label" flex="1" id="smtpServer.name.label" value="&smtpServerNamePrefix.label;"/>
|
||||
<label class="label" id="smtpServer.name.text"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
<separator/>
|
||||
<hbox id="downloadMsgsBox">
|
||||
<checkbox id="downloadMsgs"
|
||||
label="&downloadOnLogin.label;"
|
||||
accesskey="&downloadOnLogin.accesskey;"
|
||||
hidden="true"
|
||||
checked="true"/>
|
||||
</hbox>
|
||||
<spacer flex="1"/>
|
||||
#ifndef XP_MACOSX
|
||||
<description>&clickFinish.label;</description>
|
||||
#else
|
||||
<description>&clickFinish.labelMac;</description>
|
||||
#endif
|
||||
</vbox>
|
||||
</wizardpage>
|
||||
|
||||
<wizardpage id="ispPage1"/>
|
||||
<wizardpage id="ispPage2"/>
|
||||
<wizardpage id="ispPage3"/>
|
||||
<wizardpage id="ispPage4"/>
|
||||
<wizardpage id="ispPage5"/>
|
||||
<wizardpage id="ispPage6"/>
|
||||
<wizardpage id="ispPage7"/>
|
||||
<wizardpage id="ispPage8"/>
|
||||
<wizardpage id="ispPage9"/>
|
||||
<wizardpage id="ispPage10"/>
|
||||
<wizardpage id="ispPage11"/>
|
||||
<wizardpage id="ispPage12"/>
|
||||
<wizardpage id="ispPage13"/>
|
||||
<wizardpage id="ispPage14"/>
|
||||
<wizardpage id="ispPage15"/>
|
||||
<wizardpage id="ispPage16"/>
|
||||
|
||||
</wizard>
|
||||
46
mailnews/base/prefs/content/SmtpServerEdit.js
Normal file
46
mailnews/base/prefs/content/SmtpServerEdit.js
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
Components.utils.import("resource:///modules/hostnameUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
|
||||
var gSmtpServer;
|
||||
|
||||
function onLoad(event)
|
||||
{
|
||||
gSmtpServer = window.arguments[0].server;
|
||||
initSmtpSettings(gSmtpServer);
|
||||
}
|
||||
|
||||
function onAccept()
|
||||
{
|
||||
if (!isLegalHostNameOrIP(cleanUpHostName(gSmtpHostname.value))) {
|
||||
let prefsBundle = document.getElementById("bundle_prefs");
|
||||
let brandBundle = document.getElementById("bundle_brand");
|
||||
let alertTitle = brandBundle.getString("brandShortName");
|
||||
let alertMsg = prefsBundle.getString("enterValidServerName");
|
||||
Services.prompt.alert(window, alertTitle, alertMsg);
|
||||
|
||||
window.arguments[0].result = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we didn't have an SMTP server to initialize with,
|
||||
// we must be creating one.
|
||||
try {
|
||||
if (!gSmtpServer) {
|
||||
gSmtpServer = MailServices.smtp.createServer();
|
||||
window.arguments[0].addSmtpServer = gSmtpServer.key;
|
||||
}
|
||||
|
||||
saveSmtpSettings(gSmtpServer);
|
||||
} catch (ex) {
|
||||
Components.utils.reportError("Error saving smtp server: " + ex);
|
||||
}
|
||||
|
||||
window.arguments[0].result = true;
|
||||
return true;
|
||||
}
|
||||
28
mailnews/base/prefs/content/SmtpServerEdit.xul
Normal file
28
mailnews/base/prefs/content/SmtpServerEdit.xul
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/messenger.css" type="text/css"?>
|
||||
<?xul-overlay href="chrome://messenger/content/smtpEditOverlay.xul"?>
|
||||
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/dialogs.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE dialog SYSTEM "chrome://messenger/locale/smtpEditOverlay.dtd">
|
||||
|
||||
<dialog title="&smtpEditTitle.label;"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="onLoad();"
|
||||
ondialogaccept="return onAccept();">
|
||||
<stringbundle id="bundle_prefs"
|
||||
src="chrome://messenger/locale/prefs.properties"/>
|
||||
<stringbundle id="bundle_brand"
|
||||
src="chrome://branding/locale/brand.properties"/>
|
||||
<stringbundle id="bundle_messenger"
|
||||
src="chrome://messenger/locale/messenger.properties"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/SmtpServerEdit.js"/>
|
||||
<vbox id="smtpServerEditor"/>
|
||||
</dialog>
|
||||
462
mailnews/base/prefs/content/accountUtils.js
Normal file
462
mailnews/base/prefs/content/accountUtils.js
Normal file
|
|
@ -0,0 +1,462 @@
|
|||
/* -*- Mode: Java; 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/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
|
||||
var gAnyValidIdentity = false; //If there are no valid identities for any account
|
||||
// returns the first account with an invalid server or identity
|
||||
|
||||
var gNewAccountToLoad = null; // used to load new messages if we come from the mail3pane
|
||||
|
||||
function getInvalidAccounts(accounts)
|
||||
{
|
||||
let numAccounts = accounts.length;
|
||||
let invalidAccounts = new Array;
|
||||
let numIdentities = 0;
|
||||
for (let i = 0; i < numAccounts; i++) {
|
||||
let account = accounts.queryElementAt(i, Components.interfaces.nsIMsgAccount);
|
||||
try {
|
||||
if (!account.incomingServer.valid) {
|
||||
invalidAccounts[invalidAccounts.length] = account;
|
||||
// skip to the next account
|
||||
continue;
|
||||
}
|
||||
} catch (ex) {
|
||||
// this account is busted, just keep going
|
||||
continue;
|
||||
}
|
||||
|
||||
var identities = account.identities;
|
||||
numIdentities = identities.length;
|
||||
|
||||
for (var j = 0; j < numIdentities; j++) {
|
||||
let identity = identities.queryElementAt(j, Components.interfaces.nsIMsgIdentity);
|
||||
if (identity.valid) {
|
||||
gAnyValidIdentity = true;
|
||||
}
|
||||
else {
|
||||
invalidAccounts[invalidAccounts.length] = account;
|
||||
}
|
||||
}
|
||||
}
|
||||
return invalidAccounts;
|
||||
}
|
||||
|
||||
function showMailIntegrationDialog() {
|
||||
const nsIShellService = Components.interfaces.nsIShellService;
|
||||
|
||||
try {
|
||||
var shellService = Components.classes["@mozilla.org/suite/shell-service;1"]
|
||||
.getService(nsIShellService);
|
||||
var appTypesCheck = shellService.shouldBeDefaultClientFor &
|
||||
(nsIShellService.MAIL | nsIShellService.NEWS);
|
||||
|
||||
// show the default client dialog only if we have at least one account,
|
||||
// if we should check for the default client, and we want to check if we are
|
||||
// the default for mail/news and are not the default client for mail/news
|
||||
if (appTypesCheck && shellService.shouldCheckDefaultClient &&
|
||||
!shellService.isDefaultClient(true, appTypesCheck))
|
||||
window.openDialog("chrome://communicator/content/defaultClientDialog.xul",
|
||||
"DefaultClient", "modal,centerscreen,chrome,resizable=no");
|
||||
} catch (ex) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that there is at least one account. If not, open a new account wizard.
|
||||
*
|
||||
* @param wizardCallback if the wizard is run, callback when it is done.
|
||||
* @param needsIdentity True only when verifyAccounts is called from the
|
||||
* compose window. This last condition is so that we open
|
||||
* the account wizard if the user does not have any
|
||||
* identities defined and tries to compose mail.
|
||||
* @param wizardOpen optional param that allows the caller to specify a
|
||||
* different method to open a wizard. The wizardOpen method
|
||||
* takes wizardCallback as an argument. The wizardCallback
|
||||
* doesn't take any arguments.
|
||||
*/
|
||||
function verifyAccounts(wizardCallback, needsIdentity, wizardOpen)
|
||||
{
|
||||
var openWizard = false;
|
||||
var prefillAccount;
|
||||
var state=true;
|
||||
var ret = true;
|
||||
|
||||
try {
|
||||
// migrate quoting preferences from global to per account. This function returns
|
||||
// true if it had to migrate, which we will use to mean this is a just migrated
|
||||
// or new profile
|
||||
var newProfile = migrateGlobalQuotingPrefs(MailServices.accounts.allIdentities);
|
||||
|
||||
var accounts = MailServices.accounts.accounts;
|
||||
|
||||
// as long as we have some accounts, we're fine.
|
||||
var accountCount = accounts.length;
|
||||
var invalidAccounts = getInvalidAccounts(accounts);
|
||||
if (invalidAccounts.length > 0 && invalidAccounts.length == accountCount) {
|
||||
prefillAccount = invalidAccounts[0];
|
||||
}
|
||||
|
||||
// if there are no accounts, or all accounts are "invalid"
|
||||
// then kick off the account migration. Or if this is a new (to Mozilla) profile.
|
||||
// MCD can set up accounts without the profile being used yet
|
||||
if (newProfile) {
|
||||
// check if MCD is configured. If not, say this is not a new profile
|
||||
// so that we don't accidentally remigrate non MCD profiles.
|
||||
var adminUrl;
|
||||
try {
|
||||
adminUrl = Services.prefs.getCharPref("autoadmin.global_config_url");
|
||||
}
|
||||
catch (ex) {}
|
||||
if (!adminUrl)
|
||||
newProfile = false;
|
||||
}
|
||||
if ((newProfile && !accountCount) || accountCount == invalidAccounts.length)
|
||||
openWizard = true;
|
||||
|
||||
// openWizard is true if messenger migration returns some kind of
|
||||
// error (including those cases where there is nothing to migrate).
|
||||
// prefillAccount is non-null if there is at least one invalid account.
|
||||
// gAnyValidIdentity is true when you've got at least one *valid*
|
||||
// identity. Since local and RSS folders are identity-less accounts, if you
|
||||
// only have one of those, it will be false.
|
||||
// needsIdentity is true only when verifyAccounts is called from the
|
||||
// compose window. This last condition is so that we open the account
|
||||
// wizard if the user does not have any identities defined and tries to
|
||||
// compose mail.
|
||||
|
||||
if (openWizard || prefillAccount || ((!gAnyValidIdentity) && needsIdentity))
|
||||
{
|
||||
if (wizardOpen != undefined)
|
||||
wizardOpen(wizardCallback)
|
||||
else
|
||||
MsgAccountWizard(wizardCallback);
|
||||
ret = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
var localFoldersExists;
|
||||
try
|
||||
{
|
||||
localFoldersExists = MailServices.accounts.localFoldersServer;
|
||||
}
|
||||
catch (ex)
|
||||
{
|
||||
localFoldersExists = false;
|
||||
}
|
||||
|
||||
// we didn't create the MsgAccountWizard - we need to verify that local folders exists.
|
||||
if (!localFoldersExists)
|
||||
MailServices.accounts.createLocalMailAccount();
|
||||
}
|
||||
|
||||
// This will do nothing on platforms without a shell service
|
||||
const NS_SHELLSERVICE_CID = "@mozilla.org/suite/shell-service;1"
|
||||
if (NS_SHELLSERVICE_CID in Components.classes)
|
||||
{
|
||||
// hack, set a time out to do this, so that the window can load first
|
||||
setTimeout(showMailIntegrationDialog, 0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
catch (ex) {
|
||||
dump("error verifying accounts " + ex + "\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// we do this from a timer because if this is called from the onload=
|
||||
// handler, then the parent window doesn't appear until after the wizard
|
||||
// has closed, and this is confusing to the user
|
||||
function MsgAccountWizard(wizardCallback)
|
||||
{
|
||||
setTimeout(function() { msgOpenAccountWizard(wizardCallback); }, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the Old Mail Account Wizard, or focus it if it's already open.
|
||||
*
|
||||
* @param wizardCallback if the wizard is run, callback when it is done.
|
||||
* @param type - optional account type token, for Tb.
|
||||
* @see msgNewMailAccount below for the new implementation.
|
||||
*/
|
||||
function msgOpenAccountWizard(wizardCallback, type)
|
||||
{
|
||||
gNewAccountToLoad = null;
|
||||
|
||||
window.openDialog("chrome://messenger/content/AccountWizard.xul", "AccountWizard",
|
||||
"chrome,modal,titlebar,centerscreen",
|
||||
{okCallback: wizardCallback, acctType: type});
|
||||
|
||||
loadInboxForNewAccount();
|
||||
|
||||
// If we started with no servers at all and "smtp servers" list selected,
|
||||
// refresh display somehow. Bug 58506.
|
||||
// TODO Better fix: select newly created account (in all cases)
|
||||
if (typeof(getCurrentAccount) == "function" && // in AccountManager, not menu
|
||||
!getCurrentAccount())
|
||||
selectServer(null, null);
|
||||
}
|
||||
|
||||
function initAccountWizardTB(args) {
|
||||
let type = args[0] && args[0].acctType;
|
||||
let selType = type == "newsgroups" ? "newsaccount" :
|
||||
type == "movemail" ? "Movemail" : null;
|
||||
let accountwizard = document.getElementById("AccountWizard");
|
||||
let acctyperadio = document.getElementById("acctyperadio");
|
||||
let feedRadio = acctyperadio.querySelector("radio[value='Feeds']");
|
||||
if (feedRadio)
|
||||
feedRadio.remove();
|
||||
if (selType) {
|
||||
acctyperadio.selectedItem = acctyperadio.querySelector("radio[value='"+selType+"']");
|
||||
accountwizard.advance("identitypage");
|
||||
}
|
||||
else
|
||||
acctyperadio.selectedItem = acctyperadio.getItemAtIndex(0);
|
||||
}
|
||||
|
||||
function AddFeedAccount() {
|
||||
window.openDialog("chrome://messenger-newsblog/content/feedAccountWizard.xul",
|
||||
"", "chrome,modal,titlebar,centerscreen");
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the account settings window on the specified account
|
||||
* and page of settings. If the window is already open it is only focused.
|
||||
*
|
||||
* @param selectPage The xul file name for the viewing page or
|
||||
* null for the account main page. Other pages are
|
||||
* 'am-server.xul', 'am-copies.xul', 'am-offline.xul',
|
||||
* 'am-addressing.xul', 'am-smtp.xul'
|
||||
* @param aServer The server of the account to select. Optional.
|
||||
*/
|
||||
function MsgAccountManager(selectPage, aServer)
|
||||
{
|
||||
var existingAccountManager = Services.wm.getMostRecentWindow("mailnews:accountmanager");
|
||||
|
||||
if (existingAccountManager)
|
||||
existingAccountManager.focus();
|
||||
else {
|
||||
if (!aServer) {
|
||||
if (typeof GetSelectedMsgFolders === "function") {
|
||||
let folders = GetSelectedMsgFolders();
|
||||
if (folders.length > 0)
|
||||
aServer = folders[0].server;
|
||||
}
|
||||
if (!aServer && (typeof GetDefaultAccountRootFolder === "function")) {
|
||||
let folder = GetDefaultAccountRootFolder();
|
||||
if (folder instanceof Components.interfaces.nsIMsgFolder)
|
||||
aServer = folder.server;
|
||||
}
|
||||
}
|
||||
|
||||
window.openDialog("chrome://messenger/content/AccountManager.xul",
|
||||
"AccountManager",
|
||||
"chrome,centerscreen,modal,titlebar,resizable",
|
||||
{ server: aServer, selectPage: selectPage });
|
||||
}
|
||||
}
|
||||
|
||||
function loadInboxForNewAccount()
|
||||
{
|
||||
// gNewAccountToLoad is set in the final screen of the Account Wizard if a POP account
|
||||
// was created, the download messages box is checked, and the wizard was opened from the 3pane
|
||||
if (gNewAccountToLoad) {
|
||||
var rootMsgFolder = gNewAccountToLoad.incomingServer.rootMsgFolder;
|
||||
const kInboxFlag = Components.interfaces.nsMsgFolderFlags.Inbox;
|
||||
var inboxFolder = rootMsgFolder.getFolderWithFlags(kInboxFlag);
|
||||
SelectFolder(inboxFolder.URI);
|
||||
window.focus();
|
||||
setTimeout(MsgGetMessage, 0);
|
||||
gNewAccountToLoad = null;
|
||||
}
|
||||
}
|
||||
|
||||
// returns true if we migrated - it knows this because 4.x did not have the
|
||||
// pref mailnews.quotingPrefs.version, so if it's not set, we're either
|
||||
// migrating from 4.x, or a much older version of Mozilla.
|
||||
function migrateGlobalQuotingPrefs(allIdentities)
|
||||
{
|
||||
// if reply_on_top and auto_quote exist then, if non-default
|
||||
// migrate and delete, if default just delete.
|
||||
var reply_on_top = 0;
|
||||
var auto_quote = true;
|
||||
var quotingPrefs = 0;
|
||||
var migrated = false;
|
||||
try {
|
||||
quotingPrefs = Services.prefs.getIntPref("mailnews.quotingPrefs.version");
|
||||
} catch (ex) {}
|
||||
|
||||
// If the quotingPrefs version is 0 then we need to migrate our preferences
|
||||
if (quotingPrefs == 0) {
|
||||
migrated = true;
|
||||
try {
|
||||
reply_on_top = Services.prefs.getIntPref("mailnews.reply_on_top");
|
||||
auto_quote = Services.prefs.getBoolPref("mail.auto_quote");
|
||||
} catch (ex) {}
|
||||
|
||||
if (!auto_quote || reply_on_top) {
|
||||
let numIdentities = allIdentities.length;
|
||||
var identity = null;
|
||||
for (var j = 0; j < numIdentities; j++) {
|
||||
identity = allIdentities.queryElementAt(j, Components.interfaces.nsIMsgIdentity);
|
||||
if (identity.valid) {
|
||||
identity.autoQuote = auto_quote;
|
||||
identity.replyOnTop = reply_on_top;
|
||||
}
|
||||
}
|
||||
}
|
||||
Services.prefs.setIntPref("mailnews.quotingPrefs.version", 1);
|
||||
}
|
||||
return migrated;
|
||||
}
|
||||
|
||||
// we do this from a timer because if this is called from the onload=
|
||||
// handler, then the parent window doesn't appear until after the wizard
|
||||
// has closed, and this is confusing to the user
|
||||
function NewMailAccount(msgWindow, okCallback, extraData)
|
||||
{
|
||||
if (!msgWindow)
|
||||
throw new Error("NewMailAccount must be given a msgWindow.");
|
||||
|
||||
// Populate the extra data.
|
||||
if (!extraData)
|
||||
extraData = {};
|
||||
extraData.msgWindow = msgWindow;
|
||||
|
||||
let mail3Pane = Services.wm.getMostRecentWindow("mail:3pane");
|
||||
|
||||
if (!extraData.NewMailAccount)
|
||||
extraData.NewMailAccount = NewMailAccount;
|
||||
|
||||
if (!extraData.msgNewMailAccount)
|
||||
extraData.msgNewMailAccount = msgNewMailAccount;
|
||||
|
||||
if (!extraData.NewComposeMessage)
|
||||
extraData.NewComposeMessage = mail3Pane.ComposeMessage;
|
||||
|
||||
if (!extraData.openAddonsMgr)
|
||||
extraData.openAddonsMgr = mail3Pane.openAddonsMgr;
|
||||
|
||||
if (!extraData.okCallback)
|
||||
extraData.okCallback = null;
|
||||
|
||||
if (!extraData.success)
|
||||
extraData.success = false;
|
||||
|
||||
setTimeout(extraData.msgNewMailAccount, 0, msgWindow, okCallback, extraData);
|
||||
}
|
||||
|
||||
function NewMailAccountProvisioner(aMsgWindow, args) {
|
||||
if (!args)
|
||||
args = {};
|
||||
if (!aMsgWindow)
|
||||
aMsgWindow = MailServices.mailSession.topmostMsgWindow;
|
||||
|
||||
args.msgWindow = aMsgWindow;
|
||||
|
||||
let mail3Pane = Services.wm.getMostRecentWindow("mail:3pane");
|
||||
|
||||
// If we couldn't find a 3pane, bail out.
|
||||
if (!mail3Pane) {
|
||||
Components.utils.reportError("Could not find a 3pane to connect to.");
|
||||
return;
|
||||
}
|
||||
|
||||
let tabmail = mail3Pane.document.getElementById("tabmail");
|
||||
|
||||
if (!tabmail) {
|
||||
Components.utils.reportError("Could not find a tabmail in the 3pane!");
|
||||
return;
|
||||
}
|
||||
|
||||
// If there's already an accountProvisionerTab open, just focus it instead
|
||||
// of opening a new dialog.
|
||||
let apTab = tabmail.getTabInfoForCurrentOrFirstModeInstance(
|
||||
tabmail.tabModes["accountProvisionerTab"]);
|
||||
|
||||
if (apTab) {
|
||||
tabmail.switchToTab(apTab);
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX make sure these are all defined in all contexts... to be on the safe
|
||||
// side, just get a mail:3pane and borrow the functions from it?
|
||||
if (!args.NewMailAccount)
|
||||
args.NewMailAccount = NewMailAccount;
|
||||
|
||||
if (!args.msgNewMailAccount)
|
||||
args.msgNewMailAccount = msgNewMailAccount;
|
||||
|
||||
if (!args.NewComposeMessage)
|
||||
args.NewComposeMessage = mail3Pane.ComposeMessage;
|
||||
|
||||
if (!args.openAddonsMgr)
|
||||
args.openAddonsMgr = mail3Pane.openAddonsMgr;
|
||||
|
||||
if (!args.okCallback)
|
||||
args.okCallback = null;
|
||||
|
||||
let windowParams = "chrome,titlebar,centerscreen,width=640,height=480";
|
||||
|
||||
if (!args.success) {
|
||||
args.success = false;
|
||||
// If we're not opening up the success dialog, then our window should be
|
||||
// modal.
|
||||
windowParams = "modal," + windowParams;
|
||||
}
|
||||
|
||||
// NOTE: If you're a developer, and you notice that the jQuery code in
|
||||
// accountProvisioner.xhtml isn't throwing errors or warnings, that's due
|
||||
// to bug 688273. Just make the window non-modal to get those errors and
|
||||
// warnings back, and then clear this comment when bug 688273 is closed.
|
||||
window.openDialog(
|
||||
"chrome://messenger/content/newmailaccount/accountProvisioner.xhtml",
|
||||
"AccountCreation",
|
||||
windowParams,
|
||||
args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the New Mail Account Wizard, or focus it if it's already open.
|
||||
*
|
||||
* @param msgWindow a msgWindow for us to use to verify the accounts.
|
||||
* @param okCallback an optional callback for us to call back to if
|
||||
* everything's okay.
|
||||
* @param extraData an optional param that allows us to pass data in and
|
||||
* out. Used in the upcoming AccountProvisioner add-on.
|
||||
* @see msgOpenAccountWizard above for the previous implementation.
|
||||
*/
|
||||
function msgNewMailAccount(msgWindow, okCallback, extraData)
|
||||
{
|
||||
if (!msgWindow)
|
||||
throw new Error("msgNewMailAccount must be given a msgWindow.");
|
||||
|
||||
let existingWindow = Services.wm.getMostRecentWindow("mail:autoconfig");
|
||||
if (existingWindow) {
|
||||
existingWindow.focus();
|
||||
} else {
|
||||
// disabling modal for the time being, see 688273 REMOVEME
|
||||
window.openDialog("chrome://messenger/content/accountcreation/emailWizard.xul",
|
||||
"AccountSetup", "chrome,titlebar,centerscreen",
|
||||
{msgWindow:msgWindow,
|
||||
okCallback:okCallback,
|
||||
extraData:extraData});
|
||||
}
|
||||
|
||||
/*
|
||||
// TODO: Enable this block of code once the dialog above is made modal.
|
||||
// If we started with no servers at all and "smtp servers" list selected,
|
||||
// refresh display somehow. Bug 58506.
|
||||
// TODO Better fix: select newly created account (in all cases)
|
||||
let existingAccountManager =
|
||||
Services.wm.getMostRecentWindow("mailnews:accountmanager");
|
||||
// in AccountManager, not menu
|
||||
if (existingAccountManager && typeof(getCurrentAccount) == "function" &&
|
||||
!getCurrentAccount()) {
|
||||
selectServer(null, null);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/* -*- Mode: C++; 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/. */
|
||||
|
||||
/**
|
||||
* This class implements nsIBadCertListener. It's job is to prevent "bad cert"
|
||||
* security dialogs from being shown to the user. We call back to the
|
||||
* 'callback' object's method "processCertError" so that it can deal with it as
|
||||
* needed (in the case of autoconfig, setting up temporary overrides).
|
||||
*/
|
||||
function BadCertHandler(callback)
|
||||
{
|
||||
this._init(callback);
|
||||
}
|
||||
|
||||
BadCertHandler.prototype =
|
||||
{
|
||||
_init: function(callback) {
|
||||
this._callback = callback;
|
||||
},
|
||||
|
||||
// Suppress any certificate errors
|
||||
notifyCertProblem: function(socketInfo, status, targetSite) {
|
||||
return this._callback.processCertError(socketInfo, status, targetSite);
|
||||
},
|
||||
|
||||
// nsIInterfaceRequestor
|
||||
getInterface: function(iid) {
|
||||
return this.QueryInterface(iid);
|
||||
},
|
||||
|
||||
// nsISupports
|
||||
QueryInterface: function(iid) {
|
||||
if (!iid.equals(Components.interfaces.nsIBadCertListener2) &&
|
||||
!iid.equals(Components.interfaces.nsIInterfaceRequestor) &&
|
||||
!iid.equals(Components.interfaces.nsISupports))
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
259
mailnews/base/prefs/content/accountcreation/accountConfig.js
Normal file
259
mailnews/base/prefs/content/accountcreation/accountConfig.js
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
/**
|
||||
* This file creates the class AccountConfig, which is a JS object that holds
|
||||
* a configuration for a certain account. It is *not* created in the backend
|
||||
* yet (use aw-createAccount.js for that), and it may be incomplete.
|
||||
*
|
||||
* Several AccountConfig objects may co-exist, e.g. for autoconfig.
|
||||
* One AccountConfig object is used to prefill and read the widgets
|
||||
* in the Wizard UI.
|
||||
* When we autoconfigure, we autoconfig writes the values into a
|
||||
* new object and returns that, and the caller can copy these
|
||||
* values into the object used by the UI.
|
||||
*
|
||||
* See also
|
||||
* <https://wiki.mozilla.org/Thunderbird:Autoconfiguration:ConfigFileFormat>
|
||||
* for values stored.
|
||||
*/
|
||||
|
||||
function AccountConfig()
|
||||
{
|
||||
this.incoming = this.createNewIncoming();
|
||||
this.incomingAlternatives = [];
|
||||
this.outgoing = this.createNewOutgoing();
|
||||
this.outgoingAlternatives = [];
|
||||
this.identity =
|
||||
{
|
||||
// displayed real name of user
|
||||
realname : "%REALNAME%",
|
||||
// email address of user, as shown in From of outgoing mails
|
||||
emailAddress : "%EMAILADDRESS%",
|
||||
};
|
||||
this.inputFields = [];
|
||||
this.domains = [];
|
||||
};
|
||||
AccountConfig.prototype =
|
||||
{
|
||||
// @see createNewIncoming()
|
||||
incoming : null,
|
||||
// @see createNewOutgoing()
|
||||
outgoing : null,
|
||||
/**
|
||||
* Other servers which can be used instead of |incoming|,
|
||||
* in order of decreasing preference.
|
||||
* (|incoming| itself should not be included here.)
|
||||
* { Array of incoming/createNewIncoming() }
|
||||
*/
|
||||
incomingAlternatives : null,
|
||||
outgoingAlternatives : null,
|
||||
// OAuth2 configuration, if needed.
|
||||
oauthSettings : null,
|
||||
// just an internal string to refer to this. Do not show to user.
|
||||
id : null,
|
||||
// who created the config.
|
||||
// { one of kSource* }
|
||||
source : 0,
|
||||
displayName : null,
|
||||
// { Array of { varname (value without %), displayName, exampleValue } }
|
||||
inputFields : null,
|
||||
// email address domains for which this config is applicable
|
||||
// { Array of Strings }
|
||||
domains : null,
|
||||
|
||||
/**
|
||||
* Factory function for incoming and incomingAlternatives
|
||||
*/
|
||||
createNewIncoming : function()
|
||||
{
|
||||
return {
|
||||
// { String-enum: "pop3", "imap", "nntp" }
|
||||
type : null,
|
||||
hostname : null,
|
||||
// { Integer }
|
||||
port : null,
|
||||
// May be a placeholder (starts and ends with %). { String }
|
||||
username : null,
|
||||
password : null,
|
||||
// { enum: 1 = plain, 2 = SSL/TLS, 3 = STARTTLS always, 0 = not inited }
|
||||
// ('TLS when available' is insecure and not supported here)
|
||||
socketType : 0,
|
||||
/**
|
||||
* true when the cert is invalid (and thus SSL useless), because it's
|
||||
* 1) not from an accepted CA (including self-signed certs)
|
||||
* 2) for a different hostname or
|
||||
* 3) expired.
|
||||
* May go back to false when user explicitly accepted the cert.
|
||||
*/
|
||||
badCert : false,
|
||||
/**
|
||||
* How to log in to the server: plaintext or encrypted pw, GSSAPI etc.
|
||||
* Defined by Ci.nsMsgAuthMethod
|
||||
* Same as server pref "authMethod".
|
||||
*/
|
||||
auth : 0,
|
||||
/**
|
||||
* Other auth methods that we think the server supports.
|
||||
* They are ordered by descreasing preference.
|
||||
* (|auth| itself is not included in |authAlternatives|)
|
||||
* {Array of Ci.nsMsgAuthMethod} (same as .auth)
|
||||
*/
|
||||
authAlternatives : null,
|
||||
// in minutes { Integer }
|
||||
checkInterval : 10,
|
||||
loginAtStartup : true,
|
||||
// POP3 only:
|
||||
// Not yet implemented. { Boolean }
|
||||
useGlobalInbox : false,
|
||||
leaveMessagesOnServer : true,
|
||||
daysToLeaveMessagesOnServer : 14,
|
||||
deleteByAgeFromServer : true,
|
||||
// When user hits delete, delete from local store and from server
|
||||
deleteOnServerWhenLocalDelete : true,
|
||||
downloadOnBiff : true,
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Factory function for outgoing and outgoingAlternatives
|
||||
*/
|
||||
createNewOutgoing : function()
|
||||
{
|
||||
return {
|
||||
type : "smtp",
|
||||
hostname : null,
|
||||
port : null, // see incoming
|
||||
username : null, // see incoming. may be null, if auth is 0.
|
||||
password : null, // see incoming. may be null, if auth is 0.
|
||||
socketType : 0, // see incoming
|
||||
badCert : false, // see incoming
|
||||
auth : 0, // see incoming
|
||||
authAlternatives : null, // see incoming
|
||||
addThisServer : true, // if we already have an SMTP server, add this
|
||||
// if we already have an SMTP server, use it.
|
||||
useGlobalPreferredServer : false,
|
||||
// we should reuse an already configured SMTP server.
|
||||
// nsISmtpServer.key
|
||||
existingServerKey : null,
|
||||
// user display value for existingServerKey
|
||||
existingServerLabel : null,
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a deep copy of this object,
|
||||
* i.e. modifying the copy will not affect the original object.
|
||||
*/
|
||||
copy : function()
|
||||
{
|
||||
// Workaround: deepCopy() fails to preserve base obj (instanceof)
|
||||
var result = new AccountConfig();
|
||||
for (var prop in this)
|
||||
result[prop] = deepCopy(this[prop]);
|
||||
|
||||
return result;
|
||||
},
|
||||
isComplete : function()
|
||||
{
|
||||
return (!!this.incoming.hostname && !!this.incoming.port &&
|
||||
!!this.incoming.socketType && !!this.incoming.auth &&
|
||||
!!this.incoming.username &&
|
||||
(!!this.outgoing.existingServerKey ||
|
||||
(!!this.outgoing.hostname && !!this.outgoing.port &&
|
||||
!!this.outgoing.socketType && !!this.outgoing.auth &&
|
||||
!!this.outgoing.username)));
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
// enum consts
|
||||
|
||||
// .source
|
||||
AccountConfig.kSourceUser = 1; // user manually entered the config
|
||||
AccountConfig.kSourceXML = 2; // config from XML from ISP or Mozilla DB
|
||||
AccountConfig.kSourceGuess = 3; // guessConfig()
|
||||
|
||||
|
||||
/**
|
||||
* Some fields on the account config accept placeholders (when coming from XML).
|
||||
*
|
||||
* These are the predefined ones
|
||||
* * %EMAILADDRESS% (full email address of the user, usually entered by user)
|
||||
* * %EMAILLOCALPART% (email address, part before @)
|
||||
* * %EMAILDOMAIN% (email address, part after @)
|
||||
* * %REALNAME%
|
||||
* as well as those defined in account.inputFields.*.varname, with % added
|
||||
* before and after.
|
||||
*
|
||||
* These must replaced with real values, supplied by the user or app,
|
||||
* before the account is created. This is done here. You call this function once
|
||||
* you have all the data - gathered the standard vars mentioned above as well as
|
||||
* all listed in account.inputFields, and pass them in here. This function will
|
||||
* insert them in the fields, returning a fully filled-out account ready to be
|
||||
* created.
|
||||
*
|
||||
* @param account {AccountConfig}
|
||||
* The account data to be modified. It may or may not contain placeholders.
|
||||
* After this function, it should not contain placeholders anymore.
|
||||
* This object will be modified in-place.
|
||||
*
|
||||
* @param emailfull {String}
|
||||
* Full email address of this account, e.g. "joe@example.com".
|
||||
* Empty of incomplete email addresses will/may be rejected.
|
||||
*
|
||||
* @param realname {String}
|
||||
* Real name of user, as will appear in From of outgoing messages
|
||||
*
|
||||
* @param password {String}
|
||||
* The password for the incoming server and (if necessary) the outgoing server
|
||||
*/
|
||||
function replaceVariables(account, realname, emailfull, password)
|
||||
{
|
||||
sanitize.nonemptystring(emailfull);
|
||||
let emailsplit = emailfull.split("@");
|
||||
assert(emailsplit.length == 2,
|
||||
"email address not in expected format: must contain exactly one @");
|
||||
let emaillocal = sanitize.nonemptystring(emailsplit[0]);
|
||||
let emaildomain = sanitize.hostname(emailsplit[1]);
|
||||
sanitize.label(realname);
|
||||
sanitize.nonemptystring(realname);
|
||||
|
||||
let otherVariables = {};
|
||||
otherVariables.EMAILADDRESS = emailfull;
|
||||
otherVariables.EMAILLOCALPART = emaillocal;
|
||||
otherVariables.EMAILDOMAIN = emaildomain;
|
||||
otherVariables.REALNAME = realname;
|
||||
|
||||
if (password) {
|
||||
account.incoming.password = password;
|
||||
account.outgoing.password = password; // set member only if auth required?
|
||||
}
|
||||
account.incoming.username = _replaceVariable(account.incoming.username,
|
||||
otherVariables);
|
||||
account.outgoing.username = _replaceVariable(account.outgoing.username,
|
||||
otherVariables);
|
||||
account.incoming.hostname =
|
||||
_replaceVariable(account.incoming.hostname, otherVariables);
|
||||
if (account.outgoing.hostname) // will be null if user picked existing server.
|
||||
account.outgoing.hostname =
|
||||
_replaceVariable(account.outgoing.hostname, otherVariables);
|
||||
account.identity.realname =
|
||||
_replaceVariable(account.identity.realname, otherVariables);
|
||||
account.identity.emailAddress =
|
||||
_replaceVariable(account.identity.emailAddress, otherVariables);
|
||||
account.displayName = _replaceVariable(account.displayName, otherVariables);
|
||||
}
|
||||
|
||||
function _replaceVariable(variable, values)
|
||||
{
|
||||
let str = variable;
|
||||
if (typeof(str) != "string")
|
||||
return str;
|
||||
|
||||
for (let varname in values)
|
||||
str = str.replace("%" + varname + "%", values[varname]);
|
||||
|
||||
return str;
|
||||
}
|
||||
333
mailnews/base/prefs/content/accountcreation/createInBackend.js
Normal file
333
mailnews/base/prefs/content/accountcreation/createInBackend.js
Normal file
|
|
@ -0,0 +1,333 @@
|
|||
/* -*- 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);
|
||||
|
||||
if (inServer.authMethod == Ci.nsMsgAuthMethod.OAuth2) {
|
||||
inServer.setCharValue("oauth2.scope", config.oauthSettings.scope);
|
||||
inServer.setCharValue("oauth2.issuer", config.oauthSettings.issuer);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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); }
|
||||
}
|
||||
1959
mailnews/base/prefs/content/accountcreation/emailWizard.js
Normal file
1959
mailnews/base/prefs/content/accountcreation/emailWizard.js
Normal file
File diff suppressed because it is too large
Load diff
493
mailnews/base/prefs/content/accountcreation/emailWizard.xul
Normal file
493
mailnews/base/prefs/content/accountcreation/emailWizard.xul
Normal file
|
|
@ -0,0 +1,493 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/accountCreation.css"
|
||||
type="text/css"?>
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
|
||||
%brandDTD;
|
||||
<!ENTITY % acDTD SYSTEM "chrome://messenger/locale/accountCreation.dtd">
|
||||
%acDTD;
|
||||
]>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
id="autoconfigWizard"
|
||||
windowtype="mail:autoconfig"
|
||||
title="&autoconfigWizard.title;"
|
||||
onload="gEmailConfigWizard.onLoad();"
|
||||
onkeypress="gEmailConfigWizard.onKeyDown(event);"
|
||||
onclose="gEmailConfigWizard.onWizardShutdown();"
|
||||
onunload="gEmailConfigWizard.onWizardShutdown();"
|
||||
>
|
||||
|
||||
<stringbundleset>
|
||||
<stringbundle id="bundle_brand"
|
||||
src="chrome://branding/locale/brand.properties"/>
|
||||
<stringbundle id="strings"
|
||||
src="chrome://messenger/locale/accountCreation.properties"/>
|
||||
<stringbundle id="utilstrings"
|
||||
src="chrome://messenger/locale/accountCreationUtil.properties"/>
|
||||
<stringbundle id="bundle_messenger"
|
||||
src="chrome://messenger/locale/messenger.properties"/>
|
||||
</stringbundleset>
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/accountcreation/util.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/accountcreation/accountConfig.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/accountcreation/emailWizard.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/accountcreation/sanitizeDatatypes.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/accountcreation/fetchhttp.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/accountcreation/readFromXML.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/accountcreation/guessConfig.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/accountcreation/verifyConfig.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/accountcreation/fetchConfig.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/accountcreation/createInBackend.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/accountcreation/MyBadCertHandler.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/accountUtils.js" />
|
||||
|
||||
<keyset id="mailKeys">
|
||||
<key keycode="VK_ESCAPE" oncommand="window.close();"/>
|
||||
</keyset>
|
||||
|
||||
<panel id="insecureserver-cleartext-panel" class="popup-panel">
|
||||
<hbox>
|
||||
<image class="insecureLarry"/>
|
||||
<vbox flex="1">
|
||||
<description class="title">&insecureServer.tooltip.title;</description>
|
||||
<description class="details">
|
||||
&insecureUnencrypted.description;</description>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</panel>
|
||||
<panel id="insecureserver-selfsigned-panel" class="popup-panel">
|
||||
<hbox>
|
||||
<image class="insecureLarry"/>
|
||||
<vbox flex="1">
|
||||
<description class="title">&insecureServer.tooltip.title;</description>
|
||||
<description class="details">
|
||||
&insecureSelfSigned.description;</description>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</panel>
|
||||
<panel id="secureserver-panel" class="popup-panel">
|
||||
<hbox>
|
||||
<image class="secureLarry"/>
|
||||
<vbox flex="1">
|
||||
<description class="title">&secureServer.description;</description>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</panel>
|
||||
|
||||
<tooltip id="insecureserver-cleartext">
|
||||
<hbox>
|
||||
<image class="insecureLarry"/>
|
||||
<vbox>
|
||||
<description class="title">&insecureServer.tooltip.title;</description>
|
||||
<description class="details">
|
||||
&insecureServer.tooltip.details;</description>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</tooltip>
|
||||
<tooltip id="insecureserver-selfsigned">
|
||||
<hbox>
|
||||
<image class="insecureLarry"/>
|
||||
<vbox>
|
||||
<description class="title">&insecureServer.tooltip.title;</description>
|
||||
<description class="details">
|
||||
&insecureServer.tooltip.details;</description>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</tooltip>
|
||||
<tooltip id="secureservertooltip">
|
||||
<hbox>
|
||||
<image class="secureLarry"/>
|
||||
<description class="title">&secureServer.description;</description>
|
||||
</hbox>
|
||||
</tooltip>
|
||||
<tooltip id="optional-password">
|
||||
<description>&password.text;</description>
|
||||
</tooltip>
|
||||
|
||||
<spacer id="fullwidth"/>
|
||||
|
||||
<vbox id="mastervbox" class="mastervbox" flex="1">
|
||||
<grid id="initialSettings">
|
||||
<columns>
|
||||
<column/>
|
||||
<column/>
|
||||
<column/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<label accesskey="&name.accesskey;"
|
||||
class="autoconfigLabel"
|
||||
value="&name.label;"
|
||||
control="realname"/>
|
||||
<textbox id="realname"
|
||||
class="padded"
|
||||
placeholder="&name.placeholder;"
|
||||
oninput="gEmailConfigWizard.onInputRealname();"
|
||||
onblur="gEmailConfigWizard.onBlurRealname();"/>
|
||||
<hbox>
|
||||
<description id="nametext" class="initialDesc">&name.text;</description>
|
||||
<image id="nameerroricon"
|
||||
hidden="true"
|
||||
class="warningicon"/>
|
||||
<description id="nameerror" class="errordescription" hidden="true"/>
|
||||
</hbox>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label accesskey="&email.accesskey;"
|
||||
class="autoconfigLabel"
|
||||
value="&email.label;"
|
||||
control="email"/>
|
||||
<textbox id="email"
|
||||
class="padded uri-element"
|
||||
placeholder="&email.placeholder;"
|
||||
oninput="gEmailConfigWizard.onInputEmail();"
|
||||
onblur="gEmailConfigWizard.onBlurEmail();"/>
|
||||
<hbox>
|
||||
<image id="emailerroricon"
|
||||
hidden="true"
|
||||
class="warningicon"/>
|
||||
<description id="emailerror" class="errordescription" hidden="true"/>
|
||||
</hbox>
|
||||
</row>
|
||||
<row align="center">
|
||||
<!-- this starts out as text so the emptytext shows, but then
|
||||
changes to type=password once it's not empty -->
|
||||
<label accesskey="&password.accesskey;"
|
||||
class="autoconfigLabel"
|
||||
value="&password.label;"
|
||||
control="password"
|
||||
tooltip="optional-password"/>
|
||||
<textbox id="password"
|
||||
class="padded"
|
||||
placeholder="&password.placeholder;"
|
||||
type="text"
|
||||
oninput="gEmailConfigWizard.onInputPassword();"
|
||||
onfocus="gEmailConfigWizard.onFocusPassword();"
|
||||
onblur="gEmailConfigWizard.onBlurPassword();"/>
|
||||
<hbox>
|
||||
<image id="passworderroricon"
|
||||
hidden="true"
|
||||
class="warningicon"/>
|
||||
<description id="passworderror" class="errordescription" hidden="true"/>
|
||||
</hbox>
|
||||
</row>
|
||||
<row align="center" pack="start">
|
||||
<label class="autoconfigLabel"/>
|
||||
<checkbox id="remember_password"
|
||||
label="&rememberPassword.label;"
|
||||
accesskey="&rememberPassword.accesskey;"
|
||||
checked="true"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
<spacer flex="1" />
|
||||
|
||||
<hbox id="status_area" flex="1">
|
||||
<vbox id="status_img_before" pack="start"/>
|
||||
<description id="status_msg"> </description>
|
||||
<!-- Include 160 = nbsp, to make the element occupy the
|
||||
full height, for at least one line. With a normal space,
|
||||
it does not have sufficient height. -->
|
||||
<vbox id="status_img_after" pack="start"/>
|
||||
</hbox>
|
||||
|
||||
<groupbox id="result_area" hidden="true">
|
||||
<radiogroup id="result_imappop" orient="horizontal">
|
||||
<radio id="result_select_imap" label="&imapLong.label;" value="1"
|
||||
oncommand="gEmailConfigWizard.onResultIMAPOrPOP3();"/>
|
||||
<radio id="result_select_pop3" label="&pop3Long.label;" value="2"
|
||||
oncommand="gEmailConfigWizard.onResultIMAPOrPOP3();"/>
|
||||
</radiogroup>
|
||||
<grid>
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<label class="textbox-label" value="&incoming.label;"
|
||||
control="result-incoming"/>
|
||||
<textbox id="result-incoming" disabled="true" flex="1"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label class="textbox-label" value="&outgoing.label;"
|
||||
control="result-outgoing"/>
|
||||
<textbox id="result-outgoing" disabled="true" flex="1"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label class="textbox-label" value="&username.label;"
|
||||
control="result-username"/>
|
||||
<textbox id="result-username" disabled="true" flex="1"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</groupbox>
|
||||
|
||||
<groupbox id="manual-edit_area" hidden="true">
|
||||
<grid>
|
||||
<columns>
|
||||
<column/><!-- row label, e.g. "incoming" -->
|
||||
<column/><!-- protocol, e.g. "IMAP" -->
|
||||
<column flex="1"/><!-- hostname / username -->
|
||||
<column/><!-- port -->
|
||||
<column/><!-- SSL -->
|
||||
<column/><!-- auth method -->
|
||||
</columns>
|
||||
<rows>
|
||||
<row id="labels_row" align="center">
|
||||
<spacer/>
|
||||
<spacer/>
|
||||
<label value="&hostname.label;" class="columnHeader"/>
|
||||
<label value="&port.label;" class="columnHeader"/>
|
||||
<label value="&ssl.label;" class="columnHeader"/>
|
||||
<label value="&auth.label;" class="columnHeader"/>
|
||||
</row>
|
||||
<row id="incoming_server_area">
|
||||
<hbox align="center" pack="end">
|
||||
<label class="textbox-label"
|
||||
value="&incoming.label;"
|
||||
control="incoming_hostname"/>
|
||||
</hbox>
|
||||
<menulist id="incoming_protocol"
|
||||
oncommand="gEmailConfigWizard.onChangedProtocolIncoming();"
|
||||
sizetopopup="always">
|
||||
<menupopup>
|
||||
<menuitem label="&imap.label;" value="1"/>
|
||||
<menuitem label="&pop3.label;" value="2"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
<textbox id="incoming_hostname"
|
||||
oninput="gEmailConfigWizard.onInputHostname();"
|
||||
class="host uri-element"/>
|
||||
<menulist id="incoming_port"
|
||||
editable="true"
|
||||
oninput="gEmailConfigWizard.onChangedPortIncoming();"
|
||||
oncommand="gEmailConfigWizard.onChangedPortIncoming();"
|
||||
class="port">
|
||||
<menupopup/>
|
||||
</menulist>
|
||||
<menulist id="incoming_ssl"
|
||||
class="security"
|
||||
oncommand="gEmailConfigWizard.onChangedSSLIncoming();"
|
||||
sizetopopup="always">
|
||||
<menupopup>
|
||||
<!-- values defined in nsMsgSocketType -->
|
||||
<menuitem label="&autodetect.label;" value="0"/>
|
||||
<menuitem label="&noEncryption.label;" value="1"/>
|
||||
<menuitem label="&starttls.label;" value="3"/>
|
||||
<menuitem label="&sslTls.label;" value="2"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
<menulist id="incoming_authMethod"
|
||||
class="auth"
|
||||
oncommand="gEmailConfigWizard.onChangedInAuth();"
|
||||
sizetopopup="always">
|
||||
<menupopup>
|
||||
<menuitem label="&autodetect.label;" value="0"/>
|
||||
<!-- values defined in nsMsgAuthMethod -->
|
||||
<!-- labels set from messenger.properties
|
||||
to avoid duplication -->
|
||||
<menuitem id="in-authMethod-password-cleartext" value="3"/>
|
||||
<menuitem id="in-authMethod-password-encrypted" value="4"/>
|
||||
<menuitem id="in-authMethod-kerberos" value="5"/>
|
||||
<menuitem id="in-authMethod-ntlm" value="6"/>
|
||||
<menuitem id="in-authMethod-oauth2" value="10" hidden="true"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</row>
|
||||
<row id="outgoing_server_area" align="center">
|
||||
<label class="textbox-label"
|
||||
value="&outgoing.label;"
|
||||
control="outgoing_hostname"/>
|
||||
<label id="outgoing_protocol"
|
||||
value="&smtp.label;"/>
|
||||
<menulist id="outgoing_hostname"
|
||||
editable="true"
|
||||
sizetopopup="none"
|
||||
oninput="gEmailConfigWizard.onInputHostname();"
|
||||
oncommand="gEmailConfigWizard.onChangedOutgoingDropdown();"
|
||||
onpopupshowing="gEmailConfigWizard.onOpenOutgoingDropdown();"
|
||||
class="host uri-element">
|
||||
<menupopup id="outgoing_hostname_popup"/>
|
||||
</menulist>
|
||||
<menulist id="outgoing_port"
|
||||
editable="true"
|
||||
oninput="gEmailConfigWizard.onChangedPortOutgoing();"
|
||||
oncommand="gEmailConfigWizard.onChangedPortOutgoing();"
|
||||
class="port">
|
||||
<menupopup/>
|
||||
</menulist>
|
||||
<menulist id="outgoing_ssl"
|
||||
class="security"
|
||||
oncommand="gEmailConfigWizard.onChangedSSLOutgoing();"
|
||||
sizetopopup="always">
|
||||
<menupopup>
|
||||
<!-- @see incoming -->
|
||||
<menuitem label="&autodetect.label;" value="0"/>
|
||||
<menuitem label="&noEncryption.label;" value="1"/>
|
||||
<menuitem label="&starttls.label;" value="3"/>
|
||||
<menuitem label="&sslTls.label;" value="2"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
<menulist id="outgoing_authMethod"
|
||||
class="auth"
|
||||
oncommand="gEmailConfigWizard.onChangedOutAuth(this.selectedItem);"
|
||||
sizetopopup="always">
|
||||
<menupopup>
|
||||
<menuitem label="&autodetect.label;" value="0"/>
|
||||
<!-- @see incoming -->
|
||||
<menuitem id="out-authMethod-no" value="1"/>
|
||||
<menuitem id="out-authMethod-password-cleartext" value="3"/>
|
||||
<menuitem id="out-authMethod-password-encrypted" value="4"/>
|
||||
<menuitem id="out-authMethod-kerberos" value="5"/>
|
||||
<menuitem id="out-authMethod-ntlm" value="6"/>
|
||||
<menuitem id="out-authMethod-oauth2" value="10" hidden="true"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</row>
|
||||
<row id="username_area" align="center">
|
||||
<label class="textbox-label"
|
||||
value="&username.label;"/>
|
||||
<label class="columnHeader"
|
||||
value="&incoming.label;"
|
||||
control="incoming_username"/>
|
||||
<textbox id="incoming_username"
|
||||
oninput="gEmailConfigWizard.onInputInUsername();"
|
||||
class="username"/>
|
||||
<spacer/>
|
||||
<label class="columnHeader"
|
||||
id="outgoing_label"
|
||||
value="&outgoing.label;"
|
||||
control="outgoing_username"/>
|
||||
<textbox id="outgoing_username"
|
||||
oninput="gEmailConfigWizard.onInputOutUsername();"
|
||||
class="username"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</groupbox>
|
||||
|
||||
<spacer flex="1" />
|
||||
<hbox id="buttons_area">
|
||||
<hbox id="left_buttons_area" align="center" pack="start">
|
||||
<button id="provisioner_button"
|
||||
label="&switch-to-provisioner.label;"
|
||||
accesskey="&switch-to-provisioner.accesskey;"
|
||||
class="larger-button"
|
||||
oncommand="gEmailConfigWizard.onSwitchToProvisioner();"/>
|
||||
<button id="manual-edit_button"
|
||||
label="&manual-edit.label;"
|
||||
accesskey="&manual-edit.accesskey;"
|
||||
hidden="true"
|
||||
oncommand="gEmailConfigWizard.onManualEdit();"/>
|
||||
<button id="advanced-setup_button"
|
||||
label="&advancedSetup.label;"
|
||||
accesskey="&advancedSetup.accesskey;"
|
||||
disabled="true"
|
||||
hidden="true"
|
||||
oncommand="gEmailConfigWizard.onAdvancedSetup();"/>
|
||||
</hbox>
|
||||
<spacer flex="1"/>
|
||||
<hbox id="right_buttons_area" align="center" pack="end">
|
||||
<button id="stop_button"
|
||||
label="&stop.label;"
|
||||
accesskey="&stop.accesskey;"
|
||||
hidden="true"
|
||||
oncommand="gEmailConfigWizard.onStop();"/>
|
||||
<button id="cancel_button"
|
||||
label="&cancel.label;"
|
||||
accesskey="&cancel.accesskey;"
|
||||
oncommand="gEmailConfigWizard.onCancel();"/>
|
||||
<button id="half-manual-test_button"
|
||||
label="&half-manual-test.label;"
|
||||
accesskey="&half-manual-test.accesskey;"
|
||||
hidden="true"
|
||||
oncommand="gEmailConfigWizard.onHalfManualTest();"/>
|
||||
<button id="next_button"
|
||||
label="&continue.label;"
|
||||
accesskey="&continue.accesskey;"
|
||||
hidden="false"
|
||||
oncommand="gEmailConfigWizard.onNext();"/>
|
||||
<button id="create_button"
|
||||
label="&doneAccount.label;"
|
||||
accesskey="&doneAccount.accesskey;"
|
||||
class="important-button"
|
||||
hidden="true"
|
||||
oncommand="gEmailConfigWizard.onCreate();"/>
|
||||
</hbox>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
|
||||
<vbox id="warningbox" hidden="true" flex="1">
|
||||
<hbox class="warning" flex="1">
|
||||
<vbox class="larrybox">
|
||||
<image id="insecure_larry" class="insecureLarry"/>
|
||||
</vbox>
|
||||
<vbox flex="1" class="warning_text">
|
||||
<label class="warning-heading">&warning.label;</label>
|
||||
<vbox id="incoming_box">
|
||||
<hbox>
|
||||
<label class="warning_settings" value="&incomingSettings.label;"/>
|
||||
<description id="warning_incoming"/>
|
||||
</hbox>
|
||||
<label id="incoming_technical"
|
||||
class="technical_details"
|
||||
value="&technicaldetails.label;"
|
||||
onclick="gSecurityWarningDialog.toggleDetails('incoming');"/>
|
||||
<description id="incoming_details" collapsed="true"/>
|
||||
</vbox>
|
||||
<vbox id="outgoing_box">
|
||||
<hbox>
|
||||
<label class="warning_settings" value="&outgoingSettings.label;"/>
|
||||
<description id="warning_outgoing"/>
|
||||
</hbox>
|
||||
<label id="outgoing_technical"
|
||||
class="technical_details"
|
||||
value="&technicaldetails.label;"
|
||||
onclick="gSecurityWarningDialog.toggleDetails('outgoing');"/>
|
||||
<description id="outgoing_details" collapsed="true"/>
|
||||
</vbox>
|
||||
<spacer flex="10"/>
|
||||
<description id="findoutmore">
|
||||
&contactYourProvider.description;</description>
|
||||
<spacer flex="100"/>
|
||||
<checkbox id="acknowledge_warning"
|
||||
label="&confirmWarning.label;"
|
||||
accesskey="&confirmWarning.accesskey;"
|
||||
class="acknowledge_checkbox"
|
||||
oncommand="gSecurityWarningDialog.toggleAcknowledge()"/>
|
||||
<hbox>
|
||||
<button id="getmeoutofhere"
|
||||
label="&changeSettings.label;"
|
||||
accesskey="&changeSettings.accesskey;"
|
||||
oncommand="gSecurityWarningDialog.onCancel()"/>
|
||||
<spacer flex="1"/>
|
||||
<button id="iknow"
|
||||
label="&doneAccount.label;"
|
||||
accesskey="&doneAccount.accesskey;"
|
||||
disabled="true"
|
||||
oncommand="gSecurityWarningDialog.onOK()"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</window>
|
||||
240
mailnews/base/prefs/content/accountcreation/fetchConfig.js
Normal file
240
mailnews/base/prefs/content/accountcreation/fetchConfig.js
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
/**
|
||||
* Tries to find a configuration for this ISP on the local harddisk, in the
|
||||
* application install directory's "isp" subdirectory.
|
||||
* Params @see fetchConfigFromISP()
|
||||
*/
|
||||
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/JXON.js");
|
||||
|
||||
|
||||
function fetchConfigFromDisk(domain, successCallback, errorCallback)
|
||||
{
|
||||
return new TimeoutAbortable(runAsync(function()
|
||||
{
|
||||
try {
|
||||
// <TB installdir>/isp/example.com.xml
|
||||
var configLocation = Services.dirsvc.get("CurProcD", Ci.nsIFile);
|
||||
configLocation.append("isp");
|
||||
configLocation.append(sanitize.hostname(domain) + ".xml");
|
||||
|
||||
var contents =
|
||||
readURLasUTF8(Services.io.newFileURI(configLocation));
|
||||
let domParser = Cc["@mozilla.org/xmlextras/domparser;1"]
|
||||
.createInstance(Ci.nsIDOMParser);
|
||||
successCallback(readFromXML(JXON.build(
|
||||
domParser.parseFromString(contents, "text/xml"))));
|
||||
} catch (e) { errorCallback(e); }
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to get a configuration from the ISP / mail provider directly.
|
||||
*
|
||||
* Disclaimers:
|
||||
* - To support domain hosters, we cannot use SSL. That means we
|
||||
* rely on insecure DNS and http, which means the results may be
|
||||
* forged when under attack. The same is true for guessConfig(), though.
|
||||
*
|
||||
* @param domain {String} The domain part of the user's email address
|
||||
* @param emailAddress {String} The user's email address
|
||||
* @param successCallback {Function(config {AccountConfig}})} A callback that
|
||||
* will be called when we could retrieve a configuration.
|
||||
* The AccountConfig object will be passed in as first parameter.
|
||||
* @param errorCallback {Function(ex)} A callback that
|
||||
* will be called when we could not retrieve a configuration,
|
||||
* for whatever reason. This is expected (e.g. when there's no config
|
||||
* for this domain at this location),
|
||||
* so do not unconditionally show this to the user.
|
||||
* The first paramter will be an exception object or error string.
|
||||
*/
|
||||
function fetchConfigFromISP(domain, emailAddress, successCallback,
|
||||
errorCallback)
|
||||
{
|
||||
if (!Services.prefs.getBoolPref(
|
||||
"mailnews.auto_config.fetchFromISP.enabled")) {
|
||||
errorCallback("ISP fetch disabled per user preference");
|
||||
return;
|
||||
}
|
||||
|
||||
let url1 = "http://autoconfig." + sanitize.hostname(domain) +
|
||||
"/mail/config-v1.1.xml";
|
||||
// .well-known/ <http://tools.ietf.org/html/draft-nottingham-site-meta-04>
|
||||
let url2 = "http://" + sanitize.hostname(domain) +
|
||||
"/.well-known/autoconfig/mail/config-v1.1.xml";
|
||||
let sucAbortable = new SuccessiveAbortable();
|
||||
var time = Date.now();
|
||||
var urlArgs = { emailaddress: emailAddress };
|
||||
if (!Services.prefs.getBoolPref(
|
||||
"mailnews.auto_config.fetchFromISP.sendEmailAddress")) {
|
||||
delete urlArgs.emailaddress;
|
||||
}
|
||||
let fetch1 = new FetchHTTP(url1, urlArgs, false,
|
||||
function(result)
|
||||
{
|
||||
successCallback(readFromXML(result));
|
||||
},
|
||||
function(e1) // fetch1 failed
|
||||
{
|
||||
ddump("fetchisp 1 <" + url1 + "> took " + (Date.now() - time) +
|
||||
"ms and failed with " + e1);
|
||||
time = Date.now();
|
||||
if (e1 instanceof CancelledException)
|
||||
{
|
||||
errorCallback(e1);
|
||||
return;
|
||||
}
|
||||
|
||||
let fetch2 = new FetchHTTP(url2, urlArgs, false,
|
||||
function(result)
|
||||
{
|
||||
successCallback(readFromXML(result));
|
||||
},
|
||||
function(e2)
|
||||
{
|
||||
ddump("fetchisp 2 <" + url2 + "> took " + (Date.now() - time) +
|
||||
"ms and failed with " + e2);
|
||||
// return the error for the primary call,
|
||||
// unless the fetch was cancelled
|
||||
errorCallback(e2 instanceof CancelledException ? e2 : e1);
|
||||
});
|
||||
sucAbortable.current = fetch2;
|
||||
fetch2.start();
|
||||
});
|
||||
sucAbortable.current = fetch1;
|
||||
fetch1.start();
|
||||
return sucAbortable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to get a configuration for this ISP from a central database at
|
||||
* Mozilla servers.
|
||||
* Params @see fetchConfigFromISP()
|
||||
*/
|
||||
|
||||
function fetchConfigFromDB(domain, successCallback, errorCallback)
|
||||
{
|
||||
let url = Services.prefs.getCharPref("mailnews.auto_config_url");
|
||||
domain = sanitize.hostname(domain);
|
||||
|
||||
// If we don't specify a place to put the domain, put it at the end.
|
||||
if (!url.includes("{{domain}}"))
|
||||
url = url + domain;
|
||||
else
|
||||
url = url.replace("{{domain}}", domain);
|
||||
url = url.replace("{{accounts}}", MailServices.accounts.accounts.length);
|
||||
|
||||
if (!url.length)
|
||||
return errorCallback("no fetch url set");
|
||||
let fetch = new FetchHTTP(url, null, false,
|
||||
function(result)
|
||||
{
|
||||
successCallback(readFromXML(result));
|
||||
},
|
||||
errorCallback);
|
||||
fetch.start();
|
||||
return fetch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a lookup of DNS MX, to get the server who is responsible for
|
||||
* recieving mail for this domain. Then it takes the domain of that
|
||||
* server, and does another lookup (in ISPDB and possible at ISP autoconfig
|
||||
* server) and if such a config is found, returns that.
|
||||
*
|
||||
* Disclaimers:
|
||||
* - DNS is unprotected, meaning the results could be forged.
|
||||
* The same is true for fetchConfigFromISP() and guessConfig(), though.
|
||||
* - DNS MX tells us the incoming server, not the mailbox (IMAP) server.
|
||||
* They are different. This mechnism is only an approximation
|
||||
* for hosted domains (yourname.com is served by mx.hoster.com and
|
||||
* therefore imap.hoster.com - that "therefore" is exactly the
|
||||
* conclusional jump we make here.) and alternative domains
|
||||
* (e.g. yahoo.de -> yahoo.com).
|
||||
* - We make a look up for the base domain. E.g. if MX is
|
||||
* mx1.incoming.servers.hoster.com, we look up hoster.com.
|
||||
* Thanks to Services.eTLD, we also get bbc.co.uk right.
|
||||
*
|
||||
* Params @see fetchConfigFromISP()
|
||||
*/
|
||||
function fetchConfigForMX(domain, successCallback, errorCallback)
|
||||
{
|
||||
domain = sanitize.hostname(domain);
|
||||
|
||||
var sucAbortable = new SuccessiveAbortable();
|
||||
var time = Date.now();
|
||||
sucAbortable.current = getMX(domain,
|
||||
function(mxHostname) // success
|
||||
{
|
||||
ddump("getmx took " + (Date.now() - time) + "ms");
|
||||
let sld = Services.eTLD.getBaseDomainFromHost(mxHostname);
|
||||
ddump("base domain " + sld + " for " + mxHostname);
|
||||
if (sld == domain)
|
||||
{
|
||||
errorCallback("MX lookup would be no different from domain");
|
||||
return;
|
||||
}
|
||||
sucAbortable.current = fetchConfigFromDB(sld, successCallback,
|
||||
errorCallback);
|
||||
},
|
||||
errorCallback);
|
||||
return sucAbortable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the DNS MX for the domain
|
||||
*
|
||||
* The current implementation goes to a web service to do the
|
||||
* DNS resolve for us, because Mozilla unfortunately has no implementation
|
||||
* to do it. That's just a workaround. Once bug 545866 is fixed, we make
|
||||
* the DNS query directly on the client. The API of this function should not
|
||||
* change then.
|
||||
*
|
||||
* Returns (in successCallback) the hostname of the MX server.
|
||||
* If there are several entires with different preference values,
|
||||
* only the most preferred (i.e. those with the lowest value)
|
||||
* is returned. If there are several most preferred servers (i.e.
|
||||
* round robin), only one of them is returned.
|
||||
*
|
||||
* @param domain @see fetchConfigFromISP()
|
||||
* @param successCallback {function(hostname {String})
|
||||
* Called when we found an MX for the domain.
|
||||
* For |hostname|, see description above.
|
||||
* @param errorCallback @see fetchConfigFromISP()
|
||||
* @returns @see fetchConfigFromISP()
|
||||
*/
|
||||
function getMX(domain, successCallback, errorCallback)
|
||||
{
|
||||
domain = sanitize.hostname(domain);
|
||||
|
||||
let url = Services.prefs.getCharPref("mailnews.mx_service_url");
|
||||
if (!url)
|
||||
errorCallback("no URL for MX service configured");
|
||||
url += domain;
|
||||
|
||||
let fetch = new FetchHTTP(url, null, false,
|
||||
function(result)
|
||||
{
|
||||
// result is plain text, with one line per server.
|
||||
// So just take the first line
|
||||
ddump("MX query result: \n" + result + "(end)");
|
||||
assert(typeof(result) == "string");
|
||||
let first = result.split("\n")[0];
|
||||
first.toLowerCase().replace(/[^a-z0-9\-_\.]*/g, "");
|
||||
if (first.length == 0)
|
||||
{
|
||||
errorCallback("no MX found");
|
||||
return;
|
||||
}
|
||||
successCallback(first);
|
||||
},
|
||||
errorCallback);
|
||||
fetch.start();
|
||||
return fetch;
|
||||
}
|
||||
267
mailnews/base/prefs/content/accountcreation/fetchhttp.js
Normal file
267
mailnews/base/prefs/content/accountcreation/fetchhttp.js
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
/**
|
||||
* This is a small wrapper around XMLHttpRequest, which solves various
|
||||
* inadequacies of the API, e.g. error handling. It is entirely generic and
|
||||
* can be used for purposes outside of even mail.
|
||||
*
|
||||
* It does not provide download progress, but assumes that the
|
||||
* fetched resource is so small (<1 10 KB) that the roundtrip and
|
||||
* response generation is far more significant than the
|
||||
* download time of the response. In other words, it's fine for RPC,
|
||||
* but not for bigger file downloads.
|
||||
*/
|
||||
|
||||
Components.utils.import("resource://gre/modules/JXON.js");
|
||||
|
||||
/**
|
||||
* Set up a fetch.
|
||||
*
|
||||
* @param url {String} URL of the server function.
|
||||
* ATTENTION: The caller needs to make sure that the URL is secure to call.
|
||||
* @param urlArgs {Object, associative array} Parameters to add
|
||||
* to the end of the URL as query string. E.g.
|
||||
* { foo: "bla", bar: "blub blub" } will add "?foo=bla&bar=blub%20blub"
|
||||
* to the URL
|
||||
* (unless the URL already has a "?", then it adds "&foo...").
|
||||
* The values will be urlComponentEncoded, so pass them unencoded.
|
||||
* @param post {Boolean} HTTP GET or POST
|
||||
* Only influences the HTTP request method,
|
||||
* i.e. first line of the HTTP request, not the body or parameters.
|
||||
* Use POST when you modify server state,
|
||||
* GET when you only request information.
|
||||
*
|
||||
* @param successCallback {Function(result {String})}
|
||||
* Called when the server call worked (no errors).
|
||||
* |result| will contain the body of the HTTP reponse, as string.
|
||||
* @param errorCallback {Function(ex)}
|
||||
* Called in case of error. ex contains the error
|
||||
* with a user-displayable but not localized |.message| and maybe a
|
||||
* |.code|, which can be either
|
||||
* - an nsresult error code,
|
||||
* - an HTTP result error code (0...1000) or
|
||||
* - negative: 0...-100 :
|
||||
* -2 = can't resolve server in DNS etc.
|
||||
* -4 = response body (e.g. XML) malformed
|
||||
*/
|
||||
/* not yet supported:
|
||||
* @param headers {Object, associative array} Like urlArgs,
|
||||
* just that the params will be added as HTTP headers.
|
||||
* { foo: "blub blub" } will add "Foo: Blub blub"
|
||||
* The values will be urlComponentEncoded, apart from space,
|
||||
* so pass them unencoded.
|
||||
* @param headerArgs {Object, associative array} Like urlArgs,
|
||||
* just that the params will be added as HTTP headers.
|
||||
* { foo: "blub blub" } will add "X-Moz-Arg-Foo: Blub blub"
|
||||
* The values will be urlComponentEncoded, apart from space,
|
||||
* so pass them unencoded.
|
||||
* @param bodyArgs {Object, associative array} Like urlArgs,
|
||||
* just that the params will be sent x-url-encoded in the body,
|
||||
* like a HTML form post.
|
||||
* The values will be urlComponentEncoded, so pass them unencoded.
|
||||
* This cannot be used together with |uploadBody|.
|
||||
* @param uploadbody {Object} Arbitrary object, which to use as
|
||||
* body of the HTTP request. Will also set the mimetype accordingly.
|
||||
* Only supported object types, currently only E4X is supported
|
||||
* (sending XML).
|
||||
* Usually, you have nothing to upload, so just pass |null|.
|
||||
*/
|
||||
function FetchHTTP(url, urlArgs, post, successCallback, errorCallback)
|
||||
{
|
||||
assert(typeof(successCallback) == "function", "BUG: successCallback");
|
||||
assert(typeof(errorCallback) == "function", "BUG: errorCallback");
|
||||
this._url = sanitize.string(url);
|
||||
if (!urlArgs)
|
||||
urlArgs = {};
|
||||
|
||||
this._urlArgs = urlArgs;
|
||||
this._post = sanitize.boolean(post);
|
||||
this._successCallback = successCallback;
|
||||
this._errorCallback = errorCallback;
|
||||
}
|
||||
FetchHTTP.prototype =
|
||||
{
|
||||
__proto__: Abortable.prototype,
|
||||
_url : null, // URL as passed to ctor, without arguments
|
||||
_urlArgs : null,
|
||||
_post : null,
|
||||
_successCallback : null,
|
||||
_errorCallback : null,
|
||||
_request : null, // the XMLHttpRequest object
|
||||
result : null,
|
||||
|
||||
start : function()
|
||||
{
|
||||
var url = this._url;
|
||||
for (var name in this._urlArgs)
|
||||
{
|
||||
url += (!url.includes("?") ? "?" : "&") +
|
||||
name + "=" + encodeURIComponent(this._urlArgs[name]);
|
||||
}
|
||||
this._request = new XMLHttpRequest();
|
||||
let request = this._request;
|
||||
request.open(this._post ? "POST" : "GET", url);
|
||||
request.channel.loadGroup = null;
|
||||
// needs bug 407190 patch v4 (or higher) - uncomment if that lands.
|
||||
// try {
|
||||
// var channel = request.channel.QueryInterface(Ci.nsIHttpChannel2);
|
||||
// channel.connectTimeout = 5;
|
||||
// channel.requestTimeout = 5;
|
||||
// } catch (e) { dump(e + "\n"); }
|
||||
|
||||
var me = this;
|
||||
request.onload = function() { me._response(true); }
|
||||
request.onerror = function() { me._response(false); }
|
||||
request.send(null);
|
||||
},
|
||||
_response : function(success, exStored)
|
||||
{
|
||||
try
|
||||
{
|
||||
var errorCode = null;
|
||||
var errorStr = null;
|
||||
|
||||
if (success && this._request.status >= 200 &&
|
||||
this._request.status < 300) // HTTP level success
|
||||
{
|
||||
try
|
||||
{
|
||||
// response
|
||||
var mimetype = this._request.getResponseHeader("Content-Type");
|
||||
if (!mimetype)
|
||||
mimetype = "";
|
||||
mimetype = mimetype.split(";")[0];
|
||||
if (mimetype == "text/xml" ||
|
||||
mimetype == "application/xml" ||
|
||||
mimetype == "text/rdf")
|
||||
{
|
||||
this.result = JXON.build(this._request.responseXML);
|
||||
}
|
||||
else
|
||||
{
|
||||
//ddump("mimetype: " + mimetype + " only supported as text");
|
||||
this.result = this._request.responseText;
|
||||
}
|
||||
//ddump("result:\n" + this.result);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
success = false;
|
||||
errorStr = getStringBundle(
|
||||
"chrome://messenger/locale/accountCreationUtil.properties")
|
||||
.GetStringFromName("bad_response_content.error");
|
||||
errorCode = -4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
success = false;
|
||||
try
|
||||
{
|
||||
errorCode = this._request.status;
|
||||
errorStr = this._request.statusText;
|
||||
} catch (e) {
|
||||
// If we can't resolve the hostname in DNS etc., .statusText throws
|
||||
errorCode = -2;
|
||||
errorStr = getStringBundle(
|
||||
"chrome://messenger/locale/accountCreationUtil.properties")
|
||||
.GetStringFromName("cannot_contact_server.error");
|
||||
ddump(errorStr);
|
||||
}
|
||||
}
|
||||
|
||||
// Callbacks
|
||||
if (success)
|
||||
{
|
||||
try {
|
||||
this._successCallback(this.result);
|
||||
} catch (e) {
|
||||
logException(e);
|
||||
this._error(e);
|
||||
}
|
||||
}
|
||||
else if (exStored)
|
||||
this._error(exStored);
|
||||
else
|
||||
this._error(new ServerException(errorStr, errorCode, this._url));
|
||||
|
||||
if (this._finishedCallback)
|
||||
{
|
||||
try {
|
||||
this._finishedCallback(this);
|
||||
} catch (e) {
|
||||
logException(e);
|
||||
this._error(e);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
// error in our fetchhttp._response() code
|
||||
logException(e);
|
||||
this._error(e);
|
||||
}
|
||||
},
|
||||
_error : function(e)
|
||||
{
|
||||
try {
|
||||
this._errorCallback(e);
|
||||
} catch (e) {
|
||||
// error in errorCallback, too!
|
||||
logException(e);
|
||||
alertPrompt("Error in errorCallback for fetchhttp", e);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Call this between start() and finishedCallback fired.
|
||||
*/
|
||||
cancel : function(ex)
|
||||
{
|
||||
assert(!this.result, "Call already returned");
|
||||
|
||||
this._request.abort();
|
||||
|
||||
// Need to manually call error handler
|
||||
// <https://bugzilla.mozilla.org/show_bug.cgi?id=218236#c11>
|
||||
this._response(false, ex ? ex : new UserCancelledException());
|
||||
},
|
||||
/**
|
||||
* Allows caller or lib to be notified when the call is done.
|
||||
* This is useful to enable and disable a Cancel button in the UI,
|
||||
* which allows to cancel the network request.
|
||||
*/
|
||||
setFinishedCallback : function(finishedCallback)
|
||||
{
|
||||
this._finishedCallback = finishedCallback;
|
||||
}
|
||||
}
|
||||
|
||||
function CancelledException(msg)
|
||||
{
|
||||
Exception.call(this, msg);
|
||||
}
|
||||
CancelledException.prototype = Object.create(Exception.prototype);
|
||||
CancelledException.prototype.constructor = CancelledException;
|
||||
|
||||
function UserCancelledException(msg)
|
||||
{
|
||||
// The user knows they cancelled so I don't see a need
|
||||
// for a message to that effect.
|
||||
if (!msg)
|
||||
msg = "User cancelled";
|
||||
CancelledException.call(this, msg);
|
||||
}
|
||||
UserCancelledException.prototype = Object.create(CancelledException.prototype);
|
||||
UserCancelledException.prototype.constructor = UserCancelledException;
|
||||
|
||||
function ServerException(msg, code, uri)
|
||||
{
|
||||
Exception.call(this, msg);
|
||||
this.code = code;
|
||||
this.uri = uri;
|
||||
}
|
||||
ServerException.prototype = Object.create(Exception.prototype);
|
||||
ServerException.prototype.constructor = ServerException;
|
||||
|
||||
1145
mailnews/base/prefs/content/accountcreation/guessConfig.js
Normal file
1145
mailnews/base/prefs/content/accountcreation/guessConfig.js
Normal file
File diff suppressed because it is too large
Load diff
238
mailnews/base/prefs/content/accountcreation/readFromXML.js
Normal file
238
mailnews/base/prefs/content/accountcreation/readFromXML.js
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
/* -*- 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 XML snipplet (as JXON) and reads the values into
|
||||
* a new AccountConfig object.
|
||||
* It does so securely (or tries to), by trying to avoid remote execution
|
||||
* and similar holes which can appear when reading too naively.
|
||||
* Of course it cannot tell whether the actual values are correct,
|
||||
* e.g. it can't tell whether the host name is a good server.
|
||||
*
|
||||
* The XML format is documented at
|
||||
* <https://wiki.mozilla.org/Thunderbird:Autoconfiguration:ConfigFileFormat>
|
||||
*
|
||||
* @param clientConfigXML {JXON} The <clientConfig> node.
|
||||
* @return AccountConfig object filled with the data from XML
|
||||
*/
|
||||
Components.utils.import("resource:///modules/hostnameUtils.jsm");
|
||||
|
||||
function readFromXML(clientConfigXML)
|
||||
{
|
||||
function array_or_undef(value) {
|
||||
return value === undefined ? [] : value;
|
||||
}
|
||||
var exception;
|
||||
if (typeof(clientConfigXML) != "object" ||
|
||||
!("clientConfig" in clientConfigXML) ||
|
||||
!("emailProvider" in clientConfigXML.clientConfig))
|
||||
{
|
||||
dump("client config xml = " + JSON.stringify(clientConfigXML) + "\n");
|
||||
var stringBundle = getStringBundle(
|
||||
"chrome://messenger/locale/accountCreationModel.properties");
|
||||
throw stringBundle.GetStringFromName("no_emailProvider.error");
|
||||
}
|
||||
var xml = clientConfigXML.clientConfig.emailProvider;
|
||||
|
||||
var d = new AccountConfig();
|
||||
d.source = AccountConfig.kSourceXML;
|
||||
|
||||
d.id = sanitize.hostname(xml["@id"]);
|
||||
d.displayName = d.id;
|
||||
try {
|
||||
d.displayName = sanitize.label(xml.displayName);
|
||||
} catch (e) { logException(e); }
|
||||
for (var domain of xml.$domain)
|
||||
{
|
||||
try {
|
||||
d.domains.push(sanitize.hostname(domain));
|
||||
} catch (e) { logException(e); exception = e; }
|
||||
}
|
||||
if (d.domains.length == 0)
|
||||
throw exception ? exception : "need proper <domain> in XML";
|
||||
exception = null;
|
||||
|
||||
// incoming server
|
||||
for (let iX of array_or_undef(xml.$incomingServer)) // input (XML)
|
||||
{
|
||||
let iO = d.createNewIncoming(); // output (object)
|
||||
try {
|
||||
// throws if not supported
|
||||
iO.type = sanitize.enum(iX["@type"], ["pop3", "imap", "nntp"]);
|
||||
iO.hostname = sanitize.hostname(iX.hostname);
|
||||
iO.port = sanitize.integerRange(iX.port, kMinPort, kMaxPort);
|
||||
// We need a username even for Kerberos, need it even internally.
|
||||
iO.username = sanitize.string(iX.username); // may be a %VARIABLE%
|
||||
|
||||
if ("password" in iX) {
|
||||
d.rememberPassword = true;
|
||||
iO.password = sanitize.string(iX.password);
|
||||
}
|
||||
|
||||
for (let iXsocketType of array_or_undef(iX.$socketType))
|
||||
{
|
||||
try {
|
||||
iO.socketType = sanitize.translate(iXsocketType,
|
||||
{ plain : 1, SSL: 2, STARTTLS: 3 });
|
||||
break; // take first that we support
|
||||
} catch (e) { exception = e; }
|
||||
}
|
||||
if (!iO.socketType)
|
||||
throw exception ? exception : "need proper <socketType> in XML";
|
||||
exception = null;
|
||||
|
||||
for (let iXauth of array_or_undef(iX.$authentication))
|
||||
{
|
||||
try {
|
||||
iO.auth = sanitize.translate(iXauth,
|
||||
{ "password-cleartext" : Ci.nsMsgAuthMethod.passwordCleartext,
|
||||
// @deprecated TODO remove
|
||||
"plain" : Ci.nsMsgAuthMethod.passwordCleartext,
|
||||
"password-encrypted" : Ci.nsMsgAuthMethod.passwordEncrypted,
|
||||
// @deprecated TODO remove
|
||||
"secure" : Ci.nsMsgAuthMethod.passwordEncrypted,
|
||||
"GSSAPI" : Ci.nsMsgAuthMethod.GSSAPI,
|
||||
"NTLM" : Ci.nsMsgAuthMethod.NTLM,
|
||||
"OAuth2" : Ci.nsMsgAuthMethod.OAuth2 });
|
||||
break; // take first that we support
|
||||
} catch (e) { exception = e; }
|
||||
}
|
||||
if (!iO.auth)
|
||||
throw exception ? exception : "need proper <authentication> in XML";
|
||||
exception = null;
|
||||
|
||||
// defaults are in accountConfig.js
|
||||
if (iO.type == "pop3" && "pop3" in iX)
|
||||
{
|
||||
try {
|
||||
if ("leaveMessagesOnServer" in iX.pop3)
|
||||
iO.leaveMessagesOnServer =
|
||||
sanitize.boolean(iX.pop3.leaveMessagesOnServer);
|
||||
if ("daysToLeaveMessagesOnServer" in iX.pop3)
|
||||
iO.daysToLeaveMessagesOnServer =
|
||||
sanitize.integer(iX.pop3.daysToLeaveMessagesOnServer);
|
||||
} catch (e) { logException(e); }
|
||||
try {
|
||||
if ("downloadOnBiff" in iX.pop3)
|
||||
iO.downloadOnBiff = sanitize.boolean(iX.pop3.downloadOnBiff);
|
||||
} catch (e) { logException(e); }
|
||||
}
|
||||
|
||||
// processed successfully, now add to result object
|
||||
if (!d.incoming.hostname) // first valid
|
||||
d.incoming = iO;
|
||||
else
|
||||
d.incomingAlternatives.push(iO);
|
||||
} catch (e) { exception = e; }
|
||||
}
|
||||
if (!d.incoming.hostname)
|
||||
// throw exception for last server
|
||||
throw exception ? exception : "Need proper <incomingServer> in XML file";
|
||||
exception = null;
|
||||
|
||||
// outgoing server
|
||||
for (let oX of array_or_undef(xml.$outgoingServer)) // input (XML)
|
||||
{
|
||||
let oO = d.createNewOutgoing(); // output (object)
|
||||
try {
|
||||
if (oX["@type"] != "smtp")
|
||||
{
|
||||
var stringBundle = getStringBundle(
|
||||
"chrome://messenger/locale/accountCreationModel.properties");
|
||||
throw stringBundle.GetStringFromName("outgoing_not_smtp.error");
|
||||
}
|
||||
oO.hostname = sanitize.hostname(oX.hostname);
|
||||
oO.port = sanitize.integerRange(oX.port, kMinPort, kMaxPort);
|
||||
|
||||
for (let oXsocketType of array_or_undef(oX.$socketType))
|
||||
{
|
||||
try {
|
||||
oO.socketType = sanitize.translate(oXsocketType,
|
||||
{ plain : 1, SSL: 2, STARTTLS: 3 });
|
||||
break; // take first that we support
|
||||
} catch (e) { exception = e; }
|
||||
}
|
||||
if (!oO.socketType)
|
||||
throw exception ? exception : "need proper <socketType> in XML";
|
||||
exception = null;
|
||||
|
||||
for (let oXauth of array_or_undef(oX.$authentication))
|
||||
{
|
||||
try {
|
||||
oO.auth = sanitize.translate(oXauth,
|
||||
{ // open relay
|
||||
"none" : Ci.nsMsgAuthMethod.none,
|
||||
// inside ISP or corp network
|
||||
"client-IP-address" : Ci.nsMsgAuthMethod.none,
|
||||
// hope for the best
|
||||
"smtp-after-pop" : Ci.nsMsgAuthMethod.none,
|
||||
"password-cleartext" : Ci.nsMsgAuthMethod.passwordCleartext,
|
||||
// @deprecated TODO remove
|
||||
"plain" : Ci.nsMsgAuthMethod.passwordCleartext,
|
||||
"password-encrypted" : Ci.nsMsgAuthMethod.passwordEncrypted,
|
||||
// @deprecated TODO remove
|
||||
"secure" : Ci.nsMsgAuthMethod.passwordEncrypted,
|
||||
"GSSAPI" : Ci.nsMsgAuthMethod.GSSAPI,
|
||||
"NTLM" : Ci.nsMsgAuthMethod.NTLM,
|
||||
"OAuth2" : Ci.nsMsgAuthMethod.OAuth2,
|
||||
});
|
||||
|
||||
break; // take first that we support
|
||||
} catch (e) { exception = e; }
|
||||
}
|
||||
if (!oO.auth)
|
||||
throw exception ? exception : "need proper <authentication> in XML";
|
||||
exception = null;
|
||||
|
||||
if ("username" in oX ||
|
||||
// if password-based auth, we need a username,
|
||||
// so go there anyways and throw.
|
||||
oO.auth == Ci.nsMsgAuthMethod.passwordCleartext ||
|
||||
oO.auth == Ci.nsMsgAuthMethod.passwordEncrypted)
|
||||
oO.username = sanitize.string(oX.username);
|
||||
|
||||
if ("password" in oX) {
|
||||
d.rememberPassword = true;
|
||||
oO.password = sanitize.string(oX.password);
|
||||
}
|
||||
|
||||
try {
|
||||
// defaults are in accountConfig.js
|
||||
if ("addThisServer" in oX)
|
||||
oO.addThisServer = sanitize.boolean(oX.addThisServer);
|
||||
if ("useGlobalPreferredServer" in oX)
|
||||
oO.useGlobalPreferredServer =
|
||||
sanitize.boolean(oX.useGlobalPreferredServer);
|
||||
} catch (e) { logException(e); }
|
||||
|
||||
// processed successfully, now add to result object
|
||||
if (!d.outgoing.hostname) // first valid
|
||||
d.outgoing = oO;
|
||||
else
|
||||
d.outgoingAlternatives.push(oO);
|
||||
} catch (e) { logException(e); exception = e; }
|
||||
}
|
||||
if (!d.outgoing.hostname)
|
||||
// throw exception for last server
|
||||
throw exception ? exception : "Need proper <outgoingServer> in XML file";
|
||||
exception = null;
|
||||
|
||||
d.inputFields = new Array();
|
||||
for (let inputField of array_or_undef(xml.$inputField))
|
||||
{
|
||||
try {
|
||||
var fieldset =
|
||||
{
|
||||
varname : sanitize.alphanumdash(inputField["@key"]).toUpperCase(),
|
||||
displayName : sanitize.label(inputField["@label"]),
|
||||
exampleValue : sanitize.label(inputField.value)
|
||||
};
|
||||
d.inputFields.push(fieldset);
|
||||
} catch (e) { logException(e); } // for now, don't throw,
|
||||
// because we don't support custom fields yet anyways.
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
207
mailnews/base/prefs/content/accountcreation/sanitizeDatatypes.js
Normal file
207
mailnews/base/prefs/content/accountcreation/sanitizeDatatypes.js
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
/**
|
||||
* This is a generic input validation lib. Use it when you process
|
||||
* data from the network.
|
||||
*
|
||||
* Just a few functions which verify, for security purposes, that the
|
||||
* input variables (strings, if nothing else is noted) are of the expected
|
||||
* type and syntax.
|
||||
*
|
||||
* The functions take a string (unless noted otherwise) and return
|
||||
* the expected datatype in JS types. If the value is not as expected,
|
||||
* they throw exceptions.
|
||||
*/
|
||||
|
||||
Components.utils.import("resource:///modules/hostnameUtils.jsm");
|
||||
|
||||
var sanitize =
|
||||
{
|
||||
integer : function(unchecked)
|
||||
{
|
||||
if (typeof(unchecked) == "number" && !isNaN(unchecked))
|
||||
return unchecked;
|
||||
|
||||
var r = parseInt(unchecked);
|
||||
if (isNaN(r))
|
||||
throw new MalformedException("no_number.error", unchecked);
|
||||
|
||||
return r;
|
||||
},
|
||||
|
||||
integerRange : function(unchecked, min, max)
|
||||
{
|
||||
var int = this.integer(unchecked);
|
||||
if (int < min)
|
||||
throw new MalformedException("number_too_small.error", unchecked);
|
||||
|
||||
if (int > max)
|
||||
throw new MalformedException("number_too_large.error", unchecked);
|
||||
|
||||
return int;
|
||||
},
|
||||
|
||||
boolean : function(unchecked)
|
||||
{
|
||||
if (typeof(unchecked) == "boolean")
|
||||
return unchecked;
|
||||
|
||||
if (unchecked == "true")
|
||||
return true;
|
||||
|
||||
if (unchecked == "false")
|
||||
return false;
|
||||
|
||||
throw new MalformedException("boolean.error", unchecked);
|
||||
},
|
||||
|
||||
string : function(unchecked)
|
||||
{
|
||||
return String(unchecked);
|
||||
},
|
||||
|
||||
nonemptystring : function(unchecked)
|
||||
{
|
||||
if (!unchecked)
|
||||
throw new MalformedException("string_empty.error", unchecked);
|
||||
|
||||
return this.string(unchecked);
|
||||
},
|
||||
|
||||
/**
|
||||
* Allow only letters, numbers, "-" and "_".
|
||||
*
|
||||
* Empty strings not allowed (good idea?).
|
||||
*/
|
||||
alphanumdash : function(unchecked)
|
||||
{
|
||||
var str = this.nonemptystring(unchecked);
|
||||
if (!/^[a-zA-Z0-9\-\_]*$/.test(str))
|
||||
throw new MalformedException("alphanumdash.error", unchecked);
|
||||
|
||||
return str;
|
||||
},
|
||||
|
||||
/**
|
||||
* DNS hostnames like foo.bar.example.com
|
||||
* Allow only letters, numbers, "-" and "."
|
||||
* Empty strings not allowed.
|
||||
* Currently does not support IDN (international domain names).
|
||||
*/
|
||||
hostname : function(unchecked)
|
||||
{
|
||||
let str = cleanUpHostName(this.nonemptystring(unchecked));
|
||||
|
||||
// Allow placeholders. TODO move to a new hostnameOrPlaceholder()
|
||||
// The regex is "anything, followed by one or more (placeholders than
|
||||
// anything)". This doesn't catch the non-placeholder case, but that's
|
||||
// handled down below.
|
||||
if (/^[a-zA-Z0-9\-\.]*(%[A-Z0-9]+%[a-zA-Z0-9\-\.]*)+$/.test(str))
|
||||
return str;
|
||||
|
||||
if (!isLegalHostNameOrIP(str))
|
||||
throw new MalformedException("hostname_syntax.error", unchecked);
|
||||
|
||||
return str.toLowerCase();
|
||||
},
|
||||
/**
|
||||
* A non-chrome URL that's safe to request.
|
||||
*/
|
||||
url : function (unchecked)
|
||||
{
|
||||
var str = this.string(unchecked);
|
||||
if (!str.startsWith("http") && !str.startsWith("https"))
|
||||
throw new MalformedException("url_scheme.error", unchecked);
|
||||
|
||||
var uri;
|
||||
try {
|
||||
uri = Services.io.newURI(str, null, null);
|
||||
uri = uri.QueryInterface(Ci.nsIURL);
|
||||
} catch (e) {
|
||||
throw new MalformedException("url_parsing.error", unchecked);
|
||||
}
|
||||
|
||||
if (uri.scheme != "http" && uri.scheme != "https")
|
||||
throw new MalformedException("url_scheme.error", unchecked);
|
||||
|
||||
return uri.spec;
|
||||
},
|
||||
|
||||
/**
|
||||
* A value which should be shown to the user in the UI as label
|
||||
*/
|
||||
label : function(unchecked)
|
||||
{
|
||||
return this.string(unchecked);
|
||||
},
|
||||
|
||||
/**
|
||||
* Allows only certain values as input, otherwise throw.
|
||||
*
|
||||
* @param unchecked {Any} The value to check
|
||||
* @param allowedValues {Array} List of values that |unchecked| may have.
|
||||
* @param defaultValue {Any} (Optional) If |unchecked| does not match
|
||||
* anything in |mapping|, a |defaultValue| can be returned instead of
|
||||
* throwing an exception. The latter is the default and happens when
|
||||
* no |defaultValue| is passed.
|
||||
* @throws MalformedException
|
||||
*/
|
||||
enum : function(unchecked, allowedValues, defaultValue)
|
||||
{
|
||||
for (let allowedValue of allowedValues)
|
||||
{
|
||||
if (allowedValue == unchecked)
|
||||
return allowedValue;
|
||||
}
|
||||
// value is bad
|
||||
if (typeof(defaultValue) == "undefined")
|
||||
throw new MalformedException("allowed_value.error", unchecked);
|
||||
return defaultValue;
|
||||
},
|
||||
|
||||
/**
|
||||
* Like enum, allows only certain (string) values as input, but allows the
|
||||
* caller to specify another value to return instead of the input value. E.g.,
|
||||
* if unchecked == "foo", return 1, if unchecked == "bar", return 2,
|
||||
* otherwise throw. This allows to translate string enums into integer enums.
|
||||
*
|
||||
* @param unchecked {Any} The value to check
|
||||
* @param mapping {Object} Associative array. property name is the input
|
||||
* value, property value is the output value. E.g. the example above
|
||||
* would be: { foo: 1, bar : 2 }.
|
||||
* Use quotes when you need freaky characters: "baz-" : 3.
|
||||
* @param defaultValue {Any} (Optional) If |unchecked| does not match
|
||||
* anything in |mapping|, a |defaultValue| can be returned instead of
|
||||
* throwing an exception. The latter is the default and happens when
|
||||
* no |defaultValue| is passed.
|
||||
* @throws MalformedException
|
||||
*/
|
||||
translate : function(unchecked, mapping, defaultValue)
|
||||
{
|
||||
for (var inputValue in mapping)
|
||||
{
|
||||
if (inputValue == unchecked)
|
||||
return mapping[inputValue];
|
||||
}
|
||||
// value is bad
|
||||
if (typeof(defaultValue) == "undefined")
|
||||
throw new MalformedException("allowed_value.error", unchecked);
|
||||
return defaultValue;
|
||||
}
|
||||
};
|
||||
|
||||
function MalformedException(msgID, uncheckedBadValue)
|
||||
{
|
||||
var stringBundle = getStringBundle(
|
||||
"chrome://messenger/locale/accountCreationUtil.properties");
|
||||
var msg = stringBundle.GetStringFromName(msgID);
|
||||
if (kDebug)
|
||||
msg += " (bad value: " + new String(uncheckedBadValue) + ")";
|
||||
Exception.call(this, msg);
|
||||
}
|
||||
MalformedException.prototype = Object.create(Exception.prototype);
|
||||
MalformedException.prototype.constructor = MalformedException;
|
||||
|
||||
304
mailnews/base/prefs/content/accountcreation/util.js
Normal file
304
mailnews/base/prefs/content/accountcreation/util.js
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
/* -*- 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/. */
|
||||
/**
|
||||
* Some common, generic functions
|
||||
*/
|
||||
|
||||
try {
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
} catch (e) { ddump(e); } // if already declared, as in xpcshell-tests
|
||||
try {
|
||||
var Cu = Components.utils;
|
||||
} catch (e) { ddump(e); }
|
||||
|
||||
Cu.import("resource:///modules/errUtils.js");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function assert(test, errorMsg)
|
||||
{
|
||||
if (!test)
|
||||
throw new NotReached(errorMsg ? errorMsg :
|
||||
"Programming bug. Assertion failed, see log.");
|
||||
}
|
||||
|
||||
function makeCallback(obj, func)
|
||||
{
|
||||
return function()
|
||||
{
|
||||
return func.apply(obj, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs the given function sometime later
|
||||
*
|
||||
* Currently implemented using setTimeout(), but
|
||||
* can later be replaced with an nsITimer impl,
|
||||
* when code wants to use it in a module.
|
||||
*/
|
||||
function runAsync(func)
|
||||
{
|
||||
setTimeout(func, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param uriStr {String}
|
||||
* @result {nsIURI}
|
||||
*/
|
||||
function makeNSIURI(uriStr)
|
||||
{
|
||||
return Services.io.newURI(uriStr, null, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads UTF8 data from a URL.
|
||||
*
|
||||
* @param uri {nsIURI} what you want to read
|
||||
* @return {Array of String} the contents of the file, one string per line
|
||||
*/
|
||||
function readURLasUTF8(uri)
|
||||
{
|
||||
assert(uri instanceof Ci.nsIURI, "uri must be an nsIURI");
|
||||
try {
|
||||
let chan = Services.io.newChannelFromURI2(uri,
|
||||
null,
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
null,
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_OTHER);
|
||||
let is = Cc["@mozilla.org/intl/converter-input-stream;1"]
|
||||
.createInstance(Ci.nsIConverterInputStream);
|
||||
is.init(chan.open(), "UTF-8", 1024,
|
||||
Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
|
||||
|
||||
let content = "";
|
||||
let strOut = new Object();
|
||||
try {
|
||||
while (is.readString(1024, strOut) != 0)
|
||||
content += strOut.value;
|
||||
// catch in outer try/catch
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
|
||||
return content;
|
||||
} catch (e) {
|
||||
// TODO this has a numeric error message. We need to ship translations
|
||||
// into human language.
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a string (which is typically the content of a file,
|
||||
* e.g. the result returned from readURLUTF8() ), and splits
|
||||
* it into lines, and returns an array with one string per line
|
||||
*
|
||||
* Linebreaks are not contained in the result,,
|
||||
* and all of \r\n, (Windows) \r (Mac) and \n (Unix) counts as linebreak.
|
||||
*
|
||||
* @param content {String} one long string with the whole file
|
||||
* @return {Array of String} one string per line (no linebreaks)
|
||||
*/
|
||||
function splitLines(content)
|
||||
{
|
||||
content = content.replace("\r\n", "\n");
|
||||
content = content.replace("\r", "\n");
|
||||
return content.split("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bundleURI {String} chrome URL to properties file
|
||||
* @return nsIStringBundle
|
||||
*/
|
||||
function getStringBundle(bundleURI)
|
||||
{
|
||||
try {
|
||||
return Services.strings.createBundle(bundleURI);
|
||||
} catch (e) {
|
||||
throw new Exception("Failed to get stringbundle URI <" + bundleURI +
|
||||
">. Error: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Exception(msg)
|
||||
{
|
||||
this._message = msg;
|
||||
|
||||
// get stack
|
||||
try {
|
||||
not.found.here += 1; // force a native exception ...
|
||||
} catch (e) {
|
||||
this.stack = e.stack; // ... to get the current stack
|
||||
}
|
||||
}
|
||||
Exception.prototype =
|
||||
{
|
||||
get message()
|
||||
{
|
||||
return this._message;
|
||||
},
|
||||
toString : function()
|
||||
{
|
||||
return this._message;
|
||||
}
|
||||
}
|
||||
|
||||
function NotReached(msg)
|
||||
{
|
||||
Exception.call(this, msg); // call super constructor
|
||||
logException(this);
|
||||
}
|
||||
// Make NotReached extend Exception.
|
||||
NotReached.prototype = Object.create(Exception.prototype);
|
||||
NotReached.prototype.constructor = NotReached;
|
||||
|
||||
/**
|
||||
* A handle for an async function which you can cancel.
|
||||
* The async function will return an object of this type (a subtype)
|
||||
* and you can call cancel() when you feel like killing the function.
|
||||
*/
|
||||
function Abortable()
|
||||
{
|
||||
}
|
||||
Abortable.prototype =
|
||||
{
|
||||
cancel : function()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility implementation, for allowing to abort a setTimeout.
|
||||
* Use like: return new TimeoutAbortable(setTimeout(function(){ ... }, 0));
|
||||
* @param setTimeoutID {Integer} Return value of setTimeout()
|
||||
*/
|
||||
function TimeoutAbortable(setTimeoutID)
|
||||
{
|
||||
Abortable.call(this, setTimeoutID); // call super constructor
|
||||
this._id = setTimeoutID;
|
||||
}
|
||||
TimeoutAbortable.prototype = Object.create(Abortable.prototype);
|
||||
TimeoutAbortable.prototype.constructor = TimeoutAbortable;
|
||||
TimeoutAbortable.prototype.cancel = function() { clearTimeout(this._id); }
|
||||
|
||||
/**
|
||||
* Utility implementation, for allowing to abort a setTimeout.
|
||||
* Use like: return new TimeoutAbortable(setTimeout(function(){ ... }, 0));
|
||||
* @param setIntervalID {Integer} Return value of setInterval()
|
||||
*/
|
||||
function IntervalAbortable(setIntervalID)
|
||||
{
|
||||
Abortable.call(this, setIntervalID); // call super constructor
|
||||
this._id = setIntervalID;
|
||||
}
|
||||
IntervalAbortable.prototype = Object.create(Abortable.prototype);
|
||||
IntervalAbortable.prototype.constructor = IntervalAbortable;
|
||||
IntervalAbortable.prototype.cancel = function() { clearInterval(this._id); }
|
||||
|
||||
// Allows you to make several network calls, but return
|
||||
// only one Abortable object.
|
||||
function SuccessiveAbortable()
|
||||
{
|
||||
Abortable.call(this); // call super constructor
|
||||
this._current = null;
|
||||
}
|
||||
SuccessiveAbortable.prototype = {
|
||||
__proto__: Abortable.prototype,
|
||||
get current() { return this._current; },
|
||||
set current(abortable)
|
||||
{
|
||||
assert(abortable instanceof Abortable || abortable == null,
|
||||
"need an Abortable object (or null)");
|
||||
this._current = abortable;
|
||||
},
|
||||
cancel: function()
|
||||
{
|
||||
if (this._current)
|
||||
this._current.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
function deepCopy(org)
|
||||
{
|
||||
if (typeof(org) == "undefined")
|
||||
return undefined;
|
||||
if (org == null)
|
||||
return null;
|
||||
if (typeof(org) == "string")
|
||||
return org;
|
||||
if (typeof(org) == "number")
|
||||
return org;
|
||||
if (typeof(org) == "boolean")
|
||||
return org == true;
|
||||
if (typeof(org) == "function")
|
||||
return org;
|
||||
if (typeof(org) != "object")
|
||||
throw "can't copy objects of type " + typeof(org) + " yet";
|
||||
|
||||
//TODO still instanceof org != instanceof copy
|
||||
//var result = new org.constructor();
|
||||
var result = new Object();
|
||||
if (typeof(org.length) != "undefined")
|
||||
var result = new Array();
|
||||
for (var prop in org)
|
||||
result[prop] = deepCopy(org[prop]);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (typeof gEmailWizardLogger == "undefined") {
|
||||
Cu.import("resource:///modules/gloda/log4moz.js");
|
||||
var gEmailWizardLogger = Log4Moz.getConfiguredLogger("mail.wizard");
|
||||
}
|
||||
function ddump(text)
|
||||
{
|
||||
gEmailWizardLogger.info(text);
|
||||
}
|
||||
|
||||
function debugObject(obj, name, maxDepth, curDepth)
|
||||
{
|
||||
if (curDepth == undefined)
|
||||
curDepth = 0;
|
||||
if (maxDepth != undefined && curDepth > maxDepth)
|
||||
return "";
|
||||
|
||||
var result = "";
|
||||
var i = 0;
|
||||
for (let prop in obj)
|
||||
{
|
||||
i++;
|
||||
try {
|
||||
if (typeof(obj[prop]) == "object")
|
||||
{
|
||||
if (obj[prop] && obj[prop].length != undefined)
|
||||
result += name + "." + prop + "=[probably array, length " +
|
||||
obj[prop].length + "]\n";
|
||||
else
|
||||
result += name + "." + prop + "=[" + typeof(obj[prop]) + "]\n";
|
||||
result += debugObject(obj[prop], name + "." + prop,
|
||||
maxDepth, curDepth + 1);
|
||||
}
|
||||
else if (typeof(obj[prop]) == "function")
|
||||
result += name + "." + prop + "=[function]\n";
|
||||
else
|
||||
result += name + "." + prop + "=" + obj[prop] + "\n";
|
||||
} catch (e) {
|
||||
result += name + "." + prop + "-> Exception(" + e + ")\n";
|
||||
}
|
||||
}
|
||||
if (!i)
|
||||
result += name + " is empty\n";
|
||||
return result;
|
||||
}
|
||||
|
||||
function alertPrompt(alertTitle, alertMsg)
|
||||
{
|
||||
Services.prompt.alert(window, alertTitle, alertMsg);
|
||||
}
|
||||
347
mailnews/base/prefs/content/accountcreation/verifyConfig.js
Normal file
347
mailnews/base/prefs/content/accountcreation/verifyConfig.js
Normal file
|
|
@ -0,0 +1,347 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
/**
|
||||
* This checks a given config, by trying a real connection and login,
|
||||
* with username and password.
|
||||
*
|
||||
* TODO
|
||||
* - give specific errors, bug 555448
|
||||
* - return a working |Abortable| to allow cancel
|
||||
*
|
||||
* @param accountConfig {AccountConfig} The guessed account config.
|
||||
* username, password, realname, emailaddress etc. are not filled out,
|
||||
* but placeholders to be filled out via replaceVariables().
|
||||
* @param alter {boolean}
|
||||
* Try other usernames and login schemes, until login works.
|
||||
* Warning: Modifies |accountConfig|.
|
||||
*
|
||||
* This function is async.
|
||||
* @param successCallback function(accountConfig)
|
||||
* Called when we could guess the config.
|
||||
* For accountConfig, see below.
|
||||
* @param errorCallback function(ex)
|
||||
* Called when we could guess not the config, either
|
||||
* because we have not found anything or
|
||||
* because there was an error (e.g. no network connection).
|
||||
* The ex.message will contain a user-presentable message.
|
||||
*/
|
||||
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
Components.utils.import("resource://gre/modules/OAuth2Providers.jsm");
|
||||
|
||||
if (typeof gEmailWizardLogger == "undefined") {
|
||||
Cu.import("resource:///modules/gloda/log4moz.js");
|
||||
var gEmailWizardLogger = Log4Moz.getConfiguredLogger("mail.wizard");
|
||||
}
|
||||
|
||||
function verifyConfig(config, alter, msgWindow, successCallback, errorCallback)
|
||||
{
|
||||
ddump(debugObject(config, "config", 3));
|
||||
assert(config instanceof AccountConfig,
|
||||
"BUG: Arg 'config' needs to be an AccountConfig object");
|
||||
assert(typeof(alter) == "boolean");
|
||||
assert(typeof(successCallback) == "function");
|
||||
assert(typeof(errorCallback) == "function");
|
||||
|
||||
if (MailServices.accounts.findRealServer(config.incoming.username,
|
||||
config.incoming.hostname,
|
||||
sanitize.enum(config.incoming.type,
|
||||
["pop3", "imap", "nntp"]),
|
||||
config.incoming.port)) {
|
||||
errorCallback("Incoming server exists");
|
||||
return;
|
||||
}
|
||||
|
||||
// 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.password = config.incoming.password;
|
||||
if (config.incoming.socketType == 1) // plain
|
||||
inServer.socketType = Ci.nsMsgSocketType.plain;
|
||||
else if (config.incoming.socketType == 2) // SSL
|
||||
inServer.socketType = Ci.nsMsgSocketType.SSL;
|
||||
else if (config.incoming.socketType == 3) // STARTTLS
|
||||
inServer.socketType = Ci.nsMsgSocketType.alwaysSTARTTLS;
|
||||
|
||||
gEmailWizardLogger.info("Setting incoming server authMethod to " +
|
||||
config.incoming.auth);
|
||||
inServer.authMethod = config.incoming.auth;
|
||||
|
||||
try {
|
||||
// Lookup issuer if needed.
|
||||
if (config.incoming.auth == Ci.nsMsgAuthMethod.OAuth2 ||
|
||||
config.outgoing.auth == Ci.nsMsgAuthMethod.OAuth2) {
|
||||
if (!config.oauthSettings)
|
||||
config.oauthSettings = {};
|
||||
if (!config.oauthSettings.issuer || !config.oauthSettings.scope) {
|
||||
// lookup issuer or scope from hostname
|
||||
let hostname = (config.incoming.auth == Ci.nsMsgAuthMethod.OAuth2) ?
|
||||
config.incoming.hostname : config.outgoing.hostname;
|
||||
let hostDetails = OAuth2Providers.getHostnameDetails(hostname);
|
||||
if (hostDetails)
|
||||
[config.oauthSettings.issuer, config.oauthSettings.scope] = hostDetails;
|
||||
if (!config.oauthSettings.issuer || !config.oauthSettings.scope)
|
||||
throw "Could not get issuer for oauth2 authentication";
|
||||
}
|
||||
gEmailWizardLogger.info("Saving oauth parameters for issuer " +
|
||||
config.oauthSettings.issuer);
|
||||
inServer.setCharValue("oauth2.scope", config.oauthSettings.scope);
|
||||
inServer.setCharValue("oauth2.issuer", config.oauthSettings.issuer);
|
||||
gEmailWizardLogger.info("OAuth2 issuer, scope is " +
|
||||
config.oauthSettings.issuer + ", " + config.oauthSettings.scope);
|
||||
}
|
||||
|
||||
if (inServer.password ||
|
||||
inServer.authMethod == Ci.nsMsgAuthMethod.OAuth2)
|
||||
verifyLogon(config, inServer, alter, msgWindow,
|
||||
successCallback, errorCallback);
|
||||
else {
|
||||
// Avoid pref pollution, clear out server prefs.
|
||||
MailServices.accounts.removeIncomingServer(inServer, true);
|
||||
successCallback(config);
|
||||
}
|
||||
return;
|
||||
}
|
||||
catch (e) {
|
||||
gEmailWizardLogger.error("ERROR: verify logon shouldn't have failed");
|
||||
}
|
||||
// Avoid pref pollution, clear out server prefs.
|
||||
MailServices.accounts.removeIncomingServer(inServer, true);
|
||||
errorCallback(e);
|
||||
}
|
||||
|
||||
function verifyLogon(config, inServer, alter, msgWindow, successCallback,
|
||||
errorCallback)
|
||||
{
|
||||
gEmailWizardLogger.info("verifyLogon for server at " + inServer.hostName);
|
||||
// hack - save away the old callbacks.
|
||||
let saveCallbacks = msgWindow.notificationCallbacks;
|
||||
// set our own callbacks - this works because verifyLogon will
|
||||
// synchronously create the transport and use the notification callbacks.
|
||||
let listener = new urlListener(config, inServer, alter, msgWindow,
|
||||
successCallback, errorCallback);
|
||||
// our listener listens both for the url and cert errors.
|
||||
msgWindow.notificationCallbacks = listener;
|
||||
// try to work around bug where backend is clearing password.
|
||||
try {
|
||||
inServer.password = config.incoming.password;
|
||||
let uri = inServer.verifyLogon(listener, msgWindow);
|
||||
// clear msgWindow so url won't prompt for passwords.
|
||||
uri.QueryInterface(Ci.nsIMsgMailNewsUrl).msgWindow = null;
|
||||
}
|
||||
catch (e) { gEmailWizardLogger.error("verifyLogon failed: " + e); throw e;}
|
||||
finally {
|
||||
// restore them
|
||||
msgWindow.notificationCallbacks = saveCallbacks;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The url listener also implements nsIBadCertListener2. Its job is to prevent
|
||||
* "bad cert" security dialogs from being shown to the user. Currently it puts
|
||||
* up the cert override dialog, though we'd like to give the user more detailed
|
||||
* information in the future.
|
||||
*/
|
||||
|
||||
function urlListener(config, server, alter, msgWindow, successCallback,
|
||||
errorCallback)
|
||||
{
|
||||
this.mConfig = config;
|
||||
this.mServer = server;
|
||||
this.mAlter = alter;
|
||||
this.mSuccessCallback = successCallback;
|
||||
this.mErrorCallback = errorCallback;
|
||||
this.mMsgWindow = msgWindow;
|
||||
this.mCertError = false;
|
||||
this._log = Log4Moz.getConfiguredLogger("mail.wizard");
|
||||
}
|
||||
urlListener.prototype =
|
||||
{
|
||||
OnStartRunningUrl: function(aUrl)
|
||||
{
|
||||
this._log.info("Starting to test username");
|
||||
this._log.info(" username=" + (this.mConfig.incoming.username !=
|
||||
this.mConfig.identity.emailAddress) +
|
||||
", have savedUsername=" +
|
||||
(this.mConfig.usernameSaved ? "true" : "false"));
|
||||
this._log.info(" authMethod=" + this.mServer.authMethod);
|
||||
},
|
||||
|
||||
OnStopRunningUrl: function(aUrl, aExitCode)
|
||||
{
|
||||
this._log.info("Finished verifyConfig resulted in " + aExitCode);
|
||||
if (Components.isSuccessCode(aExitCode))
|
||||
{
|
||||
this._cleanup();
|
||||
this.mSuccessCallback(this.mConfig);
|
||||
}
|
||||
// Logon failed, and we aren't supposed to try other variations.
|
||||
else if (!this.mAlter)
|
||||
{
|
||||
this._cleanup();
|
||||
var errorMsg = getStringBundle(
|
||||
"chrome://messenger/locale/accountCreationModel.properties")
|
||||
.GetStringFromName("cannot_login.error");
|
||||
this.mErrorCallback(new Exception(errorMsg));
|
||||
}
|
||||
// Try other variations, unless there's a cert error, in which
|
||||
// case we'll see what the user chooses.
|
||||
else if (!this.mCertError)
|
||||
{
|
||||
this.tryNextLogon()
|
||||
}
|
||||
},
|
||||
|
||||
tryNextLogon: function()
|
||||
{
|
||||
this._log.info("tryNextLogon()");
|
||||
this._log.info(" username=" + (this.mConfig.incoming.username !=
|
||||
this.mConfig.identity.emailAddress) +
|
||||
", have savedUsername=" +
|
||||
(this.mConfig.usernameSaved ? "true" : "false"));
|
||||
this._log.info(" authMethod=" + this.mServer.authMethod);
|
||||
// check if we tried full email address as username
|
||||
if (this.mConfig.incoming.username != this.mConfig.identity.emailAddress)
|
||||
{
|
||||
this._log.info(" Changing username to email address.");
|
||||
this.mConfig.usernameSaved = this.mConfig.incoming.username;
|
||||
this.mConfig.incoming.username = this.mConfig.identity.emailAddress;
|
||||
this.mConfig.outgoing.username = this.mConfig.identity.emailAddress;
|
||||
this.mServer.username = this.mConfig.incoming.username;
|
||||
this.mServer.password = this.mConfig.incoming.password;
|
||||
verifyLogon(this.mConfig, this.mServer, this.mAlter, this.mMsgWindow,
|
||||
this.mSuccessCallback, this.mErrorCallback);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.mConfig.usernameSaved)
|
||||
{
|
||||
this._log.info(" Re-setting username.");
|
||||
// If we tried the full email address as the username, then let's go
|
||||
// back to trying just the username before trying the other cases.
|
||||
this.mConfig.incoming.username = this.mConfig.usernameSaved;
|
||||
this.mConfig.outgoing.username = this.mConfig.usernameSaved;
|
||||
this.mConfig.usernameSaved = null;
|
||||
this.mServer.username = this.mConfig.incoming.username;
|
||||
this.mServer.password = this.mConfig.incoming.password;
|
||||
}
|
||||
|
||||
// sec auth seems to have failed, and we've tried both
|
||||
// varieties of user name, sadly.
|
||||
// So fall back to non-secure auth, and
|
||||
// again try the user name and email address as username
|
||||
assert(this.mConfig.incoming.auth == this.mServer.authMethod);
|
||||
this._log.info(" Using SSL: " +
|
||||
(this.mServer.socketType == Ci.nsMsgSocketType.SSL ||
|
||||
this.mServer.socketType == Ci.nsMsgSocketType.alwaysSTARTTLS));
|
||||
if (this.mConfig.incoming.authAlternatives &&
|
||||
this.mConfig.incoming.authAlternatives.length)
|
||||
// We may be dropping back to insecure auth methods here,
|
||||
// which is not good. But then again, we already warned the user,
|
||||
// if it is a config without SSL.
|
||||
{
|
||||
this._log.info(" auth alternatives = " +
|
||||
this.mConfig.incoming.authAlternatives.join(","));
|
||||
this._log.info(" Decreasing auth.");
|
||||
this._log.info(" Have password: " +
|
||||
(this.mServer.password ? "true" : "false"));
|
||||
let brokenAuth = this.mConfig.incoming.auth;
|
||||
// take the next best method (compare chooseBestAuthMethod() in guess)
|
||||
this.mConfig.incoming.auth =
|
||||
this.mConfig.incoming.authAlternatives.shift();
|
||||
this.mServer.authMethod = this.mConfig.incoming.auth;
|
||||
// Assume that SMTP server has same methods working as incoming.
|
||||
// Broken assumption, but we currently have no SMTP verification.
|
||||
// TODO implement real SMTP verification
|
||||
if (this.mConfig.outgoing.auth == brokenAuth &&
|
||||
this.mConfig.outgoing.authAlternatives.indexOf(
|
||||
this.mConfig.incoming.auth) != -1)
|
||||
this.mConfig.outgoing.auth = this.mConfig.incoming.auth;
|
||||
this._log.info(" outgoing auth: " + this.mConfig.outgoing.auth);
|
||||
verifyLogon(this.mConfig, this.mServer, this.mAlter, this.mMsgWindow,
|
||||
this.mSuccessCallback, this.mErrorCallback);
|
||||
return;
|
||||
}
|
||||
|
||||
// Tried all variations we can. Give up.
|
||||
this._log.info("Giving up.");
|
||||
this._cleanup();
|
||||
let errorMsg = getStringBundle(
|
||||
"chrome://messenger/locale/accountCreationModel.properties")
|
||||
.GetStringFromName("cannot_login.error");
|
||||
this.mErrorCallback(new Exception(errorMsg));
|
||||
return;
|
||||
},
|
||||
|
||||
_cleanup : function()
|
||||
{
|
||||
try {
|
||||
// Avoid pref pollution, clear out server prefs.
|
||||
if (this.mServer) {
|
||||
MailServices.accounts.removeIncomingServer(this.mServer, true);
|
||||
this.mServer = null;
|
||||
}
|
||||
} catch (e) { this._log.error(e); }
|
||||
},
|
||||
|
||||
// Suppress any certificate errors
|
||||
notifyCertProblem: function(socketInfo, status, targetSite) {
|
||||
this.mCertError = true;
|
||||
this._log.error("cert error");
|
||||
let self = this;
|
||||
setTimeout(function () {
|
||||
try {
|
||||
self.informUserOfCertError(socketInfo, status, targetSite);
|
||||
} catch (e) { logException(e); }
|
||||
}, 0);
|
||||
return true;
|
||||
},
|
||||
|
||||
informUserOfCertError : function(socketInfo, status, targetSite) {
|
||||
var params = {
|
||||
exceptionAdded : false,
|
||||
sslStatus : status,
|
||||
prefetchCert : true,
|
||||
location : targetSite,
|
||||
};
|
||||
window.openDialog("chrome://pippki/content/exceptionDialog.xul",
|
||||
"","chrome,centerscreen,modal", params);
|
||||
this._log.info("cert exception dialog closed");
|
||||
this._log.info("cert exceptionAdded = " + params.exceptionAdded);
|
||||
if (!params.exceptionAdded) {
|
||||
this._cleanup();
|
||||
let errorMsg = getStringBundle(
|
||||
"chrome://messenger/locale/accountCreationModel.properties")
|
||||
.GetStringFromName("cannot_login.error");
|
||||
this.mErrorCallback(new Exception(errorMsg));
|
||||
}
|
||||
else {
|
||||
// Retry the logon now that we've added the cert exception.
|
||||
verifyLogon(this.mConfig, this.mServer, this.mAlter, this.mMsgWindow,
|
||||
this.mSuccessCallback, this.mErrorCallback);
|
||||
}
|
||||
},
|
||||
|
||||
// nsIInterfaceRequestor
|
||||
getInterface: function(iid) {
|
||||
return this.QueryInterface(iid);
|
||||
},
|
||||
|
||||
// nsISupports
|
||||
QueryInterface: function(iid) {
|
||||
if (!iid.equals(Components.interfaces.nsIBadCertListener2) &&
|
||||
!iid.equals(Components.interfaces.nsIInterfaceRequestor) &&
|
||||
!iid.equals(Components.interfaces.nsIUrlListener) &&
|
||||
!iid.equals(Components.interfaces.nsISupports))
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
79
mailnews/base/prefs/content/am-addressing.js
Normal file
79
mailnews/base/prefs/content/am-addressing.js
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function onLoad()
|
||||
{
|
||||
parent.onPanelLoaded('am-addressing.xul');
|
||||
}
|
||||
|
||||
function onInit(aPageId, aServerId)
|
||||
{
|
||||
onInitCompositionAndAddressing();
|
||||
}
|
||||
|
||||
function onInitCompositionAndAddressing()
|
||||
{
|
||||
LDAPenabling();
|
||||
quoteEnabling();
|
||||
}
|
||||
|
||||
function onEditDirectories()
|
||||
{
|
||||
window.openDialog("chrome://messenger/content/addressbook/pref-editdirectories.xul",
|
||||
"editDirectories", "chrome,modal=yes,resizable=no", null);
|
||||
}
|
||||
|
||||
function onPreInit(account, accountValues)
|
||||
{
|
||||
}
|
||||
|
||||
function LDAPenabling()
|
||||
{
|
||||
onCheckItem("identity.directoryServer", ["directories"]);
|
||||
onCheckItem("editButton", ["directories"]);
|
||||
}
|
||||
|
||||
function quoteEnabling()
|
||||
{
|
||||
var quotebox = document.getElementById("thenBox");
|
||||
var placebox = document.getElementById("placeBox");
|
||||
var quotecheck = document.getElementById("identity.autoQuote");
|
||||
|
||||
if (quotecheck.checked && !quotecheck.disabled &&
|
||||
(document.getElementById("identity.replyOnTop").value == 1)) {
|
||||
placebox.firstChild.removeAttribute("disabled");
|
||||
placebox.lastChild.removeAttribute("disabled");
|
||||
}
|
||||
else {
|
||||
placebox.firstChild.setAttribute("disabled", "true");
|
||||
placebox.lastChild.setAttribute("disabled", "true");
|
||||
}
|
||||
if (quotecheck.checked && !quotecheck.disabled) {
|
||||
quotebox.firstChild.removeAttribute("disabled");
|
||||
quotebox.lastChild.removeAttribute("disabled");
|
||||
}
|
||||
else {
|
||||
quotebox.firstChild.setAttribute("disabled", "true");
|
||||
quotebox.lastChild.setAttribute("disabled", "true");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the Preferences dialog on the tab with Addressing options.
|
||||
*/
|
||||
function showGlobalAddressingPrefs()
|
||||
{
|
||||
openPrefsFromAccountManager("paneCompose", "addressingTab", null, "addressing_pane");
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the Preferences dialog on the tab with Composing options.
|
||||
*/
|
||||
function showGlobalComposingPrefs()
|
||||
{
|
||||
openPrefsFromAccountManager("paneCompose", "generalTab", null, "composing_messages_pane");
|
||||
}
|
||||
18
mailnews/base/prefs/content/am-addressing.xul
Normal file
18
mailnews/base/prefs/content/am-addressing.xul
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xul-overlay href="chrome://messenger/content/am-addressingOverlay.xul"?>
|
||||
|
||||
<!DOCTYPE page SYSTEM "chrome://messenger/locale/am-addressing.dtd">
|
||||
|
||||
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&addressing.label;"
|
||||
onload="onLoad();">
|
||||
<vbox flex="1" style="overflow: auto;">
|
||||
<dialogheader title="&addressing.label;"/>
|
||||
<vbox id="compositionAndAddressing"/>
|
||||
</vbox>
|
||||
</page>
|
||||
135
mailnews/base/prefs/content/am-addressingOverlay.xul
Normal file
135
mailnews/base/prefs/content/am-addressingOverlay.xul
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/content/messenger.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/accountManage.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE overlay SYSTEM "chrome://messenger/locale/am-addressing.dtd">
|
||||
|
||||
<overlay xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/javascript" src="chrome://messenger/content/am-addressing.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/amUtils.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/am-prefs.js"/>
|
||||
|
||||
<vbox flex="1" id="compositionAndAddressing">
|
||||
<stringbundle id="bundle_addressBook" src="chrome://messenger/locale/addressbook/addressBook.properties"/>
|
||||
|
||||
<groupbox>
|
||||
<caption label="&compositionGroupTitle.label;"/>
|
||||
<hbox align="center">
|
||||
<checkbox wsm_persist="true" id="identity.composeHtml" label="&useHtml.label;"
|
||||
accesskey="&useHtml.accesskey;"
|
||||
prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.compose_html"/>
|
||||
</hbox>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<hbox align="center">
|
||||
<checkbox wsm_persist="true" id="identity.autoQuote" label="&autoQuote.label;"
|
||||
oncommand="quoteEnabling();" accesskey="&autoQuote.accesskey;"
|
||||
pref="true" preftype="bool" prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.auto_quote"/>
|
||||
</hbox>
|
||||
<hbox class="indent" align="center" id="thenBox">
|
||||
<label value="&then.label;" accesskey="&then.accesskey;" control="identity.replyOnTop"/>
|
||||
<menulist wsm_persist="true" id="identity.replyOnTop" oncommand="quoteEnabling();"
|
||||
pref="true" preftype="int" prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.reply_on_top">
|
||||
<menupopup>
|
||||
<menuitem value="1" label="&aboveQuote.label;"/>
|
||||
<menuitem value="0" label="&belowQuote.label;"/>
|
||||
<menuitem value="2" label="&selectAndQuote.label;"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</hbox>
|
||||
<hbox class="indent" align="center" id="placeBox">
|
||||
<label value="&place.label;" accesskey="&place.accesskey;" control="identity.sig_bottom"/>
|
||||
<menulist wsm_persist="true" id="identity.sig_bottom" genericattr="true"
|
||||
pref="true" preftype="bool" prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.sig_bottom">
|
||||
<menupopup>
|
||||
<menuitem value="true" label="&belowText.label;"/>
|
||||
<menuitem value="false" label="&aboveText.label;"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</hbox>
|
||||
|
||||
<checkbox id="identity.sig_on_reply" wsm_persist="true"
|
||||
label="&includeSigOnReply.label;"
|
||||
accesskey="&includeSigOnReply.accesskey;"
|
||||
preftype="bool" genericattr="true"
|
||||
prefstring="mail.identity.%identitykey%.sig_on_reply"/>
|
||||
|
||||
<checkbox id="identity.sig_on_fwd" wsm_persist="true"
|
||||
label="&includeSigOnForward.label;"
|
||||
accesskey="&includeSigOnForward.accesskey;"
|
||||
preftype="bool" genericattr="true"
|
||||
prefstring="mail.identity.%identitykey%.sig_on_fwd"/>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<hbox pack="start">
|
||||
<button id="globalComposingPrefsLink"
|
||||
label="&globalComposingPrefs.label;"
|
||||
accesskey="&globalComposingPrefs.accesskey;"
|
||||
oncommand="showGlobalComposingPrefs();"/>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<groupbox>
|
||||
<caption label="&addressingGroupTitle.label;"/>
|
||||
#ifndef MOZ_THUNDERBIRD
|
||||
<hbox align="center">
|
||||
<checkbox wsm_persist="true" id="identity.autocompleteToMyDomain"
|
||||
label="&autocompleteToMyDomain.label;"
|
||||
accesskey="&autocompleteToMyDomain.accesskey;"
|
||||
prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.autocompleteToMyDomain"/>
|
||||
</hbox>
|
||||
|
||||
<separator class="thin"/>
|
||||
#endif
|
||||
|
||||
<label control="identity.overrideGlobal_Pref">&addressingText.label;</label>
|
||||
<radiogroup id="identity.overrideGlobal_Pref" class="indent"
|
||||
oncommand="LDAPenabling();" wsm_persist="true"
|
||||
genericattr="true" preftype="bool"
|
||||
prefstring="mail.identity.%identitykey%.overrideGlobal_Pref">
|
||||
<radio value="false" label="&useGlobal.label;"
|
||||
accesskey="&useGlobal.accesskey;"/>
|
||||
<radio value="true" id="directories" label="&directories.label;"
|
||||
accesskey="&directories.accesskey;"/>
|
||||
<hbox class="indent">
|
||||
<menulist id="identity.directoryServer"
|
||||
wsm_persist="true" preftype="string"
|
||||
prefstring="mail.identity.%identitykey%.directoryServer"
|
||||
style="min-width: 16em;" aria-labelledby="directories">
|
||||
<menupopup class="addrbooksPopup"
|
||||
none="&directoriesNone.label;"
|
||||
remoteonly="true" value="dirPrefId"/>
|
||||
</menulist>
|
||||
<button id="editButton" label="&editDirectories.label;"
|
||||
accesskey="&editDirectories.accesskey;"
|
||||
oncommand="onEditDirectories();"/>
|
||||
</hbox>
|
||||
</radiogroup>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<hbox pack="start">
|
||||
<button id="globalAddressingPrefsLink"
|
||||
label="&globalAddressingPrefs.label;"
|
||||
accesskey="&globalAddressingPrefs.accesskey;"
|
||||
oncommand="showGlobalAddressingPrefs();"/>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
</vbox>
|
||||
</overlay>
|
||||
69
mailnews/base/prefs/content/am-archiveoptions.js
Normal file
69
mailnews/base/prefs/content/am-archiveoptions.js
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
var gIdentity = null;
|
||||
|
||||
/**
|
||||
* Load the archive options dialog, set the radio/checkbox items to the
|
||||
* appropriate values, and update the archive hierarchy example.
|
||||
*/
|
||||
function onLoadArchiveOptions() {
|
||||
// extract the account
|
||||
gIdentity = window.arguments[0];
|
||||
|
||||
let granularity = document.getElementById("archiveGranularity");
|
||||
granularity.selectedIndex = gIdentity.archiveGranularity;
|
||||
granularity.addEventListener("command", updateArchiveExample, false);
|
||||
|
||||
let kfs = document.getElementById("archiveKeepFolderStructure");
|
||||
kfs.checked = gIdentity.archiveKeepFolderStructure;
|
||||
kfs.addEventListener("command", updateArchiveExample, false);
|
||||
|
||||
updateArchiveExample();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the archive settings to the current identity.
|
||||
*/
|
||||
function onAcceptArchiveOptions() {
|
||||
gIdentity.archiveGranularity =
|
||||
document.getElementById("archiveGranularity").selectedIndex;
|
||||
gIdentity.archiveKeepFolderStructure =
|
||||
document.getElementById("archiveKeepFolderStructure").checked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the example tree to show what the current options would look like.
|
||||
*/
|
||||
function updateArchiveExample() {
|
||||
let granularity = document.getElementById("archiveGranularity").selectedIndex;
|
||||
let kfs = document.getElementById("archiveKeepFolderStructure").checked;
|
||||
let hierarchy = [ document.getElementsByClassName("root"),
|
||||
document.getElementsByClassName("year"),
|
||||
document.getElementsByClassName("month") ];
|
||||
|
||||
// First, show/hide the appropriate levels in the hierarchy and turn the
|
||||
// necessary items into containers.
|
||||
for (let i = 0; i < hierarchy.length; i++) {
|
||||
for (let j = 0; j < hierarchy[i].length; j++) {
|
||||
hierarchy[i][j].setAttribute("container", granularity > i);
|
||||
hierarchy[i][j].setAttribute("open", granularity > i);
|
||||
hierarchy[i][j].hidden = granularity < i;
|
||||
}
|
||||
}
|
||||
|
||||
// Next, handle the "keep folder structures" case by moving a tree item around
|
||||
// and making sure its parent is a container.
|
||||
let folders = document.getElementById("folders");
|
||||
folders.hidden = !kfs;
|
||||
if (kfs) {
|
||||
let parent = hierarchy[granularity][0];
|
||||
parent.setAttribute("container", true);
|
||||
parent.setAttribute("open", true);
|
||||
|
||||
let treechildren = parent.children[1];
|
||||
treechildren.appendChild(folders);
|
||||
}
|
||||
}
|
||||
99
mailnews/base/prefs/content/am-archiveoptions.xul
Normal file
99
mailnews/base/prefs/content/am-archiveoptions.xul
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/accountManage.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/messenger.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/folderPane.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE dialog SYSTEM "chrome://messenger/locale/am-archiveoptions.dtd" >
|
||||
|
||||
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
id="archive-options"
|
||||
title="&dialogTitle.label;"
|
||||
width="350" height="350"
|
||||
persist="width height"
|
||||
onload="onLoadArchiveOptions();"
|
||||
ondialogaccept="onAcceptArchiveOptions();">
|
||||
|
||||
<script type="application/javascript" src="chrome://messenger/content/am-archiveoptions.js"/>
|
||||
|
||||
<vbox flex="1">
|
||||
<label>&archiveGranularityPrefix.label;</label>
|
||||
<radiogroup id="archiveGranularity">
|
||||
<radio label="&archiveFlat.label;" accesskey="&archiveFlat.accesskey;"
|
||||
class="indent"/>
|
||||
<radio label="&archiveYearly.label;"
|
||||
accesskey="&archiveYearly.accesskey;" class="indent"/>
|
||||
<radio label="&archiveMonthly.label;"
|
||||
accesskey="&archiveMonthly.accesskey;" class="indent"/>
|
||||
</radiogroup>
|
||||
<checkbox id="archiveKeepFolderStructure"
|
||||
label="&keepFolderStructure.label;"
|
||||
accesskey="&keepFolderStructure.accesskey;"/>
|
||||
|
||||
<groupbox flex="1">
|
||||
<caption label="&archiveExample.label;"/>
|
||||
<tree id="archiveTree" hidecolumnpicker="true" disabled="true" flex="1">
|
||||
<treecols>
|
||||
<treecol primary="true" hideheader="true" flex="1"
|
||||
id="folderNameCol"/>
|
||||
</treecols>
|
||||
<treechildren>
|
||||
<treeitem class="root">
|
||||
<treerow>
|
||||
<treecell properties="specialFolder-Archive"
|
||||
label="&archiveFolderName.label;"/>
|
||||
</treerow>
|
||||
<treechildren>
|
||||
<treeitem id="folders">
|
||||
<treerow>
|
||||
<treecell label="&inboxFolderName.label;"/>
|
||||
</treerow>
|
||||
</treeitem>
|
||||
<treeitem class="year">
|
||||
<treerow>
|
||||
<treecell label="2010"/>
|
||||
</treerow>
|
||||
<treechildren>
|
||||
<treeitem class="month">
|
||||
<treerow>
|
||||
<treecell label="2010-11"/>
|
||||
</treerow>
|
||||
<treechildren/>
|
||||
</treeitem>
|
||||
<treeitem class="month">
|
||||
<treerow>
|
||||
<treecell label="2010-12"/>
|
||||
</treerow>
|
||||
<treechildren/>
|
||||
</treeitem>
|
||||
</treechildren>
|
||||
</treeitem>
|
||||
<treeitem class="year">
|
||||
<treerow>
|
||||
<treecell label="2011"/>
|
||||
</treerow>
|
||||
<treechildren>
|
||||
<treeitem class="month">
|
||||
<treerow>
|
||||
<treecell label="2011-01"/>
|
||||
</treerow>
|
||||
<treechildren/>
|
||||
</treeitem>
|
||||
<treeitem class="month">
|
||||
<treerow>
|
||||
<treecell label="2011-02"/>
|
||||
</treerow>
|
||||
<treechildren/>
|
||||
</treeitem>
|
||||
</treechildren>
|
||||
</treeitem>
|
||||
</treechildren>
|
||||
</treeitem>
|
||||
</treechildren>
|
||||
</tree>
|
||||
</groupbox>
|
||||
</vbox>
|
||||
</dialog>
|
||||
471
mailnews/base/prefs/content/am-copies.js
Normal file
471
mailnews/base/prefs/content/am-copies.js
Normal file
|
|
@ -0,0 +1,471 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
Components.utils.import("resource:///modules/MailUtils.js");
|
||||
|
||||
var gFccRadioElemChoice, gDraftsRadioElemChoice, gArchivesRadioElemChoice, gTmplRadioElemChoice;
|
||||
var gFccRadioElemChoiceLocked, gDraftsRadioElemChoiceLocked, gArchivesRadioElemChoiceLocked, gTmplRadioElemChoiceLocked;
|
||||
var gDefaultPickerMode = "1";
|
||||
|
||||
var gFccFolderWithDelim, gDraftsFolderWithDelim, gArchivesFolderWithDelim, gTemplatesFolderWithDelim;
|
||||
var gAccount;
|
||||
var gCurrentServerId;
|
||||
|
||||
function onPreInit(account, accountValues)
|
||||
{
|
||||
gAccount = account;
|
||||
var type = parent.getAccountValue(account, accountValues, "server", "type", null, false);
|
||||
hideShowControls(type);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the global radio element choices and initialize folder/account pickers.
|
||||
* Also, initialize other UI elements (cc, bcc, fcc picker controller checkboxes).
|
||||
*/
|
||||
function onInit(aPageId, aServerId)
|
||||
{
|
||||
gCurrentServerId = aServerId;
|
||||
onInitCopiesAndFolders();
|
||||
}
|
||||
|
||||
function onInitCopiesAndFolders()
|
||||
{
|
||||
SetGlobalRadioElemChoices();
|
||||
|
||||
SetFolderDisplay(gFccRadioElemChoice, gFccRadioElemChoiceLocked,
|
||||
"fcc",
|
||||
"msgFccAccountPicker",
|
||||
"identity.fccFolder",
|
||||
"msgFccFolderPicker");
|
||||
|
||||
SetFolderDisplay(gArchivesRadioElemChoice, gArchivesRadioElemChoiceLocked,
|
||||
"archive",
|
||||
"msgArchivesAccountPicker",
|
||||
"identity.archiveFolder",
|
||||
"msgArchivesFolderPicker");
|
||||
|
||||
SetFolderDisplay(gDraftsRadioElemChoice, gDraftsRadioElemChoiceLocked,
|
||||
"draft",
|
||||
"msgDraftsAccountPicker",
|
||||
"identity.draftFolder",
|
||||
"msgDraftsFolderPicker");
|
||||
|
||||
SetFolderDisplay(gTmplRadioElemChoice, gTmplRadioElemChoiceLocked,
|
||||
"tmpl",
|
||||
"msgStationeryAccountPicker",
|
||||
"identity.stationeryFolder",
|
||||
"msgStationeryFolderPicker");
|
||||
|
||||
setupCcTextbox(true);
|
||||
setupBccTextbox(true);
|
||||
setupFccItems();
|
||||
setupArchiveItems();
|
||||
|
||||
SetSpecialFolderNamesWithDelims();
|
||||
}
|
||||
|
||||
// Initialize the picker mode choices (account/folder picker) into global vars
|
||||
function SetGlobalRadioElemChoices()
|
||||
{
|
||||
var pickerModeElement = document.getElementById("identity.fccFolderPickerMode");
|
||||
gFccRadioElemChoice = pickerModeElement.getAttribute("value");
|
||||
gFccRadioElemChoiceLocked = pickerModeElement.getAttribute("disabled");
|
||||
if (!gFccRadioElemChoice) gFccRadioElemChoice = gDefaultPickerMode;
|
||||
|
||||
pickerModeElement = document.getElementById("identity.archivesFolderPickerMode");
|
||||
gArchivesRadioElemChoice = pickerModeElement.getAttribute("value");
|
||||
gArchivesRadioElemChoiceLocked = pickerModeElement.getAttribute("disabled");
|
||||
if (!gArchivesRadioElemChoice) gArchivesRadioElemChoice = gDefaultPickerMode;
|
||||
|
||||
pickerModeElement = document.getElementById("identity.draftsFolderPickerMode");
|
||||
gDraftsRadioElemChoice = pickerModeElement.getAttribute("value");
|
||||
gDraftsRadioElemChoiceLocked = pickerModeElement.getAttribute("disabled");
|
||||
if (!gDraftsRadioElemChoice) gDraftsRadioElemChoice = gDefaultPickerMode;
|
||||
|
||||
pickerModeElement = document.getElementById("identity.tmplFolderPickerMode");
|
||||
gTmplRadioElemChoice = pickerModeElement.getAttribute("value");
|
||||
gTmplRadioElemChoiceLocked = pickerModeElement.getAttribute("disabled");
|
||||
if (!gTmplRadioElemChoice) gTmplRadioElemChoice = gDefaultPickerMode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set Account and Folder elements based on the values read from
|
||||
* preferences file. Default picker mode, if none specified at this stage, is
|
||||
* set to 1 i.e., Other picker displaying the folder value read from the
|
||||
* preferences file.
|
||||
*/
|
||||
function SetFolderDisplay(pickerMode, disableMode,
|
||||
radioElemPrefix,
|
||||
accountPickerId,
|
||||
folderPickedField,
|
||||
folderPickerId)
|
||||
{
|
||||
if (!pickerMode)
|
||||
pickerMode = gDefaultPickerMode;
|
||||
|
||||
var selectAccountRadioId = radioElemPrefix + "_selectAccount";
|
||||
var selectAccountRadioElem = document.getElementById(selectAccountRadioId);
|
||||
var selectFolderRadioId = radioElemPrefix + "_selectFolder";
|
||||
var selectFolderRadioElem = document.getElementById(selectFolderRadioId);
|
||||
var accountPicker = document.getElementById(accountPickerId);
|
||||
var folderPicker = document.getElementById(folderPickerId);
|
||||
var rg = selectAccountRadioElem.radioGroup;
|
||||
var folderPickedElement = document.getElementById(folderPickedField);
|
||||
var uri = folderPickedElement.getAttribute("value");
|
||||
// Get message folder from the given uri. Second argument (false) signifies
|
||||
// that there is no need to check for the existence of special folders as
|
||||
// these folders are created on demand at runtime in case of imap accounts.
|
||||
// For POP3 accounts, special folders are created at the account creation time.
|
||||
var msgFolder = MailUtils.getFolderForURI(uri, false);
|
||||
InitFolderDisplay(msgFolder.server.rootFolder, accountPicker);
|
||||
InitFolderDisplay(msgFolder, folderPicker);
|
||||
|
||||
switch (pickerMode)
|
||||
{
|
||||
case "0" :
|
||||
rg.selectedItem = selectAccountRadioElem;
|
||||
SetPickerEnabling(accountPickerId, folderPickerId);
|
||||
break;
|
||||
|
||||
case "1" :
|
||||
rg.selectedItem = selectFolderRadioElem;
|
||||
SetPickerEnabling(folderPickerId, accountPickerId);
|
||||
break;
|
||||
|
||||
default :
|
||||
dump("Error in setting initial folder display on pickers\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// Check to see if we need to lock page elements. Disable radio buttons
|
||||
// and account/folder pickers when locked.
|
||||
if (disableMode) {
|
||||
selectAccountRadioElem.setAttribute("disabled","true");
|
||||
selectFolderRadioElem.setAttribute("disabled","true");
|
||||
accountPicker.setAttribute("disabled","true");
|
||||
folderPicker.setAttribute("disabled","true");
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the folder display based on prefs values
|
||||
function InitFolderDisplay(folder, folderPicker) {
|
||||
folderPicker.menupopup.selectFolder(folder);
|
||||
folderPicker.folder = folder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture any menulist changes and update the folder property.
|
||||
*
|
||||
* @param aGroup the prefix for the menulist we're handling (e.g. "drafts")
|
||||
* @param aType "Account" for the account picker or "Folder" for the folder
|
||||
* picker
|
||||
* @param aEvent the event that we're responding to
|
||||
*/
|
||||
function noteSelectionChange(aGroup, aType, aEvent)
|
||||
{
|
||||
var checkedElem = document.getElementById(aGroup+"_select"+aType);
|
||||
var folder = aEvent.target._folder;
|
||||
var modeValue = checkedElem.value;
|
||||
var radioGroup = checkedElem.radioGroup.getAttribute("id");
|
||||
var picker;
|
||||
|
||||
switch (radioGroup) {
|
||||
case "doFcc" :
|
||||
gFccRadioElemChoice = modeValue;
|
||||
picker = document.getElementById("msgFcc"+aType+"Picker");
|
||||
break;
|
||||
|
||||
case "messageArchives" :
|
||||
gArchivesRadioElemChoice = modeValue;
|
||||
picker = document.getElementById("msgArchives"+aType+"Picker");
|
||||
updateArchiveHierarchyButton(folder);
|
||||
break;
|
||||
|
||||
case "messageDrafts" :
|
||||
gDraftsRadioElemChoice = modeValue;
|
||||
picker = document.getElementById("msgDrafts"+aType+"Picker");
|
||||
break;
|
||||
|
||||
case "messageTemplates" :
|
||||
gTmplRadioElemChoice = modeValue;
|
||||
picker = document.getElementById("msgStationery"+aType+"Picker");
|
||||
break;
|
||||
}
|
||||
|
||||
picker.folder = folder;
|
||||
picker.menupopup.selectFolder(folder);
|
||||
}
|
||||
|
||||
// Need to append special folders when account picker is selected.
|
||||
// Create a set of global special folder vars to be suffixed to the
|
||||
// server URI of the selected account.
|
||||
function SetSpecialFolderNamesWithDelims()
|
||||
{
|
||||
var folderDelim = "/";
|
||||
/* we use internal names known to everyone like "Sent", "Templates" and "Drafts" */
|
||||
|
||||
gFccFolderWithDelim = folderDelim + "Sent";
|
||||
gArchivesFolderWithDelim = folderDelim + "Archives";
|
||||
gDraftsFolderWithDelim = folderDelim + "Drafts";
|
||||
gTemplatesFolderWithDelim = folderDelim + "Templates";
|
||||
}
|
||||
|
||||
// Save all changes on this page
|
||||
function onSave()
|
||||
{
|
||||
onSaveCopiesAndFolders();
|
||||
}
|
||||
|
||||
function onSaveCopiesAndFolders()
|
||||
{
|
||||
SaveFolderSettings( gFccRadioElemChoice,
|
||||
"doFcc",
|
||||
gFccFolderWithDelim,
|
||||
"msgFccAccountPicker",
|
||||
"msgFccFolderPicker",
|
||||
"identity.fccFolder",
|
||||
"identity.fccFolderPickerMode" );
|
||||
|
||||
SaveFolderSettings( gArchivesRadioElemChoice,
|
||||
"messageArchives",
|
||||
gArchivesFolderWithDelim,
|
||||
"msgArchivesAccountPicker",
|
||||
"msgArchivesFolderPicker",
|
||||
"identity.archiveFolder",
|
||||
"identity.archivesFolderPickerMode" );
|
||||
|
||||
SaveFolderSettings( gDraftsRadioElemChoice,
|
||||
"messageDrafts",
|
||||
gDraftsFolderWithDelim,
|
||||
"msgDraftsAccountPicker",
|
||||
"msgDraftsFolderPicker",
|
||||
"identity.draftFolder",
|
||||
"identity.draftsFolderPickerMode" );
|
||||
|
||||
SaveFolderSettings( gTmplRadioElemChoice,
|
||||
"messageTemplates",
|
||||
gTemplatesFolderWithDelim,
|
||||
"msgStationeryAccountPicker",
|
||||
"msgStationeryFolderPicker",
|
||||
"identity.stationeryFolder",
|
||||
"identity.tmplFolderPickerMode" );
|
||||
}
|
||||
|
||||
// Save folder settings and radio element choices
|
||||
function SaveFolderSettings(radioElemChoice,
|
||||
radioGroupId,
|
||||
folderSuffix,
|
||||
accountPickerId,
|
||||
folderPickerId,
|
||||
folderElementId,
|
||||
folderPickerModeId)
|
||||
{
|
||||
var formElement = document.getElementById(folderElementId);
|
||||
var uri;
|
||||
|
||||
if (radioElemChoice == "0" ||
|
||||
!document.getElementById(folderPickerId).value) {
|
||||
// Default or revert to default if no folder chosen.
|
||||
radioElemChoice = "0";
|
||||
uri = document.getElementById(accountPickerId).folder.URI;
|
||||
if (uri) {
|
||||
// Create Folder URI.
|
||||
uri = uri + folderSuffix;
|
||||
}
|
||||
}
|
||||
else if (radioElemChoice == "1") {
|
||||
uri = document.getElementById(folderPickerId).folder.URI;
|
||||
}
|
||||
else {
|
||||
dump ("Error saving folder preferences.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
formElement.setAttribute("value", uri);
|
||||
|
||||
formElement = document.getElementById(folderPickerModeId);
|
||||
formElement.setAttribute("value", radioElemChoice);
|
||||
}
|
||||
|
||||
// Check the Fcc Self item and setup associated picker state
|
||||
function setupFccItems()
|
||||
{
|
||||
var broadcaster = document.getElementById("broadcaster_doFcc");
|
||||
|
||||
var checked = document.getElementById("identity.doFcc").checked;
|
||||
if (checked) {
|
||||
broadcaster.removeAttribute("disabled");
|
||||
switch (gFccRadioElemChoice) {
|
||||
case "0" :
|
||||
if (!gFccRadioElemChoiceLocked)
|
||||
SetPickerEnabling("msgFccAccountPicker", "msgFccFolderPicker");
|
||||
SetRadioButtons("fcc_selectAccount", "fcc_selectFolder");
|
||||
break;
|
||||
|
||||
case "1" :
|
||||
if (!gFccRadioElemChoiceLocked)
|
||||
SetPickerEnabling("msgFccFolderPicker", "msgFccAccountPicker");
|
||||
SetRadioButtons("fcc_selectFolder", "fcc_selectAccount");
|
||||
break;
|
||||
|
||||
default :
|
||||
dump("Error in setting Fcc elements.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
broadcaster.setAttribute("disabled", "true");
|
||||
}
|
||||
|
||||
// Disable CC textbox if CC checkbox is not checked
|
||||
function setupCcTextbox(init)
|
||||
{
|
||||
var ccChecked = document.getElementById("identity.doCc").checked;
|
||||
var ccTextbox = document.getElementById("identity.doCcList");
|
||||
|
||||
ccTextbox.disabled = !ccChecked;
|
||||
|
||||
if (ccChecked) {
|
||||
if (ccTextbox.value == "") {
|
||||
ccTextbox.value = document.getElementById("identity.email").value;
|
||||
if (!init)
|
||||
ccTextbox.select();
|
||||
}
|
||||
} else if ((ccTextbox.value == document.getElementById("identity.email").value) ||
|
||||
(init && ccTextbox.getAttribute("value") == ""))
|
||||
ccTextbox.value = "";
|
||||
}
|
||||
|
||||
// Disable BCC textbox if BCC checkbox is not checked
|
||||
function setupBccTextbox(init)
|
||||
{
|
||||
var bccChecked = document.getElementById("identity.doBcc").checked;
|
||||
var bccTextbox = document.getElementById("identity.doBccList");
|
||||
|
||||
bccTextbox.disabled = !bccChecked;
|
||||
|
||||
if (bccChecked) {
|
||||
if (bccTextbox.value == "") {
|
||||
bccTextbox.value = document.getElementById("identity.email").value;
|
||||
if (!init)
|
||||
bccTextbox.select();
|
||||
}
|
||||
} else if ((bccTextbox.value == document.getElementById("identity.email").value) ||
|
||||
(init && bccTextbox.getAttribute("value") == ""))
|
||||
bccTextbox.value = "";
|
||||
}
|
||||
|
||||
// Enable and disable pickers based on the radio element clicked
|
||||
function SetPickerEnabling(enablePickerId, disablePickerId)
|
||||
{
|
||||
var activePicker = document.getElementById(enablePickerId);
|
||||
activePicker.removeAttribute("disabled");
|
||||
|
||||
var inactivePicker = document.getElementById(disablePickerId);
|
||||
inactivePicker.setAttribute("disabled", "true");
|
||||
}
|
||||
|
||||
// Set radio element choices and picker states
|
||||
function setPickersState(enablePickerId, disablePickerId, event)
|
||||
{
|
||||
SetPickerEnabling(enablePickerId, disablePickerId);
|
||||
|
||||
var radioElemValue = event.target.value;
|
||||
|
||||
switch (event.target.id) {
|
||||
case "fcc_selectAccount":
|
||||
case "fcc_selectFolder":
|
||||
gFccRadioElemChoice = radioElemValue;
|
||||
break;
|
||||
case "archive_selectAccount":
|
||||
case "archive_selectFolder":
|
||||
gArchivesRadioElemChoice = radioElemValue;
|
||||
updateArchiveHierarchyButton(document.getElementById(enablePickerId)
|
||||
.folder);
|
||||
break;
|
||||
case "draft_selectAccount":
|
||||
case "draft_selectFolder":
|
||||
gDraftsRadioElemChoice = radioElemValue;
|
||||
break;
|
||||
case "tmpl_selectAccount":
|
||||
case "tmpl_selectFolder":
|
||||
gTmplRadioElemChoice = radioElemValue;
|
||||
break;
|
||||
default:
|
||||
dump("Error in setting picker state.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// This routine is to restore the correct radio element
|
||||
// state when the fcc self checkbox broadcasts the change
|
||||
function SetRadioButtons(selectPickerId, unselectPickerId)
|
||||
{
|
||||
var activeRadioElem = document.getElementById(selectPickerId);
|
||||
activeRadioElem.radioGroup.selectedItem = activeRadioElem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable the archive hierarchy button depending on what folder is
|
||||
* currently selected (Gmail IMAP folders should have the button disabled, since
|
||||
* changing the archive hierarchy does nothing there.
|
||||
*
|
||||
* @param archiveFolder the currently-selected folder to store archives in
|
||||
*/
|
||||
function updateArchiveHierarchyButton(archiveFolder) {
|
||||
let isGmailImap = (archiveFolder.server.type == "imap" &&
|
||||
archiveFolder.server.QueryInterface(
|
||||
Components.interfaces.nsIImapIncomingServer)
|
||||
.isGMailServer);
|
||||
document.getElementById("archiveHierarchyButton").disabled = isGmailImap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable (as appropriate) the controls for setting archive options
|
||||
*/
|
||||
function setupArchiveItems() {
|
||||
let broadcaster = document.getElementById("broadcaster_archiveEnabled");
|
||||
let checked = document.getElementById("identity.archiveEnabled").checked;
|
||||
let archiveFolder;
|
||||
|
||||
if (checked) {
|
||||
broadcaster.removeAttribute("disabled");
|
||||
switch (gArchivesRadioElemChoice) {
|
||||
case "0":
|
||||
if (!gArchivesRadioElemChoiceLocked)
|
||||
SetPickerEnabling("msgArchivesAccountPicker", "msgArchivesFolderPicker");
|
||||
SetRadioButtons("archive_selectAccount", "archive_selectFolder");
|
||||
updateArchiveHierarchyButton(document.getElementById(
|
||||
"msgArchivesAccountPicker").folder);
|
||||
break;
|
||||
|
||||
case "1":
|
||||
if (!gArchivesRadioElemChoiceLocked)
|
||||
SetPickerEnabling("msgArchivesFolderPicker", "msgArchivesAccountPicker");
|
||||
SetRadioButtons("archive_selectFolder", "archive_selectAccount");
|
||||
updateArchiveHierarchyButton(document.getElementById(
|
||||
"msgArchivesFolderPicker").folder);
|
||||
break;
|
||||
|
||||
default:
|
||||
dump("Error in setting Archive elements.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
broadcaster.setAttribute("disabled", "true");
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a dialog to edit the folder hierarchy used when archiving messages.
|
||||
*/
|
||||
function ChangeArchiveHierarchy() {
|
||||
let identity = parent.gIdentity || parent.getCurrentAccount().defaultIdentity;
|
||||
|
||||
top.window.openDialog("chrome://messenger/content/am-archiveoptions.xul",
|
||||
"", "centerscreen,chrome,modal,titlebar,resizable=yes",
|
||||
identity);
|
||||
return true;
|
||||
}
|
||||
21
mailnews/base/prefs/content/am-copies.xul
Normal file
21
mailnews/base/prefs/content/am-copies.xul
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
|
||||
<?xul-overlay href="chrome://messenger/content/am-copiesOverlay.xul"?>
|
||||
|
||||
<!DOCTYPE page SYSTEM "chrome://messenger/locale/am-copies.dtd">
|
||||
|
||||
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="©AndFolderTitle.label;"
|
||||
onload="parent.onPanelLoaded('am-copies.xul');">
|
||||
|
||||
<vbox flex="1" style="overflow: auto;">
|
||||
<script type="application/javascript" src="chrome://messenger/content/AccountManager.js"/>
|
||||
|
||||
<dialogheader title="©AndFolderTitle.label;"/>
|
||||
<vbox id="copiesAndFolders"/>
|
||||
</vbox>
|
||||
</page>
|
||||
311
mailnews/base/prefs/content/am-copiesOverlay.xul
Normal file
311
mailnews/base/prefs/content/am-copiesOverlay.xul
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/accountManage.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/messenger.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/folderMenus.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE overlay [
|
||||
<!ENTITY % copiesDTD SYSTEM "chrome://messenger/locale/am-copies.dtd">
|
||||
%copiesDTD;
|
||||
]>
|
||||
|
||||
<overlay xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/javascript" src="chrome://messenger/content/am-copies.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/amUtils.js"/>
|
||||
|
||||
<vbox flex="1" id="copiesAndFolders">
|
||||
<stringbundleset id="stringbundleset">
|
||||
<stringbundle id="bundle_messenger" src="chrome://messenger/locale/messenger.properties"/>
|
||||
</stringbundleset>
|
||||
|
||||
<broadcaster id="broadcaster_doFcc"/>
|
||||
<broadcaster id="broadcaster_archiveEnabled"/>
|
||||
|
||||
<label hidden="true" wsm_persist="true" id="identity.fccFolder"
|
||||
pref="true" preftype="string" prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.fcc_folder"/>
|
||||
<label hidden="true" wsm_persist="true" id="identity.draftFolder"
|
||||
pref="true" preftype="string" prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.draft_folder"/>
|
||||
<label hidden="true" wsm_persist="true" id="identity.archiveFolder"
|
||||
pref="true" preftype="string" prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.archive_folder"/>
|
||||
<label hidden="true" wsm_persist="true" id="identity.stationeryFolder"
|
||||
pref="true" preftype="string" prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.stationary_folder"/>
|
||||
<label hidden="true" wsm_persist="true" id="identity.email"/>
|
||||
<label hidden="true" wsm_persist="true" id="identity.fccFolderPickerMode"
|
||||
pref="true" preftype="int" prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.fcc_folder_picker_mode"/>
|
||||
<label hidden="true" wsm_persist="true" id="identity.draftsFolderPickerMode"
|
||||
pref="true" preftype="int" prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.drafts_folder_picker_mode"/>
|
||||
<label hidden="true" wsm_persist="true" id="identity.archivesFolderPickerMode"
|
||||
pref="true" preftype="int" prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.archives_folder_picker_mode"/>
|
||||
<label hidden="true" wsm_persist="true" id="identity.tmplFolderPickerMode"
|
||||
pref="true" preftype="int" prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.tmpl_folder_picker_mode"/>
|
||||
<groupbox id="copiesGroup">
|
||||
<caption label="&sendingPrefix.label;"/>
|
||||
|
||||
<hbox align="center">
|
||||
<checkbox wsm_persist="true" id="identity.doFcc" label="&fccMailFolder.label;"
|
||||
accesskey="&fccMailFolder.accesskey;"
|
||||
prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.fcc"
|
||||
oncommand="setupFccItems();"/>
|
||||
</hbox>
|
||||
<radiogroup id="doFcc" aria-labelledby="identity.doFcc">
|
||||
<grid class="specialFolderPickerGrid">
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<radio id="fcc_selectAccount"
|
||||
value="0" label="&sentFolderOn.label;"
|
||||
accesskey="&sentFolderOn.accesskey;"
|
||||
oncommand="setPickersState('msgFccAccountPicker', 'msgFccFolderPicker', event)"
|
||||
observes="broadcaster_doFcc"/>
|
||||
<menulist id="msgFccAccountPicker"
|
||||
class="folderMenuItem"
|
||||
aria-labelledby="fcc_selectAccount"
|
||||
observes="broadcaster_doFcc">
|
||||
<menupopup id="msgFccAccountPopup" type="folder" mode="filing"
|
||||
expandFolders="false"
|
||||
oncommand="noteSelectionChange('fcc', 'Account', event)"/>
|
||||
</menulist>
|
||||
</row>
|
||||
<row align="center">
|
||||
<radio id="fcc_selectFolder"
|
||||
value="1" label="&sentInOtherFolder.label;"
|
||||
accesskey="&sentInOtherFolder.accesskey;"
|
||||
oncommand="setPickersState('msgFccFolderPicker', 'msgFccAccountPicker', event)"
|
||||
observes="broadcaster_doFcc"/>
|
||||
<menulist id="msgFccFolderPicker"
|
||||
class="folderMenuItem"
|
||||
aria-labelledby="fcc_selectFolder"
|
||||
displayformat="verbose"
|
||||
observes="broadcaster_doFcc">
|
||||
<menupopup id="msgFccFolderPopup" type="folder" mode="filing"
|
||||
class="menulist-menupopup"
|
||||
showFileHereLabel="true"
|
||||
oncommand="noteSelectionChange('fcc', 'Folder', event)"/>
|
||||
</menulist>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</radiogroup>
|
||||
|
||||
<hbox align="center" class="fccReplyFollowsParent" hidable="true" hidefor="nntp,rss">
|
||||
<checkbox wsm_persist="true" id="identity.fccReplyFollowsParent"
|
||||
label="&fccReplyFollowsParent.label;"
|
||||
accesskey="&fccReplyFollowsParent.accesskey;"
|
||||
prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.fcc_reply_follows_parent"
|
||||
observes="broadcaster_doFcc"/>
|
||||
</hbox>
|
||||
|
||||
<grid>
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
|
||||
<rows>
|
||||
<row align="center">
|
||||
<checkbox wsm_persist="true" id="identity.doCc" label="&ccAddress.label;"
|
||||
accesskey="&ccAddress.accesskey;"
|
||||
control="identity.doCcList"
|
||||
oncommand="setupCcTextbox();"
|
||||
prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.doCc"/>
|
||||
<textbox wsm_persist="true" id="identity.doCcList" flex="1"
|
||||
aria-labelledby="identity.doCc"
|
||||
prefstring="mail.identity.%identitykey%.doCcList" class="uri-element"
|
||||
placeholder="&ccAddressList.placeholder;"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<checkbox wsm_persist="true" id="identity.doBcc" label="&bccAddress.label;"
|
||||
accesskey="&bccAddress.accesskey;"
|
||||
control="identity.doBccList"
|
||||
oncommand="setupBccTextbox();"
|
||||
prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.doBcc"/>
|
||||
<textbox wsm_persist="true" id="identity.doBccList" flex="1"
|
||||
aria-labelledby="identity.doBcc"
|
||||
prefstring="mail.identity.%identitykey%.doBccList" class="uri-element"
|
||||
placeholder="&bccAddressList.placeholder;"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
|
||||
</groupbox>
|
||||
|
||||
<groupbox id="archivesGroup">
|
||||
<caption label="&archivesTitle.label;"/>
|
||||
|
||||
<hbox align="center">
|
||||
<checkbox wsm_persist="true" id="identity.archiveEnabled"
|
||||
label="&keepArchives.label;"
|
||||
accesskey="&keepArchives.accesskey;"
|
||||
prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.archive_enabled"
|
||||
oncommand="setupArchiveItems();"/>
|
||||
<spacer flex="1"/>
|
||||
<button id="archiveHierarchyButton"
|
||||
label="&archiveHierarchyButton.label;"
|
||||
accesskey="&archiveHierarchyButton.accesskey;"
|
||||
oncommand="ChangeArchiveHierarchy();"
|
||||
observes="broadcaster_archiveEnabled"/>
|
||||
</hbox>
|
||||
|
||||
<radiogroup id="messageArchives">
|
||||
<grid class="specialFolderPickerGrid">
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<radio id="archive_selectAccount"
|
||||
value="0" label="&archivesFolderOn.label;"
|
||||
accesskey="&archivesFolderOn.accesskey;"
|
||||
oncommand="setPickersState('msgArchivesAccountPicker', 'msgArchivesFolderPicker', event)"
|
||||
observes="broadcaster_archiveEnabled"/>
|
||||
<menulist id="msgArchivesAccountPicker"
|
||||
class="folderMenuItem"
|
||||
aria-labelledby="archive_selectAccount"
|
||||
observes="broadcaster_archiveEnabled">
|
||||
<menupopup id="msgArchivesAccountPopup" type="folder" mode="filing"
|
||||
expandFolders="false"
|
||||
oncommand="noteSelectionChange('archive', 'Account', event)"/>
|
||||
</menulist>
|
||||
</row>
|
||||
<row align="center">
|
||||
<radio id="archive_selectFolder"
|
||||
value="1" label="&archiveInOtherFolder.label;"
|
||||
accesskey="&archiveInOtherFolder.accesskey;"
|
||||
oncommand="setPickersState('msgArchivesFolderPicker', 'msgArchivesAccountPicker', event)"
|
||||
observes="broadcaster_archiveEnabled"/>
|
||||
<menulist id="msgArchivesFolderPicker"
|
||||
class="folderMenuItem"
|
||||
aria-labelledby="archive_selectFolder"
|
||||
displayformat="verbose"
|
||||
observes="broadcaster_archiveEnabled">
|
||||
<menupopup id="msgArchivesFolderPopup" type="folder" mode="filing"
|
||||
class="menulist-menupopup"
|
||||
showFileHereLabel="true"
|
||||
oncommand="noteSelectionChange('archive', 'Folder', event)"/>
|
||||
</menulist>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</radiogroup>
|
||||
</groupbox>
|
||||
|
||||
<groupbox id="foldersGroup">
|
||||
<caption label="&specialFolders.label;"/>
|
||||
|
||||
<hbox align="center">
|
||||
<label value="&keepDrafts2.label;" control="messageDrafts"/>
|
||||
</hbox>
|
||||
|
||||
<radiogroup id="messageDrafts">
|
||||
<grid class="specialFolderPickerGrid">
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<radio id="draft_selectAccount"
|
||||
oncommand="setPickersState('msgDraftsAccountPicker', 'msgDraftsFolderPicker', event)"
|
||||
value="0" label="&draftsFolderOn.label;"
|
||||
accesskey="&draftsFolderOn.accesskey;"/>
|
||||
<menulist id="msgDraftsAccountPicker"
|
||||
class="folderMenuItem"
|
||||
aria-labelledby="draft_selectAccount">
|
||||
<menupopup id="msgDraftAccountPopup" type="folder" mode="filing"
|
||||
expandFolders="false"
|
||||
oncommand="noteSelectionChange('draft', 'Account', event)"/>
|
||||
</menulist>
|
||||
</row>
|
||||
<row align="center">
|
||||
<radio id="draft_selectFolder"
|
||||
oncommand="setPickersState('msgDraftsFolderPicker', 'msgDraftsAccountPicker', event)"
|
||||
value="1" label="&draftInOtherFolder.label;"
|
||||
accesskey="&draftInOtherFolder.accesskey;"/>
|
||||
<menulist id="msgDraftsFolderPicker"
|
||||
class="folderMenuItem"
|
||||
aria-labelledby="draft_selectFolder"
|
||||
displayformat="verbose">
|
||||
<menupopup id="msgDraftFolderPopup" type="folder" mode="filing"
|
||||
class="menulist-menupopup"
|
||||
showFileHereLabel="true"
|
||||
oncommand="noteSelectionChange('draft', 'Folder', event)"/>
|
||||
</menulist>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</radiogroup>
|
||||
|
||||
<hbox align="center">
|
||||
<label value="&keepTemplates.label;" control="messageTemplates"/>
|
||||
</hbox>
|
||||
|
||||
<radiogroup id="messageTemplates">
|
||||
<grid class="specialFolderPickerGrid">
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<radio id="tmpl_selectAccount"
|
||||
oncommand="setPickersState('msgStationeryAccountPicker', 'msgStationeryFolderPicker', event)"
|
||||
value="0" label="&templatesFolderOn.label;"
|
||||
accesskey="&templatesFolderOn.accesskey;"/>
|
||||
<menulist id="msgStationeryAccountPicker"
|
||||
class="folderMenuItem"
|
||||
aria-labelledby="tmpl_selectAccount">
|
||||
<menupopup id="msgFccAccountPopup" type="folder" mode="filing"
|
||||
expandFolders="false"
|
||||
oncommand="noteSelectionChange('tmpl', 'Account', event)"/>
|
||||
</menulist>
|
||||
</row>
|
||||
<row align="center">
|
||||
<radio id="tmpl_selectFolder"
|
||||
oncommand="setPickersState('msgStationeryFolderPicker', 'msgStationeryAccountPicker', event)"
|
||||
value="1" label="&templateInOtherFolder.label;"
|
||||
accesskey="&templateInOtherFolder.accesskey;"/>
|
||||
<menulist id="msgStationeryFolderPicker"
|
||||
class="folderMenuItem"
|
||||
aria-labelledby="tmpl_selectFolder"
|
||||
displayformat="verbose">
|
||||
<menupopup id="msgTemplFolderPopup" type="folder" mode="filing"
|
||||
class="menulist-menupopup"
|
||||
showFileHereLabel="true"
|
||||
oncommand="noteSelectionChange('tmpl', 'Folder', event)"/>
|
||||
</menulist>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</radiogroup>
|
||||
<hbox align="center">
|
||||
<checkbox wsm_persist="true" id="identity.showSaveMsgDlg" label="&saveMessageDlg.label;"
|
||||
accesskey="&saveMessageDlg.accesskey;"
|
||||
prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.showSaveMsgDlg"/>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
</vbox>
|
||||
</overlay>
|
||||
76
mailnews/base/prefs/content/am-help.js
Normal file
76
mailnews/base/prefs/content/am-help.js
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
/**
|
||||
* Key value pairs to derive the tag based on the page loaded.
|
||||
* Each key is the page loaded when user clicks on one of the items on
|
||||
* the accounttree of the AccountManager window.
|
||||
* Value is a tag that is preset which will be used to display
|
||||
* context sensitive help.
|
||||
*/
|
||||
var pageTagPairs = {
|
||||
"chrome://messenger/content/am-main.xul": "mail_account_identity",
|
||||
"chrome://messenger/content/am-server.xul": "mail",
|
||||
"chrome://messenger/content/am-copies.xul": "mail_copies",
|
||||
"chrome://messenger/content/am-addressing.xul": "mail_addressing_settings",
|
||||
"chrome://messenger/content/am-junk.xul": "mail-account-junk",
|
||||
"chrome://messenger/content/am-offline.xul": "mail-offline-accounts",
|
||||
"chrome://messenger/content/am-smtp.xul": "mail_smtp",
|
||||
"chrome://messenger/content/am-smime.xul": "mail_security_settings",
|
||||
"chrome://messenger/content/am-serverwithnoidentities.xul": "mail_local_folders_settings",
|
||||
"chrome://messenger/content/am-mdn.xul": "mail-account-receipts",
|
||||
}
|
||||
|
||||
function doHelpButton()
|
||||
{
|
||||
// Get the URI of the page loaded in the AccountManager's content frame.
|
||||
var pageSourceURI = contentFrame.location.href;
|
||||
// Get the help tag corresponding to the page loaded.
|
||||
var helpTag = pageTagPairs[pageSourceURI];
|
||||
|
||||
// If the help tag is generic or offline, check if there is a need to set tags per server type
|
||||
if ((helpTag == "mail") || (helpTag == "mail-offline-accounts")) {
|
||||
// Get server type, as we may need to set help tags per server type for some pages
|
||||
var serverType = GetServerType();
|
||||
|
||||
/**
|
||||
* Check the page to be loaded. Following pages needed to be presented with the
|
||||
* help content that is based on server type. For any pages with such requirement
|
||||
* do add comments here about the page and a new case statement for pageSourceURI
|
||||
* switch.
|
||||
* - server settings ("chrome://messenger/content/am-server.xul")
|
||||
* - offline/diskspace settings ("chrome://messenger/content/am-offline.xul")
|
||||
*/
|
||||
switch (pageSourceURI) {
|
||||
case "chrome://messenger/content/am-server.xul":
|
||||
helpTag = "mail_server_" + serverType;
|
||||
break;
|
||||
|
||||
case "chrome://messenger/content/am-offline.xul":
|
||||
helpTag = "mail_offline_" + serverType;
|
||||
break;
|
||||
|
||||
default :
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( helpTag )
|
||||
openHelp(helpTag);
|
||||
else
|
||||
openHelp('mail');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get server type of the seleted item
|
||||
*/
|
||||
function GetServerType()
|
||||
{
|
||||
var serverType = null;
|
||||
var currentAccount = parent.getCurrentAccount();
|
||||
if (currentAccount)
|
||||
serverType = currentAccount.incomingServer.type;
|
||||
return serverType;
|
||||
}
|
||||
180
mailnews/base/prefs/content/am-identities-list.js
Normal file
180
mailnews/base/prefs/content/am-identities-list.js
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
/* -*- Mode: Java; 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/. */
|
||||
|
||||
Components.utils.import("resource:///modules/iteratorUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var gIdentityListBox; // the root <listbox> node
|
||||
var gAddButton;
|
||||
var gEditButton;
|
||||
var gSetDefaultButton;
|
||||
var gDeleteButton;
|
||||
|
||||
var gAccount = null; // the account we are showing the identities for
|
||||
|
||||
function onLoad()
|
||||
{
|
||||
gIdentityListBox = document.getElementById("identitiesList");
|
||||
gAddButton = document.getElementById("cmd_add");
|
||||
gEditButton = document.getElementById("cmd_edit");
|
||||
gSetDefaultButton = document.getElementById("cmd_default");
|
||||
gDeleteButton = document.getElementById("cmd_delete");
|
||||
|
||||
// extract the account
|
||||
gAccount = window.arguments[0].account;
|
||||
|
||||
var accountName = window.arguments[0].accountName;
|
||||
document.title = document.getElementById("bundle_prefs")
|
||||
.getFormattedString("identity-list-title", [accountName]);
|
||||
|
||||
refreshIdentityList(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuilds the listbox holding the list of identities.
|
||||
*
|
||||
* @param aSelectIndex Attempt to select the identity with this index.
|
||||
*/
|
||||
function refreshIdentityList(aSelectIndex)
|
||||
{
|
||||
// Remove all children.
|
||||
while (gIdentityListBox.hasChildNodes())
|
||||
gIdentityListBox.lastChild.remove();
|
||||
|
||||
// Build the list from the identities array.
|
||||
let identities = gAccount.identities;
|
||||
for (let identity in fixIterator(identities,
|
||||
Components.interfaces.nsIMsgIdentity))
|
||||
{
|
||||
if (identity.valid)
|
||||
{
|
||||
let listitem = document.createElement("listitem");
|
||||
listitem.setAttribute("label", identity.identityName);
|
||||
listitem.setAttribute("key", identity.key);
|
||||
gIdentityListBox.appendChild(listitem);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure one identity is always selected.
|
||||
if (!aSelectIndex || aSelectIndex < 0)
|
||||
aSelectIndex = 0;
|
||||
else if (aSelectIndex >= gIdentityListBox.itemCount)
|
||||
aSelectIndex = gIdentityListBox.itemCount - 1;
|
||||
|
||||
// This also fires the onselect event, which in turn calls updateButtons().
|
||||
gIdentityListBox.selectedIndex = aSelectIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the identity editor dialog.
|
||||
*
|
||||
* @param identity the identity (if any) to load in the dialog
|
||||
*/
|
||||
function openIdentityEditor(identity)
|
||||
{
|
||||
let args = { identity: identity, account: gAccount, result: false };
|
||||
|
||||
let indexToSelect = identity ? gIdentityListBox.selectedIndex :
|
||||
gIdentityListBox.itemCount;
|
||||
|
||||
window.openDialog("am-identity-edit.xul", "",
|
||||
"chrome,modal,resizable,centerscreen", args);
|
||||
|
||||
if (args.result)
|
||||
refreshIdentityList(indexToSelect);
|
||||
}
|
||||
|
||||
function getSelectedIdentity()
|
||||
{
|
||||
if (gIdentityListBox.selectedItems.length != 1)
|
||||
return null;
|
||||
|
||||
var identityKey = gIdentityListBox.selectedItems[0].getAttribute("key");
|
||||
let identities = gAccount.identities;
|
||||
for (let identity in fixIterator(identities,
|
||||
Components.interfaces.nsIMsgIdentity))
|
||||
{
|
||||
if (identity.valid && identity.key == identityKey)
|
||||
return identity;
|
||||
}
|
||||
|
||||
return null; // no identity found
|
||||
}
|
||||
|
||||
function onEdit(event)
|
||||
{
|
||||
var id = (event.target.localName == 'listbox') ? null : getSelectedIdentity();
|
||||
openIdentityEditor(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable buttons depending on number of identities and current selection.
|
||||
*/
|
||||
function updateButtons()
|
||||
{
|
||||
// In this listbox there should always be one item selected.
|
||||
if (gIdentityListBox.selectedItems.length != 1 || gIdentityListBox.itemCount == 0) {
|
||||
// But in case this is not met (e.g. there is no identity for some reason,
|
||||
// or the list is being rebuilt), disable all buttons.
|
||||
gEditButton.setAttribute("disabled", "true");
|
||||
gDeleteButton.setAttribute("disabled", "true");
|
||||
gSetDefaultButton.setAttribute("disabled", "true");
|
||||
return;
|
||||
}
|
||||
|
||||
gEditButton.setAttribute("disabled", "false");
|
||||
gDeleteButton.setAttribute("disabled", (gIdentityListBox.itemCount <= 1) ? "true" : "false");
|
||||
gSetDefaultButton.setAttribute("disabled", (gIdentityListBox.selectedIndex == 0) ? "true" : "false");
|
||||
// The Add command is always enabled.
|
||||
}
|
||||
|
||||
function onSetDefault(event)
|
||||
{
|
||||
let identity = getSelectedIdentity();
|
||||
if (!identity)
|
||||
return;
|
||||
|
||||
// If the first identity is selected, there is nothing to do.
|
||||
if (gIdentityListBox.selectedIndex == 0)
|
||||
return;
|
||||
|
||||
gAccount.defaultIdentity = identity;
|
||||
// Rebuilt the identity list and select the moved identity again.
|
||||
refreshIdentityList(0);
|
||||
}
|
||||
|
||||
function onDelete(event)
|
||||
{
|
||||
if (gIdentityListBox.itemCount <= 1) // don't support deleting the last identity
|
||||
return;
|
||||
|
||||
// get delete confirmation
|
||||
let selectedIdentity = getSelectedIdentity();
|
||||
|
||||
let prefsBundle = document.getElementById("bundle_prefs");
|
||||
let confirmTitle = prefsBundle.getFormattedString("identity-delete-confirm-title",
|
||||
[window.arguments[0].accountName]);
|
||||
let confirmText = prefsBundle.getFormattedString("identity-delete-confirm",
|
||||
[selectedIdentity.identityName]);
|
||||
let confirmButton = prefsBundle.getString("identity-delete-confirm-button");
|
||||
|
||||
if (Services.prompt.confirmEx(window, confirmTitle, confirmText,
|
||||
(Services.prompt.BUTTON_POS_0 * Services.prompt.BUTTON_TITLE_IS_STRING) +
|
||||
(Services.prompt.BUTTON_POS_1 * Services.prompt.BUTTON_TITLE_CANCEL),
|
||||
confirmButton, null, null, null, {}))
|
||||
return;
|
||||
|
||||
let selectedItemIndex = gIdentityListBox.selectedIndex;
|
||||
|
||||
gAccount.removeIdentity(selectedIdentity);
|
||||
|
||||
refreshIdentityList(selectedItemIndex);
|
||||
}
|
||||
|
||||
function onOk()
|
||||
{
|
||||
window.arguments[0].result = true;
|
||||
return true;
|
||||
}
|
||||
67
mailnews/base/prefs/content/am-identities-list.xul
Normal file
67
mailnews/base/prefs/content/am-identities-list.xul
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/messenger.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/accountManage.css" type="text/css"?>
|
||||
|
||||
<!-- 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/. -->
|
||||
|
||||
<!DOCTYPE dialog SYSTEM "chrome://messenger/locale/am-identities-list.dtd">
|
||||
|
||||
<dialog
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="onLoad();"
|
||||
buttons="accept"
|
||||
buttonlabelaccept="&identitiesListClose.label;"
|
||||
buttonaccesskeyaccept="&identitiesListClose.accesskey;"
|
||||
ondialogaccept="return onOk();"
|
||||
ondialogcancel="return onOk();"
|
||||
style="width: 40em;">
|
||||
|
||||
<stringbundle id="bundle_prefs" src="chrome://messenger/locale/prefs.properties"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/am-identities-list.js"/>
|
||||
|
||||
<commandset>
|
||||
<command id="cmd_add" oncommand="openIdentityEditor(null);"/>
|
||||
<command id="cmd_edit" oncommand="onEdit(event);" disabled="true"/>
|
||||
<command id="cmd_default" oncommand="onSetDefault(event);" disabled="true"/>
|
||||
<command id="cmd_delete" oncommand="onDelete(event);" disabled="true"/>
|
||||
</commandset>
|
||||
|
||||
<keyset>
|
||||
<key keycode="VK_INSERT" command="cmd_add"/>
|
||||
<key keycode="VK_DELETE" command="cmd_delete"/>
|
||||
</keyset>
|
||||
|
||||
<label control="identitiesList">&identitiesListManageDesc.label;</label>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<hbox flex="1">
|
||||
<listbox id="identitiesList"
|
||||
ondblclick="onEdit(event);"
|
||||
onselect="updateButtons();"
|
||||
seltype="single"
|
||||
flex="1"
|
||||
style="height: 0px;"/>
|
||||
|
||||
<vbox>
|
||||
<button id="addButton"
|
||||
command="cmd_add" label="&identitiesListAdd.label;"
|
||||
accesskey="&identitiesListAdd.accesskey;"/>
|
||||
<button id="editButton" disabled="true"
|
||||
command="cmd_edit" label="&identitiesListEdit.label;"
|
||||
accesskey="&identitiesListEdit.accesskey;"/>
|
||||
<button id="setDefaultButton" disabled="true"
|
||||
command="cmd_default" label="&identitiesListDefault.label;"
|
||||
accesskey="&identitiesListDefault.accesskey;"/>
|
||||
<button id="deleteButton" disabled="true"
|
||||
command="cmd_delete" label="&identitiesListDelete.label;"
|
||||
accesskey="&identitiesListDelete.accesskey;"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
||||
</dialog>
|
||||
405
mailnews/base/prefs/content/am-identity-edit.js
Normal file
405
mailnews/base/prefs/content/am-identity-edit.js
Normal file
|
|
@ -0,0 +1,405 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var gIdentity = null; // the identity we are editing (may be null for a new identity)
|
||||
var gAccount = null; // the account the identity is (or will be) associated with
|
||||
|
||||
function onLoadIdentityProperties()
|
||||
{
|
||||
// extract the account
|
||||
gIdentity = window.arguments[0].identity;
|
||||
gAccount = window.arguments[0].account;
|
||||
let prefBundle = document.getElementById("bundle_prefs");
|
||||
|
||||
// Make the dialog the same height and 90% of the width of the main Account
|
||||
// manager page when the Account manager is not maximized.
|
||||
let accountDialog = Services.wm.getMostRecentWindow("mailnews:accountmanager")
|
||||
.document;
|
||||
if (accountDialog.documentElement.getAttribute("sizemode") != "maximized") {
|
||||
document.getElementById("identityDialog").style.width =
|
||||
accountDialog.getElementById("accountManager").clientWidth * 0.9 + "px";
|
||||
document.getElementById("identityDialog").style.height =
|
||||
accountDialog.getElementById("accountManager").clientHeight + "px";
|
||||
}
|
||||
|
||||
if (gIdentity) {
|
||||
let listName = gIdentity.identityName;
|
||||
document.title = prefBundle
|
||||
.getFormattedString("identityDialogTitleEdit", [listName]);
|
||||
} else {
|
||||
document.title = prefBundle.getString("identityDialogTitleAdd");
|
||||
}
|
||||
|
||||
loadSMTPServerList();
|
||||
|
||||
initIdentityValues(gIdentity);
|
||||
initCopiesAndFolder(gIdentity);
|
||||
initCompositionAndAddressing(gIdentity);
|
||||
}
|
||||
|
||||
// based on the values of gIdentity, initialize the identity fields we expose to the user
|
||||
function initIdentityValues(identity)
|
||||
{
|
||||
function initSmtpServer(aServerKey) {
|
||||
// Select a server in the SMTP server menulist by its key.
|
||||
// The value of the identity.smtpServerKey is null when the
|
||||
// "use default server" option is used so, if we get that passed in, select
|
||||
// the useDefaultItem representing this option by using the value of "".
|
||||
document.getElementById("identity.smtpServerKey").value = aServerKey || "";
|
||||
}
|
||||
|
||||
if (identity)
|
||||
{
|
||||
document.getElementById('identity.fullName').value = identity.fullName;
|
||||
document.getElementById('identity.email').value = identity.email;
|
||||
document.getElementById('identity.replyTo').value = identity.replyTo;
|
||||
document.getElementById('identity.organization').value = identity.organization;
|
||||
document.getElementById('identity.attachSignature').checked = identity.attachSignature;
|
||||
document.getElementById('identity.htmlSigText').value = identity.htmlSigText;
|
||||
document.getElementById('identity.htmlSigFormat').checked = identity.htmlSigFormat;
|
||||
|
||||
if (identity.signature)
|
||||
document.getElementById('identity.signature').value = identity.signature.path;
|
||||
|
||||
document.getElementById('identity.attachVCard').checked = identity.attachVCard;
|
||||
document.getElementById('identity.escapedVCard').value = identity.escapedVCard;
|
||||
initSmtpServer(identity.smtpServerKey);
|
||||
|
||||
// This field does not exist for the default identity shown in the am-main.xul pane.
|
||||
let idLabel = document.getElementById("identity.label");
|
||||
if (idLabel)
|
||||
idLabel.value = identity.label;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We're adding an identity, use the best default we have.
|
||||
initSmtpServer(gAccount.defaultIdentity.smtpServerKey);
|
||||
}
|
||||
|
||||
setupSignatureItems();
|
||||
}
|
||||
|
||||
function initCopiesAndFolder(identity)
|
||||
{
|
||||
// if we are editing an existing identity, use it...otherwise copy our values from the default identity
|
||||
var copiesAndFoldersIdentity = identity ? identity : gAccount.defaultIdentity;
|
||||
|
||||
document.getElementById('identity.fccFolder').value = copiesAndFoldersIdentity.fccFolder;
|
||||
document.getElementById('identity.draftFolder').value = copiesAndFoldersIdentity.draftFolder;
|
||||
document.getElementById('identity.archiveFolder').value = copiesAndFoldersIdentity.archiveFolder;
|
||||
document.getElementById('identity.stationeryFolder').value = copiesAndFoldersIdentity.stationeryFolder;
|
||||
|
||||
document.getElementById('identity.fccFolderPickerMode').value = copiesAndFoldersIdentity.fccFolderPickerMode ? copiesAndFoldersIdentity.fccFolderPickerMode : 0;
|
||||
document.getElementById('identity.draftsFolderPickerMode').value = copiesAndFoldersIdentity.draftsFolderPickerMode ? copiesAndFoldersIdentity.draftsFolderPickerMode : 0;
|
||||
document.getElementById('identity.archivesFolderPickerMode').value = copiesAndFoldersIdentity.archivesFolderPickerMode ? copiesAndFoldersIdentity.archivesFolderPickerMode : 0;
|
||||
document.getElementById('identity.tmplFolderPickerMode').value = copiesAndFoldersIdentity.tmplFolderPickerMode ? copiesAndFoldersIdentity.tmplFolderPickerMode : 0;
|
||||
|
||||
document.getElementById('identity.doCc').checked = copiesAndFoldersIdentity.doCc;
|
||||
document.getElementById('identity.doCcList').value = copiesAndFoldersIdentity.doCcList;
|
||||
document.getElementById('identity.doBcc').checked = copiesAndFoldersIdentity.doBcc;
|
||||
document.getElementById('identity.doBccList').value = copiesAndFoldersIdentity.doBccList;
|
||||
document.getElementById('identity.doFcc').checked = copiesAndFoldersIdentity.doFcc;
|
||||
document.getElementById('identity.fccReplyFollowsParent').checked = copiesAndFoldersIdentity.fccReplyFollowsParent;
|
||||
document.getElementById('identity.showSaveMsgDlg').checked = copiesAndFoldersIdentity.showSaveMsgDlg;
|
||||
document.getElementById('identity.archiveEnabled').checked = copiesAndFoldersIdentity.archiveEnabled;
|
||||
|
||||
onInitCopiesAndFolders(); // am-copies.js method
|
||||
}
|
||||
|
||||
function initCompositionAndAddressing(identity)
|
||||
{
|
||||
// if we are editing an existing identity, use it...otherwise copy our values from the default identity
|
||||
var addressingIdentity = identity ? identity : gAccount.defaultIdentity;
|
||||
|
||||
document.getElementById('identity.directoryServer').value = addressingIdentity.directoryServer;
|
||||
document.getElementById('identity.overrideGlobal_Pref').value = addressingIdentity.overrideGlobalPref;
|
||||
let autoCompleteElement = document.getElementById('identity.autocompleteToMyDomain');
|
||||
if (autoCompleteElement) // Thunderbird does not have this element.
|
||||
autoCompleteElement.checked = addressingIdentity.autocompleteToMyDomain;
|
||||
|
||||
document.getElementById('identity.composeHtml').checked = addressingIdentity.composeHtml;
|
||||
document.getElementById('identity.autoQuote').checked = addressingIdentity.autoQuote;
|
||||
document.getElementById('identity.replyOnTop').value = addressingIdentity.replyOnTop;
|
||||
document.getElementById('identity.sig_bottom').value = addressingIdentity.sigBottom;
|
||||
document.getElementById('identity.sig_on_reply').checked = addressingIdentity.sigOnReply;
|
||||
document.getElementById('identity.sig_on_fwd').checked = addressingIdentity.sigOnForward;
|
||||
|
||||
onInitCompositionAndAddressing(); // am-addressing.js method
|
||||
}
|
||||
|
||||
function onOk()
|
||||
{
|
||||
if (!validEmailAddress())
|
||||
return false;
|
||||
|
||||
// if we are adding a new identity, create an identity, set the fields and add it to the
|
||||
// account.
|
||||
if (!gIdentity)
|
||||
{
|
||||
// ask the account manager to create a new identity for us
|
||||
gIdentity = MailServices.accounts.createIdentity();
|
||||
|
||||
// copy in the default identity settings so we inherit lots of stuff like the defaul drafts folder, etc.
|
||||
gIdentity.copy(gAccount.defaultIdentity);
|
||||
|
||||
// assume the identity is valid by default?
|
||||
gIdentity.valid = true;
|
||||
|
||||
// add the identity to the account
|
||||
gAccount.addIdentity(gIdentity);
|
||||
|
||||
// now fall through to saveFields which will save our new values
|
||||
}
|
||||
|
||||
// if we are modifying an existing identity, save the fields
|
||||
saveIdentitySettings(gIdentity);
|
||||
saveCopiesAndFolderSettings(gIdentity);
|
||||
saveAddressingAndCompositionSettings(gIdentity);
|
||||
|
||||
window.arguments[0].result = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// returns false and prompts the user if
|
||||
// the identity does not have an email address
|
||||
function validEmailAddress()
|
||||
{
|
||||
var emailAddress = document.getElementById('identity.email').value;
|
||||
|
||||
// quickly test for an @ sign to test for an email address. We don't have
|
||||
// to be anymore precise than that.
|
||||
if (!emailAddress.includes("@"))
|
||||
{
|
||||
// alert user about an invalid email address
|
||||
|
||||
var prefBundle = document.getElementById("bundle_prefs");
|
||||
|
||||
Services.prompt.alert(window, prefBundle.getString("identity-edit-req-title"),
|
||||
prefBundle.getString("identity-edit-req"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function saveIdentitySettings(identity)
|
||||
{
|
||||
if (identity)
|
||||
{
|
||||
let idLabel = document.getElementById('identity.label');
|
||||
if (idLabel)
|
||||
identity.label = idLabel.value;
|
||||
identity.fullName = document.getElementById('identity.fullName').value;
|
||||
identity.email = document.getElementById('identity.email').value;
|
||||
identity.replyTo = document.getElementById('identity.replyTo').value;
|
||||
identity.organization = document.getElementById('identity.organization').value;
|
||||
identity.attachSignature = document.getElementById('identity.attachSignature').checked;
|
||||
identity.htmlSigText = document.getElementById('identity.htmlSigText').value;
|
||||
identity.htmlSigFormat = document.getElementById('identity.htmlSigFormat').checked;
|
||||
|
||||
identity.attachVCard = document.getElementById('identity.attachVCard').checked;
|
||||
identity.escapedVCard = document.getElementById('identity.escapedVCard').value;
|
||||
identity.smtpServerKey = document.getElementById('identity.smtpServerKey').value;
|
||||
|
||||
var attachSignaturePath = document.getElementById('identity.signature').value;
|
||||
identity.signature = null; // this is important so we don't accidentally inherit the default
|
||||
|
||||
if (attachSignaturePath)
|
||||
{
|
||||
// convert signature path back into a nsIFile
|
||||
var sfile = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsIFile);
|
||||
sfile.initWithPath(attachSignaturePath);
|
||||
if (sfile.exists())
|
||||
identity.signature = sfile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function saveCopiesAndFolderSettings(identity)
|
||||
{
|
||||
onSaveCopiesAndFolders(); // am-copies.js routine
|
||||
|
||||
identity.fccFolder = document.getElementById('identity.fccFolder').value;
|
||||
identity.draftFolder = document.getElementById('identity.draftFolder').value;
|
||||
identity.archiveFolder = document.getElementById('identity.archiveFolder').value;
|
||||
identity.stationeryFolder = document.getElementById('identity.stationeryFolder').value;
|
||||
identity.fccFolderPickerMode = document.getElementById('identity.fccFolderPickerMode').value;
|
||||
identity.draftsFolderPickerMode = document.getElementById('identity.draftsFolderPickerMode').value;
|
||||
identity.archivesFolderPickerMode = document.getElementById('identity.archivesFolderPickerMode').value;
|
||||
identity.tmplFolderPickerMode = document.getElementById('identity.tmplFolderPickerMode').value;
|
||||
identity.doCc = document.getElementById('identity.doCc').checked;
|
||||
identity.doCcList = document.getElementById('identity.doCcList').value;
|
||||
identity.doBcc = document.getElementById('identity.doBcc').checked;
|
||||
identity.doBccList = document.getElementById('identity.doBccList').value;
|
||||
identity.doFcc = document.getElementById('identity.doFcc').checked;
|
||||
identity.fccReplyFollowsParent = document.getElementById('identity.fccReplyFollowsParent').checked;
|
||||
identity.showSaveMsgDlg = document.getElementById('identity.showSaveMsgDlg').checked;
|
||||
identity.archiveEnabled = document.getElementById('identity.archiveEnabled').checked;
|
||||
}
|
||||
|
||||
function saveAddressingAndCompositionSettings(identity)
|
||||
{
|
||||
identity.directoryServer = document.getElementById('identity.directoryServer').value;
|
||||
identity.overrideGlobalPref = document.getElementById('identity.overrideGlobal_Pref').value == "true";
|
||||
let autoCompleteElement = document.getElementById('identity.autocompleteToMyDomain');
|
||||
if (autoCompleteElement) // Thunderbird does not have this element.
|
||||
identity.autocompleteToMyDomain = autoCompleteElement.checked;
|
||||
identity.composeHtml = document.getElementById('identity.composeHtml').checked;
|
||||
identity.autoQuote = document.getElementById('identity.autoQuote').checked;
|
||||
identity.replyOnTop = document.getElementById('identity.replyOnTop').value;
|
||||
identity.sigBottom = document.getElementById('identity.sig_bottom').value == 'true';
|
||||
identity.sigOnReply = document.getElementById('identity.sig_on_reply').checked;
|
||||
identity.sigOnForward = document.getElementById('identity.sig_on_fwd').checked;
|
||||
}
|
||||
|
||||
function selectFile()
|
||||
{
|
||||
const nsIFilePicker = Components.interfaces.nsIFilePicker;
|
||||
|
||||
var fp = Components.classes["@mozilla.org/filepicker;1"]
|
||||
.createInstance(nsIFilePicker);
|
||||
|
||||
var prefBundle = document.getElementById("bundle_prefs");
|
||||
var title = prefBundle.getString("choosefile");
|
||||
fp.init(window, title, nsIFilePicker.modeOpen);
|
||||
fp.appendFilters(nsIFilePicker.filterAll);
|
||||
|
||||
// Get current signature folder, if there is one.
|
||||
// We can set that to be the initial folder so that users
|
||||
// can maintain their signatures better.
|
||||
var sigFolder = GetSigFolder();
|
||||
if (sigFolder)
|
||||
fp.displayDirectory = sigFolder;
|
||||
|
||||
var ret = fp.show();
|
||||
if (ret == nsIFilePicker.returnOK) {
|
||||
var folderField = document.getElementById("identity.signature");
|
||||
folderField.value = fp.file.path;
|
||||
}
|
||||
}
|
||||
|
||||
function GetSigFolder()
|
||||
{
|
||||
var sigFolder = null;
|
||||
try
|
||||
{
|
||||
var account = parent.getCurrentAccount();
|
||||
var identity = account.defaultIdentity;
|
||||
var signatureFile = identity.signature;
|
||||
|
||||
if (signatureFile)
|
||||
{
|
||||
signatureFile = signatureFile.QueryInterface(Components.interfaces.nsIFile);
|
||||
sigFolder = signatureFile.parent;
|
||||
|
||||
if (!sigFolder.exists())
|
||||
sigFolder = null;
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
dump("failed to get signature folder..\n");
|
||||
}
|
||||
return sigFolder;
|
||||
}
|
||||
|
||||
// Signature textbox is active unless option to select from file is checked.
|
||||
// If a signature is need to be attached, the associated items which
|
||||
// displays the absolute path to the signature (in a textbox) and the way
|
||||
// to select a new signature file (a button) are enabled. Otherwise, they
|
||||
// are disabled. Check to see if the attachSignature is locked to block
|
||||
// broadcasting events.
|
||||
function setupSignatureItems()
|
||||
{
|
||||
var signature = document.getElementById("identity.signature");
|
||||
var browse = document.getElementById("identity.sigbrowsebutton");
|
||||
var htmlSigText = document.getElementById("identity.htmlSigText");
|
||||
var htmlSigFormat = document.getElementById("identity.htmlSigFormat");
|
||||
var attachSignature = document.getElementById("identity.attachSignature");
|
||||
var checked = attachSignature.checked;
|
||||
|
||||
if (checked)
|
||||
{
|
||||
htmlSigText.setAttribute("disabled", "true");
|
||||
htmlSigFormat.setAttribute("disabled", "true");
|
||||
}
|
||||
else
|
||||
{
|
||||
htmlSigText.removeAttribute("disabled");
|
||||
htmlSigFormat.removeAttribute("disabled");
|
||||
}
|
||||
|
||||
if (checked && !getAccountValueIsLocked(signature))
|
||||
signature.removeAttribute("disabled");
|
||||
else
|
||||
signature.setAttribute("disabled", "true");
|
||||
|
||||
if (checked && !getAccountValueIsLocked(browse))
|
||||
browse.removeAttribute("disabled");
|
||||
else
|
||||
browse.setAttribute("disabled", "true");
|
||||
}
|
||||
|
||||
function editVCardCallback(escapedVCardStr)
|
||||
{
|
||||
var escapedVCard = document.getElementById("identity.escapedVCard");
|
||||
escapedVCard.value = escapedVCardStr;
|
||||
}
|
||||
|
||||
function editVCard()
|
||||
{
|
||||
var escapedVCard = document.getElementById("identity.escapedVCard");
|
||||
|
||||
// read vCard hidden value from UI
|
||||
window.openDialog("chrome://messenger/content/addressbook/abNewCardDialog.xul",
|
||||
"",
|
||||
"chrome,modal,resizable=no,centerscreen",
|
||||
{escapedVCardStr:escapedVCard.value, okCallback:editVCardCallback,
|
||||
titleProperty:"editVCardTitle", hideABPicker:true});
|
||||
}
|
||||
|
||||
function getAccountForFolderPickerState()
|
||||
{
|
||||
return gAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the SMTP server list for display.
|
||||
*/
|
||||
function loadSMTPServerList()
|
||||
{
|
||||
var smtpServerList = document.getElementById("identity.smtpServerKey");
|
||||
let servers = MailServices.smtp.servers;
|
||||
let defaultServer = MailServices.smtp.defaultServer;
|
||||
|
||||
var smtpPopup = smtpServerList.menupopup;
|
||||
while (smtpPopup.lastChild.nodeName != "menuseparator")
|
||||
smtpPopup.lastChild.remove();
|
||||
|
||||
while (servers.hasMoreElements())
|
||||
{
|
||||
var server = servers.getNext();
|
||||
|
||||
if (server instanceof Components.interfaces.nsISmtpServer)
|
||||
{
|
||||
var serverName = "";
|
||||
if (server.description)
|
||||
serverName = server.description + ' - ';
|
||||
else if (server.username)
|
||||
serverName = server.username + ' - ';
|
||||
serverName += server.hostname;
|
||||
|
||||
if (defaultServer.key == server.key)
|
||||
serverName += " " + document.getElementById("bundle_messenger")
|
||||
.getString("defaultServerTag");
|
||||
|
||||
smtpServerList.appendItem(serverName, server.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
154
mailnews/base/prefs/content/am-identity-edit.xul
Normal file
154
mailnews/base/prefs/content/am-identity-edit.xul
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/messenger.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/accountManage.css" type="text/css"?>
|
||||
|
||||
<?xul-overlay href="chrome://messenger/content/am-copiesOverlay.xul"?>
|
||||
<?xul-overlay href="chrome://messenger/content/am-addressingOverlay.xul"?>
|
||||
|
||||
<!DOCTYPE dialog [
|
||||
<!ENTITY % identityEditDTD SYSTEM "chrome://messenger/locale/am-identity-edit.dtd" >
|
||||
%identityEditDTD;
|
||||
<!ENTITY % identityDTD SYSTEM "chrome://messenger/locale/am-main.dtd" >
|
||||
%identityDTD;
|
||||
]>
|
||||
|
||||
<dialog id="identityDialog"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="onLoadIdentityProperties();"
|
||||
ondialogaccept="return onOk();"
|
||||
style="&identityDialog.style;">
|
||||
|
||||
<stringbundle id="bundle_prefs"
|
||||
src="chrome://messenger/locale/prefs.properties"/>
|
||||
<stringbundle id="bundle_messenger"
|
||||
src="chrome://messenger/locale/messenger.properties"/>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/am-prefs.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/am-identity-edit.js"/>
|
||||
|
||||
<broadcaster id="broadcaster_attachSignature"/>
|
||||
|
||||
<description flex="1">&identityListDesc.label;</description>
|
||||
<separator class="thin"/>
|
||||
|
||||
<tabbox flex="1" style="overflow: auto;">
|
||||
<tabs id="identitySettings">
|
||||
<tab label="&settingsTab.label;"/>
|
||||
<tab label="&copiesFoldersTab.label;"/>
|
||||
<tab label="&addressingTab.label;"/>
|
||||
</tabs>
|
||||
|
||||
<tabpanels id="identityTabsPanels" flex="1">
|
||||
<!-- Identity Settings Tab -->
|
||||
<vbox flex="1" name="settings">
|
||||
<groupbox>
|
||||
<caption label="&publicData.label;"/>
|
||||
|
||||
<grid>
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<label value="&name.label;" control="identity.fullName" accesskey="&name.accesskey;"/>
|
||||
<textbox id="identity.fullName" size="30"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label value="&email.label;" control="identity.email" accesskey="&email.accesskey;"/>
|
||||
<textbox id="identity.email" class="uri-element"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label value="&replyTo.label;" control="identity.replyTo" accesskey="&replyTo.accesskey;"/>
|
||||
<textbox id="identity.replyTo" class="uri-element" placeholder="&replyTo.placeholder;"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label value="&organization.label;" control="identity.organization" accesskey="&organization.accesskey;"/>
|
||||
<textbox id="identity.organization"/>
|
||||
</row>
|
||||
<separator class="thin"/>
|
||||
<row align="center">
|
||||
<label value="&signatureText.label;" control="identity.htmlSigText" accesskey="&signatureText.accesskey;"/>
|
||||
<checkbox id="identity.htmlSigFormat" label="&signatureHtml.label;" accesskey="&signatureHtml.accesskey;"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
|
||||
<hbox class="indent" flex="1">
|
||||
<textbox id="identity.htmlSigText" flex="1" multiline="true" wrap="off" rows="4" class="signatureBox"/>
|
||||
</hbox>
|
||||
|
||||
<hbox align="center">
|
||||
<checkbox id="identity.attachSignature" label="&signatureFile.label;" flex="1"
|
||||
accesskey="&signatureFile.accesskey;"
|
||||
oncommand="setupSignatureItems();"/>
|
||||
</hbox>
|
||||
|
||||
<hbox align="center" class="indent">
|
||||
<textbox id="identity.signature" datatype="nsIFile" flex="1" name="identity.signature"
|
||||
aria-labelledby="identity.attachSignature"
|
||||
observes="broadcaster_attachSignature" class="uri-element"/>
|
||||
<button class="push" name="browse" label="&choose.label;"
|
||||
accesskey="&choose.accesskey;"
|
||||
oncommand="selectFile()"
|
||||
observes="broadcaster_attachSignature"
|
||||
id="identity.sigbrowsebutton"/>
|
||||
</hbox>
|
||||
|
||||
<hbox align="center">
|
||||
<checkbox id="identity.attachVCard" label="&attachVCard.label;" flex="1"
|
||||
accesskey="&attachVCard.accesskey;"/>
|
||||
<button class="push" name="editVCard" label="&editVCard.label;"
|
||||
accesskey="&editVCard.accesskey;"
|
||||
oncommand="editVCard()"/>
|
||||
<label hidden="true" id="identity.escapedVCard"/>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
|
||||
<groupbox>
|
||||
<caption label="&privateData.label;"/>
|
||||
|
||||
<hbox align="center">
|
||||
<label value="&smtpName.label;"
|
||||
control="identity.smtpServerKey"
|
||||
accesskey="&smtpName.accesskey;"/>
|
||||
<menulist id="identity.smtpServerKey" flex="1">
|
||||
<menupopup id="smtpPopup">
|
||||
<menuitem value=""
|
||||
label="&smtpDefaultServer.label;"
|
||||
id="useDefaultItem"/>
|
||||
<menuseparator/>
|
||||
<!-- list will be inserted here -->
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</hbox>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<hbox align="center">
|
||||
<label value="&identityAlias.label;"
|
||||
accesskey="&identityAlias.accesskey;"
|
||||
control="identity.label"/>
|
||||
<textbox id="identity.label" flex="1"/>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
|
||||
<spacer flex="1"/>
|
||||
</vbox>
|
||||
|
||||
<!-- Copies & Folders Tab -->
|
||||
<vbox flex="1" name="copiesAndFolders" id="copiesAndFolders"/>
|
||||
|
||||
<!-- Composition & Addressing Tab -->
|
||||
<vbox flex="1" name="composeAddressing" id="compositionAndAddressing"/>
|
||||
|
||||
</tabpanels>
|
||||
</tabbox>
|
||||
</dialog>
|
||||
296
mailnews/base/prefs/content/am-junk.js
Normal file
296
mailnews/base/prefs/content/am-junk.js
Normal file
|
|
@ -0,0 +1,296 @@
|
|||
/* -*- 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/.
|
||||
*/
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
Components.utils.import("resource:///modules/iteratorUtils.jsm");
|
||||
Components.utils.import("resource:///modules/MailUtils.js");
|
||||
|
||||
var gDeferredToAccount = "";
|
||||
|
||||
function onInit(aPageId, aServerId)
|
||||
{
|
||||
// manually adjust several pref UI elements
|
||||
document.getElementById('server.spamLevel.visible').setAttribute("checked",
|
||||
document.getElementById('server.spamLevel').value > 0);
|
||||
|
||||
let deferredToURI = null;
|
||||
if (gDeferredToAccount)
|
||||
deferredToURI = MailServices.accounts
|
||||
.getAccount(gDeferredToAccount)
|
||||
.incomingServer.serverURI;
|
||||
|
||||
let spamActionTargetAccountElement =
|
||||
document.getElementById("server.spamActionTargetAccount");
|
||||
let spamActionTargetFolderElement =
|
||||
document.getElementById("server.spamActionTargetFolder");
|
||||
|
||||
let spamActionTargetAccount = spamActionTargetAccountElement.value;
|
||||
let spamActionTargetFolder = spamActionTargetFolderElement.value;
|
||||
|
||||
let moveOnSpamCheckbox = document.getElementById("server.moveOnSpam");
|
||||
let moveOnSpamValue = moveOnSpamCheckbox.checked;
|
||||
|
||||
// Check if there are any invalid junk targets and fix them.
|
||||
[ spamActionTargetAccount, spamActionTargetFolder, moveOnSpamValue ] =
|
||||
sanitizeJunkTargets(spamActionTargetAccount,
|
||||
spamActionTargetFolder,
|
||||
deferredToURI || aServerId,
|
||||
document.getElementById("server.moveTargetMode").value,
|
||||
MailUtils.getFolderForURI(aServerId, false).server.spamSettings,
|
||||
moveOnSpamValue);
|
||||
|
||||
spamActionTargetAccountElement.value = spamActionTargetAccount;
|
||||
spamActionTargetFolderElement.value = spamActionTargetFolder;
|
||||
moveOnSpamCheckbox.checked = moveOnSpamValue;
|
||||
|
||||
let server = MailUtils.getFolderForURI(spamActionTargetAccount, false);
|
||||
document.getElementById("actionAccountPopup").selectFolder(server);
|
||||
|
||||
let folder = MailUtils.getFolderForURI(spamActionTargetFolder, true);
|
||||
document.getElementById("actionFolderPopup").selectFolder(folder);
|
||||
|
||||
var currentArray = [];
|
||||
if (document.getElementById("server.useWhiteList").checked)
|
||||
currentArray = document.getElementById("server.whiteListAbURI").value.split(" ");
|
||||
|
||||
// set up the whitelist UI
|
||||
var wList = document.getElementById("whiteListAbURI");
|
||||
// Ensure the whitelist is empty
|
||||
for (let i = wList.itemCount - 1; i >= 0; i--) {
|
||||
wList.removeItemAt(i);
|
||||
}
|
||||
|
||||
// Populate the listbox with address books
|
||||
let abItems = [];
|
||||
for (let ab in fixIterator(MailServices.ab.directories,
|
||||
Components.interfaces.nsIAbDirectory)) {
|
||||
// We skip mailing lists and remote address books.
|
||||
if (ab.isMailList || ab.isRemote)
|
||||
continue;
|
||||
|
||||
abItems.push({ label: ab.dirName, URI: ab.URI });
|
||||
}
|
||||
|
||||
// Sort the list
|
||||
function sortFunc(a, b) {
|
||||
return a.label.localeCompare(b.label);
|
||||
}
|
||||
abItems.sort(sortFunc);
|
||||
|
||||
// And then append each item to the listbox
|
||||
for (let abItem of abItems) {
|
||||
let item = wList.appendItem(abItem.label, abItem.URI);
|
||||
item.setAttribute("type", "checkbox");
|
||||
item.setAttribute("class", "listitem-iconic");
|
||||
|
||||
// Due to bug 448582, we have to use setAttribute to set the
|
||||
// checked value of the listitem.
|
||||
item.setAttribute("checked", currentArray.includes(abItem.URI));
|
||||
}
|
||||
|
||||
// enable or disable the whitelist
|
||||
onAdaptiveJunkToggle();
|
||||
|
||||
// set up trusted IP headers
|
||||
var serverFilterList = document.getElementById("useServerFilterList");
|
||||
serverFilterList.value =
|
||||
document.getElementById("server.serverFilterName").value;
|
||||
if (!serverFilterList.selectedItem)
|
||||
serverFilterList.selectedIndex = 0;
|
||||
|
||||
// enable or disable the useServerFilter checkbox
|
||||
onCheckItem("useServerFilterList", ["server.useServerFilter"]);
|
||||
|
||||
updateJunkTargetsAndRetention();
|
||||
}
|
||||
|
||||
function onPreInit(account, accountValues)
|
||||
{
|
||||
if (getAccountValue(account, accountValues, "server", "type", null, false) == "pop3")
|
||||
gDeferredToAccount = getAccountValue(account, accountValues,
|
||||
"pop3", "deferredToAccount",
|
||||
null, false);
|
||||
|
||||
buildServerFilterMenuList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when someone checks or unchecks the adaptive junk mail checkbox.
|
||||
* set the value of the hidden element accordingly
|
||||
*
|
||||
* @param aValue the boolean value of the checkbox
|
||||
*/
|
||||
function updateSpamLevel(aValue)
|
||||
{
|
||||
document.getElementById('server.spamLevel').value = aValue ? 100 : 0;
|
||||
onAdaptiveJunkToggle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Propagate changes to the server filter menu list back to
|
||||
* our hidden wsm element.
|
||||
*/
|
||||
function onServerFilterListChange()
|
||||
{
|
||||
document.getElementById('server.serverFilterName').value =
|
||||
document.getElementById("useServerFilterList").value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when someone checks or unchecks the adaptive junk mail checkbox.
|
||||
* We need to enable or disable the whitelist accordingly.
|
||||
*/
|
||||
function onAdaptiveJunkToggle()
|
||||
{
|
||||
onCheckItem("whiteListAbURI", ["server.spamLevel.visible"]);
|
||||
onCheckItem("whiteListLabel", ["server.spamLevel.visible"]);
|
||||
|
||||
// Enable/disable individual listbox rows.
|
||||
// Setting enable/disable on the parent listbox does not seem to work.
|
||||
let wList = document.getElementById("whiteListAbURI");
|
||||
let wListDisabled = wList.disabled;
|
||||
|
||||
for (let i = 0; i < wList.getRowCount(); i++) {
|
||||
wList.getItemAtIndex(i).setAttribute("disabled", wListDisabled);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when someone checks or unchecks the "move new junk messages to"
|
||||
* Enable/disable the radio group accordingly.
|
||||
*/
|
||||
function updateJunkTargetsAndRetention() {
|
||||
onCheckItem("server.moveTargetMode", ["server.moveOnSpam"]);
|
||||
updateJunkTargets();
|
||||
onCheckItem("server.purgeSpam", ["server.moveOnSpam"]);
|
||||
document.getElementById("purgeLabel").disabled =
|
||||
document.getElementById("server.purgeSpam").disabled;
|
||||
updateJunkRetention();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable the folder pickers depending on which radio item is selected.
|
||||
*/
|
||||
function updateJunkTargets() {
|
||||
onCheckItem("actionTargetAccount", ["server.moveOnSpam", "moveTargetMode0"]);
|
||||
onCheckItem("actionTargetFolder", ["server.moveOnSpam", "moveTargetMode1"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable the junk deletion interval depending on the state
|
||||
* of the controlling checkbox.
|
||||
*/
|
||||
function updateJunkRetention() {
|
||||
onCheckItem("server.purgeSpamInterval", ["server.purgeSpam", "server.moveOnSpam"]);
|
||||
}
|
||||
|
||||
function onSave()
|
||||
{
|
||||
onSaveWhiteList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Propagate changes to the whitelist menu list back to
|
||||
* our hidden wsm element.
|
||||
*/
|
||||
function onSaveWhiteList()
|
||||
{
|
||||
var wList = document.getElementById("whiteListAbURI");
|
||||
var wlArray = [];
|
||||
|
||||
for (var i = 0; i < wList.getRowCount(); i++)
|
||||
{
|
||||
// Due to bug 448582, do not trust any properties of the listitems
|
||||
// as they may not return the right value or may even not exist.
|
||||
// Always get the attributes only.
|
||||
var wlNode = wList.getItemAtIndex(i);
|
||||
if (wlNode.getAttribute("checked") == "true") {
|
||||
let abURI = wlNode.getAttribute("value");
|
||||
wlArray.push(abURI);
|
||||
}
|
||||
}
|
||||
var wlValue = wlArray.join(" ");
|
||||
document.getElementById("server.whiteListAbURI").setAttribute("value", wlValue);
|
||||
document.getElementById("server.useWhiteList").checked = (wlValue != "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a new value is chosen in one of the junk target folder pickers.
|
||||
* Sets the menu label according to the folder name.
|
||||
*/
|
||||
function onActionTargetChange(aEvent, aWSMElementId)
|
||||
{
|
||||
let folder = aEvent.target._folder;
|
||||
document.getElementById(aWSMElementId).value = folder.URI;
|
||||
document.getElementById("actionFolderPopup").selectFolder(folder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumerates over the "ISPDL" directories, calling buildServerFilterListFromDir
|
||||
* for each one.
|
||||
*/
|
||||
function buildServerFilterMenuList()
|
||||
{
|
||||
const KEY_ISP_DIRECTORY_LIST = "ISPDL";
|
||||
let ispHeaderList = document.getElementById("useServerFilterList");
|
||||
|
||||
// Ensure the menulist is empty.
|
||||
ispHeaderList.removeAllItems();
|
||||
|
||||
// Now walk through the isp directories looking for sfd files.
|
||||
let ispDirectories = Services.dirsvc.get(KEY_ISP_DIRECTORY_LIST,
|
||||
Components.interfaces.nsISimpleEnumerator);
|
||||
|
||||
let menuEntries = [];
|
||||
while (ispDirectories.hasMoreElements())
|
||||
{
|
||||
let ispDirectory = ispDirectories.getNext()
|
||||
.QueryInterface(Components.interfaces.nsIFile);
|
||||
if (ispDirectory)
|
||||
menuEntries.push.apply(menuEntries, buildServerFilterListFromDir(ispDirectory, menuEntries));
|
||||
}
|
||||
|
||||
menuEntries.sort((a, b) => a.localeCompare(b));
|
||||
for (let entry of menuEntries) {
|
||||
ispHeaderList.appendItem(entry, entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function called by buildServerFilterMenuList. Enumerates over the
|
||||
* passed in directory looking for .sfd files. For each entry found, it gets
|
||||
* appended to the menu list.
|
||||
*
|
||||
* @param aDir directory to look for .sfd files
|
||||
* @param aExistingEntries Filter names already found.
|
||||
*/
|
||||
function buildServerFilterListFromDir(aDir, aExistingEntries)
|
||||
{
|
||||
let newEntries = [];
|
||||
// Now iterate over each file in the directory looking for .sfd files.
|
||||
const kSuffix = ".sfd";
|
||||
let entries = aDir.directoryEntries
|
||||
.QueryInterface(Components.interfaces.nsIDirectoryEnumerator);
|
||||
|
||||
while (entries.hasMoreElements()) {
|
||||
let entry = entries.nextFile;
|
||||
// we only care about files that end in .sfd
|
||||
if (entry.isFile() && entry.leafName.endsWith(kSuffix)) {
|
||||
let fileName = entry.leafName.slice(0, -kSuffix.length);
|
||||
// If we've already added an item with this name, then don't add it again.
|
||||
if (aExistingEntries.indexOf(fileName) == -1)
|
||||
newEntries.push(fileName);
|
||||
}
|
||||
}
|
||||
return newEntries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the Preferences dialog on the Junk settings tab.
|
||||
*/
|
||||
function showGlobalJunkPrefs()
|
||||
{
|
||||
openPrefsFromAccountManager("paneSecurity", "junkTab", null, "junk_pane");
|
||||
}
|
||||
232
mailnews/base/prefs/content/am-junk.xul
Normal file
232
mailnews/base/prefs/content/am-junk.xul
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!-- 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/.
|
||||
-->
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/accountManage.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/messenger.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/folderMenus.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
|
||||
%brandDTD;
|
||||
<!ENTITY % junkMailDTD SYSTEM "chrome://messenger/locale/am-junk.dtd">
|
||||
%junkMailDTD;
|
||||
]>
|
||||
|
||||
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:nc="http://home.netscape.com/NC-rdf#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
title="&junkSettings.label;"
|
||||
onload="parent.onPanelLoaded('am-junk.xul');">
|
||||
|
||||
<vbox flex="1" style="overflow: auto;">
|
||||
<script type="application/javascript" src="chrome://messenger/content/AccountManager.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/am-junk.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/am-prefs.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/amUtils.js"/>
|
||||
<stringbundle id="bundle_messenger" src="chrome://messenger/locale/messenger.properties"/>
|
||||
|
||||
<dialogheader title="&junkSettings.label;"/>
|
||||
|
||||
<groupbox>
|
||||
<caption label="&junkClassification.label;"/>
|
||||
|
||||
<label hidden="true"
|
||||
id="server.spamLevel"
|
||||
wsm_persist="true"
|
||||
pref="true"
|
||||
preftype="int"
|
||||
prefattribute="value"
|
||||
genericattr="true"
|
||||
prefstring="mail.server.%serverkey%.spamLevel"/>
|
||||
<label hidden="true"
|
||||
id="server.spamActionTargetAccount"
|
||||
wsm_persist="true"
|
||||
pref="true"
|
||||
preftype="string"
|
||||
prefattribute="value"
|
||||
genericattr="true"
|
||||
prefstring="mail.server.%serverkey%.spamActionTargetAccount"/>
|
||||
<label hidden="true"
|
||||
id="server.spamActionTargetFolder"
|
||||
wsm_persist="true"
|
||||
pref="true"
|
||||
preftype="string"
|
||||
prefattribute="value"
|
||||
genericattr="true"
|
||||
prefstring="mail.server.%serverkey%.spamActionTargetFolder"/>
|
||||
<label hidden="true"
|
||||
id="server.whiteListAbURI"
|
||||
wsm_persist="true"
|
||||
pref="true"
|
||||
preftype="string"
|
||||
prefattribute="value"
|
||||
genericattr="true"
|
||||
prefstring="mail.server.%serverkey%.whiteListAbURI"/>
|
||||
<label hidden="true"
|
||||
id="server.serverFilterName"
|
||||
wsm_persist="true"
|
||||
pref="true"
|
||||
preftype="string"
|
||||
prefattribute="value"
|
||||
genericattr="true"
|
||||
prefstring="mail.server.%serverkey%.serverFilterName"/>
|
||||
|
||||
<checkbox id="server.spamLevel.visible"
|
||||
oncommand="updateSpamLevel(this.checked);"
|
||||
accesskey="&level.accesskey;"
|
||||
prefstring="mail.server.%serverkey%.spamLevel"
|
||||
label="&level.label;"/>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<description width="1">&trainingDescription.label;</description>
|
||||
|
||||
<separator class="thin"/>
|
||||
<spacer height="3"/>
|
||||
|
||||
<vbox class="indent">
|
||||
<checkbox hidden="true"
|
||||
id="server.useWhiteList"
|
||||
genericattr="true"
|
||||
pref="true"
|
||||
wsm_persist="true"
|
||||
preftype="bool"
|
||||
prefstring="mail.server.%serverkey%.useWhiteList"/>
|
||||
<label id="whiteListLabel"
|
||||
accesskey="&whitelistHeader.accesskey;"
|
||||
control="whiteListAbURI">&whitelistHeader.label;</label>
|
||||
<listbox id="whiteListAbURI" rows="5"/>
|
||||
</vbox>
|
||||
|
||||
<separator/>
|
||||
|
||||
<vbox>
|
||||
<hbox>
|
||||
<checkbox id="server.useServerFilter"
|
||||
label="&ispHeaders.label;"
|
||||
accesskey="&ispHeaders.accesskey;"
|
||||
genericattr="true"
|
||||
pref="true"
|
||||
wsm_persist="true"
|
||||
preftype="bool"
|
||||
oncommand="onCheckItem('useServerFilterList', [this.id]);"
|
||||
prefstring="mail.server.%serverkey%.useServerFilter"/>
|
||||
<menulist id="useServerFilterList"
|
||||
oncommand="onServerFilterListChange();"
|
||||
aria-labelledby="server.useServerFilter"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<description width="1">&ispHeadersWarning.label;</description>
|
||||
|
||||
</groupbox>
|
||||
|
||||
<groupbox>
|
||||
<caption label="&junkActions.label;"/>
|
||||
|
||||
<checkbox id="server.moveOnSpam"
|
||||
label="&move.label;"
|
||||
accesskey="&move.accesskey;"
|
||||
oncommand="updateJunkTargetsAndRetention();"
|
||||
wsm_persist="true"
|
||||
pref="true"
|
||||
preftype="bool"
|
||||
genericattr="true"
|
||||
prefstring="mail.server.%serverkey%.moveOnSpam"/>
|
||||
|
||||
<radiogroup id="server.moveTargetMode"
|
||||
aria-labelledby="server.moveOnSpam"
|
||||
prefstring="mail.server.%serverkey%.moveTargetMode"
|
||||
wsm_persist="true"
|
||||
pref="true"
|
||||
preftype="int"
|
||||
genericattr="true"
|
||||
oncommand="updateJunkTargets();"
|
||||
prefvalue="value">
|
||||
|
||||
<grid class="specialFolderPickerGrid indent">
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row>
|
||||
<radio id="moveTargetMode0"
|
||||
value="0"
|
||||
label="&junkFolderOn.label;"
|
||||
accesskey="&junkFolderOn.accesskey;"/>
|
||||
<menulist id="actionTargetAccount"
|
||||
class="folderMenuItem"
|
||||
aria-labelledby="moveTargetMode0">
|
||||
<menupopup id="actionAccountPopup"
|
||||
type="folder"
|
||||
class="menulist-menupopup"
|
||||
expandFolders="false"
|
||||
mode="filing"
|
||||
oncommand="onActionTargetChange(event, 'server.spamActionTargetAccount');"/>
|
||||
</menulist>
|
||||
</row>
|
||||
<row>
|
||||
<radio id="moveTargetMode1"
|
||||
value="1"
|
||||
label="&otherFolder.label;"
|
||||
accesskey="&otherFolder.accesskey;"/>
|
||||
<menulist id="actionTargetFolder"
|
||||
class="folderMenuItem"
|
||||
aria-labelledby="moveTargetMode1"
|
||||
displayformat="verbose">
|
||||
<menupopup id="actionFolderPopup"
|
||||
type="folder"
|
||||
mode="junk"
|
||||
showFileHereLabel="true"
|
||||
oncommand="onActionTargetChange(event, 'server.spamActionTargetFolder');"/>
|
||||
</menulist>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</radiogroup>
|
||||
|
||||
<hbox align="center" class="indent">
|
||||
<checkbox id="server.purgeSpam"
|
||||
genericattr="true"
|
||||
pref="true"
|
||||
wsm_persist="true"
|
||||
preftype="bool"
|
||||
prefstring="mail.server.%serverkey%.purgeSpam"
|
||||
accesskey="&purge1.accesskey;"
|
||||
oncommand="updateJunkRetention();"
|
||||
label="&purge1.label;"/>
|
||||
<textbox size="3"
|
||||
type="number"
|
||||
min="1"
|
||||
id="server.purgeSpamInterval"
|
||||
genericattr="true"
|
||||
pref="true"
|
||||
wsm_persist="true"
|
||||
preftype="int"
|
||||
aria-labelledby="server.purgeSpam server.purgeSpamInterval purgeLabel"
|
||||
prefstring="mail.server.%serverkey%.purgeSpamInterval"/>
|
||||
<label id="purgeLabel"
|
||||
value="&purge2.label;"
|
||||
control="server.purgeSpamInterval"/>
|
||||
</hbox>
|
||||
|
||||
</groupbox>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<hbox pack="start">
|
||||
<button id="globalJunkPrefsLink"
|
||||
label="&globalJunkPrefs.label;"
|
||||
accesskey="&globalJunkPrefs.accesskey;"
|
||||
oncommand="showGlobalJunkPrefs();"/>
|
||||
</hbox>
|
||||
|
||||
</vbox>
|
||||
</page>
|
||||
55
mailnews/base/prefs/content/am-main.js
Normal file
55
mailnews/base/prefs/content/am-main.js
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/* -*- Mode: Java; 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/. */
|
||||
|
||||
function onInit(aPageId, aServerId)
|
||||
{
|
||||
var accountName = document.getElementById("server.prettyName");
|
||||
var title = document.getElementById("am-main-title");
|
||||
var defaultTitle = title.getAttribute("defaultTitle");
|
||||
var titleValue;
|
||||
|
||||
if(accountName.value)
|
||||
titleValue = defaultTitle+" - <"+accountName.value+">";
|
||||
else
|
||||
titleValue = defaultTitle;
|
||||
|
||||
title.setAttribute("title",titleValue);
|
||||
document.title = titleValue;
|
||||
|
||||
setupSignatureItems();
|
||||
}
|
||||
|
||||
function onPreInit(account, accountValues)
|
||||
{
|
||||
loadSMTPServerList();
|
||||
}
|
||||
|
||||
function manageIdentities()
|
||||
{
|
||||
// We want to save the current identity information before bringing up the multiple identities
|
||||
// UI. This ensures that the changes are reflected in the identity list dialog
|
||||
// onSave();
|
||||
|
||||
var account = parent.getCurrentAccount();
|
||||
if (!account)
|
||||
return;
|
||||
|
||||
var accountName = document.getElementById("server.prettyName").value;
|
||||
|
||||
var args = { account: account, accountName: accountName, result: false };
|
||||
|
||||
// save the current identity settings so they show up correctly
|
||||
// if the user just changed them in the manage identities dialog
|
||||
var identity = account.defaultIdentity;
|
||||
saveIdentitySettings(identity);
|
||||
|
||||
window.openDialog("am-identities-list.xul", "", "chrome,modal,resizable=no,centerscreen", args);
|
||||
|
||||
if (args.result) {
|
||||
// now re-initialize the default identity settings in case they changed
|
||||
identity = account.defaultIdentity; // refetch the default identity in case it changed
|
||||
initIdentityValues(identity);
|
||||
}
|
||||
}
|
||||
147
mailnews/base/prefs/content/am-main.xul
Normal file
147
mailnews/base/prefs/content/am-main.xul
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/accountManage.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE page SYSTEM "chrome://messenger/locale/am-main.dtd" >
|
||||
|
||||
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="parent.onPanelLoaded('am-main.xul');">
|
||||
|
||||
<vbox flex="1" style="overflow: auto;">
|
||||
<stringbundle id="bundle_prefs" src="chrome://messenger/locale/prefs.properties"/>
|
||||
<stringbundle id="bundle_messenger" src="chrome://messenger/locale/messenger.properties"/>
|
||||
|
||||
<script type="application/javascript" src="chrome://messenger/content/am-identity-edit.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/am-main.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/am-prefs.js"/>
|
||||
|
||||
<broadcaster id="broadcaster_attachSignature"/>
|
||||
|
||||
<dialogheader id="am-main-title" defaultTitle="&accountTitle.label;"/>
|
||||
|
||||
<hbox align="center">
|
||||
<label value="&accountName.label;" control="server.prettyName"
|
||||
accesskey="&accountName.accesskey;"/>
|
||||
<textbox wsm_persist="true" size="30" id="server.prettyName"
|
||||
prefstring="mail.server.%serverkey%.name"/>
|
||||
</hbox>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<groupbox style="width: 20em !important;" flex="1">
|
||||
<caption label="&identityTitle.label;"/>
|
||||
<description>&identityDesc.label;</description>
|
||||
<separator class="thin"/>
|
||||
<grid>
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<label value="&name.label;" control="identity.fullName"
|
||||
accesskey="&name.accesskey;"/>
|
||||
<textbox wsm_persist="true" id="identity.fullName" size="30"
|
||||
prefstring="mail.identity.%identitykey%.fullName"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label value="&email.label;" control="identity.email"
|
||||
accesskey="&email.accesskey;"/>
|
||||
<textbox wsm_persist="true" id="identity.email"
|
||||
prefstring="mail.identity.%identitykey%.useremail" class="uri-element"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label value="&replyTo.label;" control="identity.replyTo"
|
||||
accesskey="&replyTo.accesskey;"/>
|
||||
<textbox wsm_persist="true" id="identity.replyTo"
|
||||
prefstring="mail.identity.%identitykey%.reply_to" class="uri-element"
|
||||
placeholder="&replyTo.placeholder;"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label value="&organization.label;" control="identity.organization"
|
||||
accesskey="&organization.accesskey;"/>
|
||||
<textbox wsm_persist="true" id="identity.organization"
|
||||
prefstring="mail.identity.%identitykey%.organization"/>
|
||||
</row>
|
||||
<separator class="thin"/>
|
||||
<row align="center">
|
||||
<label value="&signatureText.label;" control="identity.htmlSigText" accesskey="&signatureText.accesskey;"/>
|
||||
<checkbox wsm_persist="true" id="identity.htmlSigFormat" label="&signatureHtml.label;"
|
||||
prefattribute="value" accesskey="&signatureHtml.accesskey;"
|
||||
prefstring="mail.identity.%identitykey%.htmlSigFormat"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
|
||||
<hbox class="indent" flex="1" style="min-height: 50px;">
|
||||
<textbox wsm_persist="true" id="identity.htmlSigText" multiline="true" wrap="off" rows="4" flex="1"
|
||||
prefstring="mail.identity.%identitykey%.htmlSigText" class="signatureBox"/>
|
||||
</hbox>
|
||||
|
||||
<hbox align="center">
|
||||
<checkbox wsm_persist="true" id="identity.attachSignature" label="&signatureFile.label;" flex="1"
|
||||
accesskey="&signatureFile.accesskey;"
|
||||
oncommand="setupSignatureItems();"
|
||||
prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.attach_signature"/>
|
||||
</hbox>
|
||||
|
||||
<hbox align="center" class="indent">
|
||||
<textbox wsm_persist="true" id="identity.signature" datatype="nsIFile" flex="1" name="identity.signature"
|
||||
aria-labelledby="identity.attachSignature"
|
||||
observes="broadcaster_attachSignature"
|
||||
prefstring="mail.identity.%identitykey%.sig_file" class="uri-element"/>
|
||||
<button class="push" name="browse" label="&choose.label;"
|
||||
accesskey="&choose.accesskey;"
|
||||
oncommand="selectFile()"
|
||||
observes="broadcaster_attachSignature"
|
||||
wsm_persist="true" id="identity.sigbrowsebutton"
|
||||
prefstring="mail.identity.%identitykey%.sigbrowse.disable"/>
|
||||
</hbox>
|
||||
|
||||
<hbox align="center">
|
||||
<checkbox wsm_persist="true" id="identity.attachVCard" label="&attachVCard.label;" flex="1"
|
||||
accesskey="&attachVCard.accesskey;"
|
||||
prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.attach_vcard"/>
|
||||
<button class="push" name="editVCard" label="&editVCard.label;"
|
||||
accesskey="&editVCard.accesskey;"
|
||||
oncommand="editVCard()"/>
|
||||
<label hidden="true" wsm_persist="true" id="identity.escapedVCard"
|
||||
pref="true" preftype="string" prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.escapedVCard"/>
|
||||
</hbox>
|
||||
|
||||
<separator class="thin"/>
|
||||
<hbox align="center">
|
||||
<label value="&smtpName.label;" control="identity.smtpServerKey"
|
||||
accesskey="&smtpName.accesskey;"/>
|
||||
<menulist wsm_persist="true" id="identity.smtpServerKey" flex="1"
|
||||
pref="true" preftype="string" prefattribute="value"
|
||||
prefstring="mail.identity.%identitykey%.smtpServer">
|
||||
<menupopup id="smtpPopup">
|
||||
<menuitem value="" label="&smtpDefaultServer.label;" id="useDefaultItem"/>
|
||||
<menuseparator/>
|
||||
<!-- list will be inserted here -->
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<hbox align="center">
|
||||
<spacer flex="1"/>
|
||||
<button label="&manageIdentities.label;" oncommand="manageIdentities(event);"
|
||||
accesskey="&manageIdentities.accesskey;"
|
||||
wsm_persist="true" id="identity.manageIdentitiesbutton"/>
|
||||
</hbox>
|
||||
|
||||
<spacer flex="1"/>
|
||||
</vbox>
|
||||
|
||||
</page>
|
||||
351
mailnews/base/prefs/content/am-offline.js
Normal file
351
mailnews/base/prefs/content/am-offline.js
Normal file
|
|
@ -0,0 +1,351 @@
|
|||
/* -*- Mode: Java; 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/. */
|
||||
|
||||
Components.utils.import("resource:///modules/iteratorUtils.jsm");
|
||||
|
||||
var gIncomingServer;
|
||||
var gServerType;
|
||||
var gImapIncomingServer;
|
||||
var gPref = null;
|
||||
var gLockedPref = null;
|
||||
var gOfflineMap = null; // map of folder URLs to offline flags
|
||||
|
||||
function onInit(aPageId, aServerId)
|
||||
{
|
||||
onLockPreference();
|
||||
|
||||
// init values here
|
||||
initServerSettings();
|
||||
initRetentionSettings();
|
||||
initDownloadSettings();
|
||||
initOfflineSettings();
|
||||
|
||||
onCheckItem("offline.notDownloadMin", "offline.notDownload");
|
||||
onCheckItem("nntp.downloadMsgMin", "nntp.downloadMsg");
|
||||
onCheckItem("nntp.removeBodyMin", "nntp.removeBody");
|
||||
onCheckKeepMsg();
|
||||
}
|
||||
|
||||
function initOfflineSettings()
|
||||
{
|
||||
gOfflineMap = collectOfflineFolders();
|
||||
}
|
||||
|
||||
function initServerSettings()
|
||||
{
|
||||
document.getElementById("offline.notDownload").checked = gIncomingServer.limitOfflineMessageSize;
|
||||
document.getElementById("autosync.notDownload").checked = gIncomingServer.limitOfflineMessageSize;
|
||||
if(gIncomingServer.maxMessageSize > 0)
|
||||
document.getElementById("offline.notDownloadMin").value = gIncomingServer.maxMessageSize;
|
||||
else
|
||||
document.getElementById("offline.notDownloadMin").value = "50";
|
||||
|
||||
if(gServerType == "imap") {
|
||||
gImapIncomingServer = gIncomingServer.QueryInterface(Components.interfaces.nsIImapIncomingServer);
|
||||
document.getElementById("offline.folders").checked = gImapIncomingServer.offlineDownload;
|
||||
}
|
||||
}
|
||||
|
||||
function initRetentionSettings()
|
||||
{
|
||||
let retentionSettings = gIncomingServer.retentionSettings;
|
||||
initCommonRetentionSettings(retentionSettings);
|
||||
|
||||
document.getElementById("nntp.removeBody").checked = retentionSettings.cleanupBodiesByDays;
|
||||
document.getElementById("nntp.removeBodyMin").value =
|
||||
(retentionSettings.daysToKeepBodies > 0) ? retentionSettings.daysToKeepBodies : 30;
|
||||
}
|
||||
|
||||
function initDownloadSettings()
|
||||
{
|
||||
let downloadSettings = gIncomingServer.downloadSettings;
|
||||
document.getElementById("nntp.downloadMsg").checked = downloadSettings.downloadByDate;
|
||||
document.getElementById("nntp.notDownloadRead").checked = downloadSettings.downloadUnreadOnly;
|
||||
document.getElementById("nntp.downloadMsgMin").value =
|
||||
(downloadSettings.ageLimitOfMsgsToDownload > 0) ?
|
||||
downloadSettings.ageLimitOfMsgsToDownload : 30;
|
||||
|
||||
// Figure out what the most natural division of the autosync pref into
|
||||
// a value and an interval is.
|
||||
let autosyncSelect = document.getElementById("autosyncSelect");
|
||||
let autosyncInterval = document.getElementById("autosyncInterval");
|
||||
let autosyncValue = document.getElementById("autosyncValue");
|
||||
let autosyncPref = document.getElementById("imap.autoSyncMaxAgeDays");
|
||||
let autosyncPrefValue = (autosyncPref.value == "") ? -1 :
|
||||
parseInt(autosyncPref.value, 10);
|
||||
|
||||
// Clear the preference until we're done initializing.
|
||||
autosyncPref.value = "";
|
||||
|
||||
if (autosyncPrefValue <= 0) {
|
||||
// Special-case values <= 0 to have an interval of "All" and disabled
|
||||
// controls for value and interval.
|
||||
autosyncSelect.value = 0;
|
||||
autosyncInterval.value = 1;
|
||||
autosyncInterval.disabled = true;
|
||||
autosyncValue.value = 30;
|
||||
autosyncValue.disabled = true;
|
||||
}
|
||||
else {
|
||||
// Otherwise, get the list of possible intervals, in order from
|
||||
// largest to smallest.
|
||||
let valuesToTest = [];
|
||||
for (let i = autosyncInterval.itemCount - 1; i >= 0; i--)
|
||||
valuesToTest.push(autosyncInterval.getItemAtIndex(i).value);
|
||||
|
||||
// and find the first one that divides the preference evenly.
|
||||
for (let i in valuesToTest) {
|
||||
if (!(autosyncPrefValue % valuesToTest[i])) {
|
||||
autosyncSelect.value = 1;
|
||||
autosyncInterval.value = valuesToTest[i];
|
||||
autosyncValue.value = autosyncPrefValue / autosyncInterval.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
autosyncInterval.disabled = false;
|
||||
autosyncValue.disabled = false;
|
||||
}
|
||||
autosyncPref.value = autosyncPrefValue;
|
||||
}
|
||||
|
||||
|
||||
function onPreInit(account, accountValues)
|
||||
{
|
||||
gServerType = getAccountValue(account, accountValues, "server", "type", null, false);
|
||||
hideShowControls(gServerType);
|
||||
gIncomingServer = account.incomingServer;
|
||||
gIncomingServer.type = gServerType;
|
||||
|
||||
// 10 is OFFLINE_SUPPORT_LEVEL_REGULAR, see nsIMsgIncomingServer.idl
|
||||
// currently, there is no offline without diskspace
|
||||
var titleStringID = (gIncomingServer.offlineSupportLevel >= 10) ?
|
||||
"prefPanel-synchronization" : "prefPanel-diskspace";
|
||||
|
||||
var prefBundle = document.getElementById("bundle_prefs");
|
||||
var headertitle = document.getElementById("headertitle");
|
||||
headertitle.setAttribute('title',prefBundle.getString(titleStringID));
|
||||
document.title = prefBundle.getString(titleStringID);
|
||||
|
||||
if (gServerType == "pop3") {
|
||||
var pop3Server = gIncomingServer.QueryInterface(Components.interfaces.nsIPop3IncomingServer);
|
||||
// hide retention settings for deferred accounts
|
||||
if (pop3Server.deferredToAccount.length) {
|
||||
var retentionRadio = document.getElementById("retention.keepMsg");
|
||||
retentionRadio.setAttribute("hidden", "true");
|
||||
var retentionLabel = document.getElementById("retentionDescriptionPop");
|
||||
retentionLabel.setAttribute("hidden", "true");
|
||||
var applyToFlaggedCheckbox = document.getElementById("retention.applyToFlagged");
|
||||
applyToFlaggedCheckbox.setAttribute("hidden", "true");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onClickSelect()
|
||||
{
|
||||
|
||||
top.window.openDialog("chrome://messenger/content/msgSelectOffline.xul", "", "centerscreen,chrome,modal,titlebar,resizable=yes");
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle updates to the Autosync
|
||||
*/
|
||||
function onAutosyncChange()
|
||||
{
|
||||
let autosyncSelect = document.getElementById("autosyncSelect");
|
||||
let autosyncInterval = document.getElementById("autosyncInterval");
|
||||
let autosyncValue = document.getElementById("autosyncValue");
|
||||
let autosyncPref = document.getElementById("imap.autoSyncMaxAgeDays");
|
||||
|
||||
// If we're not done initializing, don't do anything.
|
||||
// (See initDownloadSettings() for more details.)
|
||||
if (autosyncPref.value == "")
|
||||
return;
|
||||
|
||||
// If the user selected the All option, disable the autosync and the
|
||||
// textbox.
|
||||
if (autosyncSelect.value == 0) {
|
||||
autosyncPref.value = -1;
|
||||
autosyncInterval.disabled = true;
|
||||
autosyncValue.disabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
let max = 0x7FFFFFFF / (60 * 60 * 24 * autosyncInterval.value);
|
||||
autosyncValue.setAttribute("max", max);
|
||||
if (autosyncValue.value > max)
|
||||
autosyncValue.value = Math.floor(max);
|
||||
|
||||
autosyncInterval.disabled = false;
|
||||
autosyncValue.disabled = false;
|
||||
autosyncPref.value = autosyncValue.value * autosyncInterval.value;
|
||||
}
|
||||
|
||||
function onAutosyncNotDownload()
|
||||
{
|
||||
// This function is called when the autosync version of offline.notDownload
|
||||
// is changed it simply copies the new checkbox value over to the element
|
||||
// driving the preference.
|
||||
document.getElementById("offline.notDownload").checked =
|
||||
document.getElementById("autosync.notDownload").checked;
|
||||
onCheckItem("offline.notDownloadMin", "offline.notDownload");
|
||||
}
|
||||
|
||||
function onCancel()
|
||||
{
|
||||
// restore the offline flags for all folders
|
||||
restoreOfflineFolders(gOfflineMap);
|
||||
return true;
|
||||
}
|
||||
|
||||
function onSave()
|
||||
{
|
||||
var downloadSettings =
|
||||
Components.classes["@mozilla.org/msgDatabase/downloadSettings;1"]
|
||||
.createInstance(Components.interfaces.nsIMsgDownloadSettings);
|
||||
|
||||
gIncomingServer.limitOfflineMessageSize = document.getElementById("offline.notDownload").checked;
|
||||
gIncomingServer.maxMessageSize = document.getElementById("offline.notDownloadMin").value;
|
||||
|
||||
var retentionSettings = saveCommonRetentionSettings(gIncomingServer.retentionSettings);
|
||||
|
||||
retentionSettings.daysToKeepBodies = document.getElementById("nntp.removeBodyMin").value;
|
||||
retentionSettings.cleanupBodiesByDays = document.getElementById("nntp.removeBody").checked;
|
||||
|
||||
downloadSettings.downloadByDate = document.getElementById("nntp.downloadMsg").checked;
|
||||
downloadSettings.downloadUnreadOnly = document.getElementById("nntp.notDownloadRead").checked;
|
||||
downloadSettings.ageLimitOfMsgsToDownload = document.getElementById("nntp.downloadMsgMin").value;
|
||||
|
||||
gIncomingServer.retentionSettings = retentionSettings;
|
||||
gIncomingServer.downloadSettings = downloadSettings;
|
||||
|
||||
if (gImapIncomingServer) {
|
||||
// Set the pref on the incomingserver, and set the flag on all folders.
|
||||
gImapIncomingServer.offlineDownload = document.getElementById("offline.folders").checked;
|
||||
}
|
||||
}
|
||||
|
||||
// Does the work of disabling an element given the array which contains xul id/prefstring pairs.
|
||||
// Also saves the id/locked state in an array so that other areas of the code can avoid
|
||||
// stomping on the disabled state indiscriminately.
|
||||
function disableIfLocked( prefstrArray )
|
||||
{
|
||||
if (!gLockedPref)
|
||||
gLockedPref = new Array;
|
||||
|
||||
for (var i=0; i<prefstrArray.length; i++) {
|
||||
var id = prefstrArray[i].id;
|
||||
var element = document.getElementById(id);
|
||||
if (gPref.prefIsLocked(prefstrArray[i].prefstring)) {
|
||||
element.disabled = true;
|
||||
gLockedPref[id] = true;
|
||||
} else {
|
||||
element.removeAttribute("disabled");
|
||||
gLockedPref[id] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Disables xul elements that have associated preferences locked.
|
||||
function onLockPreference()
|
||||
{
|
||||
var isDownloadLocked = false;
|
||||
var isGetNewLocked = false;
|
||||
var initPrefString = "mail.server";
|
||||
var finalPrefString;
|
||||
|
||||
// This panel does not use the code in AccountManager.js to handle
|
||||
// the load/unload/disable. keep in mind new prefstrings and changes
|
||||
// to code in AccountManager, and update these as well.
|
||||
var allPrefElements = [
|
||||
{ prefstring:"limit_offline_message_size", id:"offline.notDownload"},
|
||||
{ prefstring:"limit_offline_message_size", id:"autosync.notDownload"},
|
||||
{ prefstring:"max_size", id:"offline.notDownloadMin"},
|
||||
{ prefstring:"downloadUnreadOnly", id:"nntp.notDownloadRead"},
|
||||
{ prefstring:"downloadByDate", id:"nntp.downloadMsg"},
|
||||
{ prefstring:"ageLimit", id:"nntp.downloadMsgMin"},
|
||||
{ prefstring:"retainBy", id:"retention.keepMsg"},
|
||||
{ prefstring:"daysToKeepHdrs", id:"retention.keepOldMsgMin"},
|
||||
{ prefstring:"numHdrsToKeep", id:"retention.keepNewMsgMin"},
|
||||
{ prefstring:"daysToKeepBodies", id:"nntp.removeBodyMin"},
|
||||
{ prefstring:"cleanupBodies", id:"nntp.removeBody" },
|
||||
{ prefstring:"applyToFlagged", id:"retention.applyToFlagged"},
|
||||
{ prefstring:"disable_button.selectFolder", id:"selectNewsgroupsButton"},
|
||||
{ prefstring:"disable_button.selectFolder", id:"selectImapFoldersButton"}
|
||||
];
|
||||
|
||||
finalPrefString = initPrefString + "." + gIncomingServer.key + ".";
|
||||
gPref = Services.prefs.getBranch(finalPrefString);
|
||||
|
||||
disableIfLocked( allPrefElements );
|
||||
}
|
||||
|
||||
function onCheckItem(changeElementId, checkElementId)
|
||||
{
|
||||
var element = document.getElementById(changeElementId);
|
||||
var checked = document.getElementById(checkElementId).checked;
|
||||
if(checked && !gLockedPref[checkElementId] ) {
|
||||
element.removeAttribute("disabled");
|
||||
}
|
||||
else {
|
||||
element.setAttribute("disabled", "true");
|
||||
}
|
||||
}
|
||||
|
||||
function toggleOffline()
|
||||
{
|
||||
let offline = document.getElementById("offline.folders").checked;
|
||||
let allFolders = gIncomingServer.rootFolder.descendants;
|
||||
for (let folder in fixIterator(allFolders, Components.interfaces.nsIMsgFolder)) {
|
||||
if (offline)
|
||||
folder.setFlag(Components.interfaces.nsMsgFolderFlags.Offline);
|
||||
else
|
||||
folder.clearFlag(Components.interfaces.nsMsgFolderFlags.Offline);
|
||||
}
|
||||
}
|
||||
|
||||
function collectOfflineFolders()
|
||||
{
|
||||
let offlineFolderMap = {};
|
||||
let allFolders = gIncomingServer.rootFolder.descendants;
|
||||
for (let folder in fixIterator(allFolders, Components.interfaces.nsIMsgFolder))
|
||||
offlineFolderMap[folder.folderURL] = folder.getFlag(Components.interfaces.nsMsgFolderFlags.Offline);
|
||||
|
||||
return offlineFolderMap;
|
||||
}
|
||||
|
||||
function restoreOfflineFolders(offlineFolderMap)
|
||||
{
|
||||
let allFolders = gIncomingServer.rootFolder.descendants;
|
||||
for (let folder in fixIterator(allFolders, Components.interfaces.nsIMsgFolder)) {
|
||||
if (offlineFolderMap[folder.folderURL])
|
||||
folder.setFlag(Components.interfaces.nsMsgFolderFlags.Offline);
|
||||
else
|
||||
folder.clearFlag(Components.interfaces.nsMsgFolderFlags.Offline);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the user selected a permanent removal of messages from a server
|
||||
* listed in the confirmfor attribute and warns about it.
|
||||
*
|
||||
* @param aRadio The radiogroup element containing the retention options.
|
||||
*/
|
||||
function warnServerRemove(aRadio)
|
||||
{
|
||||
let confirmFor = aRadio.getAttribute("confirmfor");
|
||||
|
||||
if (confirmFor && confirmFor.split(',').includes(gServerType) && aRadio.value != 1) {
|
||||
let prefBundle = document.getElementById("bundle_prefs");
|
||||
let title = prefBundle.getString("removeFromServerTitle");
|
||||
let question = prefBundle.getString("removeFromServer");
|
||||
if (!Services.prompt.confirm(window, title, question)) {
|
||||
// If the user doesn't agree, fall back to not deleting anything.
|
||||
aRadio.value = 1;
|
||||
onCheckKeepMsg();
|
||||
}
|
||||
}
|
||||
}
|
||||
158
mailnews/base/prefs/content/am-offline.xul
Normal file
158
mailnews/base/prefs/content/am-offline.xul
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/accountManage.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE page SYSTEM "chrome://messenger/locale/am-offline.dtd">
|
||||
|
||||
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="parent.onPanelLoaded('am-offline.xul');">
|
||||
|
||||
<vbox flex="1" style="overflow: auto;">
|
||||
<stringbundle id="bundle_prefs" src="chrome://messenger/locale/prefs.properties"/>
|
||||
|
||||
<script type="application/javascript" src="chrome://messenger/content/AccountManager.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/retention.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/am-offline.js"/>
|
||||
|
||||
<label hidden="true" wsm_persist="true" id="server.type"/>
|
||||
<label id="imap.autoSyncMaxAgeDays" hidden="true"
|
||||
wsm_persist="true" preftype="int"
|
||||
prefstring="mail.server.%serverkey%.autosync_max_age_days"/>
|
||||
|
||||
<dialogheader id="headertitle"/>
|
||||
|
||||
<groupbox id="offline.titlebox" hidefor="movemail,pop3,none,rss">
|
||||
<caption label="&syncGroupTitle.label;"/>
|
||||
|
||||
<checkbox hidefor="movemail,pop3,nntp,none"
|
||||
id="offline.folders" label="&allFoldersOffline.label;"
|
||||
oncommand="toggleOffline()"
|
||||
accesskey="&allFoldersOffline.accesskey;"/>
|
||||
|
||||
<separator class="thin" hidefor="movemail,pop3,nntp,none"/>
|
||||
|
||||
<hbox hidefor="movemail,pop3,nntp,none" align="right">
|
||||
<button label="&offlineImapAdvancedOffline.label;" accesskey="&offlineImapAdvancedOffline.accesskey;"
|
||||
oncommand="onClickSelect()" id="selectImapFoldersButton" class="selectForOfflineUseButton"/>
|
||||
</hbox>
|
||||
|
||||
<hbox hidefor="movemail,pop3,imap,none" align="right">
|
||||
<button label="&offlineSelectNntp.label;" accesskey="&offlineSelectNntp.accesskey;"
|
||||
oncommand="onClickSelect()" id="selectNewsgroupsButton" class="selectForOfflineUseButton"/>
|
||||
</hbox>
|
||||
|
||||
</groupbox>
|
||||
|
||||
<groupbox id="diskspace.titlebox">
|
||||
<caption label="&diskspaceGroupTitle.label;" hidefor="movemail,pop3,none,rss"/>
|
||||
|
||||
<description hidefor="pop3,nntp,movemail,none,rss">&doNotDownloadImap.label;</description>
|
||||
<description hidefor="pop3,imap,movemail,none,rss">&doNotDownloadNntp.label;</description>
|
||||
<description hidefor="imap,nntp,none,rss">&doNotDownloadPop3Movemail.label;</description>
|
||||
|
||||
<!-- IMAP Autosync Preference -->
|
||||
<radiogroup hidefor="pop3,nntp,movemail,none,rss" id="autosyncSelect" class="indent">
|
||||
<radio id="useAutosync.AllMsg" value="0" accesskey="&allAutosync.accesskey;"
|
||||
label="&allAutosync.label;" oncommand="onAutosyncChange();"/>
|
||||
<hbox flex="1" align="center">
|
||||
<radio id="useAutosync.ByAge" accesskey="&ageAutosync.accesskey;"
|
||||
value="1" label="&ageAutosyncBefore.label;" oncommand="onAutosyncChange();"/>
|
||||
<textbox id="autosyncValue" type="number" size="4" min="1"
|
||||
class="autosync" onchange="onAutosyncChange();"
|
||||
aria-labelledby="ageAutosyncBefore autosyncValue ageAutosyncMiddle autosyncInterval ageAutosyncAfter"/>
|
||||
<label id="ageAutosyncMiddle" control="autosyncValue" value="&ageAutosyncMiddle.label;"/>
|
||||
<menulist id="autosyncInterval" onselect="onAutosyncChange();">
|
||||
<menupopup>
|
||||
<menuitem label="&dayAgeInterval.label;" value="1"/>
|
||||
<menuitem label="&weekAgeInterval.label;" value="7"/>
|
||||
<menuitem label="&monthAgeInterval.label;" value="31"/>
|
||||
<menuitem label="&yearAgeInterval.label;" value="365"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
<label id="ageAutosyncAfter" control="autosyncInterval" value="&ageAutosyncAfter.label;"/>
|
||||
</hbox>
|
||||
</radiogroup>
|
||||
|
||||
<hbox align="center" class="indent" hidefor="rss">
|
||||
<checkbox hidefor="movemail,pop3,imap,none"
|
||||
id="nntp.notDownloadRead" wsm_persist="true"
|
||||
label="&nntpNotDownloadRead.label;"
|
||||
accesskey="&nntpNotDownloadRead.accesskey;"/>
|
||||
</hbox>
|
||||
|
||||
<hbox align="center" class="indent" hidefor="none,rss">
|
||||
<checkbox wsm_persist="true" id="offline.notDownload" hidefor="imap"
|
||||
label="&offlineNotDownload.label;"
|
||||
accesskey="&offlineNotDownload.accesskey;"
|
||||
oncommand="onCheckItem('offline.notDownloadMin', 'offline.notDownload');"/>
|
||||
<checkbox wsm_persist="true" id="autosync.notDownload" hidefor="pop3,nntp,movemail"
|
||||
label="&autosyncNotDownload.label;"
|
||||
accesskey="&autosyncNotDownload.accesskey;"
|
||||
oncommand="onAutosyncNotDownload();"/>
|
||||
<textbox wsm_persist="true" id="offline.notDownloadMin"
|
||||
type="number" min="1" increment="10" size="4" value="50"
|
||||
aria-labelledby="offline.notDownload offline.notDownloadMin kbLabel"/>
|
||||
<label value="&kb.label;" control="offline.notDownloadMin" id="kbLabel"/>
|
||||
</hbox>
|
||||
|
||||
<hbox align="center" class="indent" hidefor="movemail,pop3,imap,none,rss">
|
||||
<checkbox wsm_persist="true" id="nntp.downloadMsg"
|
||||
label="&nntpDownloadMsg.label;"
|
||||
accesskey="&nntpDownloadMsg.accesskey;"
|
||||
oncommand="onCheckItem('nntp.downloadMsgMin', 'nntp.downloadMsg');"/>
|
||||
<textbox wsm_persist="true" id="nntp.downloadMsgMin"
|
||||
type="number" min="1" size="2" value="30"
|
||||
aria-labelledby="nntp.downloadMsg nntp.downloadMsgMin daysOldLabel"/>
|
||||
<label value="&daysOld.label;" control="nntp.downloadMsgMin"
|
||||
id="daysOldLabel"/>
|
||||
</hbox>
|
||||
|
||||
<vbox align="start">
|
||||
<separator hidefor="none,rss"/>
|
||||
<label id="retentionDescription" hidefor="imap,pop3" class="desc" control="retention.keepMsg">&retentionCleanup.label;</label>
|
||||
<label id="retentionDescriptionImap" hidefor="movemail,pop3,nntp,none,rss" class="desc" control="retention.keepMsg">&retentionCleanupImap.label;</label>
|
||||
<label id="retentionDescriptionPop" hidefor="movemail,imap,nntp,none,rss" class="desc" control="retention.keepMsg">&retentionCleanupPop.label;</label>
|
||||
|
||||
<radiogroup hidefor="" confirmfor="imap,pop3" id="retention.keepMsg" class="indent"
|
||||
oncommand="warnServerRemove(this);">
|
||||
<radio id="retention.keepAllMsg" value="1" accesskey="&retentionKeepAll.accesskey;"
|
||||
label="&retentionKeepAll.label;" oncommand="onCheckKeepMsg();"/>
|
||||
<hbox flex="1" align="center">
|
||||
<radio id="retention.keepNewMsg" accesskey="&retentionKeepRecent.accesskey;"
|
||||
value="3" label="&retentionKeepRecent.label;" oncommand="onCheckKeepMsg();"/>
|
||||
<textbox id="retention.keepNewMsgMin"
|
||||
type="number" min="1" increment="10" size="4" value="2000"
|
||||
aria-labelledby="retention.keepNewMsg retention.keepNewMsgMin newMsgLabel"/>
|
||||
<label value="&message.label;" control="retention.keepNewMsgMin" id="newMsgLabel"/>
|
||||
</hbox>
|
||||
<hbox flex="1" align="center">
|
||||
<radio id="retention.keepOldMsg" accesskey="&retentionKeepMsg.accesskey;"
|
||||
value="2" label="&retentionKeepMsg.label;" oncommand="onCheckKeepMsg();"/>
|
||||
<textbox id="retention.keepOldMsgMin"
|
||||
type="number" min="1" size="4" value="30"
|
||||
aria-labelledby="retention.keepOldMsg retention.keepOldMsgMin oldMsgLabel"/>
|
||||
<label value="&daysOld.label;" control="retention.keepOldMsgMin" id="oldMsgLabel"/>
|
||||
</hbox>
|
||||
</radiogroup>
|
||||
|
||||
<hbox align="center" class="indent">
|
||||
<checkbox id="retention.applyToFlagged"
|
||||
label="&retentionApplyToFlagged.label;" hidefor=""
|
||||
accesskey="&retentionApplyToFlagged.accesskey;"
|
||||
checked="true"/>
|
||||
</hbox>
|
||||
<hbox align="center" class="indent" hidefor="movemail,pop3,imap,none,rss">
|
||||
<checkbox id="nntp.removeBody" accesskey="&nntpRemoveMsgBody.accesskey;"
|
||||
label="&nntpRemoveMsgBody.label;" oncommand="onCheckItem('nntp.removeBodyMin','nntp.removeBody');"/>
|
||||
<textbox id="nntp.removeBodyMin" size="2" value="30"
|
||||
type="number" min="1"
|
||||
aria-labelledby="nntp.removeBody nntp.removeBodyMin daysOldMsg"/>
|
||||
<label value="&daysOld.label;" control="nntp.removeBodyMin" id="daysOldMsg"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</groupbox>
|
||||
</vbox>
|
||||
</page>
|
||||
114
mailnews/base/prefs/content/am-prefs.js
Normal file
114
mailnews/base/prefs/content/am-prefs.js
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/* -*- Mode: C++; tab-width: 4; 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/. */
|
||||
|
||||
/* functions for disabling front end elements when the appropriate
|
||||
back-end preference is locked. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
/**
|
||||
* Prefs in MailNews require dynamic portions to indicate
|
||||
* which of multiple servers or identities. This function
|
||||
* takes a string and a xul element.
|
||||
*
|
||||
* @param aStr The string is a prefstring with a token %tokenname%.
|
||||
* @param aElement The xul element has an attribute of name |tokenname|
|
||||
* whose value is substituted into the string and returned
|
||||
* by the function.
|
||||
*
|
||||
* Any tokens which do not have associated attribute value
|
||||
* are not substituted, and left in the string as-is.
|
||||
*/
|
||||
function substPrefTokens(aStr, aElement)
|
||||
{
|
||||
let tokenpat = /%(\w+)%/;
|
||||
let token;
|
||||
let newprefstr = "";
|
||||
|
||||
let prefPartsArray = aStr.split(".");
|
||||
/* here's a little loop that goes through
|
||||
each part of the string separated by a dot, and
|
||||
if any parts are of the form %string%, it will replace
|
||||
them with the value of the attribute of that name from
|
||||
the xul object */
|
||||
for (let i = 0; i < prefPartsArray.length; i++) {
|
||||
token = prefPartsArray[i].match(tokenpat);
|
||||
if (token) { /* we've got a %% match */
|
||||
if (token[1]) {
|
||||
if (aElement[token[1]]) {
|
||||
newprefstr += aElement[token[1]] + "."; // here's where we get the info
|
||||
} else { /* all we got was this stinkin % */
|
||||
newprefstr += prefPartsArray[i] + ".";
|
||||
}
|
||||
}
|
||||
} else /* if (token) */ {
|
||||
newprefstr += prefPartsArray[i] + ".";
|
||||
}
|
||||
}
|
||||
newprefstr = newprefstr.slice(0, -1); // remove the last char, a dot
|
||||
if (newprefstr.length <= 0)
|
||||
newprefstr = null;
|
||||
|
||||
return newprefstr;
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple function to check if a pref in an element is locked.
|
||||
*
|
||||
* @param aElement a xul element with the pref related attributes
|
||||
* (pref, preftype, prefstring)
|
||||
* @return whether the prefstring specified in that element is
|
||||
* locked (true/false).
|
||||
* If it does not have a valid prefstring, a false is returned.
|
||||
*/
|
||||
function getAccountValueIsLocked(aElement)
|
||||
{
|
||||
let prefstring = aElement.getAttribute("prefstring");
|
||||
if (prefstring) {
|
||||
let prefstr = substPrefTokens(prefstring, aElement);
|
||||
// see if the prefstring is locked
|
||||
if (prefstr)
|
||||
return Services.prefs.prefIsLocked(prefstr);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables/disables element (slave) according to the checked state
|
||||
* of another elements (masters).
|
||||
*
|
||||
* @param aChangeElementId Slave element which should be enabled
|
||||
* if all the checkElementIDs are checked.
|
||||
* Otherwise it gets disabled.
|
||||
* @param aCheckElementIds An array of IDs of the master elements.
|
||||
*
|
||||
* See bug 728681 for the pattern on how this is used.
|
||||
*/
|
||||
function onCheckItem(aChangeElementId, aCheckElementIds)
|
||||
{
|
||||
let elementToControl = document.getElementById(aChangeElementId);
|
||||
let disabled = false;
|
||||
|
||||
for (let notifyId of aCheckElementIds) {
|
||||
let notifyElement = document.getElementById(notifyId);
|
||||
let notifyElementState = null;
|
||||
if ("checked" in notifyElement)
|
||||
notifyElementState = notifyElement.checked;
|
||||
else if ("selected" in notifyElement)
|
||||
notifyElementState = notifyElement.selected;
|
||||
else
|
||||
Components.utils.reportError("Unknown type of control element: " + notifyElement.id);
|
||||
|
||||
if (!notifyElementState) {
|
||||
disabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!disabled && getAccountValueIsLocked(elementToControl))
|
||||
disabled = true;
|
||||
|
||||
elementToControl.disabled = disabled;
|
||||
}
|
||||
157
mailnews/base/prefs/content/am-server-advanced.js
Normal file
157
mailnews/base/prefs/content/am-server-advanced.js
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// pull stuff out of window.arguments
|
||||
var gServerSettings = window.arguments[0];
|
||||
|
||||
var gFirstDeferredAccount;
|
||||
// initialize the controls with the "gServerSettings" argument
|
||||
|
||||
var gControls;
|
||||
function getControls()
|
||||
{
|
||||
if (!gControls)
|
||||
gControls = document.getElementsByAttribute("amsa_persist", "true");
|
||||
return gControls;
|
||||
}
|
||||
|
||||
function getLocalFoldersAccount()
|
||||
{
|
||||
return MailServices.accounts
|
||||
.FindAccountForServer(MailServices.accounts.localFoldersServer);
|
||||
}
|
||||
|
||||
function onLoad()
|
||||
{
|
||||
var prettyName = gServerSettings.serverPrettyName;
|
||||
|
||||
if (prettyName)
|
||||
document.getElementById("serverPrettyName").value =
|
||||
document.getElementById("bundle_prefs")
|
||||
.getFormattedString("forAccount", [prettyName]);
|
||||
|
||||
if (gServerSettings.serverType == "imap")
|
||||
{
|
||||
document.getElementById("pop3Panel").hidden = true;
|
||||
}
|
||||
else if (gServerSettings.serverType == "pop3")
|
||||
{
|
||||
document.getElementById("imapPanel").hidden = true;
|
||||
let radioGroup = document.getElementById("folderStorage");
|
||||
|
||||
gFirstDeferredAccount = gServerSettings.deferredToAccount;
|
||||
let folderPopup = document.getElementById("deferredServerPopup");
|
||||
|
||||
// The current account should not be shown in the folder picker
|
||||
// of the "other account" option.
|
||||
folderPopup._teardown();
|
||||
folderPopup.setAttribute("excludeServers",
|
||||
gServerSettings.account.incomingServer.key);
|
||||
folderPopup._ensureInitialized();
|
||||
|
||||
if (gFirstDeferredAccount.length)
|
||||
{
|
||||
// The current account is deferred.
|
||||
let account = MailServices.accounts.getAccount(gFirstDeferredAccount);
|
||||
radioGroup.value = "otherAccount";
|
||||
folderPopup.selectFolder(account.incomingServer.rootFolder);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Current account is not deferred.
|
||||
radioGroup.value = "currentAccount";
|
||||
// If there are no suitable accounts to defer to, then the menulist is
|
||||
// disabled by the picker with an appropriate message.
|
||||
folderPopup.selectFolder();
|
||||
if (gServerSettings.account.incomingServer.isDeferredTo) {
|
||||
// Some other account already defers to this account
|
||||
// therefore this one can't be deferred further.
|
||||
radioGroup.disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
let picker = document.getElementById("deferredServerFolderPicker");
|
||||
picker.disabled = radioGroup.selectedIndex != 1;
|
||||
}
|
||||
|
||||
var controls = getControls();
|
||||
|
||||
for (var i = 0; i < controls.length; i++)
|
||||
{
|
||||
var slot = controls[i].id;
|
||||
if (slot in gServerSettings)
|
||||
{
|
||||
if (controls[i].localName == "checkbox")
|
||||
controls[i].checked = gServerSettings[slot];
|
||||
else
|
||||
controls[i].value = gServerSettings[slot];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onOk()
|
||||
{
|
||||
// Handle account deferral settings for POP3 accounts.
|
||||
if (gServerSettings.serverType == "pop3")
|
||||
{
|
||||
var radioGroup = document.getElementById("folderStorage");
|
||||
var gPrefsBundle = document.getElementById("bundle_prefs");
|
||||
let picker = document.getElementById("deferredServerFolderPicker");
|
||||
|
||||
// This account wasn't previously deferred, but is now deferred.
|
||||
if (radioGroup.value != "currentAccount" && !gFirstDeferredAccount.length)
|
||||
{
|
||||
// If the user hasn't selected a folder, keep the default.
|
||||
if (!picker.selectedItem)
|
||||
return true;
|
||||
|
||||
var confirmDeferAccount =
|
||||
gPrefsBundle.getString("confirmDeferAccountWarning");
|
||||
|
||||
var confirmTitle = gPrefsBundle.getString("confirmDeferAccountTitle");
|
||||
|
||||
if (!Services.prompt.confirm(window, confirmTitle, confirmDeferAccount))
|
||||
return false;
|
||||
}
|
||||
switch (radioGroup.value)
|
||||
{
|
||||
case "currentAccount":
|
||||
gServerSettings['deferredToAccount'] = "";
|
||||
break;
|
||||
case "otherAccount":
|
||||
let server = picker.selectedItem._folder.server;
|
||||
let account = MailServices.accounts.FindAccountForServer(server);
|
||||
gServerSettings['deferredToAccount'] = account.key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Save the controls back to the "gServerSettings" array.
|
||||
var controls = getControls();
|
||||
for (var i = 0; i < controls.length; i++)
|
||||
{
|
||||
var slot = controls[i].id;
|
||||
if (slot in gServerSettings)
|
||||
{
|
||||
if (controls[i].localName == "checkbox")
|
||||
gServerSettings[slot] = controls[i].checked;
|
||||
else
|
||||
gServerSettings[slot] = controls[i].value;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Set radio element choices and picker states
|
||||
function updateInboxAccount(enablePicker)
|
||||
{
|
||||
document.getElementById("deferredServerFolderPicker").disabled = !enablePicker;
|
||||
document.getElementById("deferGetNewMail").disabled = !enablePicker;
|
||||
}
|
||||
146
mailnews/base/prefs/content/am-server-advanced.xul
Normal file
146
mailnews/base/prefs/content/am-server-advanced.xul
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/accountManage.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/messenger.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/folderMenus.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE dialog SYSTEM "chrome://messenger/locale/am-server-advanced.dtd">
|
||||
|
||||
<dialog
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&serverAdvanced.label;"
|
||||
buttons="accept,cancel"
|
||||
onload="onLoad();"
|
||||
ondialogaccept="return onOk();">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/am-server-advanced.js"/>
|
||||
<stringbundle id="bundle_prefs"
|
||||
src="chrome://messenger/locale/prefs.properties"/>
|
||||
|
||||
<label id="serverPrettyName"/>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<!-- IMAP Panel -->
|
||||
<vbox id="imapPanel">
|
||||
<hbox align="center">
|
||||
<label value="&serverDirectory.label;"
|
||||
accesskey="&serverDirectory.accesskey;"
|
||||
control="serverDirectory"/>
|
||||
<textbox amsa_persist="true" id="serverDirectory"/>
|
||||
</hbox>
|
||||
|
||||
<checkbox amsa_persist="true" id="usingSubscription"
|
||||
label="&usingSubscription.label;"
|
||||
accesskey="&usingSubscription.accesskey;"/>
|
||||
|
||||
<checkbox amsa_persist="true" id="dualUseFolders"
|
||||
label="&dualUseFolders.label;"
|
||||
accesskey="&dualUseFolders.accesskey;"/>
|
||||
|
||||
<separator class="groove"/>
|
||||
<row>
|
||||
<hbox align="center">
|
||||
<label control="maximumConnectionsNumber"
|
||||
value="&maximumConnectionsNumber.label;"
|
||||
accesskey="&maximumConnectionsNumber.accesskey;"/>
|
||||
<textbox amsa_persist="true" size="3" type="number"
|
||||
min="1" max="1000" id="maximumConnectionsNumber"/>
|
||||
</hbox>
|
||||
</row>
|
||||
|
||||
<separator class="groove"/>
|
||||
<description>&namespaceDesc.label;</description>
|
||||
<grid>
|
||||
<columns>
|
||||
<column/>
|
||||
<column/>
|
||||
<column/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<separator class="indent"/>
|
||||
<label control="personalNamespace" value="&personalNamespace.label;"
|
||||
accesskey="&personalNamespace.accesskey;"/>
|
||||
<textbox amsa_persist="true" id="personalNamespace" />
|
||||
</row>
|
||||
<row align="center">
|
||||
<separator class="indent"/>
|
||||
<label control="publicNamespace" value="&publicNamespace.label;"
|
||||
accesskey="&publicNamespace.accesskey;"/>
|
||||
<textbox amsa_persist="true" id="publicNamespace"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<separator class="indent"/>
|
||||
<label control="otherUsersNamespace" value="&otherUsersNamespace.label;"
|
||||
accesskey="&otherUsersNamespace.accesskey;"/>
|
||||
<textbox amsa_persist="true" id="otherUsersNamespace"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
<grid>
|
||||
<columns>
|
||||
<column/>
|
||||
<column/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<separator class="indent"/>
|
||||
<checkbox amsa_persist="true" id="overrideNamespaces"
|
||||
label="&overrideNamespaces.label;"
|
||||
accesskey="&overrideNamespaces.accesskey;"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</vbox>
|
||||
|
||||
|
||||
<!-- POP3 Panel -->
|
||||
<vbox id="pop3Panel">
|
||||
<label flex="1" control="folderStorage">&pop3DeferringDesc.label;</label>
|
||||
<hbox align="center">
|
||||
<radiogroup id="folderStorage"
|
||||
orient="horizontal"
|
||||
amsa_persist="true"
|
||||
onselect="updateInboxAccount(this.selectedIndex == 1);">
|
||||
<rows>
|
||||
<row>
|
||||
<radio id="deferToCurrentAccount"
|
||||
value="currentAccount"
|
||||
label="&accountInbox.label;"
|
||||
accesskey="&accountInbox.accesskey;"/>
|
||||
</row>
|
||||
<row>
|
||||
<vbox>
|
||||
<hbox>
|
||||
<radio id="deferToOtherAccount"
|
||||
value="otherAccount"
|
||||
label="&deferToServer.label;"
|
||||
accesskey="&deferToServer.accesskey;">
|
||||
</radio>
|
||||
<menulist id="deferredServerFolderPicker"
|
||||
class="folderMenuItem"
|
||||
aria-labelledby="deferToServer">
|
||||
<menupopup id="deferredServerPopup"
|
||||
type="folder"
|
||||
expandFolders="false"
|
||||
mode="deferred"
|
||||
oncommand="this.selectFolder(event.target._folder);"/>
|
||||
</menulist>
|
||||
</hbox>
|
||||
<checkbox amsa_persist="true" id="deferGetNewMail"
|
||||
label="&deferGetNewMail.label;" class="indent"
|
||||
accesskey="&deferGetNewMail.accesskey;"/>
|
||||
</vbox>
|
||||
</row>
|
||||
</rows>
|
||||
</radiogroup>
|
||||
</hbox>
|
||||
|
||||
</vbox>
|
||||
</dialog>
|
||||
13
mailnews/base/prefs/content/am-server-top.xul
Normal file
13
mailnews/base/prefs/content/am-server-top.xul
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/accountManage.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE page SYSTEM "chrome://messenger/locale/am-server-top.dtd" >
|
||||
|
||||
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
</page>
|
||||
400
mailnews/base/prefs/content/am-server.js
Normal file
400
mailnews/base/prefs/content/am-server.js
Normal file
|
|
@ -0,0 +1,400 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
Components.utils.import("resource:///modules/iteratorUtils.jsm");
|
||||
Components.utils.import("resource:///modules/MailUtils.js");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var gServer;
|
||||
|
||||
function onSave()
|
||||
{
|
||||
let storeContractID = document.getElementById("server.storeTypeMenulist")
|
||||
.selectedItem
|
||||
.value;
|
||||
document.getElementById("server.storeContractID")
|
||||
.setAttribute("value", storeContractID);
|
||||
}
|
||||
|
||||
function onInit(aPageId, aServerId)
|
||||
{
|
||||
initServerType();
|
||||
|
||||
onCheckItem("server.biffMinutes", ["server.doBiff"]);
|
||||
onCheckItem("nntp.maxArticles", ["nntp.notifyOn"]);
|
||||
setupMailOnServerUI();
|
||||
setupFixedUI();
|
||||
let serverType = document.getElementById("server.type").getAttribute("value");
|
||||
if (serverType == "imap")
|
||||
setupImapDeleteUI(aServerId);
|
||||
|
||||
// TLS Cert (External) and OAuth2 are only supported on IMAP.
|
||||
document.getElementById("authMethod-oauth2").hidden = (serverType != "imap");
|
||||
document.getElementById("authMethod-external").hidden = (serverType != "imap");
|
||||
|
||||
// "STARTTLS, if available" is vulnerable to MITM attacks so we shouldn't
|
||||
// allow users to choose it anymore. Hide the option unless the user already
|
||||
// has it set.
|
||||
hideUnlessSelected(document.getElementById("connectionSecurityType-1"));
|
||||
|
||||
// UI for account store type.
|
||||
let storeTypeElement = document.getElementById("server.storeTypeMenulist");
|
||||
// set the menuitem to match the account
|
||||
let currentStoreID = document.getElementById("server.storeContractID")
|
||||
.getAttribute("value");
|
||||
let targetItem = storeTypeElement.getElementsByAttribute("value", currentStoreID);
|
||||
storeTypeElement.selectedItem = targetItem[0];
|
||||
// disable store type change if store has already been used
|
||||
storeTypeElement.setAttribute("disabled",
|
||||
gServer.getBoolValue("canChangeStoreType") ? "false" : "true");
|
||||
}
|
||||
|
||||
function onPreInit(account, accountValues)
|
||||
{
|
||||
var type = parent.getAccountValue(account, accountValues, "server", "type", null, false);
|
||||
hideShowControls(type);
|
||||
|
||||
Services.obs.notifyObservers(null, "charsetmenu-selected", "other");
|
||||
|
||||
gServer = account.incomingServer;
|
||||
|
||||
if(!account.incomingServer.canEmptyTrashOnExit)
|
||||
{
|
||||
document.getElementById("server.emptyTrashOnExit").setAttribute("hidden", "true");
|
||||
document.getElementById("imap.deleteModel.box").setAttribute("hidden", "true");
|
||||
}
|
||||
}
|
||||
|
||||
function initServerType()
|
||||
{
|
||||
var serverType = document.getElementById("server.type").getAttribute("value");
|
||||
var propertyName = "serverType-" + serverType;
|
||||
|
||||
var messengerBundle = document.getElementById("bundle_messenger");
|
||||
var verboseName = messengerBundle.getString(propertyName);
|
||||
setDivText("servertype.verbose", verboseName);
|
||||
|
||||
secureSelect(true);
|
||||
|
||||
setLabelFromStringBundle("authMethod-no", "authNo");
|
||||
setLabelFromStringBundle("authMethod-old", "authOld");
|
||||
setLabelFromStringBundle("authMethod-kerberos", "authKerberos");
|
||||
setLabelFromStringBundle("authMethod-external", "authExternal");
|
||||
setLabelFromStringBundle("authMethod-ntlm", "authNTLM");
|
||||
setLabelFromStringBundle("authMethod-oauth2", "authOAuth2");
|
||||
setLabelFromStringBundle("authMethod-anysecure", "authAnySecure");
|
||||
setLabelFromStringBundle("authMethod-any", "authAny");
|
||||
setLabelFromStringBundle("authMethod-password-encrypted",
|
||||
"authPasswordEncrypted");
|
||||
//authMethod-password-cleartext already set in selectSelect()
|
||||
|
||||
// Hide deprecated/hidden auth options, unless selected
|
||||
hideUnlessSelected(document.getElementById("authMethod-no"));
|
||||
hideUnlessSelected(document.getElementById("authMethod-old"));
|
||||
hideUnlessSelected(document.getElementById("authMethod-anysecure"));
|
||||
hideUnlessSelected(document.getElementById("authMethod-any"));
|
||||
}
|
||||
|
||||
function hideUnlessSelected(element)
|
||||
{
|
||||
element.hidden = !element.selected;
|
||||
}
|
||||
|
||||
function setLabelFromStringBundle(elementID, stringName)
|
||||
{
|
||||
document.getElementById(elementID).label =
|
||||
document.getElementById("bundle_messenger").getString(stringName);
|
||||
}
|
||||
|
||||
function setDivText(divname, value)
|
||||
{
|
||||
var div = document.getElementById(divname);
|
||||
if (!div)
|
||||
return;
|
||||
div.setAttribute("value", value);
|
||||
}
|
||||
|
||||
|
||||
function onAdvanced()
|
||||
{
|
||||
// Store the server type and, if an IMAP or POP3 server,
|
||||
// the settings needed for the IMAP/POP3 tab into the array
|
||||
var serverSettings = {};
|
||||
var serverType = document.getElementById("server.type").getAttribute("value");
|
||||
serverSettings.serverType = serverType;
|
||||
|
||||
serverSettings.serverPrettyName = gServer.prettyName;
|
||||
serverSettings.account = top.getCurrentAccount();
|
||||
|
||||
if (serverType == "imap")
|
||||
{
|
||||
serverSettings.dualUseFolders = document.getElementById("imap.dualUseFolders").checked;
|
||||
serverSettings.usingSubscription = document.getElementById("imap.usingSubscription").checked;
|
||||
serverSettings.maximumConnectionsNumber = document.getElementById("imap.maximumConnectionsNumber").getAttribute("value");
|
||||
// string prefs
|
||||
serverSettings.personalNamespace = document.getElementById("imap.personalNamespace").getAttribute("value");
|
||||
serverSettings.publicNamespace = document.getElementById("imap.publicNamespace").getAttribute("value");
|
||||
serverSettings.serverDirectory = document.getElementById("imap.serverDirectory").getAttribute("value");
|
||||
serverSettings.otherUsersNamespace = document.getElementById("imap.otherUsersNamespace").getAttribute("value");
|
||||
serverSettings.overrideNamespaces = document.getElementById("imap.overrideNamespaces").checked;
|
||||
}
|
||||
else if (serverType == "pop3")
|
||||
{
|
||||
serverSettings.deferGetNewMail = document.getElementById("pop3.deferGetNewMail").checked;
|
||||
serverSettings.deferredToAccount = document.getElementById("pop3.deferredToAccount").getAttribute("value");
|
||||
}
|
||||
|
||||
window.openDialog("chrome://messenger/content/am-server-advanced.xul",
|
||||
"_blank", "chrome,modal,titlebar", serverSettings);
|
||||
|
||||
if (serverType == "imap")
|
||||
{
|
||||
document.getElementById("imap.dualUseFolders").checked = serverSettings.dualUseFolders;
|
||||
document.getElementById("imap.usingSubscription").checked = serverSettings.usingSubscription;
|
||||
document.getElementById("imap.maximumConnectionsNumber").setAttribute("value", serverSettings.maximumConnectionsNumber);
|
||||
// string prefs
|
||||
document.getElementById("imap.personalNamespace").setAttribute("value", serverSettings.personalNamespace);
|
||||
document.getElementById("imap.publicNamespace").setAttribute("value", serverSettings.publicNamespace);
|
||||
document.getElementById("imap.serverDirectory").setAttribute("value", serverSettings.serverDirectory);
|
||||
document.getElementById("imap.otherUsersNamespace").setAttribute("value", serverSettings.otherUsersNamespace);
|
||||
document.getElementById("imap.overrideNamespaces").checked = serverSettings.overrideNamespaces;
|
||||
}
|
||||
else if (serverType == "pop3")
|
||||
{
|
||||
document.getElementById("pop3.deferGetNewMail").checked = serverSettings.deferGetNewMail;
|
||||
document.getElementById("pop3.deferredToAccount").setAttribute("value", serverSettings.deferredToAccount);
|
||||
let pop3Server = gServer.QueryInterface(Components.interfaces.nsIPop3IncomingServer);
|
||||
// we're explicitly setting this so we'll go through the SetDeferredToAccount method
|
||||
pop3Server.deferredToAccount = serverSettings.deferredToAccount;
|
||||
// Setting the server to be deferred causes a rebuild of the account tree,
|
||||
// losing the current selection. Reselect the current server again as it
|
||||
// didn't really disappear.
|
||||
parent.selectServer(parent.getCurrentAccount().incomingServer, parent.currentPageId);
|
||||
|
||||
// Iterate over all accounts to see if any of their junk targets are now
|
||||
// invalid (pointed to the account that is now deferred).
|
||||
// If any such target is found it is reset to a new safe folder
|
||||
// (the deferred to account or Local Folders). If junk was really moved
|
||||
// to that folder (moveOnSpam = true) then moving junk is disabled
|
||||
// (so that the user notices it and checks the settings).
|
||||
// This is the same sanitization as in am-junk.js, just applied to all POP accounts.
|
||||
let deferredURI = serverSettings.deferredToAccount &&
|
||||
MailServices.accounts.getAccount(serverSettings.deferredToAccount)
|
||||
.incomingServer.serverURI;
|
||||
|
||||
for (let account in fixIterator(MailServices.accounts.accounts,
|
||||
Components.interfaces.nsIMsgAccount)) {
|
||||
let accountValues = parent.getValueArrayFor(account);
|
||||
let type = parent.getAccountValue(account, accountValues, "server", "type",
|
||||
null, false);
|
||||
// Try to keep this list of account types not having Junk settings
|
||||
// synchronized with the list in AccountManager.js.
|
||||
if (type != "nntp" && type != "rss" && type != "im") {
|
||||
let spamActionTargetAccount = parent.getAccountValue(account, accountValues,
|
||||
"server", "spamActionTargetAccount", "string", true);
|
||||
let spamActionTargetFolder = parent.getAccountValue(account, accountValues,
|
||||
"server", "spamActionTargetFolder", "string", true);
|
||||
let moveOnSpam = parent.getAccountValue(account, accountValues,
|
||||
"server", "moveOnSpam", "bool", true);
|
||||
|
||||
// Check if there are any invalid junk targets and fix them.
|
||||
[ spamActionTargetAccount, spamActionTargetFolder, moveOnSpam ] =
|
||||
sanitizeJunkTargets(spamActionTargetAccount,
|
||||
spamActionTargetFolder,
|
||||
deferredURI || account.incomingServer.serverURI,
|
||||
parent.getAccountValue(account, accountValues, "server", "moveTargetMode", "int", true),
|
||||
account.incomingServer.spamSettings,
|
||||
moveOnSpam);
|
||||
|
||||
parent.setAccountValue(accountValues, "server", "moveOnSpam", moveOnSpam);
|
||||
parent.setAccountValue(accountValues, "server", "spamActionTargetAccount",
|
||||
spamActionTargetAccount);
|
||||
parent.setAccountValue(accountValues, "server", "spamActionTargetFolder",
|
||||
spamActionTargetFolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function secureSelect(aLoading)
|
||||
{
|
||||
var socketType = document.getElementById("server.socketType").value;
|
||||
var serverType = document.getElementById("server.type").value;
|
||||
var defaultPort = gServer.protocolInfo.getDefaultServerPort(false);
|
||||
var defaultPortSecure = gServer.protocolInfo.getDefaultServerPort(true);
|
||||
var port = document.getElementById("server.port");
|
||||
var portDefault = document.getElementById("defaultPort");
|
||||
var prevDefaultPort = portDefault.value;
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
if (socketType == Ci.nsMsgSocketType.SSL) {
|
||||
portDefault.value = defaultPortSecure;
|
||||
if (port.value == "" || (!aLoading && port.value == defaultPort && prevDefaultPort != portDefault.value))
|
||||
port.value = defaultPortSecure;
|
||||
} else {
|
||||
portDefault.value = defaultPort;
|
||||
if (port.value == "" || (!aLoading && port.value == defaultPortSecure && prevDefaultPort != portDefault.value))
|
||||
port.value = defaultPort;
|
||||
}
|
||||
|
||||
// switch "insecure password" label
|
||||
setLabelFromStringBundle("authMethod-password-cleartext",
|
||||
socketType == Ci.nsMsgSocketType.SSL ||
|
||||
socketType == Ci.nsMsgSocketType.alwaysSTARTTLS ?
|
||||
"authPasswordCleartextViaSSL" : "authPasswordCleartextInsecurely");
|
||||
}
|
||||
|
||||
function setupMailOnServerUI()
|
||||
{
|
||||
onCheckItem("pop3.deleteMailLeftOnServer", ["pop3.leaveMessagesOnServer"]);
|
||||
setupAgeMsgOnServerUI();
|
||||
}
|
||||
|
||||
function setupAgeMsgOnServerUI()
|
||||
{
|
||||
const kLeaveMsgsId = "pop3.leaveMessagesOnServer";
|
||||
const kDeleteByAgeId = "pop3.deleteByAgeFromServer";
|
||||
onCheckItem(kDeleteByAgeId, [kLeaveMsgsId]);
|
||||
onCheckItem("daysEnd", [kLeaveMsgsId]);
|
||||
onCheckItem("pop3.numDaysToLeaveOnServer", [kLeaveMsgsId, kDeleteByAgeId]);
|
||||
}
|
||||
|
||||
function setupFixedUI()
|
||||
{
|
||||
var controls = [document.getElementById("fixedServerName"),
|
||||
document.getElementById("fixedUserName"),
|
||||
document.getElementById("fixedServerPort")];
|
||||
|
||||
var len = controls.length;
|
||||
for (var i=0; i<len; i++) {
|
||||
var fixedElement = controls[i];
|
||||
var otherElement = document.getElementById(fixedElement.getAttribute("use"));
|
||||
|
||||
fixedElement.setAttribute("collapsed", "true");
|
||||
otherElement.removeAttribute("collapsed");
|
||||
}
|
||||
}
|
||||
|
||||
function BrowseForNewsrc()
|
||||
{
|
||||
const nsIFilePicker = Components.interfaces.nsIFilePicker;
|
||||
const nsIFile = Components.interfaces.nsIFile;
|
||||
|
||||
var newsrcTextBox = document.getElementById("nntp.newsrcFilePath");
|
||||
var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
|
||||
fp.init(window,
|
||||
document.getElementById("browseForNewsrc").getAttribute("filepickertitle"),
|
||||
nsIFilePicker.modeSave);
|
||||
|
||||
var currentNewsrcFile;
|
||||
try {
|
||||
currentNewsrcFile = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(nsIFile);
|
||||
currentNewsrcFile.initWithPath(newsrcTextBox.value);
|
||||
} catch (e) {
|
||||
dump("Failed to create nsIFile instance for the current newsrc file.\n");
|
||||
}
|
||||
|
||||
if (currentNewsrcFile) {
|
||||
fp.displayDirectory = currentNewsrcFile.parent;
|
||||
fp.defaultString = currentNewsrcFile.leafName;
|
||||
}
|
||||
|
||||
fp.appendFilters(nsIFilePicker.filterAll);
|
||||
|
||||
if (fp.show() != nsIFilePicker.returnCancel)
|
||||
newsrcTextBox.value = fp.file.path;
|
||||
}
|
||||
|
||||
function setupImapDeleteUI(aServerId)
|
||||
{
|
||||
// read delete_model preference
|
||||
var deleteModel = document.getElementById("imap.deleteModel").getAttribute("value");
|
||||
selectImapDeleteModel(deleteModel);
|
||||
|
||||
// read trash_folder_name preference
|
||||
var trashFolderName = getTrashFolderName();
|
||||
|
||||
// set folderPicker menulist
|
||||
var trashPopup = document.getElementById("msgTrashFolderPopup");
|
||||
trashPopup._teardown();
|
||||
trashPopup._parentFolder = MailUtils.getFolderForURI(aServerId);
|
||||
trashPopup._ensureInitialized();
|
||||
|
||||
// TODO: There is something wrong here, selectFolder() fails even if the
|
||||
// folder does exist. Try to fix in bug 802609.
|
||||
let trashFolder = MailUtils.getFolderForURI(aServerId + "/" + trashFolderName, false);
|
||||
try {
|
||||
trashPopup.selectFolder(trashFolder);
|
||||
} catch(ex) {
|
||||
trashPopup.parentNode.setAttribute("label", trashFolder.prettyName);
|
||||
}
|
||||
trashPopup.parentNode.folder = trashFolder;
|
||||
}
|
||||
|
||||
function selectImapDeleteModel(choice)
|
||||
{
|
||||
// set deleteModel to selected mode
|
||||
document.getElementById("imap.deleteModel").setAttribute("value", choice);
|
||||
|
||||
switch (choice)
|
||||
{
|
||||
case "0" : // markDeleted
|
||||
// disable folderPicker
|
||||
document.getElementById("msgTrashFolderPicker").setAttribute("disabled", "true");
|
||||
break;
|
||||
case "1" : // moveToTrashFolder
|
||||
// enable folderPicker
|
||||
document.getElementById("msgTrashFolderPicker").removeAttribute("disabled");
|
||||
break;
|
||||
case "2" : // deleteImmediately
|
||||
// disable folderPicker
|
||||
document.getElementById("msgTrashFolderPicker").setAttribute("disabled", "true");
|
||||
break;
|
||||
default :
|
||||
dump("Error in enabling/disabling server.TrashFolderPicker\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Capture any menulist changes from folderPicker
|
||||
function folderPickerChange(aEvent)
|
||||
{
|
||||
var folder = aEvent.target._folder;
|
||||
var folderPath = getFolderPathFromRoot(folder);
|
||||
|
||||
// Set the value to be persisted.
|
||||
document.getElementById("imap.trashFolderName")
|
||||
.setAttribute("value", folderPath);
|
||||
|
||||
// Update the widget to show/do correct things even for subfolders.
|
||||
var trashFolderPicker = document.getElementById("msgTrashFolderPicker");
|
||||
trashFolderPicker.menupopup.selectFolder(folder);
|
||||
}
|
||||
|
||||
/** Generate the relative folder path from the root. */
|
||||
function getFolderPathFromRoot(folder)
|
||||
{
|
||||
var path = folder.name;
|
||||
var parentFolder = folder.parent;
|
||||
while (parentFolder && parentFolder != folder.rootFolder) {
|
||||
path = parentFolder.name + "/" + path;
|
||||
parentFolder = parentFolder.parent;
|
||||
}
|
||||
// IMAP Inbox URI's start with INBOX, not Inbox.
|
||||
return path.replace(/^Inbox/, "INBOX");
|
||||
}
|
||||
|
||||
// Get trash_folder_name from prefs
|
||||
function getTrashFolderName()
|
||||
{
|
||||
var trashFolderName = document.getElementById("imap.trashFolderName").getAttribute("value");
|
||||
// if the preference hasn't been set, set it to a sane default
|
||||
if (!trashFolderName) {
|
||||
trashFolderName = "Trash";
|
||||
document.getElementById("imap.trashFolderName").setAttribute("value",trashFolderName);
|
||||
}
|
||||
return trashFolderName;
|
||||
}
|
||||
468
mailnews/base/prefs/content/am-server.xul
Normal file
468
mailnews/base/prefs/content/am-server.xul
Normal file
|
|
@ -0,0 +1,468 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!--
|
||||
|
||||
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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/accountManage.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/messenger.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/folderMenus.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/content/charsetList.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE page [
|
||||
<!ENTITY % trashDTD SYSTEM "chrome://messenger/locale/am-server-top.dtd">
|
||||
%trashDTD;
|
||||
]>
|
||||
|
||||
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&serverSettings.label;"
|
||||
onload="parent.onPanelLoaded('am-server.xul');">
|
||||
|
||||
<vbox flex="1" style="overflow: auto;">
|
||||
<script type="application/javascript" src="chrome://messenger/content/AccountManager.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/am-server.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/am-prefs.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/amUtils.js"/>
|
||||
<stringbundle id="bundle_messenger" src="chrome://messenger/locale/messenger.properties"/>
|
||||
|
||||
<label hidden="true" wsm_persist="true" id="server.type"/>
|
||||
<label hidden="true"
|
||||
wsm_persist="true"
|
||||
preftype="string"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.storeContractID"
|
||||
genericattr="true"
|
||||
id="server.storeContractID"/>
|
||||
|
||||
<dialogheader title="&serverSettings.label;"/>
|
||||
|
||||
<grid>
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
<column/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<label value="&serverType.label;"/>
|
||||
<label id="servertype.verbose"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<hbox>
|
||||
<label value="&serverName.label;" accesskey="&serverName.accesskey;"
|
||||
control="server.realHostName"/>
|
||||
</hbox>
|
||||
<hbox align="center">
|
||||
<label id="fixedServerName" collapsed="true" use="server.realHostName"/>
|
||||
<textbox wsm_persist="true"
|
||||
size="20"
|
||||
flex="1"
|
||||
id="server.realHostName"
|
||||
prefstring="mail.server.%serverkey%.realhostname"
|
||||
class="uri-element"/>
|
||||
</hbox>
|
||||
<hbox align="center">
|
||||
<label hidefor="movemail" value="&port.label;"
|
||||
accesskey="&port.accesskey;" control="server.port"/>
|
||||
<label id="fixedServerPort" hidefor="movemail"
|
||||
collapsed="true" use="server.port"/>
|
||||
<textbox wsm_persist="true" size="3" id="server.port"
|
||||
preftype="int" hidefor="movemail"
|
||||
prefstring="mail.server.%serverkey%.port"
|
||||
type="number" min="1" max="65535" increment="1"/>
|
||||
<label value="&serverPortDefault.label;" hidefor="movemail"/>
|
||||
<label id="defaultPort" hidefor="movemail"/>
|
||||
</hbox>
|
||||
</row>
|
||||
<row align="center">
|
||||
<hbox align="center" hidefor="nntp">
|
||||
<label value="&userName.label;"
|
||||
accesskey="&userName.accesskey;"
|
||||
control="server.realUsername"/>
|
||||
</hbox>
|
||||
<hbox align="center" hidefor="nntp">
|
||||
<label id="fixedUserName" collapsed="true" use="server.realUsername"/>
|
||||
<textbox wsm_persist="true"
|
||||
size="20"
|
||||
flex="1"
|
||||
id="server.realUsername"
|
||||
prefstring="mail.server.%serverkey%.realusername"/>
|
||||
</hbox>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<groupbox hidefor="movemail">
|
||||
<caption label="&securitySettings.label;"/>
|
||||
|
||||
<grid flex="1">
|
||||
<columns>
|
||||
<column/>
|
||||
<column/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<label value="&connectionSecurity.label;"
|
||||
accesskey="&connectionSecurity.accesskey;"
|
||||
control="server.socketType"/>
|
||||
<menulist wsm_persist="true" id="server.socketType"
|
||||
oncommand="secureSelect();">
|
||||
<menupopup id="server.socketTypePopup">
|
||||
<menuitem value="0" label="&connectionSecurityType-0.label;"/>
|
||||
<menuitem id="connectionSecurityType-1"
|
||||
value="1" label="&connectionSecurityType-1.label;"
|
||||
disabled="true"/>
|
||||
<menuitem value="2" label="&connectionSecurityType-2.label;"
|
||||
hidefor="nntp"/>
|
||||
<menuitem value="3" label="&connectionSecurityType-3.label;"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</row>
|
||||
<row align="center" hidefor="nntp,movemail">
|
||||
<label value="&authMethod.label;"
|
||||
accesskey="&authMethod.accesskey;"
|
||||
control="server.authMethod"/>
|
||||
<!-- same in smtpEditOverlay.xul/js -->
|
||||
<menulist id="server.authMethod"
|
||||
wsm_persist="true"
|
||||
preftype="int" type="number"
|
||||
prefstring="mail.server.%serverkey%.authMethod">
|
||||
<menupopup id="server.authMethodPopup">
|
||||
<menuitem id="authMethod-no" value="1"/>
|
||||
<menuitem id="authMethod-old" value="2"/>
|
||||
<menuitem id="authMethod-password-cleartext" value="3"/>
|
||||
<menuitem id="authMethod-password-encrypted" value="4"/>
|
||||
<menuitem id="authMethod-kerberos" value="5"/>
|
||||
<menuitem id="authMethod-ntlm" value="6"/>
|
||||
<menuitem id="authMethod-external" value="7"/>
|
||||
<menuitem id="authMethod-oauth2" value="10"/>
|
||||
<menuitem id="authMethod-anysecure" value="8"/>
|
||||
<menuitem id="authMethod-any" value="9"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</groupbox>
|
||||
|
||||
<groupbox>
|
||||
<caption label="&serverSettings.label;"/>
|
||||
<vbox align="start">
|
||||
<checkbox wsm_persist="true"
|
||||
id="server.loginAtStartUp"
|
||||
label="&loginAtStartup.label;"
|
||||
accesskey="&loginAtStartup.accesskey;"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.login_at_startup"/>
|
||||
</vbox>
|
||||
<hbox align="center">
|
||||
<checkbox wsm_persist="true"
|
||||
id="server.doBiff"
|
||||
label="&biffStart.label;"
|
||||
accesskey="&biffStart.accesskey;"
|
||||
oncommand="onCheckItem('server.biffMinutes', [this.id]);"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.check_new_mail"/>
|
||||
<textbox wsm_persist="true"
|
||||
id="server.biffMinutes"
|
||||
type="number"
|
||||
size="3"
|
||||
min="1"
|
||||
increment="1"
|
||||
aria-labelledby="server.doBiff server.biffMinutes biffEnd"
|
||||
preftype="int"
|
||||
prefstring="mail.server.%serverkey%.check_time"/>
|
||||
<label id="biffEnd"
|
||||
control="server.biffMinutes"
|
||||
value="&biffEnd.label;"/>
|
||||
</hbox>
|
||||
<vbox align="start"
|
||||
hidefor="pop3,nntp,movemail">
|
||||
<checkbox wsm_persist="true"
|
||||
id="imap.useIdle"
|
||||
label="&useIdleNotifications.label;"
|
||||
accesskey="&useIdleNotifications.accesskey;"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.use_idle"/>
|
||||
</vbox>
|
||||
|
||||
<!-- Necessary for POP3 and Movemail (Bug 480945) -->
|
||||
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=480945 -->
|
||||
<vbox align="start" hidefor="imap,nntp">
|
||||
<checkbox wsm_persist="true" id="server.downloadOnBiff"
|
||||
label="&downloadOnBiff.label;" prefattribute="value"
|
||||
accesskey="&downloadOnBiff.accesskey;"
|
||||
prefstring="mail.server.%serverkey%.download_on_biff"/>
|
||||
</vbox>
|
||||
<!-- POP3 -->
|
||||
<vbox align="start" hidefor="imap,nntp,movemail">
|
||||
<checkbox wsm_persist="true" id="pop3.headersOnly"
|
||||
label="&headersOnly.label;"
|
||||
accesskey="&headersOnly.accesskey;"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.headers_only"/>
|
||||
|
||||
<checkbox wsm_persist="true" id="pop3.leaveMessagesOnServer"
|
||||
label="&leaveOnServer.label;" oncommand="setupMailOnServerUI();"
|
||||
accesskey="&leaveOnServer.accesskey;"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.leave_on_server"/>
|
||||
|
||||
<hbox align="center">
|
||||
<checkbox wsm_persist="true" id="pop3.deleteByAgeFromServer" class="indent"
|
||||
label="&deleteByAgeFromServer.label;" oncommand="setupAgeMsgOnServerUI();"
|
||||
accesskey="&deleteByAgeFromServer.accesskey;"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.delete_by_age_from_server"/>
|
||||
<textbox wsm_persist="true" id="pop3.numDaysToLeaveOnServer" size="3"
|
||||
aria-labelledby="pop3.deleteByAgeFromServer pop3.numDaysToLeaveOnServer daysEnd"
|
||||
preftype="int" type="number" min="1" increment="1"
|
||||
prefstring="mail.server.%serverkey%.num_days_to_leave_on_server"/>
|
||||
<label id="daysEnd" control="pop3.numDaysToLeaveOnServer" value="&daysEnd.label;"/>
|
||||
</hbox>
|
||||
|
||||
<checkbox wsm_persist="true" id="pop3.deleteMailLeftOnServer" class="indent"
|
||||
label="&deleteOnServer2.label;"
|
||||
accesskey="&deleteOnServer2.accesskey;"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.delete_mail_left_on_server"/>
|
||||
|
||||
<!-- hidden elements for data transfer to and from advanced... dialog -->
|
||||
<hbox flex="1" hidefor="imap,nntp,movemail" hidden="true">
|
||||
<checkbox hidden="true" wsm_persist="true" id="pop3.deferGetNewMail"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.deferGetNewMail"/>
|
||||
<label hidden="true" wsm_persist="true" id="pop3.deferredToAccount"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.deferredToAccount"/>
|
||||
|
||||
</hbox>
|
||||
</vbox>
|
||||
<!-- IMAP -->
|
||||
<label hidden="true" wsm_persist="true" id="imap.trashFolderName"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.trash_folder_name"/>
|
||||
|
||||
<hbox align="center" hidefor="pop3,nntp,movemail">
|
||||
<label value="&deleteMessagePrefix.label;" align="left"
|
||||
control="imap.deleteModel"/>
|
||||
</hbox>
|
||||
<vbox>
|
||||
<hbox align="center"
|
||||
id="imap.deleteModel.box"
|
||||
hidefor="pop3,nntp,movemail"
|
||||
flex="1">
|
||||
<radiogroup id="imap.deleteModel"
|
||||
wsm_persist="true"
|
||||
oncommand="selectImapDeleteModel(this.value);"
|
||||
prefstring="mail.server.%serverkey%.delete_model">
|
||||
<grid class="specialFolderPickerGrid">
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<radio id="modelMoveToTrash"
|
||||
value="1"
|
||||
label="&modelMoveToTrash.label;"
|
||||
accesskey="&modelMoveToTrash.accesskey;"/>
|
||||
<menulist id="msgTrashFolderPicker" flex="1"
|
||||
class="folderMenuItem"
|
||||
maxwidth="300" crop="center"
|
||||
aria-labelledby="modelMoveToTrash"
|
||||
displayformat="verbose">
|
||||
<menupopup id="msgTrashFolderPopup"
|
||||
type="folder"
|
||||
mode="filing"
|
||||
showFileHereLabel="true"
|
||||
oncommand="folderPickerChange(event);"/>
|
||||
</menulist>
|
||||
</row>
|
||||
<row align="center">
|
||||
<radio id="modelMarkDeleted"
|
||||
value="0"
|
||||
label="&modelMarkDeleted.label;"
|
||||
accesskey="&modelMarkDeleted.accesskey;"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<radio id="modelDeleteImmediately"
|
||||
value="2"
|
||||
label="&modelDeleteImmediately.label;"
|
||||
accesskey="&modelDeleteImmediately.accesskey;"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</radiogroup>
|
||||
</hbox>
|
||||
<hbox pack="end">
|
||||
<!-- This button should have identical attributes to the
|
||||
server.popAdvancedButton except the hidefor attribute. -->
|
||||
<button label="&advancedButton.label;"
|
||||
accesskey="&advancedButton.accesskey;"
|
||||
oncommand="onAdvanced();"
|
||||
wsm_persist="true"
|
||||
id="server.imapAdvancedButton"
|
||||
prefstring="mail.server.%serverkey%.advanced.disable"
|
||||
hidefor="pop3,nntp,movemail"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<!-- Advanced IMAP settings -->
|
||||
<hbox flex="1" hidefor="pop3,nntp,movemail" hidden="true">
|
||||
<checkbox hidden="true" wsm_persist="true" id="imap.dualUseFolders"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.dual_use_folders"/>
|
||||
<checkbox hidden="true" wsm_persist="true" id="imap.usingSubscription"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.using_subscription"/>
|
||||
<label hidden="true" wsm_persist="true" id="imap.maximumConnectionsNumber"/>
|
||||
<label hidden="true" wsm_persist="true" id="imap.personalNamespace"/>
|
||||
<label hidden="true" wsm_persist="true" id="imap.publicNamespace"/>
|
||||
<label hidden="true" wsm_persist="true" id="imap.otherUsersNamespace"/>
|
||||
<label hidden="true" wsm_persist="true" id="imap.serverDirectory"/>
|
||||
<checkbox hidden="true" wsm_persist="true" id="imap.overrideNamespaces"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.override_namespaces"/>
|
||||
</hbox>
|
||||
|
||||
<!-- NNTP -->
|
||||
<hbox hidefor="pop3,imap,movemail" align="center">
|
||||
<checkbox wsm_persist="true" id="nntp.notifyOn"
|
||||
label="&maxMessagesStart.label;"
|
||||
accesskey="&maxMessagesStart.accesskey;"
|
||||
oncommand="onCheckItem('nntp.maxArticles', [this.id]);"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.notify.on"/>
|
||||
<textbox wsm_persist="true" id="nntp.maxArticles"
|
||||
type="number" size="4" min="1" increment="10"
|
||||
aria-labelledby="nntp.notifyOn nntp.maxArticles maxMessagesEnd"
|
||||
preftype="int"
|
||||
prefstring="mail.server.%serverkey%.max_articles"/>
|
||||
<label control="nntp.maxArticles" value="&maxMessagesEnd.label;" id="maxMessagesEnd"/>
|
||||
</hbox>
|
||||
<checkbox hidefor="pop3,imap,movemail" wsm_persist="true" id="nntp.pushAuth"
|
||||
label="&alwaysAuthenticate.label;"
|
||||
accesskey="&alwaysAuthenticate.accesskey;"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.always_authenticate"/>
|
||||
|
||||
<!-- take out for now - bug 45079
|
||||
<hbox flex="1" hidefor="pop3,imap,movemail">
|
||||
<groupbox>
|
||||
<caption class="header" label="&abbreviate.label;"/>
|
||||
|
||||
<radiogroup wsm_persist="true" id="nntp.abbreviate">
|
||||
<radio value="true"
|
||||
label="&abbreviateOn.label;"/>
|
||||
<radio value="false"
|
||||
label="&abbreviateOff.label;"/>
|
||||
</radiogroup>
|
||||
</groupbox>
|
||||
</hbox>
|
||||
-->
|
||||
|
||||
</groupbox>
|
||||
|
||||
<groupbox>
|
||||
<caption label="&messageStorage.label;"/>
|
||||
|
||||
<hbox align="end">
|
||||
<vbox align="start" flex="1" id="exitHandlingBox=">
|
||||
<checkbox hidefor="pop3,nntp,movemail"
|
||||
wsm_persist="true"
|
||||
id="imap.cleanupInboxOnExit"
|
||||
label="&expungeOnExit.label;"
|
||||
accesskey="&expungeOnExit.accesskey;"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.cleanup_inbox_on_exit"/>
|
||||
<checkbox hidefor="nntp"
|
||||
wsm_persist="true"
|
||||
id="server.emptyTrashOnExit"
|
||||
label="&emptyTrashOnExit.label;"
|
||||
accesskey="&emptyTrashOnExit.accesskey;"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.empty_trash_on_exit"/>
|
||||
</vbox>
|
||||
<button label="&advancedButton.label;"
|
||||
accesskey="&advancedButton.accesskey;"
|
||||
oncommand="onAdvanced();"
|
||||
wsm_persist="true"
|
||||
id="server.popAdvancedButton"
|
||||
prefstring="mail.server.%serverkey%.advanced.disable"
|
||||
hidefor="imap,nntp,movemail"/>
|
||||
</hbox>
|
||||
<hbox align="center">
|
||||
<label value="&storeType.label;"
|
||||
accesskey="&storeType.accesskey;"
|
||||
control="server.storeTypeMenulist"/>
|
||||
<menulist id="server.storeTypeMenulist">
|
||||
<menupopup id="server.storeTypeMenupopup">
|
||||
<menuitem id="server.mboxStore"
|
||||
value="@mozilla.org/msgstore/berkeleystore;1"
|
||||
label="&mboxStore2.label;"/>
|
||||
<menuitem id="server.maildirStore"
|
||||
value="@mozilla.org/msgstore/maildirstore;1"
|
||||
label="&maildirStore.label;"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</hbox>
|
||||
|
||||
<vbox hidefor="imap,pop3,movemail">
|
||||
<label value="&newsrcFilePath.label;" control="nntp.newsrcFilePath"/>
|
||||
<hbox align="center">
|
||||
<textbox readonly="true"
|
||||
wsm_persist="true"
|
||||
flex="1"
|
||||
id="nntp.newsrcFilePath"
|
||||
datatype="nsIFile"
|
||||
prefstring="mail.server.%serverkey%.newsrc.file"
|
||||
class="uri-element"/>
|
||||
<button id="browseForNewsrc"
|
||||
label="&browseNewsrc.label;"
|
||||
filepickertitle="&newsrcPicker.label;"
|
||||
accesskey="&browseNewsrc.accesskey;"
|
||||
oncommand="BrowseForNewsrc();"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<vbox>
|
||||
<label value="&localPath.label;" control="server.localPath"/>
|
||||
<hbox align="center">
|
||||
<textbox readonly="true"
|
||||
wsm_persist="true"
|
||||
flex="1"
|
||||
id="server.localPath"
|
||||
datatype="nsIFile"
|
||||
prefstring="mail.server.%serverkey%.directory"
|
||||
class="uri-element"/>
|
||||
<button id="browseForLocalFolder"
|
||||
label="&browseFolder.label;"
|
||||
filepickertitle="&localFolderPicker.label;"
|
||||
accesskey="&browseFolder.accesskey;"
|
||||
oncommand="BrowseForLocalFolders();"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
</groupbox>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<hbox hidefor="imap,pop3,movemail" align="center" valign="middle" iscontrolcontainer="true">
|
||||
<label value="&serverDefaultCharset2.label;" control="nntp.charset"/>
|
||||
<menulist hidable="true"
|
||||
type="charset"
|
||||
hidefor="imap,pop3,movemail"
|
||||
wsm_persist="true"
|
||||
id="nntp.charset"
|
||||
preftype="string"
|
||||
prefstring="mail.server.%serverkey%.charset"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</page>
|
||||
34
mailnews/base/prefs/content/am-serverwithnoidentities.js
Normal file
34
mailnews/base/prefs/content/am-serverwithnoidentities.js
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/* -*- Mode: Java; 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/. */
|
||||
|
||||
var gServer;
|
||||
|
||||
function onInit(aPageId, aServerId) {
|
||||
|
||||
// UI for account store type
|
||||
let storeTypeElement = document.getElementById("server.storeTypeMenulist");
|
||||
// set the menuitem to match the account
|
||||
let currentStoreID = document.getElementById("server.storeContractID")
|
||||
.getAttribute("value");
|
||||
let targetItem = storeTypeElement.getElementsByAttribute("value", currentStoreID);
|
||||
storeTypeElement.selectedItem = targetItem[0];
|
||||
// disable store type change if store has already been used
|
||||
storeTypeElement.setAttribute("disabled",
|
||||
gServer.getBoolValue("canChangeStoreType") ? "false" : "true");
|
||||
}
|
||||
|
||||
function onPreInit(account, accountValues) {
|
||||
gServer = account.incomingServer;
|
||||
}
|
||||
|
||||
function onSave()
|
||||
{
|
||||
let storeContractID = document.getElementById("server.storeTypeMenulist")
|
||||
.selectedItem
|
||||
.value;
|
||||
document.getElementById("server.storeContractID")
|
||||
.setAttribute("value", storeContractID);
|
||||
}
|
||||
|
||||
77
mailnews/base/prefs/content/am-serverwithnoidentities.xul
Normal file
77
mailnews/base/prefs/content/am-serverwithnoidentities.xul
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/accountManage.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE page [
|
||||
<!ENTITY % accountNoIdentDTD SYSTEM "chrome://messenger/locale/am-serverwithnoidentities.dtd" >%accountNoIdentDTD;
|
||||
<!ENTITY % accountServerTopDTD SYSTEM "chrome://messenger/locale/am-server-top.dtd">%accountServerTopDTD;
|
||||
]>
|
||||
|
||||
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&accountTitle.label;"
|
||||
onload="parent.onPanelLoaded('am-serverwithnoidentities.xul');">
|
||||
|
||||
<script type="application/javascript" src="chrome://messenger/content/am-serverwithnoidentities.js"/>
|
||||
<script type="application/javascript" src="chrome://messenger/content/amUtils.js"/>
|
||||
|
||||
<dialogheader title="&accountTitle.label;"/>
|
||||
|
||||
<label hidden="true"
|
||||
wsm_persist="true"
|
||||
preftype="string"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.storeContractID"
|
||||
genericattr="true"
|
||||
id="server.storeContractID"/>
|
||||
|
||||
<description class="secDesc">&accountSettingsDesc.label;</description>
|
||||
<hbox align="center">
|
||||
<label value="&accountName.label;" control="server.prettyName"
|
||||
accesskey="&accountName.accesskey;"/>
|
||||
<textbox wsm_persist="true" size="30" id="server.prettyName"
|
||||
prefstring="mail.server.%serverkey%.name"/>
|
||||
</hbox>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<groupbox>
|
||||
<caption label="&messageStorage.label;"/>
|
||||
|
||||
<vbox align="start">
|
||||
<checkbox wsm_persist="true" id="server.emptyTrashOnExit"
|
||||
label="&emptyTrashOnExit.label;"
|
||||
accesskey="&emptyTrashOnExit.accesskey;"
|
||||
prefattribute="value"
|
||||
prefstring="mail.server.%serverkey%.empty_trash_on_exit"/>
|
||||
<hbox align="center">
|
||||
<label value="&storeType.label;"
|
||||
accesskey="&storeType.accesskey;"
|
||||
control="server.storeTypeMenulist"/>
|
||||
<menulist id="server.storeTypeMenulist">
|
||||
<menupopup id="server.storeTypeMenupopup">
|
||||
<menuitem id="server.mboxStore"
|
||||
value="@mozilla.org/msgstore/berkeleystore;1"
|
||||
label="&mboxStore2.label;"/>
|
||||
<menuitem id="server.maildirStore"
|
||||
value="@mozilla.org/msgstore/maildirstore;1"
|
||||
label="&maildirStore.label;"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<label value="&localPath.label;" control="server.localPath"/>
|
||||
<hbox align="center">
|
||||
<textbox readonly="true" wsm_persist="true" flex="1" id="server.localPath" datatype="nsIFile"
|
||||
prefstring="mail.server.%serverkey%.directory" class="uri-element"/>
|
||||
<button id="browseForLocalFolder" label="&browseFolder.label;" filepickertitle="&localFolderPicker.label;"
|
||||
accesskey="&browseFolder.accesskey;" oncommand="BrowseForLocalFolders()"/>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
</page>
|
||||
256
mailnews/base/prefs/content/am-smtp.js
Normal file
256
mailnews/base/prefs/content/am-smtp.js
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
/* -*- Mode: Java; 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/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
|
||||
var gSmtpServerListWindow =
|
||||
{
|
||||
mBundle: null,
|
||||
mServerList: null,
|
||||
mAddButton: null,
|
||||
mEditButton: null,
|
||||
mDeleteButton: null,
|
||||
mSetDefaultServerButton: null,
|
||||
|
||||
onLoad: function()
|
||||
{
|
||||
parent.onPanelLoaded('am-smtp.xul');
|
||||
|
||||
this.mBundle = document.getElementById("bundle_messenger");
|
||||
this.mServerList = document.getElementById("smtpList");
|
||||
this.mAddButton = document.getElementById("addButton");
|
||||
this.mEditButton = document.getElementById("editButton");
|
||||
this.mDeleteButton = document.getElementById("deleteButton");
|
||||
this.mSetDefaultServerButton = document.getElementById("setDefaultButton");
|
||||
|
||||
this.refreshServerList("", false);
|
||||
|
||||
this.updateButtons(this.getSelectedServer());
|
||||
},
|
||||
|
||||
onSelectionChanged: function(aEvent)
|
||||
{
|
||||
if (this.mServerList.selectedItems.length <= 0)
|
||||
return;
|
||||
|
||||
var server = this.getSelectedServer();
|
||||
this.updateButtons(server);
|
||||
this.updateServerInfoBox(server);
|
||||
},
|
||||
|
||||
onDeleteServer: function (aEvent)
|
||||
{
|
||||
var server = this.getSelectedServer();
|
||||
if (server)
|
||||
{
|
||||
// confirm deletion
|
||||
let cancel = Services.prompt.confirmEx(window,
|
||||
this.mBundle.getString('smtpServers-confirmServerDeletionTitle'),
|
||||
this.mBundle.getFormattedString('smtpServers-confirmServerDeletion', [server.hostname], 1),
|
||||
Services.prompt.STD_YES_NO_BUTTONS, null, null, null, null, { });
|
||||
|
||||
if (!cancel)
|
||||
{
|
||||
MailServices.smtp.deleteServer(server);
|
||||
parent.replaceWithDefaultSmtpServer(server.key);
|
||||
this.refreshServerList("", true);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onAddServer: function (aEvent)
|
||||
{
|
||||
this.openServerEditor(null);
|
||||
},
|
||||
|
||||
onEditServer: function (aEvent)
|
||||
{
|
||||
if (this.mServerList.selectedItems.length <= 0)
|
||||
return;
|
||||
this.openServerEditor(this.getSelectedServer());
|
||||
},
|
||||
|
||||
onSetDefaultServer: function(aEvent)
|
||||
{
|
||||
if (this.mServerList.selectedItems.length <= 0)
|
||||
return;
|
||||
|
||||
MailServices.smtp.defaultServer = this.getSelectedServer();
|
||||
this.refreshServerList(MailServices.smtp.defaultServer.key, true);
|
||||
},
|
||||
|
||||
updateButtons: function(aServer)
|
||||
{
|
||||
// can't delete default server
|
||||
if (MailServices.smtp.defaultServer == aServer)
|
||||
{
|
||||
this.mSetDefaultServerButton.setAttribute("disabled", "true");
|
||||
this.mDeleteButton.setAttribute("disabled", "true");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.mSetDefaultServerButton.removeAttribute("disabled");
|
||||
this.mDeleteButton.removeAttribute("disabled");
|
||||
}
|
||||
|
||||
if (this.mServerList.selectedItems.length == 0)
|
||||
this.mEditButton.setAttribute("disabled", "true");
|
||||
else
|
||||
this.mEditButton.removeAttribute("disabled");
|
||||
},
|
||||
|
||||
updateServerInfoBox: function(aServer)
|
||||
{
|
||||
var noneSelected = this.mBundle.getString("smtpServerList-NotSpecified");
|
||||
|
||||
document.getElementById('nameValue').value = aServer.hostname;
|
||||
document.getElementById('descriptionValue').value = aServer.description || noneSelected;
|
||||
document.getElementById('portValue').value = aServer.port;
|
||||
document.getElementById('userNameValue').value = aServer.username || noneSelected;
|
||||
document.getElementById('useSecureConnectionValue').value =
|
||||
this.mBundle.getString("smtpServer-ConnectionSecurityType-" +
|
||||
aServer.socketType);
|
||||
|
||||
const AuthMethod = Components.interfaces.nsMsgAuthMethod;
|
||||
const SocketType = Components.interfaces.nsMsgSocketType;
|
||||
var authStr = "";
|
||||
switch (aServer.authMethod)
|
||||
{
|
||||
case AuthMethod.none:
|
||||
authStr = "authNo";
|
||||
break;
|
||||
case AuthMethod.passwordEncrypted:
|
||||
authStr = "authPasswordEncrypted";
|
||||
break;
|
||||
case AuthMethod.GSSAPI:
|
||||
authStr = "authKerberos";
|
||||
break;
|
||||
case AuthMethod.NTLM:
|
||||
authStr = "authNTLM";
|
||||
break;
|
||||
case AuthMethod.secure:
|
||||
authStr = "authAnySecure";
|
||||
break;
|
||||
case AuthMethod.passwordCleartext:
|
||||
authStr = (aServer.socketType == SocketType.SSL ||
|
||||
aServer.socketType == SocketType.alwaysSTARTTLS)
|
||||
? "authPasswordCleartextViaSSL"
|
||||
: "authPasswordCleartextInsecurely";
|
||||
break;
|
||||
case AuthMethod.OAuth2:
|
||||
authStr = "authOAuth2";
|
||||
break;
|
||||
default:
|
||||
// leave empty
|
||||
Components.utils.reportError("Warning: unknown value for smtpserver... authMethod: " +
|
||||
aServer.authMethod);
|
||||
}
|
||||
if (authStr)
|
||||
document.getElementById("authMethodValue").value =
|
||||
this.mBundle.getString(authStr);
|
||||
},
|
||||
|
||||
refreshServerList: function(aServerKeyToSelect, aFocusList)
|
||||
{
|
||||
// remove all children
|
||||
while (this.mServerList.hasChildNodes())
|
||||
this.mServerList.lastChild.remove();
|
||||
|
||||
this.fillSmtpServers(this.mServerList,
|
||||
MailServices.smtp.servers,
|
||||
MailServices.smtp.defaultServer);
|
||||
|
||||
if (aServerKeyToSelect)
|
||||
this.setSelectedServer(this.mServerList.querySelector('[key="' + aServerKeyToSelect + '"]'));
|
||||
else // select the default server
|
||||
this.setSelectedServer(this.mServerList.querySelector('[default="true"]'));
|
||||
|
||||
if (aFocusList)
|
||||
this.mServerList.focus();
|
||||
},
|
||||
|
||||
fillSmtpServers: function(aListBox, aServers, aDefaultServer)
|
||||
{
|
||||
if (!aListBox || !aServers)
|
||||
return;
|
||||
|
||||
while (aServers.hasMoreElements())
|
||||
{
|
||||
var server = aServers.getNext();
|
||||
|
||||
if (server instanceof Components.interfaces.nsISmtpServer)
|
||||
{
|
||||
var isDefault = (aDefaultServer.key == server.key);
|
||||
|
||||
var listitem = this.createSmtpListItem(server, isDefault);
|
||||
aListBox.appendChild(listitem);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
createSmtpListItem: function(aServer, aIsDefault)
|
||||
{
|
||||
var listitem = document.createElement("listitem");
|
||||
var serverName = "";
|
||||
|
||||
if (aServer.description)
|
||||
serverName = aServer.description + ' - ';
|
||||
else if (aServer.username)
|
||||
serverName = aServer.username + ' - ';
|
||||
|
||||
serverName += aServer.hostname;
|
||||
|
||||
if (aIsDefault)
|
||||
{
|
||||
serverName += " " + this.mBundle.getString("defaultServerTag");
|
||||
listitem.setAttribute("default", "true");
|
||||
}
|
||||
|
||||
listitem.setAttribute("label", serverName);
|
||||
listitem.setAttribute("key", aServer.key);
|
||||
listitem.setAttribute("class", "smtpServerListItem");
|
||||
|
||||
// give it some unique id
|
||||
listitem.id = "smtpServer." + aServer.key;
|
||||
return listitem;
|
||||
},
|
||||
|
||||
openServerEditor: function(aServer)
|
||||
{
|
||||
var args = {server: aServer,
|
||||
result: false,
|
||||
addSmtpServer: ""};
|
||||
|
||||
window.openDialog("chrome://messenger/content/SmtpServerEdit.xul",
|
||||
"smtpEdit", "chrome,titlebar,modal,centerscreen", args);
|
||||
|
||||
// now re-select the server which was just added
|
||||
if (args.result)
|
||||
this.refreshServerList(aServer ? aServer.key : args.addSmtpServer, true);
|
||||
|
||||
return args.result;
|
||||
},
|
||||
|
||||
setSelectedServer: function(aServer)
|
||||
{
|
||||
if (!aServer)
|
||||
return;
|
||||
|
||||
setTimeout(function(aServerList) {
|
||||
aServerList.ensureElementIsVisible(aServer);
|
||||
aServerList.selectItem(aServer);
|
||||
}, 0, this.mServerList);
|
||||
},
|
||||
|
||||
getSelectedServer: function()
|
||||
{
|
||||
if (this.mServerList.selectedItems.length == 0)
|
||||
return null;
|
||||
|
||||
let serverKey = this.mServerList.selectedItems[0].getAttribute("key");
|
||||
return MailServices.smtp.getServerByKey(serverKey);
|
||||
}
|
||||
};
|
||||
112
mailnews/base/prefs/content/am-smtp.xul
Normal file
112
mailnews/base/prefs/content/am-smtp.xul
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/accountManage.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE page SYSTEM "chrome://messenger/locale/am-advanced.dtd">
|
||||
|
||||
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&smtpServer.label;"
|
||||
onload="gSmtpServerListWindow.onLoad();">
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/amUtils.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/am-smtp.js"/>
|
||||
|
||||
<stringbundle id="bundle_messenger"
|
||||
src="chrome://messenger/locale/messenger.properties"/>
|
||||
|
||||
<vbox flex="1" style="overflow: auto;">
|
||||
<dialogheader title="&smtpServer.label;"/>
|
||||
|
||||
<label control="smtpList">&smtpDescription.label;</label>
|
||||
<separator class="thin"/>
|
||||
|
||||
<hbox flex="1">
|
||||
<listbox id="smtpList"
|
||||
onselect="gSmtpServerListWindow.onSelectionChanged(event);"
|
||||
ondblclick="gSmtpServerListWindow.onEditServer(event);"
|
||||
flex="1"/>
|
||||
|
||||
<vbox>
|
||||
<button id="addButton"
|
||||
oncommand="gSmtpServerListWindow.onAddServer(event);"
|
||||
label="&smtpListAdd.label;"
|
||||
accesskey="&smtpListAdd.accesskey;"/>
|
||||
<button id="editButton"
|
||||
oncommand="gSmtpServerListWindow.onEditServer(event);"
|
||||
label="&smtpListEdit.label;"
|
||||
accesskey="&smtpListEdit.accesskey;"/>
|
||||
<separator/>
|
||||
<button id="deleteButton" disabled="true"
|
||||
oncommand="gSmtpServerListWindow.onDeleteServer(event);"
|
||||
label="&smtpListDelete.label;"
|
||||
accesskey="&smtpListDelete.accesskey;"/>
|
||||
<button id="setDefaultButton" disabled="true"
|
||||
oncommand="gSmtpServerListWindow.onSetDefaultServer(event);"
|
||||
label="&smtpListSetDefault.label;"
|
||||
accesskey="&smtpListSetDefault.accesskey;"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
||||
<separator/>
|
||||
|
||||
<label class="header">&serverDetails.label;</label>
|
||||
<hbox id="smtpServerInfoBox">
|
||||
<stack flex="1" class="inset">
|
||||
<spacer id="backgroundBox"/>
|
||||
<grid>
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<hbox pack="end">
|
||||
<label id="descriptionLabel"
|
||||
value="&serverDescription.label;"
|
||||
control="descriptionValue"/>
|
||||
</hbox>
|
||||
<textbox id="descriptionValue" readonly="true" class="plain"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<hbox pack="end">
|
||||
<label id="nameLabel" value="&serverName.label;" control="nameValue"/>
|
||||
</hbox>
|
||||
<textbox id="nameValue" readonly="true" class="plain"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<hbox pack="end">
|
||||
<label id="portLabel" value="&serverPort.label;" control="portValue"/>
|
||||
</hbox>
|
||||
<textbox id="portValue" readonly="true" class="plain"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<hbox pack="end">
|
||||
<label id="userNameLabel" value="&userName.label;" control="userNameValue"/>
|
||||
</hbox>
|
||||
<textbox id="userNameValue" readonly="true" class="plain"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<hbox pack="end">
|
||||
<label id="authMethodLabel" value="&authMethod.label;" control="authMethodValue"/>
|
||||
</hbox>
|
||||
<textbox id="authMethodValue" readonly="true" class="plain"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<hbox pack="end">
|
||||
<label id="connectionSecurityLabel" value="&connectionSecurity.label;"
|
||||
control="useSecureConnectionValue"/>
|
||||
</hbox>
|
||||
<textbox id="useSecureConnectionValue" readonly="true" class="plain"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</stack>
|
||||
</hbox>
|
||||
<separator flex="1"/>
|
||||
</vbox>
|
||||
</page>
|
||||
205
mailnews/base/prefs/content/amUtils.js
Normal file
205
mailnews/base/prefs/content/amUtils.js
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
/* -*- Mode: C++; tab-width: 4; 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/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
Components.utils.import("resource:///modules/MailUtils.js");
|
||||
Components.utils.import("resource:///modules/iteratorUtils.jsm");
|
||||
|
||||
function BrowseForLocalFolders()
|
||||
{
|
||||
const nsIFilePicker = Components.interfaces.nsIFilePicker;
|
||||
const nsIFile = Components.interfaces.nsIFile;
|
||||
|
||||
var currentFolderTextBox = document.getElementById("server.localPath");
|
||||
var fp = Components.classes["@mozilla.org/filepicker;1"]
|
||||
.createInstance(nsIFilePicker);
|
||||
|
||||
fp.init(window,
|
||||
document.getElementById("browseForLocalFolder")
|
||||
.getAttribute("filepickertitle"),
|
||||
nsIFilePicker.modeGetFolder);
|
||||
|
||||
var currentFolder = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(nsIFile);
|
||||
currentFolder.initWithPath(currentFolderTextBox.value);
|
||||
fp.displayDirectory = currentFolder;
|
||||
|
||||
if (fp.show() != nsIFilePicker.returnOK)
|
||||
return;
|
||||
|
||||
// Retrieve the selected folder.
|
||||
let selectedFolder = fp.file;
|
||||
|
||||
// Check if the folder can be used for mail storage.
|
||||
if (!top.checkDirectoryIsUsable(selectedFolder))
|
||||
return;
|
||||
|
||||
currentFolderTextBox.value = selectedFolder.path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return server/folder name formatted with server name if needed.
|
||||
*
|
||||
* @param aTargetFolder nsIMsgFolder to format name for
|
||||
* If target.isServer then only its name is returned.
|
||||
* Otherwise return the name as "<foldername> on <servername>".
|
||||
*/
|
||||
function prettyFolderName(aTargetFolder)
|
||||
{
|
||||
if (aTargetFolder.isServer)
|
||||
return aTargetFolder.prettyName;
|
||||
|
||||
return document.getElementById("bundle_messenger")
|
||||
.getFormattedString("verboseFolderFormat",
|
||||
[aTargetFolder.prettyName,
|
||||
aTargetFolder.server.prettyName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks validity of junk target server name and folder.
|
||||
*
|
||||
* @param aTargetURI the URI specification to check
|
||||
* @param aIsServer true if the URI specifies only a server (without folder)
|
||||
*
|
||||
* @return the value of aTargetURI if it is valid (usable), otherwise null
|
||||
*/
|
||||
function checkJunkTargetFolder(aTargetURI, aIsServer)
|
||||
{
|
||||
try {
|
||||
// Does the target account exist?
|
||||
let targetServer = MailUtils.getFolderForURI(aTargetURI + (aIsServer ? "/Junk" : ""),
|
||||
!aIsServer).server;
|
||||
|
||||
// If the target server has deferred storage, Junk can't be stored into it.
|
||||
if (targetServer.rootFolder != targetServer.rootMsgFolder)
|
||||
return null;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return aTargetURI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a usable target for storing Junk mail.
|
||||
* If the passed in server URI is not usable, choose Local Folders.
|
||||
*
|
||||
* @param aTargetURI the URI of a server or folder to try first
|
||||
* @param aIsServer true if the URI specifies only a server (without folder)
|
||||
*
|
||||
* @return the server/folder URI of a usable target for storing Junk
|
||||
*/
|
||||
function chooseJunkTargetFolder(aTargetURI, aIsServer)
|
||||
{
|
||||
let server = null;
|
||||
|
||||
if (aTargetURI) {
|
||||
server = MailUtils.getFolderForURI(aTargetURI, false).server;
|
||||
if (!server.canCreateFoldersOnServer || !server.canSearchMessages ||
|
||||
(server.rootFolder != server.rootMsgFolder))
|
||||
server = null;
|
||||
}
|
||||
if (!server)
|
||||
server = MailServices.accounts.localFoldersServer;
|
||||
|
||||
return server.serverURI + (!aIsServer ? "/Junk" : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes junk target folders if they point to an invalid/unusable (e.g. deferred)
|
||||
* folder/account. Only returns the new safe values. It is up to the caller
|
||||
* to push them to the proper elements/prefs.
|
||||
*
|
||||
* @param aSpamActionTargetAccount The value of the server.*.spamActionTargetAccount pref value (URI).
|
||||
* @param aSpamActionTargetFolder The value of the server.*.spamActionTargetFolder pref value (URI).
|
||||
* @param aProposedTarget The URI of a new target to try.
|
||||
* @param aMoveTargetModeValue The value of the server.*.moveTargetMode pref value (0/1).
|
||||
* @param aServerSpamSettings The nsISpamSettings object of any server
|
||||
* (used just for the MOVE_TARGET_MODE_* constants).
|
||||
* @param aMoveOnSpam The server.*.moveOnSpam pref value (bool).
|
||||
*
|
||||
* @return an array containing:
|
||||
* newTargetAccount new safe junk target account
|
||||
* newTargetAccount new safe junk target folder
|
||||
* newMoveOnSpam new moveOnSpam value
|
||||
*/
|
||||
function sanitizeJunkTargets(aSpamActionTargetAccount,
|
||||
aSpamActionTargetFolder,
|
||||
aProposedTarget,
|
||||
aMoveTargetModeValue,
|
||||
aServerSpamSettings,
|
||||
aMoveOnSpam)
|
||||
{
|
||||
// Check if folder targets are valid.
|
||||
aSpamActionTargetAccount = checkJunkTargetFolder(aSpamActionTargetAccount, true);
|
||||
if (!aSpamActionTargetAccount) {
|
||||
// If aSpamActionTargetAccount is not valid,
|
||||
// reset to default behavior to NOT move junk messages...
|
||||
if (aMoveTargetModeValue == aServerSpamSettings.MOVE_TARGET_MODE_ACCOUNT)
|
||||
aMoveOnSpam = false;
|
||||
|
||||
// ... and find a good default target.
|
||||
aSpamActionTargetAccount = chooseJunkTargetFolder(aProposedTarget, true);
|
||||
}
|
||||
|
||||
aSpamActionTargetFolder = checkJunkTargetFolder(aSpamActionTargetFolder, false);
|
||||
if (!aSpamActionTargetFolder) {
|
||||
// If aSpamActionTargetFolder is not valid,
|
||||
// reset to default behavior to NOT move junk messages...
|
||||
if (aMoveTargetModeValue == aServerSpamSettings.MOVE_TARGET_MODE_FOLDER)
|
||||
aMoveOnSpam = false;
|
||||
|
||||
// ... and find a good default target.
|
||||
aSpamActionTargetFolder = chooseJunkTargetFolder(aProposedTarget, false);
|
||||
}
|
||||
|
||||
return [ aSpamActionTargetAccount, aSpamActionTargetFolder, aMoveOnSpam ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens Preferences (Options) dialog on the Advanced pane, General tab
|
||||
* so that the user sees where the global receipts settings can be found.
|
||||
*
|
||||
* @param aTBPaneId Thunderbird pref paneID to open.
|
||||
* @param aTBTabId Thunderbird tabID to open.
|
||||
* @param aTBOtherArgs Other arguments to send to the pref tab.
|
||||
* @param aSMPaneId Seamonkey pref pane to open.
|
||||
*/
|
||||
function openPrefsFromAccountManager(aTBPaneId, aTBTabId, aTBOtherArgs, aSMPaneId) {
|
||||
let win = Services.wm.getMostRecentWindow("mail:3pane") ||
|
||||
Services.wm.getMostRecentWindow("mail:messageWindow") ||
|
||||
Services.wm.getMostRecentWindow("msgcompose");
|
||||
if (!win)
|
||||
return;
|
||||
|
||||
// If openOptionsDialog() exists, we are in Thunderbird.
|
||||
if (typeof win.openOptionsDialog == "function")
|
||||
win.openOptionsDialog(aTBPaneId, aTBTabId, aTBOtherArgs);
|
||||
// If goPreferences() exists, we are in Seamonkey.
|
||||
if (typeof win.goPreferences == "function")
|
||||
win.goPreferences(aSMPaneId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given account name already exists in any account.
|
||||
*
|
||||
* @param aAccountName The account name string to look for.
|
||||
* @param aAccountKey Optional. The key of an account that is skipped when
|
||||
* searching the name. If unset, do not skip any account.
|
||||
*/
|
||||
function accountNameExists(aAccountName, aAccountKey)
|
||||
{
|
||||
for (let account in fixIterator(MailServices.accounts.accounts,
|
||||
Components.interfaces.nsIMsgAccount))
|
||||
{
|
||||
if (account.key != aAccountKey && account.incomingServer &&
|
||||
aAccountName == account.incomingServer.prettyName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
73
mailnews/base/prefs/content/aw-accname.js
Normal file
73
mailnews/base/prefs/content/aw-accname.js
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/* -*- Mode: Java; 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/. */
|
||||
|
||||
var gPrefsBundle;
|
||||
|
||||
function acctNamePageValidate()
|
||||
{
|
||||
var accountname = document.getElementById("prettyName").value;
|
||||
var canAdvance = accountname ? true : false;
|
||||
|
||||
// Check if this accountname already exists. If so, return false so that
|
||||
// user can enter a different unique account name.
|
||||
if (canAdvance && accountNameExists(accountname))
|
||||
canAdvance = false;
|
||||
|
||||
document.documentElement.canAdvance = canAdvance;
|
||||
}
|
||||
|
||||
function acctNamePageUnload() {
|
||||
var pageData = parent.GetPageData();
|
||||
|
||||
// fix for bug #255473
|
||||
// allow for multiple RSS accounts.
|
||||
// if our isp.rdf file defines "wizardAutoGenerateUniqueHostname"
|
||||
// we generate a unique hostname until we have one that doesn't exist
|
||||
// for RSS accounts, in rss.rdf, userName, hostName and serverType
|
||||
// default to the same thing, so we need to do this to allow for
|
||||
// multiple RSS accounts. Note, they can all have the same pretty name.
|
||||
if (gCurrentAccountData &&
|
||||
gCurrentAccountData.wizardAutoGenerateUniqueHostname)
|
||||
{
|
||||
var serverType = parent.getCurrentServerType(pageData);
|
||||
var userName = parent.getCurrentUserName(pageData);
|
||||
var hostName = parent.getCurrentHostname(pageData);
|
||||
var hostNamePref = hostName;
|
||||
var i = 2;
|
||||
while (parent.AccountExists(userName, hostName, serverType))
|
||||
{
|
||||
// If "Feeds" exists, try "Feeds-2", then "Feeds-3", etc.
|
||||
hostName = hostNamePref + "-" + i;
|
||||
i++;
|
||||
}
|
||||
setPageData(pageData, "server", "hostname", hostName);
|
||||
}
|
||||
|
||||
var accountname = document.getElementById("prettyName").value;
|
||||
setPageData(pageData, "accname", "prettyName", accountname);
|
||||
// Set this to true so we know the user has set the name.
|
||||
setPageData(pageData, "accname", "userset", true);
|
||||
return true;
|
||||
}
|
||||
|
||||
function acctNamePageInit()
|
||||
{
|
||||
gPrefsBundle = document.getElementById("bundle_prefs");
|
||||
var accountNameInput = document.getElementById("prettyName");
|
||||
if (accountNameInput.value=="") {
|
||||
var pageData = parent.GetPageData();
|
||||
var type = parent.getCurrentServerType(pageData);
|
||||
var accountName;
|
||||
|
||||
if (gCurrentAccountData && gCurrentAccountData.wizardAccountName)
|
||||
accountName = gCurrentAccountData.wizardAccountName;
|
||||
else if (type == "nntp")
|
||||
accountName = pageData.newsserver.hostname.value;
|
||||
else
|
||||
accountName = pageData.identity.email.value;
|
||||
accountNameInput.value = accountName;
|
||||
}
|
||||
acctNamePageValidate();
|
||||
}
|
||||
114
mailnews/base/prefs/content/aw-accounttype.js
Normal file
114
mailnews/base/prefs/content/aw-accounttype.js
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/* -*- Mode: Java; 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/. */
|
||||
|
||||
function setAccountTypeData()
|
||||
{
|
||||
var rg = document.getElementById("acctyperadio");
|
||||
var selectedItemId = rg.selectedItem.id;
|
||||
var mail = selectedItemId == "mailaccount";
|
||||
var news = selectedItemId == "newsaccount";
|
||||
|
||||
var pageData = parent.GetPageData();
|
||||
setPageData(pageData, "accounttype", "mailaccount", mail);
|
||||
setPageData(pageData, "accounttype", "newsaccount", news);
|
||||
|
||||
// Other account type, e.g. Movemail
|
||||
setPageData(pageData, "accounttype", "otheraccount", !(news || mail));
|
||||
}
|
||||
|
||||
function acctTypePageUnload() {
|
||||
gCurrentAccountData = null;
|
||||
setAccountTypeData();
|
||||
initializeIspData();
|
||||
setupWizardPanels();
|
||||
return true;
|
||||
}
|
||||
|
||||
function setupWizardPanels() {
|
||||
if (gCurrentAccountData && gCurrentAccountData.useOverlayPanels) {
|
||||
if ("testingIspServices" in this) {
|
||||
if ("SetPageMappings" in this && testingIspServices()) {
|
||||
SetPageMappings(document.documentElement.currentPage.id, "done");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var pageData = parent.GetPageData();
|
||||
|
||||
// We default this to false, even though we could set it to true if we
|
||||
// are going to display the page. However as the accname page will set
|
||||
// it to true for us, we'll just default it to false and not work it out
|
||||
// twice.
|
||||
setPageData(pageData, "accname", "userset", false);
|
||||
|
||||
// If we need to skip wizardpanels, set the wizard to jump to the
|
||||
// summary page i.e., last page. Otherwise, set the flow based
|
||||
// on type of account (mail or news) user is creating.
|
||||
var skipPanels = "";
|
||||
try {
|
||||
if (gCurrentAccountData.wizardSkipPanels)
|
||||
skipPanels = gCurrentAccountData.wizardSkipPanels.toString().toLowerCase();
|
||||
} catch(ex) {}
|
||||
|
||||
// "done" is the only required panel for all accounts. We used to require an identity panel but not anymore.
|
||||
// initialize wizardPanels with the optional mail/news panels
|
||||
var wizardPanels, i;
|
||||
var isMailAccount = pageData.accounttype.mailaccount;
|
||||
var isNewsAccount = pageData.accounttype.newsaccount;
|
||||
if (skipPanels == "true") // Support old syntax of true/false for wizardSkipPanels
|
||||
wizardPanels = new Array("identitypage");
|
||||
else if (isMailAccount && isMailAccount.value)
|
||||
wizardPanels = new Array("identitypage", "incomingpage", "outgoingpage", "accnamepage");
|
||||
else if (isNewsAccount && isNewsAccount.value)
|
||||
wizardPanels = new Array("identitypage", "newsserver", "accnamepage");
|
||||
else { // An account created by an extension and XUL overlays
|
||||
var button = document.getElementById("acctyperadio").selectedItem;
|
||||
wizardPanels = button.value.split(/ *, */);
|
||||
}
|
||||
|
||||
// Create a hash table of the panels to skip
|
||||
var skipArray = skipPanels.split(",");
|
||||
var skipHash = new Array();
|
||||
for (i = 0; i < skipArray.length; i++)
|
||||
skipHash[skipArray[i]] = skipArray[i];
|
||||
|
||||
// Remove skipped panels
|
||||
i = 0;
|
||||
while (i < wizardPanels.length) {
|
||||
if (wizardPanels[i] in skipHash)
|
||||
wizardPanels.splice(i, 1);
|
||||
else
|
||||
i++;
|
||||
}
|
||||
|
||||
wizardPanels.push("done");
|
||||
|
||||
// Set up order of panels
|
||||
for (i = 0; i < (wizardPanels.length-1); i++)
|
||||
setNextPage(wizardPanels[i], wizardPanels[i+1]);
|
||||
|
||||
// make the account type page go to the very first of our approved wizard panels...this is usually going to
|
||||
// be accounttype --> identitypage unless we were configured to skip the identity page
|
||||
setNextPage("accounttype",wizardPanels[0]);
|
||||
}
|
||||
|
||||
function initializeIspData()
|
||||
{
|
||||
let mailAccount = document.getElementById("mailaccount");
|
||||
if (!mailAccount || !mailAccount.selected) {
|
||||
parent.SetCurrentAccountData(null);
|
||||
}
|
||||
|
||||
// now reflect the datasource up into the parent
|
||||
var accountSelection = document.getElementById("acctyperadio");
|
||||
|
||||
var ispName = accountSelection.selectedItem.id;
|
||||
|
||||
dump("initializing ISP data for " + ispName + "\n");
|
||||
|
||||
if (!ispName || ispName == "") return;
|
||||
|
||||
parent.PrefillAccountForIsp(ispName);
|
||||
}
|
||||
215
mailnews/base/prefs/content/aw-done.js
Normal file
215
mailnews/base/prefs/content/aw-done.js
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
|
||||
var gPrefsBundle;
|
||||
|
||||
function donePageInit() {
|
||||
var pageData = parent.GetPageData();
|
||||
var currentAccountData = gCurrentAccountData;
|
||||
|
||||
if ("testingIspServices" in this) {
|
||||
if (testingIspServices()) {
|
||||
if ("setOtherISPServices" in this) {
|
||||
setOtherISPServices();
|
||||
}
|
||||
|
||||
if (currentAccountData && currentAccountData.useOverlayPanels && currentAccountData.createNewAccount) {
|
||||
var backButton = document.documentElement.getButton("back");
|
||||
backButton.setAttribute("disabled", true);
|
||||
|
||||
var cancelButton = document.documentElement.getButton("cancel");
|
||||
cancelButton.setAttribute("disabled", true);
|
||||
|
||||
setPageData(pageData, "identity", "email", gEmailAddress);
|
||||
setPageData(pageData, "identity", "fullName", gUserFullName);
|
||||
setPageData(pageData, "login", "username", gScreenName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gPrefsBundle = document.getElementById("bundle_prefs");
|
||||
var showMailServerDetails = true;
|
||||
|
||||
if (currentAccountData) {
|
||||
// find out if we need to hide server details
|
||||
showMailServerDetails = currentAccountData.showServerDetailsOnWizardSummary;
|
||||
// Change the username field description to email field label in aw-identity
|
||||
if (currentAccountData.emailIDFieldTitle)
|
||||
setUserNameDescField(currentAccountData.emailIDFieldTitle);
|
||||
}
|
||||
|
||||
// Find out if we need to hide details for incoming servers
|
||||
var hideIncoming = (gCurrentAccountData && gCurrentAccountData.wizardHideIncoming);
|
||||
|
||||
var email = "";
|
||||
if (pageData.identity && pageData.identity.email) {
|
||||
// fixup the email
|
||||
email = pageData.identity.email.value;
|
||||
if (email.split('@').length < 2 &&
|
||||
currentAccountData &&
|
||||
currentAccountData.domain)
|
||||
email += "@" + currentAccountData.domain;
|
||||
}
|
||||
setDivTextFromForm("identity.email", email);
|
||||
|
||||
var userName="";
|
||||
if (pageData.login && pageData.login.username)
|
||||
userName = pageData.login.username.value;
|
||||
if (!userName && email) {
|
||||
if (currentAccountData && currentAccountData.incomingServerUserNameRequiresDomain == undefined)
|
||||
currentAccountData.incomingServerUserNameRequiresDomain = false;
|
||||
userName = getUsernameFromEmail(email, currentAccountData &&
|
||||
currentAccountData.incomingServerUserNameRequiresDomain);
|
||||
}
|
||||
// Hide the "username" field if we don't want to show information
|
||||
// on the incoming server.
|
||||
setDivTextFromForm("server.username", hideIncoming ? null : userName);
|
||||
|
||||
var smtpUserName="";
|
||||
if (pageData.login && pageData.login.smtpusername)
|
||||
smtpUserName = pageData.login.smtpusername.value;
|
||||
if (!smtpUserName && email)
|
||||
smtpUserName = getUsernameFromEmail(email, currentAccountData &&
|
||||
currentAccountData.smtpUserNameRequiresDomain);
|
||||
setDivTextFromForm("smtpServer.username", smtpUserName);
|
||||
|
||||
if (pageData.accname && pageData.accname.prettyName) {
|
||||
// If currentAccountData has a pretty name (e.g. news link or from
|
||||
// isp data) only set the user name with the pretty name if the
|
||||
// pretty name originally came from ispdata
|
||||
if ((currentAccountData &&
|
||||
currentAccountData.incomingServer.prettyName) &&
|
||||
(pageData.ispdata &&
|
||||
pageData.ispdata.supplied &&
|
||||
pageData.ispdata.supplied.value))
|
||||
{
|
||||
// Get the polished account name - if the user has modified the
|
||||
// account name then use that, otherwise use the userName.
|
||||
pageData.accname.prettyName.value =
|
||||
gPrefsBundle.getFormattedString("accountName",
|
||||
[currentAccountData.incomingServer.prettyName,
|
||||
(pageData.accname.userset && pageData.accname.userset.value) ? pageData.accname.prettyName.value : userName]);
|
||||
}
|
||||
// else just use the default supplied name
|
||||
|
||||
setDivTextFromForm("account.name", pageData.accname.prettyName.value);
|
||||
} else {
|
||||
setDivTextFromForm("account.name", "");
|
||||
}
|
||||
|
||||
// Show mail servers (incoming&outgoing) details
|
||||
// based on current account data. ISP can set
|
||||
// rdf value of literal showServerDetailsOnWizardSummary
|
||||
// to false to hide server details
|
||||
if (showMailServerDetails && !serverIsNntp(pageData)) {
|
||||
var incomingServerName="";
|
||||
if (pageData.server && pageData.server.hostname) {
|
||||
incomingServerName = pageData.server.hostname.value;
|
||||
if (!incomingServerName &&
|
||||
currentAccountData &&
|
||||
currentAccountData.incomingServer.hostname)
|
||||
incomingServerName = currentAccountData.incomingServer.hostName;
|
||||
}
|
||||
// Hide the incoming server name field if the user specified
|
||||
// wizardHideIncoming in the ISP defaults file
|
||||
setDivTextFromForm("server.name", hideIncoming ? null : incomingServerName);
|
||||
setDivTextFromForm("server.port", pageData.server.port ? pageData.server.port.value : null);
|
||||
var incomingServerType="";
|
||||
if (pageData.server && pageData.server.servertype) {
|
||||
incomingServerType = pageData.server.servertype.value;
|
||||
if (!incomingServerType &&
|
||||
currentAccountData &&
|
||||
currentAccountData.incomingServer.type)
|
||||
incomingServerType = currentAccountData.incomingServer.type;
|
||||
}
|
||||
setDivTextFromForm("server.type", incomingServerType.toUpperCase());
|
||||
|
||||
var smtpServerName="";
|
||||
if (pageData.server && pageData.server.smtphostname) {
|
||||
let smtpServer = MailServices.smtp.defaultServer;
|
||||
smtpServerName = pageData.server.smtphostname.value;
|
||||
if (!smtpServerName && smtpServer && smtpServer.hostname)
|
||||
smtpServerName = smtpServer.hostname;
|
||||
}
|
||||
setDivTextFromForm("smtpServer.name", smtpServerName);
|
||||
}
|
||||
else {
|
||||
setDivTextFromForm("server.name", null);
|
||||
setDivTextFromForm("server.type", null);
|
||||
setDivTextFromForm("server.port", null);
|
||||
setDivTextFromForm("smtpServer.name", null);
|
||||
}
|
||||
|
||||
if (serverIsNntp(pageData)) {
|
||||
var newsServerName="";
|
||||
if (pageData.newsserver && pageData.newsserver.hostname)
|
||||
newsServerName = pageData.newsserver.hostname.value;
|
||||
if (newsServerName) {
|
||||
// No need to show username for news account
|
||||
setDivTextFromForm("server.username", null);
|
||||
}
|
||||
setDivTextFromForm("newsServer.name", newsServerName);
|
||||
setDivTextFromForm("server.port", null);
|
||||
}
|
||||
else {
|
||||
setDivTextFromForm("newsServer.name", null);
|
||||
}
|
||||
|
||||
var isPop = false;
|
||||
if (pageData.server && pageData.server.servertype) {
|
||||
isPop = (pageData.server.servertype.value == "pop3");
|
||||
}
|
||||
|
||||
hideShowDownloadMsgsUI(isPop);
|
||||
}
|
||||
|
||||
function hideShowDownloadMsgsUI(isPop)
|
||||
{
|
||||
// only show the "download messages now" UI
|
||||
// if this is a pop account, we are online, and this was opened
|
||||
// from the 3 pane
|
||||
var downloadMsgs = document.getElementById("downloadMsgs");
|
||||
if (isPop) {
|
||||
if (!Services.io.offline) {
|
||||
if (window.opener.location.href == "chrome://messenger/content/messenger.xul") {
|
||||
downloadMsgs.hidden = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// else hide it
|
||||
downloadMsgs.hidden = true;
|
||||
}
|
||||
|
||||
function setDivTextFromForm(divid, value) {
|
||||
|
||||
// collapse the row if the div has no value
|
||||
var div = document.getElementById(divid);
|
||||
if (!value) {
|
||||
div.setAttribute("collapsed","true");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
div.removeAttribute("collapsed");
|
||||
}
|
||||
|
||||
// otherwise fill in the .text element
|
||||
div = document.getElementById(divid+".text");
|
||||
if (!div) return;
|
||||
|
||||
// set the value
|
||||
div.setAttribute("value", value);
|
||||
}
|
||||
|
||||
function setUserNameDescField(name)
|
||||
{
|
||||
if (name) {
|
||||
var userNameField = document.getElementById("server.username.label");
|
||||
userNameField.setAttribute("value", name);
|
||||
}
|
||||
}
|
||||
212
mailnews/base/prefs/content/aw-identity.js
Normal file
212
mailnews/base/prefs/content/aw-identity.js
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
/* -*- Mode: C++; tab-width: 4; 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/. */
|
||||
|
||||
var gCurrentDomain;
|
||||
var gPrefsBundle;
|
||||
|
||||
function identityPageValidate()
|
||||
{
|
||||
var canAdvance = false;
|
||||
var name = document.getElementById("fullName").value;
|
||||
let email = document.getElementById("email").value.trim();
|
||||
|
||||
if (name && email) {
|
||||
canAdvance = gCurrentDomain ? emailNameIsLegal(email) : emailNameAndDomainAreLegal(email);
|
||||
|
||||
if (gCurrentDomain && canAdvance) {
|
||||
// For prefilled ISP data we must check if the account already exists as
|
||||
// there is no second chance. The email is the username since the user
|
||||
// fills in [______]@example.com.
|
||||
var pageData = parent.GetPageData();
|
||||
var serverType = parent.getCurrentServerType(pageData);
|
||||
var hostName = parent.getCurrentHostname(pageData);
|
||||
var usernameWithDomain = email + "@" + gCurrentDomain;
|
||||
if (parent.AccountExists(email, hostName, serverType) ||
|
||||
parent.AccountExists(usernameWithDomain, hostName, serverType))
|
||||
canAdvance = false;
|
||||
}
|
||||
}
|
||||
|
||||
document.documentElement.canAdvance = canAdvance;
|
||||
}
|
||||
|
||||
function identityPageUnload()
|
||||
{
|
||||
var pageData = parent.GetPageData();
|
||||
var name = document.getElementById("fullName").value;
|
||||
let email = document.getElementById("email").value.trim();
|
||||
setPageData(pageData, "identity", "fullName", name);
|
||||
setPageData(pageData, "identity", "email", email);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// This is for the case when the code appends the domain
|
||||
// unnecessarily.
|
||||
// This simply gets rid of "@domain" from "foo@domain"
|
||||
|
||||
function fixPreFilledEmail()
|
||||
{
|
||||
var emailElement = document.getElementById("email");
|
||||
var email = emailElement.value;
|
||||
var emailArray = email.split('@');
|
||||
|
||||
if (gCurrentDomain) {
|
||||
// check if user entered an @ sign even though we have a domain
|
||||
if (emailArray.length >= 2) {
|
||||
email = emailArray[0];
|
||||
emailElement.value = email;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function checks for common illegal characters.
|
||||
* It shouldn't be too strict, since we do more extensive tests later.
|
||||
*/
|
||||
function emailNameIsLegal(aString)
|
||||
{
|
||||
return aString && !/[^!-?A-~]/.test(aString);
|
||||
}
|
||||
|
||||
function emailNameAndDomainAreLegal(aString)
|
||||
{
|
||||
return /^[!-?A-~]+\@[A-Za-z0-9.-]+$/.test(aString);
|
||||
}
|
||||
|
||||
function identityPageInit()
|
||||
{
|
||||
gCurrentDomain = null;
|
||||
gPrefsBundle = document.getElementById("bundle_prefs");
|
||||
clearEmailTextItems();
|
||||
setEmailDescriptionText();
|
||||
checkForDomain();
|
||||
checkForFullName();
|
||||
checkForEmail();
|
||||
fixPreFilledEmail();
|
||||
identityPageValidate();
|
||||
}
|
||||
|
||||
function clearEmailTextItems()
|
||||
{
|
||||
var emailDescText = document.getElementById("emailDescText");
|
||||
|
||||
if (emailDescText.hasChildNodes())
|
||||
emailDescText.firstChild.remove();
|
||||
|
||||
var postEmailText = document.getElementById("postEmailText");
|
||||
postEmailText.setAttribute("value", "");
|
||||
postEmailText.hidden = true;
|
||||
}
|
||||
|
||||
// Use email example data that ISP has provided. ISP data, if avaialble
|
||||
// for the choice user has made, will be read into CurrentAccountData.
|
||||
// Default example data from properties will be used when the info is missing.
|
||||
function setEmailDescriptionText()
|
||||
{
|
||||
var emailDescText = document.getElementById("emailDescText");
|
||||
var emailFieldLabel = document.getElementById("emailFieldLabel");
|
||||
var currentAccountData = parent.gCurrentAccountData;
|
||||
|
||||
var displayText = null;
|
||||
var emailFieldLabelData = null;
|
||||
var setDefaultEmailDescStrings = true;
|
||||
|
||||
// Set the default field label
|
||||
emailFieldLabel.setAttribute("value", gPrefsBundle.getString("emailFieldText"));
|
||||
|
||||
// Get values for customized data from current account
|
||||
if (currentAccountData)
|
||||
{
|
||||
var emailProvider = currentAccountData.emailProviderName;
|
||||
var sampleEmail = currentAccountData.sampleEmail;
|
||||
var sampleUserName = currentAccountData.sampleUserName;
|
||||
var emailIDDesc = currentAccountData.emailIDDescription;
|
||||
var emailIDTitle = currentAccountData.emailIDFieldTitle;
|
||||
|
||||
if (emailProvider &&
|
||||
sampleEmail &&
|
||||
sampleUserName &&
|
||||
emailIDDesc &&
|
||||
emailIDTitle)
|
||||
{
|
||||
// Get email description data
|
||||
displayText = gPrefsBundle.getFormattedString("customizedEmailText",
|
||||
[emailProvider,
|
||||
emailIDDesc,
|
||||
sampleEmail,
|
||||
sampleUserName]);
|
||||
|
||||
// Set emailfield label
|
||||
emailFieldLabelData = emailIDTitle;
|
||||
emailFieldLabel.setAttribute("value", emailFieldLabelData);
|
||||
|
||||
// Need to display customized data. Turn off default settings.
|
||||
setDefaultEmailDescStrings = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (setDefaultEmailDescStrings)
|
||||
{
|
||||
// Check for obtained values and set with default values if needed
|
||||
var username = gPrefsBundle.getString("exampleEmailUserName");
|
||||
var domain = gPrefsBundle.getString("exampleEmailDomain");
|
||||
|
||||
displayText = gPrefsBundle.getFormattedString("defaultEmailText",
|
||||
[username, domain]);
|
||||
}
|
||||
|
||||
// Create a text nodes with text to be displayed
|
||||
var emailDescTextNode = document.createTextNode(displayText);
|
||||
|
||||
// Display the dynamically generated text for email description
|
||||
emailDescText.appendChild(emailDescTextNode);
|
||||
}
|
||||
|
||||
// retrieve the current domain from the parent wizard window,
|
||||
// and update the UI to add the @domain static text
|
||||
function checkForDomain()
|
||||
{
|
||||
var accountData = parent.gCurrentAccountData;
|
||||
if (!accountData || !accountData.domain)
|
||||
return;
|
||||
|
||||
// save in global variable
|
||||
gCurrentDomain = accountData.domain;
|
||||
var postEmailText = document.getElementById("postEmailText");
|
||||
postEmailText.setAttribute("value", "@" + gCurrentDomain);
|
||||
postEmailText.hidden = false;
|
||||
}
|
||||
|
||||
function checkForFullName() {
|
||||
var name = document.getElementById("fullName");
|
||||
if (name.value=="") {
|
||||
try {
|
||||
var userInfo = Components.classes["@mozilla.org/userinfo;1"].getService(Components.interfaces.nsIUserInfo);
|
||||
name.value = userInfo.fullname;
|
||||
}
|
||||
catch (ex) {
|
||||
// dump ("checkForFullName failed: " + ex + "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkForEmail()
|
||||
{
|
||||
var email = document.getElementById("email");
|
||||
var pageData = parent.GetPageData();
|
||||
if (pageData && pageData.identity && pageData.identity.email) {
|
||||
email.value = pageData.identity.email.value;
|
||||
}
|
||||
if (email.value=="") {
|
||||
try {
|
||||
var userInfo = Components.classes["@mozilla.org/userinfo;1"].getService(Components.interfaces.nsIUserInfo);
|
||||
email.value = userInfo.emailAddress;
|
||||
}
|
||||
catch (ex) {
|
||||
// dump ("checkForEmail failed: " + ex + "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
176
mailnews/base/prefs/content/aw-incoming.js
Normal file
176
mailnews/base/prefs/content/aw-incoming.js
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
/* -*- Mode: C++; 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/. */
|
||||
|
||||
Components.utils.import("resource:///modules/hostnameUtils.jsm");
|
||||
|
||||
var gOnMailServersPage;
|
||||
var gOnNewsServerPage;
|
||||
var gHideIncoming;
|
||||
var gProtocolInfo = null;
|
||||
|
||||
function incomingPageValidate()
|
||||
{
|
||||
var canAdvance = true;
|
||||
var hostName;
|
||||
|
||||
if (gOnMailServersPage) {
|
||||
hostName = document.getElementById("incomingServer").value;
|
||||
if (!gHideIncoming && !isLegalHostNameOrIP(cleanUpHostName(hostName)))
|
||||
canAdvance = false;
|
||||
}
|
||||
if (gOnNewsServerPage) {
|
||||
hostName = document.getElementById("newsServer").value;
|
||||
if (!isLegalHostNameOrIP(cleanUpHostName(hostName)))
|
||||
canAdvance = false;
|
||||
}
|
||||
|
||||
if (canAdvance) {
|
||||
var pageData = parent.GetPageData();
|
||||
var serverType = parent.getCurrentServerType(pageData);
|
||||
var username = document.getElementById("username").value;
|
||||
if (gProtocolInfo && gProtocolInfo.requiresUsername && !username ||
|
||||
parent.AccountExists(username, hostName, serverType))
|
||||
canAdvance = false;
|
||||
}
|
||||
|
||||
document.documentElement.canAdvance = canAdvance;
|
||||
}
|
||||
|
||||
function incomingPageUnload()
|
||||
{
|
||||
var pageData = parent.GetPageData();
|
||||
|
||||
if (gOnMailServersPage) {
|
||||
// If we have hidden the incoming server dialogs, we don't want
|
||||
// to set the server to an empty value here
|
||||
if (!gHideIncoming) {
|
||||
var incomingServerName = document.getElementById("incomingServer");
|
||||
setPageData(pageData, "server", "hostname", cleanUpHostName(incomingServerName.value));
|
||||
}
|
||||
var serverport = document.getElementById("serverPort").value;
|
||||
setPageData(pageData, "server", "port", serverport);
|
||||
var username = document.getElementById("username").value;
|
||||
setPageData(pageData, "login", "username", username);
|
||||
}
|
||||
else if (gOnNewsServerPage) {
|
||||
var newsServerName = document.getElementById("newsServer");
|
||||
setPageData(pageData, "newsserver", "hostname", cleanUpHostName(newsServerName.value));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function incomingPageInit() {
|
||||
gOnMailServersPage = (document.documentElement.currentPage.id == "incomingpage");
|
||||
gOnNewsServerPage = (document.documentElement.currentPage.id == "newsserver");
|
||||
if (gOnNewsServerPage)
|
||||
{
|
||||
var newsServer = document.getElementById("newsServer");
|
||||
var pageData = parent.GetPageData();
|
||||
try
|
||||
{
|
||||
newsServer.value = pageData.newsserver.hostname.value;
|
||||
}
|
||||
catch (ex){}
|
||||
}
|
||||
|
||||
gHideIncoming = false;
|
||||
if (gCurrentAccountData && gCurrentAccountData.wizardHideIncoming)
|
||||
gHideIncoming = true;
|
||||
|
||||
var incomingServerbox = document.getElementById("incomingServerbox");
|
||||
var serverTypeBox = document.getElementById("serverTypeBox");
|
||||
if (incomingServerbox && serverTypeBox) {
|
||||
if (gHideIncoming) {
|
||||
incomingServerbox.setAttribute("hidden", "true");
|
||||
serverTypeBox.setAttribute("hidden", "true");
|
||||
}
|
||||
else {
|
||||
incomingServerbox.removeAttribute("hidden");
|
||||
serverTypeBox.removeAttribute("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
// Server type selection (pop3 or imap) is for mail accounts only
|
||||
var pageData = parent.GetPageData();
|
||||
var isMailAccount = pageData.accounttype.mailaccount.value;
|
||||
var isOtherAccount = pageData.accounttype.otheraccount.value;
|
||||
if (isMailAccount && !gHideIncoming) {
|
||||
var serverTypeRadioGroup = document.getElementById("servertype");
|
||||
/*
|
||||
* Check to see if the radiogroup has any value. If there is no
|
||||
* value, this must be the first time user visting this page in the
|
||||
* account setup process. So, the default is set to pop3. If there
|
||||
* is a value (it's used automatically), user has already visited
|
||||
* page and server type selection is done. Once user visits the page,
|
||||
* the server type value from then on will persist (whether the selection
|
||||
* came from the default or the user action).
|
||||
*/
|
||||
if (!serverTypeRadioGroup.value) {
|
||||
/*
|
||||
* if server type was set to imap in isp data, then
|
||||
* we preset the server type radio group accordingly,
|
||||
* otherwise, use pop3 as the default.
|
||||
*/
|
||||
var serverTypeRadioItem = document.getElementById(pageData.server &&
|
||||
pageData.server.servertype && pageData.server.servertype.value == "imap" ?
|
||||
"imap" : "pop3");
|
||||
serverTypeRadioGroup.selectedItem = serverTypeRadioItem; // Set pop3 server type as default selection
|
||||
}
|
||||
var leaveMessages = document.getElementById("leaveMessagesOnServer");
|
||||
var deferStorage = document.getElementById("deferStorage");
|
||||
setServerType();
|
||||
setServerPrefs(leaveMessages);
|
||||
setServerPrefs(deferStorage);
|
||||
}
|
||||
else if (isOtherAccount) {
|
||||
document.getElementById("deferStorageBox").hidden = true;
|
||||
}
|
||||
|
||||
if (pageData.server && pageData.server.hostname) {
|
||||
var incomingServerTextBox = document.getElementById("incomingServer");
|
||||
if (incomingServerTextBox && incomingServerTextBox.value == "")
|
||||
incomingServerTextBox.value = pageData.server.hostname.value;
|
||||
}
|
||||
|
||||
// pageData.server is not a real nsMsgIncomingServer so it does not have
|
||||
// protocolInfo property implemented.
|
||||
let type = parent.getCurrentServerType(pageData);
|
||||
gProtocolInfo = Components.classes["@mozilla.org/messenger/protocol/info;1?type=" + type]
|
||||
.getService(Components.interfaces.nsIMsgProtocolInfo);
|
||||
var loginNameInput = document.getElementById("username");
|
||||
|
||||
if (loginNameInput.value == "") {
|
||||
if (gProtocolInfo.requiresUsername) {
|
||||
// since we require a username, use the uid from the email address
|
||||
loginNameInput.value = parent.getUsernameFromEmail(pageData.identity.email.value, gCurrentAccountData &&
|
||||
gCurrentAccountData.incomingServerUserNameRequiresDomain);
|
||||
}
|
||||
}
|
||||
incomingPageValidate();
|
||||
}
|
||||
|
||||
function setServerType()
|
||||
{
|
||||
var pageData = parent.GetPageData();
|
||||
var serverType = document.getElementById("servertype").value;
|
||||
var deferStorageBox = document.getElementById("deferStorageBox");
|
||||
var leaveMessages = document.getElementById("leaveMsgsOnSrvrBox");
|
||||
var port = serverType == "pop3" ? 110 : 143;
|
||||
|
||||
document.getElementById("serverPort").value = port;
|
||||
document.getElementById("defaultPortValue").value = port;
|
||||
|
||||
deferStorageBox.hidden = serverType == "imap";
|
||||
leaveMessages.hidden = serverType == "imap";
|
||||
setPageData(pageData, "server", "servertype", serverType);
|
||||
setPageData(pageData, "server", "port", port);
|
||||
incomingPageValidate();
|
||||
}
|
||||
|
||||
function setServerPrefs(aThis)
|
||||
{
|
||||
setPageData(parent.GetPageData(), "server", aThis.id, aThis.checked);
|
||||
}
|
||||
151
mailnews/base/prefs/content/aw-outgoing.js
Normal file
151
mailnews/base/prefs/content/aw-outgoing.js
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
Components.utils.import("resource:///modules/hostnameUtils.jsm");
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
|
||||
var gProtocolInfo = null;
|
||||
var gPrefsBundle;
|
||||
|
||||
function outgoingPageValidate() {
|
||||
let canAdvance = true;
|
||||
|
||||
let smtpServer = document.getElementById("smtphostname").value;
|
||||
let usingDefaultSMTP = document.getElementById("noSmtp").hidden;
|
||||
if (!usingDefaultSMTP && !isLegalHostNameOrIP(cleanUpHostName(smtpServer)))
|
||||
canAdvance = false;
|
||||
|
||||
document.documentElement.canAdvance = canAdvance;
|
||||
}
|
||||
|
||||
function outgoingPageUnload() {
|
||||
var pageData = parent.GetPageData();
|
||||
var username = document.getElementById("username").value;
|
||||
let smtpserver = document.getElementById("smtphostname").value;
|
||||
setPageData(pageData, "server", "smtphostname", cleanUpHostName(smtpserver));
|
||||
|
||||
// If SMTP username box is blank it is because the
|
||||
// incoming and outgoing server names were the same,
|
||||
// so set to be same as incoming username
|
||||
var smtpusername = document.getElementById("smtpusername").value || username;
|
||||
|
||||
setPageData(pageData, "login", "smtpusername", smtpusername);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function outgoingPageInit() {
|
||||
gPrefsBundle = document.getElementById("bundle_prefs");
|
||||
var pageData = parent.GetPageData();
|
||||
|
||||
var smtpServer = null;
|
||||
var smtpCreateNewServer = gCurrentAccountData && gCurrentAccountData.smtpCreateNewServer;
|
||||
|
||||
// Don't use the default smtp server if smtp server creation was explicitly
|
||||
// requested in isp rdf.
|
||||
// If we're reusing the default smtp we should not set the smtp hostname.
|
||||
if (MailServices.smtp.defaultServer && !smtpCreateNewServer) {
|
||||
smtpServer = MailServices.smtp.defaultServer;
|
||||
setPageData(pageData, "identity", "smtpServerKey", "");
|
||||
}
|
||||
|
||||
var noSmtpBox = document.getElementById("noSmtp");
|
||||
var haveSmtpBox = document.getElementById("haveSmtp");
|
||||
|
||||
var boxToHide;
|
||||
var boxToShow;
|
||||
|
||||
if (pageData.server && pageData.server.smtphostname && smtpCreateNewServer) {
|
||||
var smtpTextBox = document.getElementById("smtphostname");
|
||||
if (smtpTextBox && smtpTextBox.value == "")
|
||||
smtpTextBox.value = pageData.server.smtphostname.value;
|
||||
}
|
||||
|
||||
if (smtpServer && smtpServer.hostname) {
|
||||
// we have a hostname, so modify and show the static text and
|
||||
// store the value of the default smtp server in the textbox.
|
||||
modifyStaticText(smtpServer.hostname, "1")
|
||||
boxToShow = haveSmtpBox;
|
||||
boxToHide = noSmtpBox;
|
||||
}
|
||||
else {
|
||||
// no default hostname yet
|
||||
boxToShow = noSmtpBox;
|
||||
boxToHide = haveSmtpBox;
|
||||
}
|
||||
|
||||
if (boxToHide)
|
||||
boxToHide.setAttribute("hidden", "true");
|
||||
|
||||
if (boxToShow)
|
||||
boxToShow.removeAttribute("hidden");
|
||||
|
||||
var smtpNameInput = document.getElementById("smtpusername");
|
||||
smtpServer = MailServices.smtp.defaultServer;
|
||||
if (smtpServer && smtpServer.hostname && smtpServer.username) {
|
||||
// we have a default SMTP server, so modify and show the static text
|
||||
// and store the username for the default server in the textbox.
|
||||
modifyStaticText(smtpServer.username, "2")
|
||||
hideShowLoginSettings(2, 1, 3);
|
||||
smtpNameInput.value = smtpServer.username;
|
||||
}
|
||||
else {
|
||||
// no default SMTP server yet, so need to compare
|
||||
// incoming and outgoing server names
|
||||
var smtpServerName = pageData.server.smtphostname.value;
|
||||
var incomingServerName = pageData.server.hostname.value;
|
||||
if (smtpServerName == incomingServerName) {
|
||||
// incoming and outgoing server names are the same, so show
|
||||
// the static text and make sure textbox blank for later tests.
|
||||
modifyStaticText(smtpServerName, "3")
|
||||
hideShowLoginSettings(3, 1, 2);
|
||||
smtpNameInput.value = "";
|
||||
}
|
||||
else {
|
||||
// incoming and outgoing server names are different, so set smtp
|
||||
// username's textbox to be the same as incoming's one, unless already set.
|
||||
hideShowLoginSettings(1, 2, 3);
|
||||
smtpNameInput.value = smtpNameInput.value || loginNameInput.value;
|
||||
}
|
||||
}
|
||||
outgoingPageValidate();
|
||||
}
|
||||
|
||||
function modifyStaticText(smtpMod, smtpBox)
|
||||
{
|
||||
// modify the value in the smtp display if we already have a
|
||||
// smtp server so that the single string displays the hostname
|
||||
// or username for the smtp server.
|
||||
var smtpStatic = document.getElementById("smtpStaticText"+smtpBox);
|
||||
if (smtpStatic && smtpStatic.hasChildNodes())
|
||||
smtpStatic.childNodes[0].nodeValue = smtpStatic.getAttribute("prefix") +
|
||||
smtpMod + smtpStatic.getAttribute("suffix");
|
||||
}
|
||||
|
||||
function hideShowLoginSettings(aEle, bEle, cEle)
|
||||
{
|
||||
document.getElementById("loginSet" + aEle).hidden = false;
|
||||
document.getElementById("loginSet" + bEle).hidden = true;
|
||||
document.getElementById("loginSet" + cEle).hidden = true;
|
||||
}
|
||||
|
||||
var savedPassword="";
|
||||
|
||||
function onSavePassword(target) {
|
||||
dump("savePassword changed! (" + target.checked + ")\n");
|
||||
var passwordField = document.getElementById("server.password");
|
||||
if (!passwordField) return;
|
||||
|
||||
if (target.checked) {
|
||||
passwordField.removeAttribute("disabled");
|
||||
passwordField.value = savedPassword;
|
||||
}
|
||||
else {
|
||||
passwordField.setAttribute("disabled", "true");
|
||||
savedPassword = passwordField.value;
|
||||
passwordField.value = "";
|
||||
}
|
||||
|
||||
}
|
||||
166
mailnews/base/prefs/content/ispUtils.js
Normal file
166
mailnews/base/prefs/content/ispUtils.js
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
/* -*- Mode: Java; 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/. */
|
||||
|
||||
// using the rdf service extensively here
|
||||
var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService);
|
||||
|
||||
// all the RDF resources we'll be retrieving
|
||||
var NC = "http://home.netscape.com/NC-rdf#";
|
||||
var Server = rdf.GetResource(NC + "Server");
|
||||
var SmtpServer = rdf.GetResource(NC + "SmtpServer");
|
||||
var ServerHost = rdf.GetResource(NC + "ServerHost");
|
||||
var ServerType = rdf.GetResource(NC + "ServerType");
|
||||
var PrefixIsUsername = rdf.GetResource(NC + "PrefixIsUsername");
|
||||
var UseAuthenticatedSmtp= rdf.GetResource(NC + "UseAuthenticatedSmtp");
|
||||
|
||||
// this is possibly expensive, not sure what to do here
|
||||
var ispDefaults;
|
||||
|
||||
var nsIRDFResource = Components.interfaces.nsIRDFResource;
|
||||
var nsIRDFLiteral = Components.interfaces.nsIRDFLiteral;
|
||||
|
||||
var ispRoot = rdf.GetResource("NC:ispinfo");
|
||||
|
||||
// given an ISP's domain URI, look up all relevant information about it
|
||||
function getIspDefaultsForUri(domainURI)
|
||||
{
|
||||
if (!ispDefaults)
|
||||
ispDefaults = rdf.GetDataSource("rdf:ispdefaults");
|
||||
|
||||
var domainRes = rdf.GetResource(domainURI);
|
||||
|
||||
var result = dataSourceToObject(ispDefaults, domainRes);
|
||||
|
||||
if (!result) return null;
|
||||
|
||||
// The domainURI should be in the format domain:example.com. (Where
|
||||
// example.com is the domain name to use for all email addresses). If
|
||||
// it does not match this pattern, then it is possible no domain
|
||||
// has been specified, so we should leave it uninitialized.
|
||||
if (domainURI.startsWith("domain:")) {
|
||||
// add this extra attribute which is the domain itself
|
||||
var domainData = domainURI.split(':');
|
||||
if (domainData.length > 1) {
|
||||
// To faciltate distributing two different account types for one ISP,
|
||||
// it's possible to add parameters to the domain URI
|
||||
// - e.g. domain:example.com?type=imap.
|
||||
// This is necessary so RDF doesn't think they're the same.
|
||||
|
||||
// Save the domain, but only the part up to the (possible) question mark.
|
||||
result.domain = domainData[1].replace(/\?.*/, "");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// construct an ISP's domain URI based on it's domain
|
||||
// (i.e. turns example.com -> domain:example.com)
|
||||
function getIspDefaultsForDomain(domain) {
|
||||
let domainURI = "domain:" + domain;
|
||||
return getIspDefaultsForUri(domainURI);
|
||||
}
|
||||
|
||||
// Given an email address (like "joe@example.com") look up
|
||||
function getIspDefaultsForEmail(email) {
|
||||
|
||||
var emailData = getEmailInfo(email);
|
||||
|
||||
var ispData = null;
|
||||
if (emailData)
|
||||
ispData = getIspDefaultsForDomain(emailData.domain);
|
||||
|
||||
prefillIspData(ispData, email);
|
||||
|
||||
return ispData;
|
||||
}
|
||||
|
||||
// given an email address, split it into username and domain
|
||||
// return in an associative array
|
||||
function getEmailInfo(email) {
|
||||
if (!email) return null;
|
||||
|
||||
var result = new Object;
|
||||
|
||||
var emailData = email.split('@');
|
||||
|
||||
if (emailData.length != 2) {
|
||||
dump("bad e-mail address!\n");
|
||||
return null;
|
||||
}
|
||||
|
||||
// all the variables we'll be returning
|
||||
result.username = emailData[0];
|
||||
result.domain = emailData[1];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function prefillIspData(ispData, email, fullName) {
|
||||
if (!ispData) return;
|
||||
|
||||
// make sure these objects exist
|
||||
if (!ispData.identity) ispData.identity = new Object;
|
||||
if (!ispData.incomingServer) ispData.incomingServer = new Object;
|
||||
|
||||
// fill in e-mail if it's not already there
|
||||
if (email && !ispData.identity.email)
|
||||
ispData.identity.email = email;
|
||||
|
||||
var emailData = getEmailInfo(email);
|
||||
if (emailData) {
|
||||
|
||||
// fill in the username (assuming the ISP doesn't prevent it)
|
||||
if (!ispData.incomingServer.userName &&
|
||||
!ispData.incomingServer.noDefaultUsername)
|
||||
ispData.incomingServer.username = emailData.username;
|
||||
}
|
||||
}
|
||||
|
||||
// this function will extract an entire datasource into a giant
|
||||
// associative array for easy retrieval from JS
|
||||
var NClength = NC.length;
|
||||
function dataSourceToObject(datasource, root)
|
||||
{
|
||||
var result = null;
|
||||
var arcs = datasource.ArcLabelsOut(root);
|
||||
|
||||
while (arcs.hasMoreElements()) {
|
||||
var arc = arcs.getNext().QueryInterface(nsIRDFResource);
|
||||
|
||||
var arcName = arc.Value;
|
||||
arcName = arcName.substring(NClength, arcName.length);
|
||||
|
||||
if (!result) result = new Object;
|
||||
|
||||
var target = datasource.GetTarget(root, arc, true);
|
||||
|
||||
var value;
|
||||
var targetHasChildren = false;
|
||||
try {
|
||||
target = target.QueryInterface(nsIRDFResource);
|
||||
targetHasChildren = true;
|
||||
} catch (ex) {
|
||||
target = target.QueryInterface(nsIRDFLiteral);
|
||||
}
|
||||
|
||||
if (targetHasChildren)
|
||||
value = dataSourceToObject(datasource, target);
|
||||
else {
|
||||
value = target.Value;
|
||||
|
||||
// fixup booleans/numbers/etc
|
||||
if (value == "true") value = true;
|
||||
else if (value == "false") value = false;
|
||||
else {
|
||||
var num = Number(value);
|
||||
if (!isNaN(num)) value = num;
|
||||
}
|
||||
}
|
||||
|
||||
// add this value
|
||||
result[arcName] = value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
156
mailnews/base/prefs/content/removeAccount.js
Normal file
156
mailnews/base/prefs/content/removeAccount.js
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var gServer;
|
||||
var gDialog;
|
||||
|
||||
function onLoad(event) {
|
||||
gServer = window.arguments[0].account.incomingServer;
|
||||
gDialog = document.documentElement;
|
||||
|
||||
let bundle = document.getElementById("bundle_removeAccount");
|
||||
let removeQuestion = bundle.getFormattedString("removeQuestion",
|
||||
[gServer.prettyName]);
|
||||
document.getElementById("accountName").textContent = removeQuestion;
|
||||
|
||||
// Allow to remove account data if it has a local storage.
|
||||
let localDirectory = gServer.localPath;
|
||||
if (localDirectory && localDirectory.exists()) {
|
||||
localDirectory.normalize();
|
||||
|
||||
// Do not allow removal if localPath is outside of profile folder.
|
||||
let profilePath = Services.dirsvc.get("ProfD", Components.interfaces.nsIFile);
|
||||
profilePath.normalize();
|
||||
|
||||
// TODO: bug 77652, decide what to do for deferred accounts.
|
||||
// And inform the user if the account localPath is outside the profile.
|
||||
if ((gServer.isDeferredTo ||
|
||||
(gServer instanceof Components.interfaces.nsIPop3IncomingServer &&
|
||||
gServer.deferredToAccount)) ||
|
||||
!profilePath.contains(localDirectory)) {
|
||||
document.getElementById("removeData").disabled = true;
|
||||
}
|
||||
} else {
|
||||
document.getElementById("removeDataPossibility").collapsed = true;
|
||||
}
|
||||
|
||||
if (gServer.type == "im") {
|
||||
let dataCheckbox = document.getElementById("removeData");
|
||||
dataCheckbox.label = dataCheckbox.getAttribute("labelChat");
|
||||
dataCheckbox.accessKey = dataCheckbox.getAttribute("accesskeyChat");
|
||||
}
|
||||
|
||||
enableRemove();
|
||||
window.sizeToContent();
|
||||
}
|
||||
|
||||
function enableRemove() {
|
||||
gDialog.getButton("accept").disabled =
|
||||
(!document.getElementById("removeAccount").checked &&
|
||||
!document.getElementById("removeData").checked);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the local directory.
|
||||
*/
|
||||
function openLocalDirectory() {
|
||||
let nsLocalFile = Components.Constructor("@mozilla.org/file/local;1",
|
||||
"nsILocalFile", "initWithPath");
|
||||
let localDir = gServer.localPath.path;
|
||||
try {
|
||||
new nsLocalFile(localDir).reveal();
|
||||
} catch(e) {
|
||||
// Reveal may fail e.g. on Linux, then just show the path as a string.
|
||||
document.getElementById("localDirectory").value = localDir;
|
||||
document.getElementById("localDirectory").collapsed = false;
|
||||
}
|
||||
}
|
||||
|
||||
function showInfo() {
|
||||
let descs = document.querySelectorAll("vbox.indent");
|
||||
for (let desc of descs) {
|
||||
desc.collapsed = false;
|
||||
}
|
||||
|
||||
// TODO: bug 1238271, this should use showFor attributes if possible.
|
||||
if (gServer.type == "imap" || gServer.type == "nntp") {
|
||||
document.getElementById("serverAccount").collapsed = false;
|
||||
} else if (gServer.type == "im") {
|
||||
document.getElementById("chatAccount").collapsed = false;
|
||||
} else {
|
||||
document.getElementById("localAccount").collapsed = false;
|
||||
}
|
||||
|
||||
window.sizeToContent();
|
||||
gDialog.getButton("disclosure").disabled = true;
|
||||
gDialog.getButton("disclosure").blur();
|
||||
}
|
||||
|
||||
function removeAccount() {
|
||||
let removeAccount = document.getElementById("removeAccount").checked;
|
||||
let removeData = document.getElementById("removeData").checked;
|
||||
try {
|
||||
// Remove the requested account data.
|
||||
if (removeAccount) {
|
||||
// Remove account
|
||||
// Need to save these before the account and its server is removed.
|
||||
let serverUri = gServer.type + "://" + gServer.hostName;
|
||||
let serverUsername = gServer.username;
|
||||
|
||||
MailServices.accounts.removeAccount(window.arguments[0].account, removeData);
|
||||
window.arguments[0].result = true;
|
||||
|
||||
// Remove password information.
|
||||
let logins = Services.logins.findLogins({}, serverUri, null, serverUri);
|
||||
for (let i = 0; i < logins.length; i++) {
|
||||
if (logins[i].username == serverUsername) {
|
||||
Services.logins.removeLogin(logins[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (removeData) {
|
||||
// Remove files only.
|
||||
// TODO: bug 1302193
|
||||
window.arguments[0].result = false;
|
||||
}
|
||||
|
||||
document.getElementById("status").selectedPanel =
|
||||
document.getElementById("success");
|
||||
} catch (ex) {
|
||||
document.getElementById("status").selectedPanel =
|
||||
document.getElementById("failure");
|
||||
Components.utils.reportError("Failure to remove account: " + ex);
|
||||
window.arguments[0].result = false;
|
||||
}
|
||||
}
|
||||
|
||||
function onAccept() {
|
||||
// If Cancel is disabled, we already tried to remove the account
|
||||
// and can only close the dialog.
|
||||
if (gDialog.getButton("cancel").disabled)
|
||||
return true;
|
||||
|
||||
gDialog.getButton("accept").disabled = true;
|
||||
gDialog.getButton("cancel").disabled = true;
|
||||
gDialog.getButton("disclosure").disabled = true;
|
||||
|
||||
// Change the "Remove" to an "OK" button by clearing the custom label.
|
||||
gDialog.removeAttribute("buttonlabelaccept");
|
||||
gDialog.removeAttribute("buttonaccesskeyaccept");
|
||||
gDialog.getButton("accept").removeAttribute("label");
|
||||
gDialog.getButton("accept").removeAttribute("accesskey");
|
||||
gDialog.buttons = "accept";
|
||||
|
||||
document.getElementById("infoPane").selectedIndex = 1;
|
||||
window.sizeToContent();
|
||||
|
||||
removeAccount();
|
||||
|
||||
gDialog.getButton("accept").disabled = false;
|
||||
return false;
|
||||
}
|
||||
87
mailnews/base/prefs/content/removeAccount.xul
Normal file
87
mailnews/base/prefs/content/removeAccount.xul
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://messenger/skin/messenger.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://messenger/skin/dialogs.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE dialog [
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
|
||||
%brandDTD;
|
||||
<!ENTITY % removalDTD SYSTEM "chrome://messenger/locale/removeAccount.dtd">
|
||||
%removalDTD;
|
||||
]>
|
||||
|
||||
<dialog id="removeAccountDialog"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&dialogTitle;"
|
||||
width="600"
|
||||
buttons="accept,disclosure,cancel"
|
||||
buttonlabelaccept="&removeButton.label;"
|
||||
buttonaccesskeyaccept="&removeButton.accesskey;"
|
||||
defaultButton="cancel"
|
||||
onload="onLoad();"
|
||||
ondialogdisclosure="showInfo();"
|
||||
ondialogaccept="return onAccept();">
|
||||
<stringbundle id="bundle_removeAccount"
|
||||
src="chrome://messenger/locale/removeAccount.properties"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/removeAccount.js"/>
|
||||
<deck id="infoPane">
|
||||
<vbox flex="1">
|
||||
<label id="accountName"></label>
|
||||
<separator class="thin"/>
|
||||
<checkbox id="removeAccount"
|
||||
label="&removeAccount.label;"
|
||||
checked="true"
|
||||
disabled="true"
|
||||
accesskey="&removeAccount.accesskey;"
|
||||
oncommand="enableRemove();"/>
|
||||
<vbox class="indent" collapsed="true">
|
||||
<description>
|
||||
&removeAccount.desc;
|
||||
</description>
|
||||
</vbox>
|
||||
<vbox id="removeDataPossibility" collapsed="false">
|
||||
<checkbox id="removeData"
|
||||
label="&removeData.label;"
|
||||
labelChat="&removeData.label;"
|
||||
checked="false"
|
||||
accesskey="&removeData.accesskey;"
|
||||
accesskeyChat="&removeData.accesskey;"
|
||||
oncommand="enableRemove();"/>
|
||||
<vbox class="indent" collapsed="true">
|
||||
<description id="localAccount" collapsed="true">
|
||||
&removeDataLocalAccount.desc;
|
||||
</description>
|
||||
<description id="serverAccount" collapsed="true">
|
||||
&removeDataServerAccount.desc;
|
||||
</description>
|
||||
<description id="chatAccount" collapsed="true">
|
||||
&removeDataLocalAccount.desc;
|
||||
</description>
|
||||
<hbox align="center">
|
||||
<button id="showLocalDirectory"
|
||||
label="&showData.label;"
|
||||
accesskey="&showData.accesskey;"
|
||||
oncommand="openLocalDirectory();"/>
|
||||
<label id="localDirectory" collapsed="true"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</vbox>
|
||||
</vbox>
|
||||
<vbox align="center">
|
||||
<spacer flex="1"/>
|
||||
<deck id="status">
|
||||
<vbox align="center">
|
||||
<label>&progressPending;</label>
|
||||
<progressmeter mode="undetermined"/>
|
||||
</vbox>
|
||||
<label id="success">&progressSuccess;</label>
|
||||
<label id="failure">&progressFailure;</label>
|
||||
</deck>
|
||||
<spacer flex="1"/>
|
||||
</vbox>
|
||||
</deck>
|
||||
</dialog>
|
||||
182
mailnews/base/prefs/content/smtpEditOverlay.js
Normal file
182
mailnews/base/prefs/content/smtpEditOverlay.js
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
/* -*- Mode: Java; 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/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
|
||||
// be real hacky with document.getElementById until document.controls works
|
||||
// with the new XUL widgets
|
||||
|
||||
var gSmtpUsername;
|
||||
var gSmtpDescription;
|
||||
var gSmtpUsernameLabel;
|
||||
var gSmtpHostname;
|
||||
var gSmtpPort;
|
||||
var gSmtpAuthMethod;
|
||||
var gSmtpSocketType;
|
||||
var gPort;
|
||||
var gDefaultPort;
|
||||
var Ci = Components.interfaces;
|
||||
|
||||
function initSmtpSettings(server) {
|
||||
gSmtpUsername = document.getElementById("smtp.username");
|
||||
gSmtpDescription = document.getElementById("smtp.description");
|
||||
gSmtpUsernameLabel = document.getElementById("smtp.username.label");
|
||||
gSmtpHostname = document.getElementById("smtp.hostname");
|
||||
gSmtpPort = document.getElementById("smtp.port");
|
||||
gSmtpAuthMethod = document.getElementById("smtp.authMethod");
|
||||
gSmtpSocketType = document.getElementById("smtp.socketType");
|
||||
gDefaultPort = document.getElementById("smtp.defaultPort");
|
||||
gPort = document.getElementById("smtp.port");
|
||||
|
||||
if (server) {
|
||||
gSmtpHostname.value = server.hostname;
|
||||
gSmtpDescription.value = server.description;
|
||||
gSmtpPort.value = server.port;
|
||||
gSmtpUsername.value = server.username;
|
||||
gSmtpAuthMethod.value = server.authMethod;
|
||||
gSmtpSocketType.value = (server.socketType < 4) ? server.socketType : 1;
|
||||
} else {
|
||||
// New server, load default values.
|
||||
gSmtpAuthMethod.value = Services.prefs.getIntPref("mail.smtpserver.default.authMethod");
|
||||
gSmtpSocketType.value = Services.prefs.getIntPref("mail.smtpserver.default.try_ssl");
|
||||
}
|
||||
|
||||
// Although sslChanged will set a label for cleartext password,
|
||||
// we need to use the long label so that we can size the dialog.
|
||||
setLabelFromStringBundle("authMethod-no", "authNo");
|
||||
setLabelFromStringBundle("authMethod-password-encrypted",
|
||||
"authPasswordEncrypted");
|
||||
setLabelFromStringBundle("authMethod-password-cleartext",
|
||||
"authPasswordCleartextInsecurely");
|
||||
setLabelFromStringBundle("authMethod-kerberos", "authKerberos");
|
||||
setLabelFromStringBundle("authMethod-ntlm", "authNTLM");
|
||||
setLabelFromStringBundle("authMethod-oauth2", "authOAuth2");
|
||||
setLabelFromStringBundle("authMethod-anysecure", "authAnySecure");
|
||||
setLabelFromStringBundle("authMethod-any", "authAny");
|
||||
|
||||
sizeToContent();
|
||||
|
||||
sslChanged(false);
|
||||
authMethodChanged(false);
|
||||
|
||||
if (MailServices.smtp.defaultServer)
|
||||
onLockPreference();
|
||||
|
||||
// Hide deprecated/hidden auth options, unless selected
|
||||
hideUnlessSelected(document.getElementById("authMethod-anysecure"));
|
||||
hideUnlessSelected(document.getElementById("authMethod-any"));
|
||||
|
||||
// "STARTTLS, if available" is vulnerable to MITM attacks so we shouldn't
|
||||
// allow users to choose it anymore. Hide the option unless the user already
|
||||
// has it set.
|
||||
hideUnlessSelected(document.getElementById("connectionSecurityType-1"));
|
||||
}
|
||||
|
||||
function hideUnlessSelected(element)
|
||||
{
|
||||
element.hidden = !element.selected;
|
||||
}
|
||||
|
||||
function setLabelFromStringBundle(elementID, stringName)
|
||||
{
|
||||
document.getElementById(elementID).label =
|
||||
document.getElementById("bundle_messenger").getString(stringName);
|
||||
}
|
||||
|
||||
// Disables xul elements that have associated preferences locked.
|
||||
function onLockPreference()
|
||||
{
|
||||
try {
|
||||
let allPrefElements = {
|
||||
hostname: gSmtpHostname,
|
||||
description: gSmtpDescription,
|
||||
port: gSmtpPort,
|
||||
authMethod: gSmtpAuthMethod,
|
||||
try_ssl: gSmtpSocketType
|
||||
};
|
||||
disableIfLocked(allPrefElements);
|
||||
} catch (e) { // non-fatal
|
||||
Components.utils.reportError("Error while getting locked prefs: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the work of disabling an element given the array which contains xul id/prefstring pairs.
|
||||
*
|
||||
* @param prefstrArray array of XUL elements to check
|
||||
*
|
||||
* TODO: try to merge this with disableIfLocked function in am-offline.js (bug 755885)
|
||||
*/
|
||||
function disableIfLocked(prefstrArray)
|
||||
{
|
||||
let finalPrefString = "mail.smtpserver." +
|
||||
MailServices.smtp.defaultServer.key + ".";
|
||||
let smtpPrefBranch = Services.prefs.getBranch(finalPrefString);
|
||||
|
||||
for (let prefstring in prefstrArray)
|
||||
if (smtpPrefBranch.prefIsLocked(prefstring))
|
||||
prefstrArray[prefstring].disabled = true;
|
||||
}
|
||||
|
||||
function saveSmtpSettings(server)
|
||||
{
|
||||
//dump("Saving to " + server + "\n");
|
||||
if (server) {
|
||||
server.hostname = cleanUpHostName(gSmtpHostname.value);
|
||||
server.description = gSmtpDescription.value;
|
||||
server.port = gSmtpPort.value;
|
||||
server.authMethod = gSmtpAuthMethod.value;
|
||||
server.username = gSmtpUsername.value;
|
||||
server.socketType = gSmtpSocketType.value;
|
||||
}
|
||||
}
|
||||
|
||||
function authMethodChanged(userAction)
|
||||
{
|
||||
var noUsername = gSmtpAuthMethod.value == Ci.nsMsgAuthMethod.none;
|
||||
gSmtpUsername.disabled = noUsername;
|
||||
gSmtpUsernameLabel.disabled = noUsername;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the default port to SMTP or SMTPS, dependending on
|
||||
* the |gSmtpSocketType| value, and sets the port to use to this default,
|
||||
* if that's appropriate.
|
||||
*
|
||||
* @param userAction false for dialog initialization,
|
||||
* true for user action.
|
||||
*/
|
||||
function sslChanged(userAction)
|
||||
{
|
||||
const DEFAULT_SMTP_PORT = "587";
|
||||
const DEFAULT_SMTPS_PORT = "465";
|
||||
var socketType = gSmtpSocketType.value;
|
||||
var otherDefaultPort;
|
||||
var prevDefaultPort = gDefaultPort.value;
|
||||
|
||||
if (socketType == Ci.nsMsgSocketType.SSL) {
|
||||
gDefaultPort.value = DEFAULT_SMTPS_PORT;
|
||||
otherDefaultPort = DEFAULT_SMTP_PORT;
|
||||
} else {
|
||||
gDefaultPort.value = DEFAULT_SMTP_PORT;
|
||||
otherDefaultPort = DEFAULT_SMTPS_PORT;
|
||||
}
|
||||
|
||||
// If the port is not set,
|
||||
// or the user is causing the default port to change,
|
||||
// and the port is set to the default for the other protocol,
|
||||
// then set the port to the default for the new protocol.
|
||||
if ((gPort.value == 0) ||
|
||||
(userAction && (gDefaultPort.value != prevDefaultPort) &&
|
||||
(gPort.value == otherDefaultPort)))
|
||||
gPort.value = gDefaultPort.value;
|
||||
|
||||
// switch "insecure password" label
|
||||
setLabelFromStringBundle("authMethod-password-cleartext",
|
||||
socketType == Ci.nsMsgSocketType.SSL ||
|
||||
socketType == Ci.nsMsgSocketType.alwaysSTARTTLS ?
|
||||
"authPasswordCleartextViaSSL" : "authPasswordCleartextInsecurely");
|
||||
}
|
||||
124
mailnews/base/prefs/content/smtpEditOverlay.xul
Normal file
124
mailnews/base/prefs/content/smtpEditOverlay.xul
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!-- 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/. -->
|
||||
|
||||
<!DOCTYPE overlay SYSTEM "chrome://messenger/locale/smtpEditOverlay.dtd">
|
||||
|
||||
<overlay xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://messenger/content/smtpEditOverlay.js"/>
|
||||
|
||||
<vbox id="smtpServerEditor">
|
||||
<groupbox>
|
||||
<caption label="&settings.caption;"/>
|
||||
<grid flex="1">
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<label value="&serverDescription.label;"
|
||||
accesskey="&serverDescription.accesskey;"
|
||||
control="smtp.description"/>
|
||||
<textbox id="smtp.description"
|
||||
flex="1"
|
||||
preftype="string"
|
||||
prefstring="mail.smtpserver.%serverkey%.description"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label value="&serverName.label;"
|
||||
accesskey="&serverName.accesskey;"
|
||||
control="smtp.hostname"/>
|
||||
<textbox id="smtp.hostname"
|
||||
flex="1"
|
||||
preftype="string"
|
||||
class="uri-element"
|
||||
prefstring="mail.smtpserver.%serverkey%.hostname"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label value="&serverPort.label;"
|
||||
accesskey="&serverPort.accesskey;"
|
||||
control="smtp.port"/>
|
||||
<hbox align="center">
|
||||
<textbox id="smtp.port"
|
||||
type="number"
|
||||
min="0"
|
||||
max="65535"
|
||||
size="5"
|
||||
preftype="int"
|
||||
prefstring="mail.smtpserver.%serverkey%.port"/>
|
||||
<label value="&serverPortDefault.label;"/>
|
||||
<label id="smtp.defaultPort"/>
|
||||
</hbox>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</groupbox>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<groupbox>
|
||||
<caption label="&security.caption;"/>
|
||||
|
||||
<grid flex="1">
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<label value="&connectionSecurity.label;"
|
||||
accesskey="&connectionSecurity.accesskey;"
|
||||
control="smtp.socketType"/>
|
||||
<menulist id="smtp.socketType" oncommand="sslChanged(true);"
|
||||
prefstring="mail.smtpserver.%serverkey%.try_ssl">
|
||||
<menupopup id="smtp.socketTypePopup">
|
||||
<menuitem value="0" label="&connectionSecurityType-0.label;"/>
|
||||
<menuitem id="connectionSecurityType-1"
|
||||
value="1" label="&connectionSecurityType-1.label;"
|
||||
disabled="true" hidden="true"/>
|
||||
<menuitem value="2" label="&connectionSecurityType-2.label;"/>
|
||||
<menuitem value="3" label="&connectionSecurityType-3.label;"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label value="&authMethod.label;"
|
||||
accesskey="&authMethod.accesskey;"
|
||||
control="server.authMethod"/>
|
||||
<!-- same in am-server.xul/js -->
|
||||
<menulist id="smtp.authMethod"
|
||||
oncommand="authMethodChanged(true);"
|
||||
wsm_persist="true"
|
||||
preftype="int" type="number"
|
||||
prefstring="mail.smtpserver.%serverkey%.authMethod">
|
||||
<menupopup id="smtp.authMethodPopup">
|
||||
<menuitem id="authMethod-no" value="1"/>
|
||||
<menuitem id="authMethod-password-cleartext" value="3"/>
|
||||
<menuitem id="authMethod-password-encrypted" value="4"/>
|
||||
<menuitem id="authMethod-kerberos" value="5"/>
|
||||
<menuitem id="authMethod-ntlm" value="6"/>
|
||||
<menuitem id="authMethod-oauth2" value="10"/>
|
||||
<menuitem id="authMethod-anysecure" value="8"/>
|
||||
<menuitem id="authMethod-any" value="9"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</row>
|
||||
<row id="smtp.username.box" align="center">
|
||||
<label id="smtp.username.label" value="&userName.label;"
|
||||
accesskey="&userName.accesskey;"
|
||||
control="smtp.username"/>
|
||||
<textbox id="smtp.username" flex="1"
|
||||
preftype="string"
|
||||
prefstring="mail.smtpserver.%serverkey%.username"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</groupbox>
|
||||
</vbox>
|
||||
</overlay>
|
||||
Loading…
Add table
Add a link
Reference in a new issue