Fetch mail server config directly from ISP. Bug 534722, r=bwinton, ui-r=clarkbw
authorBen Bucksch <ben.bucksch@beonex.com>
Fri, 19 Mar 2010 22:00:22 +0100
changeset 5210 a03eae58454850ee02dd1a84287f3e61bd44be77
parent 5209 47d93faea82a862c7308eceb3be6efc07f182797
child 5211 895928822eb3ea5a70c6294e71df940f61af84f5
push idunknown
push userunknown
push dateunknown
reviewersbwinton, clarkbw
bugs534722
Fetch mail server config directly from ISP. Bug 534722, r=bwinton, ui-r=clarkbw
mail/locales/en-US/chrome/messenger/accountCreation.properties
mailnews/base/prefs/content/accountcreation/emailWizard.js
mailnews/base/prefs/content/accountcreation/fetchConfig.js
mailnews/base/prefs/content/accountcreation/util.js
--- a/mail/locales/en-US/chrome/messenger/accountCreation.properties
+++ b/mail/locales/en-US/chrome/messenger/accountCreation.properties
@@ -6,23 +6,33 @@ cleartext_warning=%1$S does not use encr
 selfsigned_warning=%1$S does not use a trusted certificate.
 selfsigned_details=Normally, a secure mail server will present a trusted certificate to prove that it is really the server it claims to be. The connection to the mail server will be encrypted but cannot be validated as being the correct server.
 cleartext_details=Insecure mail servers do not use encrypted connections to protect your passwords and private information. By connecting to this server you could expose your password and private information.
 
 # LOCALIZATION NOTE(default_server_tag): Used to indicate the default smtp server in the server dropdown list.
 default_server_tag= (default)
 
 # config titles
-# LOCALIZATION NOTE(looking_up_settings): %1$S will be the brandShortName.
-looking_up_settings=%1$S is looking up the settings for your email account.
-manually_edit_config=Editing Config
-# LOCALIZATION NOTE(found_settings): %1$S will be the brandShortName.
-found_settings=%1$S has found the settings for your email account.
+# LOCALIZATION NOTE(looking_up_settings_disk): Referring to Thunderbird installation folder on user's harddisk
+looking_up_settings_disk=Looking up configuration: Thunderbird installation
+looking_up_settings_isp=Looking up configuration: Email provider
+# LOCALIZATION NOTE(looking_up_settings_db): Do not translate or replace Mozilla. It stands for the public project mozilla.org, not Mozilla Messaging. The database is a generic, public domain facility usable by any client.
+looking_up_settings_db=Looking up configuration: Mozilla ISP database
+# LOCALIZATION NOTE(looking_up_settings_guess): We are checking common server names like pop., pop3., smtp., mail., without knowing whether they exist or really serve this email account. If a server responds, we try to talk to it via POP/IMAP/SMTP protocols and query its capabilities. If that succeeds, we assume we found a configuration. Of course, it may still be wrong, but it often works.
+looking_up_settings_guess=Looking up configuration: Trying common server names
+# LOCALIZATION NOTE(found_settings_disk): Referring to Thunderbird installation folder on user's harddisk
+found_settings_disk=The following settings were found on: Thunderbird installation
+found_settings_isp=The following settings were found from: Email provider
+# LOCALIZATION NOTE(found_settings_db): Do not translate or replace Mozilla. It stands for the public project mozilla.org, not Mozilla Messaging. The database is a generic, public domain facility usable by any client.
+found_settings_db=The following settings were found from: Mozilla ISP database
+# LOCALIZATION NOTE(found_settings_guess): We tried common mail server names and we found a mail server and talked to it and it responded properly, so we think we found a suitable configuration, but we are only about 80% certain that it is the correct setting for this email address. There's a chance that email address may not actually be served by this server and it won't work, or that there is a better server.
+found_settings_guess=The following settings were found by trying common server names
 # LOCALIZATION NOTE(failed_to_find_settings): %1$S will be the brandShortName.
 failed_to_find_settings=%1$S failed to find the settings for your email account.
+manually_edit_config=Editing Config
 
 # config subtitles
 check_preconfig=checking for pre-configuration…
 found_preconfig=found pre-configuration
 checking_config=checking configuration…
 found_config=Found configuration of your account
 checking_mozilla_config=checking Mozilla Community configurations…
 found_isp_config=found a configuration
@@ -40,14 +50,15 @@ password_ok=Password ok!
 user_pass_invalid=Username or password invalid
 check_server_details=Checking server details
 check_in_server_details=Checking incoming server details
 check_out_server_details=Checking outgoing server details
 
 error_creating_account=Error Creating Account
 incoming_server_exists=Incoming server already exists.
 
+# LOCALIZATION NOTE(no_encryption): Neither SSL/TLS nor STARTTLS. Transmission of emails in cleartext over the Internet.
 no_encryption=No encryption
 ssl_tls=SSL/TLS
 starttls=STARTTLS
 
 please_enter_name=Please enter your name.
 double_check_email=Double check this email address!
--- a/mailnews/base/prefs/content/accountcreation/emailWizard.js
+++ b/mailnews/base/prefs/content/accountcreation/emailWizard.js
@@ -411,55 +411,64 @@ EmailConfigWizard.prototype =
     }
     else
       rememberPasswordElt.disabled = false;
   },
 
   findConfig : function(domain, email)
   {
     gEmailWizardLogger.info("findConfig()");
-    this.startSpinner("all", "looking_up_settings");
     if (this._probeAbortable)
     {
       gEmailWizardLogger.info("aborting existing config search");
       this._probeAbortable.cancel();
     }
+    this.startSpinner("all", "looking_up_settings_disk");
     var me = this;
-    this._probeAbortable = 
-      fetchConfigFromDisk(
-        domain,
-        function(config) // success
-        {
-          me.foundConfig(config);
-          me.stopSpinner("found_settings");
-          me._probeAbortable = null;
-        },
-        function(e) // fetchConfigFromDisk failed
-        {
-          gEmailWizardLogger.info("fetchConfigFromDisk failed: " + e);
-          me.startSpinner("all", "looking_up_settings");
-          me._probeAbortable = 
-            fetchConfigFromDB(
-              domain,
+    this._probeAbortable = fetchConfigFromDisk(domain,
+      function(config) // success
+      {
+        me.foundConfig(config);
+        me.stopSpinner("found_settings_disk");
+        me._probeAbortable = null;
+      },
+      function(e) // fetchConfigFromDisk failed
+      {
+        gEmailWizardLogger.info("fetchConfigFromDisk failed: " + e);
+        me.startSpinner("all", "looking_up_settings_isp");
+        me._probeAbortable = fetchConfigFromISP(domain, email,
+          function(config) // success
+          {
+            me.foundConfig(config);
+            me.stopSpinner("found_settings_isp");
+            me.showEditButton();
+            me._probeAbortable = null;
+          },
+          function(e) // fetchConfigFromISP failed
+          {
+            gEmailWizardLogger.info("fetchConfigFromISP failed: " + e);
+            me.startSpinner("all", "looking_up_settings_db");
+            me._probeAbortable = fetchConfigFromDB(domain,
               function(config) // success
               {
                 me.foundConfig(config);
-                me.stopSpinner("found_settings");
+                me.stopSpinner("found_settings_db");
                 me.showEditButton();
                 me._probeAbortable = null;
               },
               function(e) // fetchConfigFromDB failed
               {
                 gEmailWizardLogger.info("fetchConfigFromDB failed: " + e);
                 var initialConfig = new AccountConfig();
                 me._prefillConfig(initialConfig);
-                me.startSpinner("all", "looking_up_settings")
-                me._guessConfig(domain, initialConfig, 'both');
+                me.startSpinner("all", "looking_up_settings_guess")
+                me._guessConfig(domain, initialConfig, "both");
               });
           });
+      });
   },
 
   _guessConfig : function(domain, initialConfig, which)
   {
     let me = this;
     // guessConfig takes several callback functions, which we define inline.
     me._probeAbortable = guessConfig(domain,
           function(type, hostname, port, ssl, done, config) // progress
@@ -486,34 +495,34 @@ EmailConfigWizard.prototype =
           function(config) // success
           {
             me.foundConfig(config);
             gEmailWizardLogger.info("in success, incomingState = " +
                                     me._incomingState + " outgoingState = " +
                                     me._outgoingState);
             if (me._incomingState == 'done' && me._outgoingState == 'done')
             {
-              me.stopSpinner("found_settings");
+              me.stopSpinner("found_settings_guess");
               _hide("stop_button");
               _show("edit_button");
             }
             else if (me._incomingState == 'done' && me._outgoingState != 'probing')
             {
               if (me._outgoingState == "failed")
                 me.stopSpinner("failed_to_find_settings");
               else
-                me.stopSpinner("found_settings");
+                me.stopSpinner("found_settings_guess");
               me.editConfigDetails();
             }
             else if (me._outgoingState == 'done' && me._incomingState != 'probing')
             {
               if (me._incomingState == "failed")
                 me.stopSpinner("failed_to_find_settings");
               else
-                me.stopSpinner("found_settings");
+                me.stopSpinner("found_settings_guess");
               me.editConfigDetails();
             }
             if (me._outgoingState != 'probing' &&
                 me._incomingState != 'probing')
               me._probeAbortable = null;
 
           },
           function(e, config) // guessconfig failed
--- a/mailnews/base/prefs/content/accountcreation/fetchConfig.js
+++ b/mailnews/base/prefs/content/accountcreation/fetchConfig.js
@@ -65,30 +65,55 @@ function fetchConfigFromDisk(domain, suc
  *         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)
 {
-  let url = "https://autoconfig." + sanitize.hostname(domain) +
-            "/mail/mozilla.xml";
-  let fetch = new FetchHTTP(url, { emailaddress: emailAddress }, false,
-                            function(result)
-                            {
-                              successCallback(readFromXML(result));
-                            },
-                            errorCallback);
-  fetch.start();
-  return fetch;
+  let url1 = "http://autoconfig." + sanitize.hostname(domain) +
+             "/mail/config-v1.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.xml";
+  let sucAbortable = new SuccessiveAbortable();
+  var time = Date.now();
+  let fetch1 = new FetchHTTP(
+    url1, { emailaddress: emailAddress }, 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();
+      let fetch2 = new FetchHTTP(
+        url2, { emailaddress: emailAddress }, false,
+        function(result)
+        {
+          successCallback(readFromXML(result));
+        },
+        function(e2)
+        {
+          ddump("fetchisp 2 <" + url2 + "> took " + (Date.now() - time) +
+              "ms and failed with " + e2);
+          errorCallback(e1); // return error for primary call
+        });
+      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()
  */
 
--- a/mailnews/base/prefs/content/accountcreation/util.js
+++ b/mailnews/base/prefs/content/accountcreation/util.js
@@ -232,16 +232,43 @@ IntervalAbortable.prototype =
 {
   cancel : function()
   {
     clearInterval(this._id);
   }
 }
 extend(IntervalAbortable, Abortable);
 
+
+// Allows you to make several network calls, but return only one Abortable object.
+function SuccessiveAbortable()
+{
+  this._current = null;
+}
+SuccessiveAbortable.prototype =
+{
+  set current(abortable)
+  {
+    assert(abortable instanceof Abortable || abortable == null,
+        "need an Abortable object (or null)");
+    this._current = abortable;
+  },
+  get current()
+  {
+    return this._current;
+  },
+  cancel : function()
+  {
+    if (this._current)
+      this._current.cancel();
+  },
+}
+extend(SuccessiveAbortable, Abortable);
+
+
 function deepCopy(org)
 {
   if (typeof(org) == "undefined")
     return undefined;
   if (org == null)
     return null;
   if (typeof(org) == "string")
     return org;