Bug 1606339 - Migrate Yahoo users to OAuth2 to deal with Yahoo password login shutdown. r=mkmelin a=wsmwk
authorAlessandro Castellani <alessandro@thunderbird.net>
Wed, 30 Sep 2020 09:29:43 -0700
changeset 40810 42e842ed7fef1409feb36eb274170eff27b22d2b
parent 40809 faa3265fa49ca5274c89e5f0ccc7d410b1e5b6c1
child 40811 801b0298e24180d598a039c567080916aae2cdc6
push id406
push userthunderbird@calypsoblue.org
push dateMon, 19 Oct 2020 19:46:44 +0000
reviewersmkmelin, wsmwk
bugs1606339
Bug 1606339 - Migrate Yahoo users to OAuth2 to deal with Yahoo password login shutdown. r=mkmelin a=wsmwk
mail/base/modules/MailMigrator.jsm
mail/base/test/unit/test_yahoo_oauth_migration.js
mail/base/test/unit/xpcshell.ini
--- a/mail/base/modules/MailMigrator.jsm
+++ b/mail/base/modules/MailMigrator.jsm
@@ -113,17 +113,17 @@ var MailMigrator = {
   /* eslint-disable complexity */
   /**
    * Determine if the UI has been upgraded in a way that requires us to reset
    * some user configuration.  If so, performs the resets.
    */
   _migrateUI() {
     // The code for this was ported from
     // mozilla/browser/components/nsBrowserGlue.js
-    const UI_VERSION = 21;
+    const UI_VERSION = 22;
     const MESSENGER_DOCURL = "chrome://messenger/content/messenger.xhtml";
     const MESSENGERCOMPOSE_DOCURL =
       "chrome://messenger/content/messengercompose/messengercompose.xhtml";
     const UI_VERSION_PREF = "mail.ui-rdf.version";
     let currentUIVersion = Services.prefs.getIntPref(UI_VERSION_PREF, 0);
 
     if (currentUIVersion >= UI_VERSION) {
       return;
@@ -499,16 +499,42 @@ var MailMigrator = {
 
       // Make "bad" msgcompose.font_face value "tt" be "monospace" instead.
       if (currentUIVersion < 21) {
         if (Services.prefs.getStringPref("msgcompose.font_face") == "tt") {
           Services.prefs.setStringPref("msgcompose.font_face", "monospace");
         }
       }
 
+      // Migrate Yahoo users to OAuth2, since "normal password" is going away
+      // on October 20, 2020.
+      if (currentUIVersion < 22) {
+        // Loop through all the currently stored accounts.
+        for (let account of MailServices.accounts.accounts) {
+          // Skip if not a Yahoo account.
+          if (!account.incomingServer.hostName.endsWith("mail.yahoo.com")) {
+            continue;
+          }
+
+          // Change Incoming server to OAuth2.
+          account.incomingServer.authMethod = Ci.nsMsgAuthMethod.OAuth2;
+        }
+
+        // Loop through all the currently stored servers.
+        for (let server of MailServices.smtp.servers) {
+          // Skip if not a Yahoo server.
+          if (!server.hostname.endsWith("mail.yahoo.com")) {
+            continue;
+          }
+
+          // Change Outgoing SMTP server to OAuth2.
+          server.authMethod = Ci.nsMsgAuthMethod.OAuth2;
+        }
+      }
+
       // Update the migration version.
       Services.prefs.setIntPref(UI_VERSION_PREF, UI_VERSION);
     } catch (e) {
       Cu.reportError(
         "Migrating from UI version " +
           currentUIVersion +
           " to " +
           UI_VERSION +
new file mode 100644
--- /dev/null
+++ b/mail/base/test/unit/test_yahoo_oauth_migration.js
@@ -0,0 +1,230 @@
+/* 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/. */
+
+/**
+ * Test migrating Yahoo users to OAuth2, since "normal password" is going away
+ * on October 20, 2020.
+ */
+
+var { MailMigrator } = ChromeUtils.import(
+  "resource:///modules/MailMigrator.jsm"
+);
+var { localAccountUtils } = ChromeUtils.import(
+  "resource://testing-common/mailnews/LocalAccountUtils.jsm"
+);
+var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+var gAccountList = [
+  // POP Yahoo account + Yahoo Server.
+  {
+    type: "pop3",
+    port: 1234,
+    user: "pop3user",
+    password: "pop3password",
+    hostname: "pop3.mail.yahoo.com",
+    socketType: Ci.nsMsgSocketType.plain,
+    authMethod: Ci.nsMsgAuthMethod.passwordCleartext,
+    smtpServers: [
+      {
+        port: 3456,
+        user: "imapout",
+        password: "imapoutpassword",
+        isDefault: true,
+        hostname: "smtp.mail.yahoo.com",
+        socketType: Ci.nsMsgSocketType.alwaysSTARTTLS,
+        authMethod: Ci.nsMsgAuthMethod.passwordCleartext,
+      },
+    ],
+  },
+  // IMAP Yahoo account + Google Server.
+  {
+    type: "imap",
+    port: 2345,
+    user: "imapuser",
+    password: "imappassword",
+    hostname: "imap.mail.yahoo.com",
+    socketType: Ci.nsMsgSocketType.trySTARTTLS,
+    authMethod: Ci.nsMsgAuthMethod.passwordCleartext,
+    smtpServers: [
+      {
+        port: 3456,
+        user: "imapout",
+        password: "imapoutpassword",
+        isDefault: false,
+        hostname: "smtp.mail.google.com",
+        socketType: Ci.nsMsgSocketType.alwaysSTARTTLS,
+        authMethod: Ci.nsMsgAuthMethod.passwordEncrypted,
+      },
+    ],
+  },
+  // IMAP Google account + Yahoo Server.
+  {
+    type: "imap",
+    port: 2345,
+    user: "imap2user",
+    password: "imap2password",
+    hostname: "imap.mail.google.com",
+    socketType: Ci.nsMsgSocketType.trySTARTTLS,
+    authMethod: Ci.nsMsgAuthMethod.passwordCleartext,
+    smtpServers: [
+      {
+        port: 3456,
+        user: "imapout",
+        password: "imapoutpassword",
+        isDefault: false,
+        hostname: "smtp.mail.yahoo.com",
+        socketType: Ci.nsMsgSocketType.alwaysSTARTTLS,
+        authMethod: Ci.nsMsgAuthMethod.passwordEncrypted,
+      },
+    ],
+  },
+  // IMAP Invalid account + Invalid Server.
+  {
+    type: "imap",
+    port: 2345,
+    user: "imap2user",
+    password: "imap2password",
+    hostname: "imap.mail.foo.invalid",
+    socketType: Ci.nsMsgSocketType.trySTARTTLS,
+    authMethod: Ci.nsMsgAuthMethod.passwordCleartext,
+    smtpServers: [
+      {
+        port: 3456,
+        user: "imapout",
+        password: "imapoutpassword",
+        isDefault: false,
+        hostname: "smtp.mail.foo.invalid",
+        socketType: Ci.nsMsgSocketType.alwaysSTARTTLS,
+        authMethod: Ci.nsMsgAuthMethod.passwordEncrypted,
+      },
+    ],
+  },
+];
+
+// An array of the incoming servers created from the setup_accounts() method.
+var gIncomingServers = [];
+
+// An array of the outgoing servers created from the setup_accounts() method.
+var gOutgoingServers = [];
+
+// An array of the accounts created from the setup_accounts() method.
+var gAccounts = [];
+
+/**
+ * Set up accounts based on the given data.
+ */
+function setup_accounts() {
+  for (let details of gAccountList) {
+    let server = localAccountUtils.create_incoming_server(
+      details.type,
+      details.port,
+      details.user,
+      details.password,
+      details.hostname
+    );
+    server.socketType = details.socketType;
+    server.authMethod = details.authMethod;
+
+    // Add the newly created server to the array for testing.
+    gIncomingServers.push(server);
+
+    let account = MailServices.accounts.FindAccountForServer(server);
+    for (let smtpDetails of details.smtpServers) {
+      let outgoing = localAccountUtils.create_outgoing_server(
+        smtpDetails.port,
+        smtpDetails.user,
+        smtpDetails.password,
+        smtpDetails.hostname
+      );
+      outgoing.socketType = smtpDetails.socketType;
+      outgoing.authMethod = smtpDetails.authMethod;
+      localAccountUtils.associate_servers(
+        account,
+        outgoing,
+        smtpDetails.isDefault
+      );
+
+      // Add the newly created server to the array for testing.
+      gOutgoingServers.push(outgoing);
+
+      // Add the newly created account to the array for cleanup.
+      gAccounts.push(account);
+    }
+  }
+}
+
+function test_yahoo_oauth_migration() {
+  setup_accounts();
+
+  for (let server of gIncomingServers) {
+    // Confirm all the incoming servers are not using OAuth2 after the setup.
+    Assert.notEqual(
+      server.authMethod,
+      Ci.nsMsgAuthMethod.OAuth2,
+      "Incoming server doesn't use OAuth2"
+    );
+  }
+
+  for (let server of gOutgoingServers) {
+    // Confirm all the outgoing servers are not using OAuth2 after the setup.
+    Assert.notEqual(
+      server.authMethod,
+      Ci.nsMsgAuthMethod.OAuth2,
+      "Outgoing server doesn't use OAuth2"
+    );
+  }
+
+  // Run the migration.
+  Services.prefs.setIntPref("mail.ui-rdf.version", 21);
+  MailMigrator._migrateUI();
+
+  for (let server of gIncomingServers) {
+    // Confirm only the Yahoo incoming servers are using OAuth2 after migration.
+    if (!server.hostName.endsWith("mail.yahoo.com")) {
+      Assert.notEqual(
+        server.authMethod,
+        Ci.nsMsgAuthMethod.OAuth2,
+        "Incoming server doesn't use OAuth2 after migration"
+      );
+      continue;
+    }
+
+    Assert.equal(
+      server.authMethod,
+      Ci.nsMsgAuthMethod.OAuth2,
+      "Incoming server uses OAuth2 after migration"
+    );
+  }
+
+  for (let server of gOutgoingServers) {
+    // Confirm only the Yahoo outgoing servers are using OAuth2 after migration.
+    if (!server.hostname.endsWith("mail.yahoo.com")) {
+      Assert.notEqual(
+        server.authMethod,
+        Ci.nsMsgAuthMethod.OAuth2,
+        "Outgoing server doesn't use OAuth2 after migration"
+      );
+      continue;
+    }
+
+    Assert.equal(
+      server.authMethod,
+      Ci.nsMsgAuthMethod.OAuth2,
+      "Outgoing server uses OAuth2 after migration"
+    );
+  }
+
+  // Remove our test accounts and servers to leave the profile clean.
+  for (let account of gAccounts) {
+    MailServices.accounts.removeAccount(account);
+  }
+
+  for (let server of gOutgoingServers) {
+    MailServices.smtp.deleteServer(server);
+  }
+}
+
+function run_test() {
+  test_yahoo_oauth_migration();
+}
--- a/mail/base/test/unit/xpcshell.ini
+++ b/mail/base/test/unit/xpcshell.ini
@@ -13,11 +13,12 @@ run-sequentially = Avoid bustage.
 run-sequentially = Avoid bustage.
 [test_viewWrapper_logic.js]
 [test_viewWrapper_realFolder.js]
 [test_viewWrapper_virtualFolder.js]
 [test_viewWrapper_virtualFolderCustomTerm.js]
 run-sequentially = Avoid bustage.
 [test_windows_font_migration.js]
 skip-if = os != "win"
+[test_yahoo_oauth_migration.js]
 [test_mailGlue_distribution.js]
 
 [include:xpcshell_maildir.ini]