Rewrite authentication logic (in IMAP, POP, SMTP) (more below) Bug 525238, r=bienvenu, r=bwinton (accountcreation), sr=NeilAway, ui-r=clarkbw
authorBen Bucksch <ben.bucksch@beonex.com>
Sat, 20 Mar 2010 02:11:28 +0100
changeset 5211 895928822eb3
parent 5210 a03eae584548
child 5212 efae333beb46
push id4023
push usermozilla.BenB@bucksch.org
push date2010-03-20 01:11 +0000
treeherdercomm-central@895928822eb3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbienvenu, bwinton, NeilAway, clarkbw
bugs525238, 339050, 524698
Rewrite authentication logic (in IMAP, POP, SMTP) (more below) Bug 525238, r=bienvenu, r=bwinton (accountcreation), sr=NeilAway, ui-r=clarkbw - Add pref to specifically set plaintext password auth, encrypted pw auth, Kerberos, NTLM. This allows to show proper error (without pw dialog) for Kerberos failure (bug 339050) and to invoke a Kerberos OS password prompt (bug 524698). - For that, and because it was badly needed, also rewrite authentication login. This fixes many bugs, e.g. users getting a password prompt when login failed for reasons other than password (e.g. POP server limiting to checks every 15 minutes). - Create migration.jsm where we can update profiles on startup. - Change IDL constants for SSL, per Neil
mail/base/content/mailContextMenus.js
mail/base/content/msgHdrViewOverlay.js
mail/base/content/msgMail3PaneWindow.js
mail/locales/en-US/chrome/messenger/am-advanced.dtd
mail/locales/en-US/chrome/messenger/am-server-top.dtd
mail/locales/en-US/chrome/messenger/imapMsgs.properties
mail/locales/en-US/chrome/messenger/localMsgs.properties
mail/locales/en-US/chrome/messenger/messenger.properties
mail/locales/en-US/chrome/messenger/messengercompose/composeMsgs.properties
mail/locales/en-US/chrome/messenger/smtpEditOverlay.dtd
mailnews/base/prefs/content/AccountManager.js
mailnews/base/prefs/content/SmtpServerEdit.xul
mailnews/base/prefs/content/accountUtils.js
mailnews/base/prefs/content/accountcreation/accountConfig.js
mailnews/base/prefs/content/accountcreation/createInBackend.js
mailnews/base/prefs/content/accountcreation/emailWizard.js
mailnews/base/prefs/content/accountcreation/guessConfig.js
mailnews/base/prefs/content/accountcreation/readFromXML.js
mailnews/base/prefs/content/accountcreation/verifyConfig.js
mailnews/base/prefs/content/am-server.js
mailnews/base/prefs/content/am-server.xul
mailnews/base/prefs/content/am-smtp.js
mailnews/base/prefs/content/am-smtp.xul
mailnews/base/prefs/content/smtpEditOverlay.js
mailnews/base/prefs/content/smtpEditOverlay.xul
mailnews/base/public/MailNewsTypes2.idl
mailnews/base/public/nsIMsgIncomingServer.idl
mailnews/base/util/Makefile.in
mailnews/base/util/migration.jsm
mailnews/base/util/nsMsgIncomingServer.cpp
mailnews/base/util/nsMsgProtocol.cpp
mailnews/compose/public/nsISmtpServer.idl
mailnews/compose/src/nsComposeStrings.h
mailnews/compose/src/nsMsgSend.cpp
mailnews/compose/src/nsSmtpProtocol.cpp
mailnews/compose/src/nsSmtpProtocol.h
mailnews/compose/src/nsSmtpServer.cpp
mailnews/compose/src/nsSmtpService.cpp
mailnews/compose/test/unit/head_compose.js
mailnews/compose/test/unit/test_bug155172.js
mailnews/compose/test/unit/test_sendMailMessage.js
mailnews/compose/test/unit/test_smtpAuthMethods.js
mailnews/compose/test/unit/test_smtpPassword.js
mailnews/compose/test/unit/test_smtpPassword2.js
mailnews/compose/test/unit/test_smtpPasswordFailure1.js
mailnews/compose/test/unit/test_smtpPasswordFailure2.js
mailnews/imap/src/nsImapCore.h
mailnews/imap/src/nsImapIncomingServer.cpp
mailnews/imap/src/nsImapProtocol.cpp
mailnews/imap/src/nsImapProtocol.h
mailnews/imap/src/nsImapServerResponseParser.cpp
mailnews/imap/src/nsImapStringBundle.h
mailnews/imap/test/unit/test_imapAuthMethods.js
mailnews/import/oexpress/nsOESettings.cpp
mailnews/import/outlook/src/nsOutlookSettings.cpp
mailnews/local/public/nsIPop3IncomingServer.idl
mailnews/local/src/nsLocalStrings.h
mailnews/local/src/nsPop3IncomingServer.cpp
mailnews/local/src/nsPop3Protocol.cpp
mailnews/local/src/nsPop3Protocol.h
mailnews/local/test/unit/test_pop3AuthMethods.js
mailnews/local/test/unit/test_pop3GSSAPIFail.js
mailnews/local/test/unit/test_pop3ServerBrokenCRAMDisconnect.js
mailnews/local/test/unit/test_pop3ServerBrokenCRAMFail.js
mailnews/mailnews.js
mailnews/mapi/mapihook/src/msgMapiMain.cpp
mailnews/news/src/nsNNTPProtocol.cpp
mailnews/news/src/nsNewsFolder.cpp
mailnews/news/src/nsNntpIncomingServer.cpp
mailnews/news/src/nsNntpService.cpp
suite/common/src/nsSuiteGlue.js
suite/locales/en-US/chrome/mailnews/compose/composeMsgs.properties
suite/locales/en-US/chrome/mailnews/imapMsgs.properties
suite/locales/en-US/chrome/mailnews/localMsgs.properties
suite/locales/en-US/chrome/mailnews/messenger.properties
suite/locales/en-US/chrome/mailnews/pref/am-advanced.dtd
suite/locales/en-US/chrome/mailnews/pref/am-server-top.dtd
suite/locales/en-US/chrome/mailnews/pref/smtpEditOverlay.dtd
--- a/mail/base/content/mailContextMenus.js
+++ b/mail/base/content/mailContextMenus.js
@@ -627,17 +627,18 @@ function getEmail (url)
 }
 
 function CopyMessageUrl()
 {
   try {
     var hdr = gDBView.hdrForFirstSelectedMessage;
     var server = hdr.folder.server;
 
-    var url = (server.socketType == Components.interfaces.nsIMsgIncomingServer.useSSL) ?
+    // TODO let backend construct URL and return as attribute
+    var url = (server.socketType == Components.interfaces.nsMsgSocketType.SSL) ?
               "snews://" : "news://";
     url += server.hostName + ":" + server.port + "/" + hdr.messageId;
 
     var clipboard = Components.classes["@mozilla.org/widget/clipboardhelper;1"]
                               .getService(Components.interfaces.nsIClipboardHelper);
     clipboard.copyString(url);
   }
   catch (ex) {
--- a/mail/base/content/msgHdrViewOverlay.js
+++ b/mail/base/content/msgHdrViewOverlay.js
@@ -1504,18 +1504,19 @@ function CopyNewsgroupName(newsgroupNode
 function CopyNewsgroupURL(newsgroupNode)
 {
   let server = GetNewsgroupServer();
   if (!server)
     return;
 
   let ng = newsgroupNode.getAttribute("newsgroup");
 
+  // TODO let backend construct URL and return as attribute
   let url;
-  if (server.socketType != Components.interfaces.nsIMsgIncomingServer.useSSL) {
+  if (server.socketType != Components.interfaces.nsMsgSocketType.SSL) {
     url = "news://" + server.hostName;
     if (server.port != Components.interfaces.nsINntpUrl.DEFAULT_NNTP_PORT)
       url += ":" + server.port;
     url += "/" + ng;
   }
   else {
     url = "snews://" + server.hostName;
     if (server.port != Components.interfaces.nsINntpUrl.DEFAULT_NNTPS_PORT)
--- a/mail/base/content/msgMail3PaneWindow.js
+++ b/mail/base/content/msgMail3PaneWindow.js
@@ -41,17 +41,19 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 Components.utils.import("resource://gre/modules/folderUtils.jsm");
 Components.utils.import("resource://app/modules/activity/activityModules.js");
 Components.utils.import("resource://app/modules/jsTreeSelection.js");
 Components.utils.import("resource://app/modules/MailConsts.js");
+Components.utils.import("resource://app/modules/errUtils.js");
 Components.utils.import("resource://app/modules/IOUtils.js");
+Components.utils.import("resource://app/modules/migration.jsm");
 
 /* This is where functions related to the 3 pane window are kept */
 
 // from MailNewsTypes.h
 const nsMsgKey_None = 0xFFFFFFFF;
 const nsMsgViewIndex_None = 0xFFFFFFFF;
 const kMailCheckOncePrefName = "mail.startup.enabledMailCheckOnce";
 
@@ -236,16 +238,18 @@ function AutoConfigWizard(okCallback)
   NewMailAccount(msgWindow, okCallback);
 }
 
 /**
  * Called on startup to initialize various parts of the main window
  */
 function OnLoadMessenger()
 {
+  migrateMailnews();
+
   // update the pane config before we exit onload otherwise the user may see a flicker if we poke the document
   // in delayedOnLoadMessenger...
   UpdateMailPaneConfig(false);
   document.loadBindingDocument('chrome://global/content/bindings/textbox.xml');
 
   // Set a sane starting width/height for all resolutions on new profiles.
   // Do this before the window loads.
   if (!document.documentElement.hasAttribute("width"))
--- a/mail/locales/en-US/chrome/messenger/am-advanced.dtd
+++ b/mail/locales/en-US/chrome/messenger/am-advanced.dtd
@@ -15,9 +15,9 @@
 <!ENTITY smtpListSetDefault.label "Set Default">
 <!ENTITY smtpListSetDefault.accesskey "t">
 
 <!ENTITY serverDescription.label "Description: ">
 <!ENTITY serverName.label "Server Name: ">
 <!ENTITY serverPort.label "Port: ">
 <!ENTITY userName.label   "User Name: ">
 <!ENTITY connectionSecurity.label "Connection Security: ">
-<!ENTITY useSecureAuthentication.label   "Secure Authentication: ">
+<!ENTITY authMethod.label   "Authentication method: ">
--- a/mail/locales/en-US/chrome/messenger/am-server-top.dtd
+++ b/mail/locales/en-US/chrome/messenger/am-server-top.dtd
@@ -19,18 +19,18 @@
 <!ENTITY biffStart.accesskey "y">
 <!ENTITY biffEnd.label "minutes">
 <!ENTITY connectionSecurity.label "Connection security:">
 <!ENTITY connectionSecurity.accesskey "u">
 <!ENTITY connectionSecurityType-0.label "None">
 <!ENTITY connectionSecurityType-1.label "STARTTLS, if available">
 <!ENTITY connectionSecurityType-2.label "STARTTLS">
 <!ENTITY connectionSecurityType-3.label "SSL/TLS">
-<!ENTITY useSecAuth.label "Use secure authentication">
-<!ENTITY useSecAuth.accesskey "i">
+<!ENTITY authMethod.label "Authentication method:">
+<!ENTITY authMethod.accesskey "i">
 <!ENTITY leaveOnServer.label "Leave messages on server">
 <!ENTITY leaveOnServer.accesskey "g">
 <!ENTITY headersOnly.label "Fetch headers only">
 <!ENTITY headersOnly.accesskey "e">
 <!ENTITY deleteByAgeFromServer.label "For at most">
 <!ENTITY deleteByAgeFromServer.accesskey "o">
 <!ENTITY daysEnd.label "days">
 <!ENTITY deleteOnServer2.label "Until I delete them">
--- a/mail/locales/en-US/chrome/messenger/imapMsgs.properties
+++ b/mail/locales/en-US/chrome/messenger/imapMsgs.properties
@@ -362,28 +362,39 @@ 5096=This server does not support quotas
 ## @loc None
 5097=There are no storage quotas on this folder.
 
 # Out of memory
 ## @name IMAP_OUT_OF_MEMORY
 ## @loc None
 5100=Application is out of memory.
 
-## @name IMAP_AUTH_SECURE_NOTSUPPORTED
+## @name IMAP_AUTH_MECH_NOT_SUPPORTED
 ## @loc None
-5102=You cannot log in to %S because you have enabled secure authentication and this server does not support it.\n\nTo log in, turn off secure authentication for this account.
+# LOCALIZATION NOTE (5101): %S is the server hostname
+5101=The IMAP server %S does not support the selected authentication method. Please change the 'Authentication method' in the 'Account Settings | Server settings'.
+
+## @name IMAP_AUTH_MECH_FAILED
+## @loc None
+# LOCALIZATION NOTE (5102): %S is the server hostname
+5102=All login mechanisms for %S failed. Please check the password or change the 'Authentication method' in the 'Account Settings | Server settings'.
 
 ## @name IMAP_COPYING_MESSAGE_OF
 ## @loc None
 # LOCALIZATION NOTE (Error 5103): Do not translate the word "%S" below.
 # Place the word %3$S in your translation where the name of the destination folder should appear.
 # Place the word %1$S where the currently copying message should appear.
 # Place the word %2$S where the total number of messages should appear.
 5103=Copying Message %1$S of %2$S to %3$S
 
+## @name IMAP_AUTH_GSSAPI_FAILED
+## @loc None
+# LOCALIZATION NOTE (5104): %S is the server hostname
+5104=The Kerberos/GSSAPI ticket was not accepted by the IMAP server %S. Please check that you are logged in to the Kerberos/GSSAPI realm.
+
 ## @name IMAP_MOVE_FOLDER_TO_TRASH
 ## @loc None
 # LOCALIZATION NOTE (5105): Do not translate the word %S below.
 # "%S" is the the name of the folder.
 5105=Are you sure you want to delete the folder '%S'?
 
 ## @name IMAP_DELETE_NO_TRASH
 ## @loc None
@@ -394,12 +405,22 @@ 5106=Deleting this folder is not undoabl
 ## @name IMAP_DELETE_FOLDER_DIALOG_TITLE
 ## @loc None
 5107=Delete Folder
 
 ## @name IMAP_DELETE_FOLDER_BUTTON_LABEL
 ## @loc None
 5108=&Delete Folder
 
-## @name IMAP_LOGIN_DISABLED
+## @name IMAP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_NO_SSL
+## @loc None
+# LOCALIZATION NOTE (5109): %S is the server hostname
+5109=The IMAP server %S does not seem to support encrypted passwords. If you just set up the account, please try changing to 'Password, transmitted insecurely' as the 'Authentication method' in the 'Account Settings | Server settings'. If it used to work and now suddenly fails, this is a common scenario how someone could steal your password.
+
+## @name IMAP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_SSL
 ## @loc None
-# LOCALIZATION NOTE (5109): %S is the server address
-5109=You cannot log in to %S because the server doesn't allow plaintext authentication without STARTTLS or SSL/TLS. Try enabling connection security or secure authentication in the account settings.
+# LOCALIZATION NOTE (5110): %S is the server hostname
+5110=The IMAP server %S does not seem to support encrypted passwords. If you just set up this account, please try changing to 'Normal password' as the 'Authentication method' in the 'Account Settings | Server settings'. If it used to work and now suddenly fails, please contact your email administrator or provider.
+
+## @name IMAP_AUTH_CHANGE_PLAIN_TO_ENCRYPT
+## @loc None
+# LOCALIZATION NOTE (5111): %S is the server hostname
+5111=The IMAP server %S does not allow plaintext passwords. Please try changing to 'Encrypted password' as the 'Authentication method' in the 'Account Settings | Server settings'.
--- a/mail/locales/en-US/chrome/messenger/localMsgs.properties
+++ b/mail/locales/en-US/chrome/messenger/localMsgs.properties
@@ -160,20 +160,25 @@ 4027=Copying %S of %S messages to %S
 ## @loc None
 4028=Moving %S of %S messages to %S
 
 # Status - write error occurred
 ## @name POP3_MESSAGE_FOLDER_BUSY
 ## @loc None
 4029=This folder is being processed. Please wait until processing is complete to get messages.
 
-# secure authentication failed
-## @name CANNOT_PROCESS_SECURE_AUTH
+# Authentication server caps and pref don't match
+## @name POP3_AUTH_MECH_NOT_SUPPORTED
 ## @loc None
-4030=Mail server does not support secure authentication.
+4030=The server does not support the selected authentication method. Please change the 'Authentication method' in the 'Account Settings | Server settings'.
+
+# Status - Could not log in to GSSAPI, and it was the only method
+## @name POP3_GSSAPI_FAILURE
+## @loc None
+4031=The Kerberos/GSSAPI ticket was not accepted by the POP server. Please check that you are logged in to the Kerberos/GSSAPI realm.
 
 ## @name MOVEMAIL_CANT_OPEN_SPOOL_FILE
 ## @loc None
 4033=Unable to open mail spool file %S.
 
 ## @name MOVEMAIL_CANT_CREATE_LOCK
 ## @loc None
 4034=Unable to create lock file %S. For movemail to work, it is necessary to create lock files in the mail spool directory. On many systems, this is best accomplished by making the spool directory be mode 01777.
@@ -207,21 +212,16 @@ 4040=The POP3 mail server (%S) does not 
 ## @name POP3_SERVER_DOES_NOT_SUPPORT_THE_TOP_COMMAND
 ## @loc None
 # LOCALIZATION NOTE(4011): The following sentence should be translated in this way:
 # Do not translate "POP3"
 # Do not translate "%S". Place %S in your translation where the name of the server should appear.
 # Do not translate "TOP"
 4041=The POP3 mail server (%S) does not support the TOP command. Without server support for this, we cannot implement the ``Maximum Message Size'' or ``Fetch Headers Only'' preference.  This option has been disabled, and messages will be downloaded regardless of their size.
 
-# secure authentication failed and unsure why
-## @name CANNOT_PROCESS_APOP_AUTH
-## @loc None
-4042=The mail server does not support secure authentication or you have entered an incorrect password. Please check your password, or turn off secure authentication in the Server Settings for your mail server in the Account Settings window.\n
-
 ## @name NS_ERROR_COULD_NOT_CONNECT_VIA_TLS
 ## @loc None
 4043=Unable to establish TLS connection to POP3 server. The server may be down or may be incorrectly configured. Please verify the correct configuration in the Server Settings for your mail server in the Account Settings window and try again.
 
 ## @name POP3_MOVE_FOLDER_TO_TRASH
 ## @loc None
 # LOCALIZATION NOTE (4044): Do not translate the word %S below.
 # "%S" is the the name of the folder.
@@ -229,8 +229,24 @@ 4044=Are you sure you want to delete the
 
 ## @name POP3_DELETE_FOLDER_DIALOG_TITLE
 ## @loc None
 4045=Delete Folder
 
 ## @name POP3_DELETE_FOLDER_BUTTON_LABEL
 ## @loc None
 4046=&Delete Folder
+
+## @name POP3_AUTH_INTERNAL_ERROR
+## @loc None
+4047=Internal state error during POP3 server authentication. This is an internal, unexpected error in the application, please report it as bug.
+
+## @name POP3_AUTH_CHANGE_ENCRYPT_TO_PLAIN_NO_SSL
+## @loc None
+4048=This POP3 server does not seem to support encrypted passwords. If you just set up the account, please try changing to 'Password, transmitted insecurely' as the 'Authentication method' in the 'Account Settings | Server settings'. If it used to work and now suddenly fails, this is a common scenario how someone could steal your password.
+
+## @name POP3_AUTH_CHANGE_ENCRYPT_TO_PLAIN_SSL
+## @loc None
+4049=This POP3 server does not seem to support encrypted passwords. If you just set up this account, please try changing to 'Normal password' as the 'Authentication method' in the 'Account Settings | Server settings'. If it used to work and now suddenly fails, please contact your email administrator or provider.
+
+## @name POP3_AUTH_CHANGE_PLAIN_TO_ENCRYPT
+## @loc None
+4050=This POP3 server does not allow plaintext passwords. Please try changing to 'Encrypted password' as the 'Authentication method' in the 'Account Settings | Server settings'.
--- a/mail/locales/en-US/chrome/messenger/messenger.properties
+++ b/mail/locales/en-US/chrome/messenger/messenger.properties
@@ -128,16 +128,27 @@ smtpServer-ConnectionSecurityType-0=None
 smtpServer-ConnectionSecurityType-1=STARTTLS, if available
 smtpServer-ConnectionSecurityType-2=STARTTLS
 smtpServer-ConnectionSecurityType-3=SSL/TLS
 smtpServer-SecureAuthentication-Type-false=No
 smtpServer-SecureAuthentication-Type-true=Yes
 smtpServers-confirmServerDeletionTitle=Delete Server
 smtpServers-confirmServerDeletion=Are you sure you want to delete the server: \n %S?
 
+# Account Settings - Both Incoming and SMTP server
+authNo=No authentication
+authOld=Password, original method (insecure)
+authPasswordCleartextInsecurely=Password, transmitted insecurely
+authPasswordCleartextViaSSL=Normal password
+authPasswordEncrypted=Encrypted password
+authKerberos=Kerberos / GSSAPI
+authNTLM=NTLM
+authAnySecure=Any secure method (deprecated)
+authAny=Any method (insecure)
+
 # LOCALIZATION NOTE(serverType-nntp): Do not translate "NNTP" in the line below
 serverType-nntp=News Server (NNTP)
 # LOCALIZATION NOTE(serverType-pop3): Do not translate "POP" in the line below
 serverType-pop3=POP Mail Server
 # LOCALIZATION NOTE(serverType-imap): Do not translate "IMAP" in the line below
 serverType-imap=IMAP Mail Server
 serverType-none=Local Mail Store
 # LOCALIZATION NOTE(serverType-movemail): DONT_TRANSLATE
--- a/mail/locales/en-US/chrome/messenger/messengercompose/composeMsgs.properties
+++ b/mail/locales/en-US/chrome/messenger/messengercompose/composeMsgs.properties
@@ -203,31 +203,31 @@ 12570=There was an error attaching %S. P
 12571=There was an error copying the message to the Sent folder. Retry?
 
 ## @name NS_ERROR_SMTP_GREETING
 12572=An error occurred sending mail: The mail server sent an incorrect greeting:  %s.
 
 ## @name NS_ERROR_SENDING_RCPT_COMMAND
 12575=An error occurred while sending mail. The mail server responded:  %1$s. Please check the message recipient %2$s and try again.
 
-## @name NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER_INSECAUTH
-12579=An error occurred sending mail: Unable to authenticate to SMTP server %S. The server does not support any compatible insecure authentication mechanism but you have chosen insecure authentication. Try switching on secure authentication or contact your service provider.
+## @name NS_ERROR_SMTP_AUTH_FAILURE
+12576=Unable to authenticate to SMTP server %S. Please check the password, and verify the 'Authentication method' in 'Account Settings | Outgoing server (SMTP)'.
+
+## @name NS_ERROR_SMTP_AUTH_GSSAPI
+12579=The Kerberos/GSSAPI ticket was not accepted by the SMTP server %S. Please check that you are logged in to the Kerberos/GSSAPI realm.
 
-## @name NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER_SECAUTH
-12580=An error occurred sending mail: Unable to authenticate to SMTP server %S. The server does not support any compatible secure authentication mechanism but you have chosen secure authentication. Try switching off secure authentication or contact your service provider.
+## @name NS_ERROR_SMTP_AUTH_MECH_NOT_SUPPORTED
+12580=The SMTP server %S does not support the selected authentication method. Please change the 'Authentication method' in the 'Account Settings | Outgoing Server (SMTP)'.
 
-## @name NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER_AUTH_NONE
-12581=An error occurred sending mail: Unable to authenticate to SMTP server %S. It does not support authentication (SMTP-AUTH) but you have chosen to use authentication. Uncheck 'Use name and password' for that server or contact your service provider.
+## @name NS_ERROR_SMTP_AUTH_NOT_SUPPORTED
+12581=Unable to authenticate to SMTP server %S. It does not support authentication (SMTP-AUTH) but you have chosen to use authentication. Please change the 'Authentication method' to 'None' in the 'Account Settings | Outgoing Server (SMTP)' or contact your email service provider for instructions.
 
 ## @name NS_ERROR_STARTTLS_FAILED_EHLO_STARTTLS
 12582=An error occurred sending mail: Unable to establish a secure link with SMTP server %S using STARTTLS since it doesn't advertise that feature. Switch off STARTTLS for that server or contact your service provider.
 
-## @name NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER
-12583=An error occurred sending mail: Unable to log in to SMTP server %S. The server may be incorrectly configured. Please verify that your SMTP server settings are correct and try again.
-
 ## @name NS_ERROR_SMTP_PASSWORD_UNDEFINED
 12584=An error occurred sending mail: Could not get password for %S. The message was not sent.
 
 ## @name NS_ERROR_SMTP_TEMP_SIZE_EXCEEDED
 12586=The size of the message you are trying to send exceeds a temporary size limit of the server. The message was not sent; try to reduce the message size or wait some time and try again. The server responded:  %s.
 
 ## @name NS_ERROR_SMTP_PERM_SIZE_EXCEEDED_1
 12587=The size of the message you are trying to send exceeds the global size limit (%d bytes) of the server. The message was not sent; reduce the message size and try again.
@@ -245,16 +245,26 @@ 12590=The message could not be sent beca
 12591=The message could not be sent because the connection to SMTP server %S was lost in the middle of the transaction. Try again or contact your network administrator.
 
 ## @name NS_ERROR_SMTP_SEND_FAILED_TIMEOUT
 12592=The message could not be sent because the connection to SMTP server %S timed out. Try again or contact your network administrator.
 
 ## @name NS_ERROR_SMTP_SEND_FAILED_UNKNOWN_REASON
 12593=The message could not be sent using SMTP server %S for an unknown reason. Please verify that your SMTP server settings are correct and try again, or contact your network administrator.
 
+## @name NS_ERROR_SMTP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_NO_SSL
+12594=The SMTP server %S does not seem to support encrypted passwords. If you just set up the account, please try changing to 'Password, transmitted insecurely' as the 'Authentication method' in the 'Account Settings | Server settings'. If it used to work and now suddenly fails, this is a common scenario how someone could steal your password.
+
+## @name NS_ERROR_SMTP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_SSL
+12595=The SMTP server %S does not seem to support encrypted passwords. If you just set up this account, please try changing to 'Normal password' as the 'Authentication method' in the 'Account Settings | Server settings'. If it used to work and now suddenly fails, please contact your email administrator or provider.
+
+## @name NS_ERROR_SMTP_AUTH_CHANGE_PLAIN_TO_ENCRYPT
+12596=The SMTP server %S does not allow plaintext passwords. Please try changing to 'Encrypted password' as the 'Authentication method' in the 'Account Settings | Server settings'.
+
+
 ## Strings use for the save message dialog shown when the user close a message compose window
 saveDlogTitle=Save Message
 saveDlogMessage=Message has not been sent. Do you want to save the message in the Drafts folder?
 
 ## generics string
 defaultSubject=(no subject)
 chooseFileToAttach=Attach File(s)
 
--- a/mail/locales/en-US/chrome/messenger/smtpEditOverlay.dtd
+++ b/mail/locales/en-US/chrome/messenger/smtpEditOverlay.dtd
@@ -1,22 +1,20 @@
 <!ENTITY settings.caption "Settings">
 <!ENTITY security.caption "Security and Authentication">
 <!ENTITY serverName.label "Server Name:">
 <!ENTITY serverName.accesskey "S">
 <!ENTITY serverDescription.label "Description:">
 <!ENTITY serverDescription.accesskey "D">
 <!ENTITY serverPort.label "Port:">
 <!ENTITY serverPort.accesskey "P">
-<!ENTITY alwaysUseUsername.label "Use name and password">
-<!ENTITY alwaysUseUsername.accesskey "U">
 <!ENTITY userName.label "User Name:">
 <!ENTITY userName.accesskey "m">
-<!ENTITY useSecAuth.label "Use secure authentication">
-<!ENTITY useSecAuth.accesskey "i">
 <!ENTITY connectionSecurity.label "Connection security:">
 <!ENTITY connectionSecurity.accesskey "n">
 <!ENTITY connectionSecurityType-0.label "None">
 <!ENTITY connectionSecurityType-1.label "STARTTLS, if available">
 <!ENTITY connectionSecurityType-2.label "STARTTLS">
 <!ENTITY connectionSecurityType-3.label "SSL/TLS">
 <!ENTITY smtpEditTitle.label "SMTP Server">
 <!ENTITY serverPortDefault.label "Default:">
+<!ENTITY authMethod.label "Authentication method:">
+<!ENTITY authMethod.accesskey "i">
--- a/mailnews/base/prefs/content/AccountManager.js
+++ b/mailnews/base/prefs/content/AccountManager.js
@@ -383,39 +383,16 @@ function onAddAccount() {
 function AddMailAccount()
 {
   let msgWindow = Components.classes["@mozilla.org/messenger/services/session;1"]
                             .getService(Components.interfaces.nsIMsgMailSession)
                             .topmostMsgWindow;
   NewMailAccount(msgWindow);
 }
 
-function ReloadSmtpPanel()
-{
-  var smtpUsername = top.frames["contentFrame"].document.getElementById("smtp.username");
-  var smtpHostname = top.frames["contentFrame"].document.getElementById("smtp.hostname");
-  var smtpPort = top.frames["contentFrame"].document.getElementById("smtp.port");
-  var smtpUseUsername = top.frames["contentFrame"].document.getElementById("smtp.useUsername");
-  var smtpAuthMethod = top.frames["contentFrame"].document.getElementById("smtp.authMethod");
-  var smtpTrySSL = top.frames["contentFrame"].document.getElementById("smtp.trySSL");
-
-  var defaultServer = smtpService.defaultServer;
-
-  smtpUsername.value = defaultServer.username;
-  smtpHostname.value = defaultServer.hostname;
-  smtpPort.value = defaultServer.port ? defaultServer.port : "";
-  smtpAuthMethod.setAttribute("value", defaultServer.authMethod);
-  if (smtpAuthMethod.getAttribute("value") == "1")
-    smtpUseUsername.checked = true;
-  var elements = smtpTrySSL.getElementsByAttribute("value", defaultServer.trySSL);
-  if (!elements.item(0))
-    elements = smtpTrySSL.getElementsByAttribute("value", "1");
-  smtpTrySSL.selectedItem = elements[0];
-}
-
 function onSetDefault(event) {
   if (event.target.getAttribute("disabled") == "true") return;
 
   Components.classes["@mozilla.org/messenger/account-manager;1"]
             .getService(Components.interfaces.nsIMsgAccountManager)
             .defaultAccount = currentAccount;
   setEnabled(document.getElementById("setDefaultButton"), false);
 }
--- a/mailnews/base/prefs/content/SmtpServerEdit.xul
+++ b/mailnews/base/prefs/content/SmtpServerEdit.xul
@@ -47,12 +47,13 @@
 
 <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="amUtils.js"/>
 <script type="application/javascript" src="SmtpServerEdit.js"/>
 <vbox id="smtpServerEditor"/>
 </dialog>
--- a/mailnews/base/prefs/content/accountUtils.js
+++ b/mailnews/base/prefs/content/accountUtils.js
@@ -208,32 +208,32 @@ function verifyAccounts(wizardCallback, 
 // 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);
 }
 
+// @see msgNewMailAccount below
 function msgOpenAccountWizard(wizardCallback)
 {
   gNewAccountToLoad = null;
 
   window.openDialog("chrome://messenger/content/AccountWizard.xul", "AccountWizard",
                     "chrome,modal,titlebar,centerscreen", {okCallback: wizardCallback});
 
   loadInboxForNewAccount();
 
-  // For the first account we need to reset the default smtp server in the
-  // panel, by accessing smtpServers we are actually ensuring the smtp server
-  // list is loaded.
-  var smtpService = Components.classes["@mozilla.org/messengercompose/smtp;1"].getService(Components.interfaces.nsISmtpService);
-  var servers = smtpService.smtpServers;
-  try{ReloadSmtpPanel();}
-  catch(ex){}
+  // 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);
 }
 
 // selectPage: the xul file name for the viewing page, 
 // null for the account main page, other pages are
 // 'am-server.xul', 'am-copies.xul', 'am-offline.xul', 
 // 'am-addressing.xul', 'am-smtp.xul'
 function MsgAccountManager(selectPage)
 {
@@ -317,22 +317,30 @@ function migrateGlobalQuotingPrefs(allId
 // has closed, and this is confusing to the user
 function NewMailAccount(msgWindow, okCallback)
 {
   if (!msgWindow)
     throw new Error("NewMailAccount must be given a msgWindow.");
   setTimeout(msgNewMailAccount, 0, msgWindow, okCallback);
 }
 
+// @see msgOpenAccountWizard above
 function msgNewMailAccount(msgWindow, okCallback)
 {
   if (!msgWindow)
     throw new Error("msgNewMailAccount must be given a msgWindow.");
   let wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
                      .getService()
                      .QueryInterface(Components.interfaces.nsIWindowMediator);
   let existingWindow = wm.getMostRecentWindow("mail:autoconfig");
   if (existingWindow)
     existingWindow.focus();
   else
     window.openDialog("chrome://messenger/content/accountcreation/emailWizard.xul",
                       "AccountSetup", "chrome,titlebar,centerscreen",{msgWindow:msgWindow, okCallback:okCallback});
+
+  // 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);
 }
--- a/mailnews/base/prefs/content/accountcreation/accountConfig.js
+++ b/mailnews/base/prefs/content/accountcreation/accountConfig.js
@@ -58,17 +58,21 @@ function AccountConfig()
     type : null, // string-enum: "pop3", "imap", "nntp"
     hostname: null,
     port : null, // Integer
     username : null, // String. May be a placeholder (starts and ends with %).
     password : null,
     // enum: 1 = plain, 2 = SSL/TLS, 3 = STARTTLS always
     // ('TLS when available' is insecure and not supported here)
     socketType : null,
-    auth : null, // enum: 1 = plain, 2 = "secure"
+    /**
+     * Defined by Ci.nsMsgAuthMethod
+     * Same as server pref "authMethod".
+     */
+    auth : 0,
     checkInterval : 10, // Integer, in seconds
     loginAtStartup : true,
     // POP3 only:
     useGlobalInbox : false, // boolean. Not yet implemented.
     leaveMessagesOnServer : true,
     daysToLeaveMessagesOnServer : 14,
     deleteByAgeFromServer : true,
     // When user hits delete, delete from local store and from server
@@ -77,17 +81,17 @@ function AccountConfig()
   },
   this.outgoing =
   {
     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 : null, // see incoming
-    auth : null, // see incoming. 0 for no auth.
+    auth : null, // see incoming
     addThisServer: true, // if we already have an SMTP server, add this or not.
     // if we already have an SMTP server, use it.
     useGlobalPreferredServer : false,
     existingServerKey : null, // we should reuse an already configures SMTP server. This is nsISmtpServer.key.
     existingServerLabel : null // user display value for existingServerKey
   },
   this.identity =
   {
--- a/mailnews/base/prefs/content/accountcreation/createInBackend.js
+++ b/mailnews/base/prefs/content/accountcreation/createInBackend.js
@@ -54,29 +54,28 @@ function createAccountInBackend(config)
                     .getService(Ci.nsISmtpService);
 
   // incoming server
   var inServer = accountManager.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);
 
   // SSL
   if (config.incoming.socketType == 1) // plain
-    inServer.socketType = Ci.nsIMsgIncomingServer.defaultSocket;
+    inServer.socketType = Ci.nsMsgSocketType.plain;
   else if (config.incoming.socketType == 2) // SSL / TLS
-    inServer.socketType = Ci.nsIMsgIncomingServer.useSSL;
+    inServer.socketType = Ci.nsMsgSocketType.SSL;
   else if (config.incoming.socketType == 3) // STARTTLS
-    inServer.socketType = Ci.nsIMsgIncomingServer.alwaysUseTLS;
-  // auth
-  if (config.incoming.auth == 2) // "secure" auth
-    inServer.useSecAuth = true;
+    inServer.socketType = Ci.nsMsgSocketType.alwaysSTARTTLS;
   //inServer.prettyName = config.displayName;
   inServer.prettyName = config.identity.emailAddress;
 
   inServer.doBiff = true;
   inServer.biffMinutes = config.incoming.checkInterval;
   let prefs = Cc["@mozilla.org/preferences-service;1"]
               .getService(Ci.nsIPrefBranch);
   const loginAtStartupPrefTemplate =
@@ -115,46 +114,43 @@ function createAccountInBackend(config)
                       config.incoming.deleteOnServerWhenLocalDelete);
     prefs.setBoolPref(ageFromServerPref,
                       config.incoming.deleteByAgeFromServer);
     prefs.setBoolPref(downloadOnBiffPref,
                       config.incoming.downloadOnBiff);
   }
   inServer.valid = true;
 
-  let username = config.outgoing.auth > 0 ? config.outgoing.username : null;
+  let username = config.outgoing.auth > 1 ? config.outgoing.username : null;
   let outServer = smtpManager.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 = smtpManager.createSmtpServer();
     outServer.hostname = config.outgoing.hostname;
     outServer.port = config.outgoing.port;
-    if (config.outgoing.auth > 0)
+    outServer.authMethod = config.outgoing.auth;
+    if (config.outgoing.auth > 1)
     {
-      outServer.authMethod = 1;
-      outServer.useSecAuth = config.outgoing.auth == 2;
       outServer.username = config.incoming.username;
       outServer.password = config.incoming.password;
       if (config.rememberPassword && config.incoming.password.length)
         rememberPassword(outServer, config.incoming.password);
     }
-    else
-      outServer.authMethod = 0;
 
     if (config.outgoing.socketType == 1) // no SSL
-      outServer.trySSL = 0; // nsSmtpProtocol.h, line 115
+      outServer.socketType = Ci.nsMsgSocketType.plain;
     else if (config.outgoing.socketType == 2) // SSL / TLS
-      outServer.trySSL = 3;
+      outServer.socketType = Ci.nsMsgSocketType.SSL;
     else if (config.outgoing.socketType == 3) // STARTTLS
-      outServer.trySSL = 2;
+      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 (!smtpManager.defaultServer ||
--- a/mailnews/base/prefs/content/accountcreation/emailWizard.js
+++ b/mailnews/base/prefs/content/accountcreation/emailWizard.js
@@ -776,20 +776,22 @@ EmailConfigWizard.prototype =
       }
     }
 
     document.getElementById('create_button').disabled = true;
     var me = this;
     if (!this._verifiedConfig)
       this.verifyConfig(function(successfulConfig) // success
                         {
-                          // the incoming auth might have changed, so we
+                          // the auth might have changed, so we
                           // should back-port it to the current config.
                           me._currentConfigFilledIn.incoming.auth =
                               successfulConfig.incoming.auth;
+                          me._currentConfigFilledIn.outgoing.auth =
+                              successfulConfig.outgoing.auth;
                           me.finish();
                         },
                         function(e) // failure
                         {
                           document.getElementById('create_button').disabled = false;
                           me.editConfigDetails();
                         });
     else
--- a/mailnews/base/prefs/content/accountcreation/guessConfig.js
+++ b/mailnews/base/prefs/content/accountcreation/guessConfig.js
@@ -141,57 +141,58 @@ function guessConfig(domain, progressCal
     }
     if ((incomingDone || incomingEx) && (outgoingDone || outgoingEx))
     {
       successCallback(resultConfig);
       return;
     }
   };
 
-  var outgoingSuccess = function(type, hostname, port, ssl, secureAuth,
+  var outgoingSuccess = function(type, hostname, port, ssl, authMethods,
                                   badCert, targetSite)
   {
     assert(type == SMTP, "I only know SMTP for outgoing");
     // Ensure there are no previously saved outgoing errors if we've got success
     // here.
     outgoingEx = null;
     resultConfig.outgoing.hostname = hostname;
     resultConfig.outgoing.port = port;
-    // non-auth smtp servers must be rare at this point.
-    resultConfig.outgoing.auth = 1;
     resultConfig.outgoing.socketType = sslConvertToSocketType(ssl);
+    resultConfig.outgoing.auth = chooseBestAuthMethod(authMethods);
+    resultConfig.outgoing.authAlternatives = authMethods;
     resultConfig.outgoing.badCert = badCert;
 
     progressCallback(protocolToString(type), hostname, port,
                      sslConvertToSocketType(ssl), true, resultConfig);
     outgoingDone = true;
     checkDone();
   };
 
   var outgoingError = function(ex)
   {
     outgoingEx = ex;
     checkDone();
   };
 
-  var incomingSuccess = function(type, hostname, port, ssl, secureAuth, badCert,
+  var incomingSuccess = function(type, hostname, port, ssl, authMethods, badCert,
                                  targetSite)
   {
     ddump("incomingSuccess outgoingDone = " + outgoingDone + "\n");
     ddump("incoming success username = " + resultConfig.incoming.username + "\n");
     // Ensure there are no previously saved incoming errors if we've got success
     // here.
     incomingEx = null;
     resultConfig.incoming.hostname = hostname;
     resultConfig.incoming.port = port;
     resultConfig.incoming.type = protocolToString(type);
     resultConfig.incoming.socketType =  sslConvertToSocketType(ssl);
+    resultConfig.incoming.auth = chooseBestAuthMethod(authMethods);
+    resultConfig.incoming.authAlternatives = authMethods;
     resultConfig.incoming.badCert = badCert;
     resultConfig.incoming.targetSite = targetSite;
-    resultConfig.incoming.auth = secureAuth ? 2 : 1;
 
     progressCallback(protocolToString(type), hostname, port,
                      sslConvertToSocketType(ssl), true, resultConfig);
     incomingDone = true;
     checkDone();
   };
 
   var incomingError = function(ex)
@@ -350,16 +351,19 @@ function protocolToString(type)
 
 /**
  * @param successCallback {function(type, hostname, port, ssl)} Called when the
  * config is OK
  *    type @see constants above
  *    hostname {String}
  *    port {Integer}
  *    ssl @see constants above
+ *    authMethods {Array of possible auth types}, @see _advertisesAuthMethods()
+ *    selfSignedCert {Boolean}
+ *    sslTargetSite {String}
  * @param errorCallback {function(ex)} Called when we could not find a config
  * @param progressCallback { function(hostname, port) } Called when we tried
  *    (will try?) a new hostname and port
  */
 function HostDetector(progressCallback, successCallback, errorCallback)
 {
   this._init(progressCallback, successCallback, errorCallback);
 }
@@ -538,26 +542,26 @@ HostDetector.prototype =
     else
     {
       if (curTry[1] != TLS || this._matchTLS(curTry, wiredata))
       {
         this._log.info("non-null data: " + wiredata.toString());
         let type = curTry[0];
         let port = curTry[2];
         let ssl = curTry[1];
-        let secureAuth = this._advertisesSecureAuth(type, wiredata);
+        let authMethods = this._advertisesAuthMethods(type, wiredata); // TODO
         if (this._selfSignedCert)
         {
           // the callback will put up the cert exception dialog, so
           // clear the override here.
           this._log.info("clearing validity override");
           gOverrideService.clearValidityOverride(this._host, curTry[2]);
         }
         this._log.info("SUCCESS, _selfSignedCert = " + this._selfSignedCert);
-        this.mSuccessCallback(type, this._host, port, ssl, secureAuth,
+        this.mSuccessCallback(type, this._host, port, ssl, authMethods,
                               this._selfSignedCert, this._targetSite);
         return; // stop trying, you're done!
       }
     }
 
     // report success if you found it.
     this.keepTrying()
   },
@@ -565,42 +569,70 @@ HostDetector.prototype =
   cancel : function()
   {
     this._cancel = true;
     // XXX this is not enough -- we have to actively stop the network calls, as
     // they may result in callbacks e.g. to the cert handler.  If the dialog is
     // gone by the time this happens, the javascript stack is horked.
   },
 
-  _advertisesSecureAuth : function(protocol, capaResponse)
+  /**
+   * Which auth mechanism the server claims to support.
+   * (That doesn't necessarily reflect reality, it is more an upper bound.)
+   * @returns Array with values for AccountConfig.incoming/outgoing.auth ,
+   * in decreasing order of preference.
+   * E.g. [ 5, 4 ] for a server that supports only Kerberos and encrypted passwords.
+   */
+  _advertisesAuthMethods : function(protocol, capaResponse)
   {
-    // for imap to support secure auth,
-    // capabilities needs to return 1 or more of the following:
+    // for imap, capabilities contain one or more of the following for secure auth:
     // "AUTH=CRAM-MD5", "AUTH=NTLM", "AUTH=GSSAPI", "AUTH=MSN"
     // for pop3, the auth mechanisms are returned in capa as the following:
     // "CRAM-MD5", "NTLM", "MSN", "GSSAPI"
     // For smtp, EHLO will return AUTH and then a list of the
     // mechanism(s) supported, e.g.,
     // AUTH LOGIN NTLM MSN CRAM-MD5 GSSAPI
+    var result = new Array();
     let line = capaResponse.join("\n")
+    var prefix = "";
     if (protocol == POP)
-      return /CRAM-MD5|NTLM|MSN|GSSAPI/.test(line);
-    if (protocol == IMAP)
-      return /AUTH=(CRAM-MD5|NTLM|MSN|GSSAPI)/.test(line);
-    if (protocol == SMTP)
-      return /AUTH (CRAM-MD5|NTLM|MSN|GSSAPI)/.test(line);
+      prefix = "";
+    else if (protocol == IMAP)
+      prefix = "AUTH=";
+    else if (protocol == SMTP)
+      prefix = "AUTH ";
+    if (new RegExp(prefix + "GSSAPI").test(line))
+      result.push(Ci.nsMsgAuthMethod.GSSAPI);
+    if (new RegExp(prefix + "(NTLM|MSN)").test(line))
+      result.push(Ci.nsMsgAuthMethod.NTLM);
+    if (new RegExp(prefix + "CRAM-MD5").test(line))
+      result.push(Ci.nsMsgAuthMethod.passwordEncrypted);
+    if ( ! (protocol == IMAP && /LOGINDISABLED/.test(line)))
+      result.push(Ci.nsMsgAuthMethod.passwordCleartext);
+    return result;
   },
 
   _matchTLS : function(curTry, result)
   {
       return curTry != null && curTry[1] == TLS &&
              hasTLS(result.join("\n"), curTry[0]);
   }
 }
 
+/**
+ * @param authMethods @see return value of _advertisesAuthMethods()
+ * @return one of them, the preferred one
+ * Note: this might be Kerberos, which might not actually work,
+ * so you might need to try the others, too.
+ */
+function chooseBestAuthMethod(authMethods)
+{
+  return authMethods[0]; // take first (= most preferred)
+}
+
 function IncomingHostDetector(progressCallback, successCallback, errorCallback)
 {
   this._init(progressCallback, successCallback, errorCallback);
 }
 
 IncomingHostDetector.prototype =
 {
   __proto__ : new HostDetector(),
--- a/mailnews/base/prefs/content/accountcreation/readFromXML.js
+++ b/mailnews/base/prefs/content/accountcreation/readFromXML.js
@@ -69,17 +69,24 @@ function readFromXML(clientConfigXML)
 
   // incoming server
   var iX = xml.incomingServer; // input (XML)
   var iO = d.incoming; // output (object)
   iO.type = sanitize.enum(iX.@type, ["pop3", "imap", "nntp"]);
   iO.hostname = sanitize.hostname(iX.hostname);
   iO.port = sanitize.integerRange(iX.port, 1, 65535);
   iO.username = sanitize.string(iX.username); // may be a %VARIABLE%
-  iO.auth = sanitize.translate(iX.authentication, { plain : 1, secure : 2 }); // TODO "secure"
+  iO.auth = sanitize.translate(iX.authentication,
+        { "password-clear" : Ci.nsMsgAuthMethod.passwordCleartext,
+          plain : Ci.nsMsgAuthMethod.passwordCleartext,
+          "password-encrypted" : Ci.nsMsgAuthMethod.passwordEncrypted,
+          secure : Ci.nsMsgAuthMethod.passwordEncrypted,
+          GSSAPI : Ci.nsMsgAuthMethod.GSSAPI,
+          NTLM : Ci.nsMsgAuthMethod.NTLM });
+  ddump("<authentication> = " + iX.authentication + ", incom.authMethod = " + iO.auth);
   iO.socketType = sanitize.translate(iX.socketType, { plain : 1, SSL: 2, STARTTLS: 3 });
   if (iO.type == "pop3" && "pop3" in iX)
   {
     if ("leaveMessagesOnServer" in iX.pop3)
       iO.leaveMessagesOnServer = sanitize.boolean(iX.pop3.leaveMessagesOnServer);
     if ("daysToLeaveMessagesOnServer" in iX.pop3)
       iO.daysToLeaveMessagesOnServer = sanitize.integer(iX.pop3.daysToLeaveMessagesOnServer);
     if ("downloadOnBiff" in iX.pop3)
@@ -97,19 +104,26 @@ function readFromXML(clientConfigXML)
   oO.hostname = sanitize.hostname(oX.hostname);
   oO.port = sanitize.integerRange(oX.port, 1, 65535);
   if ("username" in oX)
     oO.username = sanitize.string(oX.username);
 
   oO.socketType = sanitize.translate(oX.socketType,
                                      { plain : 1, SSL: 2, STARTTLS: 3 });
   oO.auth = sanitize.translate(oX.authentication,
-                               { none : 0 /* e.g. IP-address-based */,
-                                 plain : 1, secure : 2,  // TODO "secure"
-                                 "smtp-after-pop" : 0 /* hope for the best */});
+        { none : Ci.nsMsgAuthMethod.none, // open relay
+          "client-IP-address" : Ci.nsMsgAuthMethod.none, // inside ISP or corp network
+          "smtp-after-pop" : Ci.nsMsgAuthMethod.none, // hope for the best
+          "password-clear" : Ci.nsMsgAuthMethod.passwordCleartext,
+          plain : Ci.nsMsgAuthMethod.passwordCleartext,
+          "password-encrypted" : Ci.nsMsgAuthMethod.passwordEncrypted,
+          secure : Ci.nsMsgAuthMethod.passwordEncrypted,
+          GSSAPI : Ci.nsMsgAuthMethod.GSSAPI,
+          NTLM : Ci.nsMsgAuthMethod.NTLM });
+  ddump("<authentication> = " + iX.authentication + ", outgoing.authMethod = " + oO.auth);
   if ("addThisServer" in oX)
     oO.addThisServer = sanitize.boolean(oX.addThisServer);
   if ("useGlobalPreferredServer" in oX)
     oO.useGlobalPreferredServer = sanitize.boolean(oX.useGlobalPreferredServer);
 
   for each (var inputField in xml.inputField)
   {
     if (!d.inputFields)
--- a/mailnews/base/prefs/content/accountcreation/verifyConfig.js
+++ b/mailnews/base/prefs/content/accountcreation/verifyConfig.js
@@ -80,25 +80,22 @@ function verifyConfig(config, alter, msg
   var inServer =
     accountManager.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.nsIMsgIncomingServer.defaultSocket;
+    inServer.socketType = Ci.nsMsgSocketType.plain;
   else if (config.incoming.socketType == 2) // SSL
-    inServer.socketType = Ci.nsIMsgIncomingServer.useSSL;
-  else if (config.incoming.socketType == 3) // TLS
-    inServer.socketType = Ci.nsIMsgIncomingServer.alwaysUseTLS;
-
-  // auth
-  if (config.incoming.auth == 2) // "secure" auth
-    inServer.useSecAuth = true;
+    inServer.socketType = Ci.nsMsgSocketType.SSL;
+  else if (config.incoming.socketType == 3) // STARTTLS
+    inServer.socketType = Ci.nsMsgSocketType.alwaysSTARTTLS;
+  inServer.authMethod = config.incoming.auth;
 
   try {
     if (inServer.password)
       verifyLogon(config, inServer, alter, msgWindow,
                   successCallback, errorCallback);
     else {
       // Avoid pref pollution, clear out server prefs.
       accountManager.removeIncomingServer(inServer, true);
@@ -155,20 +152,20 @@ function urlListener(config, server, alt
   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));
-    this._log.info("  secAuth=" + this.mServer.useSecAuth);
-    this._log.info("  savedUsername=" +
-                   (this.mConfig.usernameSaved ? "true" : "false"));
+                          this.mConfig.identity.emailAddress) +
+                          ", have savedUsername=" +
+                          (this.mConfig.usernameSaved ? "true" : "false"));
+    this._log.info("  authMethod=" + this.mServer.authMethod);
   },
 
   OnStopRunningUrl: function(aUrl, aExitCode)
   {
     if (Components.isSuccessCode(aExitCode))
     {
       this._cleanup();
       this.mSuccessCallback(this.mConfig);
@@ -180,29 +177,28 @@ urlListener.prototype =
       var stringBundle = getStringBundle("chrome://messenger/locale/accountCreationModel.properties");
       var errorMsg = stringBundle.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)
     {
-      ddump("trying next logon\n");
       this.tryNextLogon()
     }
   },
 
   tryNextLogon: function()
   {
     this._log.info("tryNextLogon()");
     this._log.info("  username=" + (this.mConfig.incoming.username !=
-                                    this.mConfig.identity.emailAddress));
-    this._log.info("  secAuth=" + this.mServer.useSecAuth);
-    this._log.info("  savedUsername=" +
-                   (this.mConfig.usernameSaved ? "true" : "false"));
+                          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.mServer.username = this.mConfig.incoming.username;
       this.mServer.password = this.mConfig.incoming.password;
@@ -219,34 +215,47 @@ urlListener.prototype =
       this.mConfig.incoming.username = this.mConfig.usernameSaved;
       this.mConfig.usernameSaved = null;
     }
 
     // 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
-    if (this.mServer.useSecAuth &&
-        (this.mServer.socketType == Ci.nsIMsgIncomingServer.useSSL ||
-         this.mServer.socketType == Ci.nsIMsgIncomingServer.alwaysUseTLS))
+    assert(this.mConfig.incoming.auth == this.mServer.authMethod);
+    assert(!this.mConfig.incoming.authAlternatives ||
+           this.mConfig.incoming.auth == this.mConfig.incoming.authAlternatives[0]);
+    this._log.info("  Using SSL: " +
+        (this.mServer.socketType == Ci.nsMsgSocketType.SSL ||
+         this.mServer.socketType == Ci.nsMsgSocketType.alwaysSTARTTLS));
+    this._log.info("  auth alternatives count = " + (this.mConfig.incoming.authAlternatives ?
+         this.mConfig.incoming.authAlternatives.length : "none"));
+    if (this.mConfig.incoming.authAlternatives &&
+        this.mConfig.incoming.authAlternatives.length > 1)/* &&
+        (this.mConfig.incoming.authAlternatives[1] >
+            Ci.nsMsgAuthMethod.passwordCleartext || // next best auth is secure
+         this.mServer.socketType == Ci.nsMsgSocketType.SSL ||
+         this.mServer.socketType == Ci.nsMsgSocketType.alwaysSTARTTLS))*/
     {
-      this._log.info("  Changing useSecAuth to false.");
-      this._log.info("  password=" +
+      this._log.info("  Decreasing auth.");
+      this._log.info("  Have password: " +
                      (this.mServer.password ? "true" : "false"));
-      this.mConfig.incoming.auth = 1; // "insecure" auth
-      this.mServer.useSecAuth = false;
+      this.mConfig.incoming.authAlternatives.shift(); // it failed, so remove it from list of possibilities
+      this.mConfig.incoming.auth = this.mConfig.incoming.authAlternatives[0]; // take the next best method
+      this.mConfig.outgoing.auth = this.mConfig.incoming.auth; // TODO good idea???
+      this.mServer.authMethod = this.mConfig.incoming.auth;
       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;
     }
 
     // Tried all variations we can. Give up.
-    this._log.info("  Giving up.");
+    this._log.info("Giving up.");
     this._cleanup();
     let stringBundle = getStringBundle("chrome://messenger/locale/accountCreationModel.properties");
     let errorMsg = stringBundle.GetStringFromName("cannot_login.error");
     this.mErrorCallback(new Exception(errorMsg));
     return;
   },
 
   _cleanup : function()
@@ -260,29 +269,29 @@ urlListener.prototype =
   },
 
   // Suppress any certificate errors
   notifyCertProblem: function(socketInfo, status, targetSite) {
     if (!status)
       return true;
 
     this.mCertError = true;
-    ddump("got cert error\n");
+    this._log.error("cert error");
     setTimeout(this.informUserOfCertError, 0, socketInfo, targetSite, this);
     return true;
   },
 
   informUserOfCertError : function(socketInfo, targetSite, self) {
     let params = { exceptionAdded : false };
     params.prefetchCert = true;
     params.location = targetSite;
     window.openDialog("chrome://pippki/content/exceptionDialog.xul",
                       "","chrome,centerscreen,modal", params);
-    ddump("after exception dialog\n");
-    ddump("exceptionAdded = " + params.exceptionAdded + "\n");
+    self._log.info("cert exception dialog closed");
+    self._log.info("cert exceptionAdded = " + params.exceptionAdded);
     if (!params.exceptionAdded) {
       self._cleanup();
       let stringBundle = getStringBundle("chrome://messenger/locale/accountCreationModel.properties");
       let errorMsg = stringBundle.GetStringFromName("cannot_login.error");
       self.mErrorCallback(new Exception(errorMsg));
     }
     else {
       // Retry the logon now that we've added the cert exception.
--- a/mailnews/base/prefs/content/am-server.js
+++ b/mailnews/base/prefs/content/am-server.js
@@ -39,34 +39,33 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 var gServer;
 var gObserver;
+const Ci = Components.interfaces;
 
 function onInit(aPageId, aServerId) 
 {
   initServerType();
 
   onCheckItem("server.biffMinutes", "server.doBiff");
   onCheckItem("nntp.maxArticles", "nntp.notifyOn");
   setupMailOnServerUI();
   setupFixedUI();
   if (document.getElementById("server.type").getAttribute("value") == "imap")
     setupImapDeleteUI(aServerId);
 
   // "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.
-  var hidden = (document.getElementById("server.socketType").value !=
-                Components.interfaces.nsIMsgIncomingServer.tryTLS);
-  document.getElementById("connectionSecurityType-1").hidden = hidden;
+  hideUnlessSelected(document.getElementById("connectionSecurityType-1"));
 }
 
 function onPreInit(account, accountValues)
 {
   var type = parent.getAccountValue(account, accountValues, "server", "type", null, false);
   hideShowControls(type);
 
   gObserver= Components.classes["@mozilla.org/observer-service;1"].
@@ -86,22 +85,44 @@ 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);
 
-  var isSecureSelected = (document.getElementById("server.socketType").value ==
-                          Components.interfaces.nsIMsgIncomingServer.useSSL);
+  secureSelect();
+
+  setLabelFromStringBundle("authMethod-no", "authNo");
+  setLabelFromStringBundle("authMethod-old", "authOld");
+  setLabelFromStringBundle("authMethod-kerberos", "authKerberos");
+  setLabelFromStringBundle("authMethod-ntlm", "authNTLM");
+  setLabelFromStringBundle("authMethod-anysecure", "authAnySecure");
+  setLabelFromStringBundle("authMethod-any", "authAny");
+  setLabelFromStringBundle("authMethod-password-encrypted",
+      "authPasswordEncrypted");
+  //authMethod-password-cleartext already set in selectSelect()
 
-  var protocolInfo = Components.classes["@mozilla.org/messenger/protocol/info;1?type=" + serverType]
-                               .getService(Components.interfaces.nsIMsgProtocolInfo);
-  document.getElementById("defaultPort").value = protocolInfo.getDefaultServerPort(isSecureSelected);
+  // 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);
@@ -159,38 +180,42 @@ function onAdvanced()
     var pop3Server = gServer.QueryInterface(Components.interfaces.nsIPop3IncomingServer);
     // we're explicitly setting this so we'll go through the SetDeferredToAccount method
     pop3Server.deferredToAccount = serverSettings.deferredToAccount;
   }
 }
 
 function secureSelect()
 {
-    var serverType   = document.getElementById("server.type").getAttribute("value");
+    var socketType = document.getElementById("server.socketType").value;
+    var serverType = document.getElementById("server.type").value;
     var protocolInfo = Components.classes["@mozilla.org/messenger/protocol/info;1?type=" + serverType]
                                  .getService(Components.interfaces.nsIMsgProtocolInfo);
 
-    var isSecureSelected = (document.getElementById("server.socketType").value ==
-                            Components.interfaces.nsIMsgIncomingServer.useSSL);
-
     var defaultPort = protocolInfo.getDefaultServerPort(false);
     var defaultPortSecure = protocolInfo.getDefaultServerPort(true);
     var port = document.getElementById("server.port");
     var portDefault = document.getElementById("defaultPort");
     var prevDefaultPort = portDefault.value;
 
-    if (isSecureSelected) {
+    if (socketType == Ci.nsMsgSocketType.SSL) {
       portDefault.value = defaultPortSecure;
       if (port.value == "" || (port.value == defaultPort && prevDefaultPort != portDefault.value))
         port.value = defaultPortSecure;
     } else {
         portDefault.value = defaultPort;
         if (port.value == "" || (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 onCheckItem(changeElementId, checkElementId)
 {
     var element = document.getElementById(changeElementId);
     var notify = document.getElementById(checkElementId);
     var checked = notify.checked;
 
--- a/mailnews/base/prefs/content/am-server.xul
+++ b/mailnews/base/prefs/content/am-server.xul
@@ -111,39 +111,63 @@
       </row>
     </rows>
   </grid>
 
   <separator class="thin"/>
 
   <groupbox hidefor="movemail">
     <caption label="&securitySettings.label;"/>
-    <hbox 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>
-    </hbox>
 
-    <checkbox wsm_persist="true" id="server.useSecAuth"
-              label="&useSecAuth.label;" hidefor="nntp,movemail"
-              accesskey="&useSecAuth.accesskey;"
-              prefattribute="value"
-              prefstring="mail.server.%serverkey%.useSecAuth"/>
+    <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-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;"
--- a/mailnews/base/prefs/content/am-smtp.js
+++ b/mailnews/base/prefs/content/am-smtp.js
@@ -134,19 +134,53 @@ var gSmtpServerListWindow =
   {
     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.trySSL);
-    document.getElementById('useSecureAuthenticationValue').value =
-      this.mBundle.getString("smtpServer-SecureAuthentication-Type-" + aServer.useSecAuth);
+      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;
+      default:
+        // leave empty
+        dump("Warning: unknown value for smtpserver...authMethod: " +
+             aServer.authMethod + "\n");
+    }
+    if (authStr)
+      document.getElementById("authMethodValue").value =
+          this.mBundle.getString(authStr);
   },
 
   refreshServerList: function(aServerKeyToSelect, aFocusList)
   {
     // remove all children
     while (this.mServerList.hasChildNodes())
       this.mServerList.removeChild(this.mServerList.lastChild);
 
--- a/mailnews/base/prefs/content/am-smtp.xul
+++ b/mailnews/base/prefs/content/am-smtp.xul
@@ -1,14 +1,12 @@
 <?xml version="1.0"?>
 
 <?xml-stylesheet href="chrome://messenger/skin/accountManage.css" type="text/css"?>
 
-<?xul-overlay href="chrome://messenger/content/smtpEditOverlay.xul"?>
-
 <!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="amUtils.js"/>
   <script type="application/javascript" src="am-smtp.js"/>
   
@@ -62,18 +60,18 @@
             <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="useSecureAuthenticationLabel" value="&useSecureAuthentication.label;" control="useSecureAuthenticationValue"/></hbox>
-              <textbox id="useSecureAuthenticationValue" readonly="true" class="plain"/>
+              <hbox pack="end"><label 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>
--- a/mailnews/base/prefs/content/smtpEditOverlay.js
+++ b/mailnews/base/prefs/content/smtpEditOverlay.js
@@ -40,167 +40,168 @@
 // 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 gSmtpUseSecAuth;
-var gSmtpUseUsername;
 var gSmtpAuthMethod;
-var gSmtpTrySSL;
+var gSmtpSocketType;
 var gSmtpPrefBranch;
 var gPrefBranch = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
 var gSmtpService = Components.classes["@mozilla.org/messengercompose/smtp;1"].getService(Components.interfaces.nsISmtpService);
-var gSavedUsername = "";
 var gPort;
 var gDefaultPort;
+const 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");
-    gSmtpUseUsername = document.getElementById("smtp.useUsername");
     gSmtpAuthMethod = document.getElementById("smtp.authMethod");
-    gSmtpTrySSL = document.getElementById("smtp.trySSL");
-    gSmtpUseSecAuth = document.getElementById("smtp.useSecAuth");
+    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 ? server.port : "";
         gSmtpUsername.value = server.username;
-        gSmtpAuthMethod.setAttribute("value", server.authMethod);
-        gSmtpTrySSL.value = (server.trySSL < 4) ? server.trySSL : 1;
-        gSmtpUseSecAuth.checked = server.useSecAuth == "1";
+        gSmtpAuthMethod.value = server.authMethod;
+        gSmtpSocketType.value = (server.socketType < 4) ? server.socketType : 1;
     } else {
-        const PREF_AUTH_ANY = 1; // From nsSmtpProtocol.h
-        gSmtpAuthMethod.setAttribute("value", PREF_AUTH_ANY);
-        const PREF_SECURE_NEVER = 0; // From nsSmtpProtocol.h
-        gSmtpTrySSL.value = PREF_SECURE_NEVER;
+        // When does that happen? TODO Get default prefs, if realistic, otherwise remove
+        gSmtpAuthMethod.value = 3; // cleartext
+        gSmtpSocketType.value = 0;
     }
 
-    gSmtpUseUsername.checked = (gSmtpAuthMethod.getAttribute("value") == "1");
+    sslChanged(false);
+    authMethodChanged(false);
 
-    //dump("gSmtpAuthMethod = <" + gSmtpAuthMethod.localName + ">\n");
-    //dump("gSmtpAuthMethod.value = " + gSmtpAuthMethod.getAttribute("value") + "\n");
-
-    onUseUsername(gSmtpUseUsername, false);
-    selectProtocol(false);
     if (gSmtpService.defaultServer)
       onLockPreference();
 
-    //"STARTTLS, if available" is vulnerable to MITM attacks so we shouldn't
+    setLabelFromStringBundle("authMethod-no", "authNo");
+    setLabelFromStringBundle("authMethod-kerberos", "authKerberos");
+    setLabelFromStringBundle("authMethod-ntlm", "authNTLM");
+    setLabelFromStringBundle("authMethod-anysecure", "authAnySecure");
+    setLabelFromStringBundle("authMethod-any", "authAny");
+    setLabelFromStringBundle("authMethod-password-encrypted",
+        "authPasswordEncrypted");
+    //authMethod-password-cleartext already set in sslChanged()
+
+    // 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.
-    const PREF_SECURE_TRY_STARTTLS = 1; // From nsSmtpProtocol.h
-    var hidden = (document.getElementById("smtp.trySSL").value != PREF_SECURE_TRY_STARTTLS);
-    document.getElementById("connectionSecurityType-1").hidden = hidden;
+    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()
 {
-    var defaultSmtpServerKey = gPrefBranch.getCharPref("mail.smtp.defaultserver");
-    var finalPrefString = "mail.smtpserver." + defaultSmtpServerKey + "."; 
+  try {
+    var finalPrefString = "mail.smtpserver." +
+        gSmtpService.defaultServer.key + ".";
 
     var prefService = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService);
 
     var allPrefElements = {
       hostname:     gSmtpHostname,
       description:  gSmtpDescription,
       port:         gSmtpPort,
-      use_username: gSmtpUseUsername,
-      try_ssl:      gSmtpTrySSL
+      authMethod:   gSmtpAuthMethod,
+      try_ssl:      gSmtpSocketType
     };
 
     gSmtpPrefBranch = prefService.getBranch(finalPrefString);
     disableIfLocked( allPrefElements );
+  } catch (e) { dump("error while locking prefs: " + e + "\n"); } // non-fatal
 } 
 
 // 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 )
 {
   for (var prefstring in prefstrArray)
     if (gSmtpPrefBranch.prefIsLocked(prefstring))
       prefstrArray[prefstring].disabled = true;
 }
 
 function saveSmtpSettings(server)
 {
-    gSmtpAuthMethod.setAttribute("value", gSmtpUseUsername.checked ? "1" : "0");
-
     //dump("Saving to " + server + "\n");
     if (server) {
         server.hostname = gSmtpHostname.value;
         server.description = gSmtpDescription.value;
         server.port = gSmtpPort.value;
-        server.authMethod = (gSmtpUseUsername.checked ? 1 : 0);
-        //dump("Saved authmethod = " + server.authMethod +
-        //     " but checked = " + gSmtpUseUsername.checked + "\n");
+        server.authMethod = gSmtpAuthMethod.value;
         server.username = gSmtpUsername.value;
-        server.trySSL = gSmtpTrySSL.value;
-        server.useSecAuth = gSmtpUseSecAuth.checked;
+        server.socketType = gSmtpSocketType.value;
     }
 }
 
-function onUseUsername(checkbox, dofocus)
+function authMethodChanged(userAction)
 {
-    if (checkbox.checked) {
-        // not only do we enable the elements when the check box is checked,
-        // but we also make sure that it's not disabled (ie locked) as well.
-        if (!checkbox.disabled) {
-            gSmtpUsername.removeAttribute("disabled");
-            gSmtpUsernameLabel.removeAttribute("disabled");
-            gSmtpUseSecAuth.removeAttribute("disabled");
-        }
-        if (dofocus)
-            gSmtpUsername.focus();
-        if (gSavedUsername && gSavedUsername != "")
-            gSmtpUsername.value = gSavedUsername;
-    } else {
-        gSavedUsername = gSmtpUsername.value;
-        gSmtpUsername.value = "";
-        gSmtpUsername.setAttribute("disabled", "true");
-        gSmtpUsernameLabel.setAttribute("disabled", "true");
-        gSmtpUseSecAuth.setAttribute("disabled", "true");
-    }
+  var noUsername = gSmtpAuthMethod.value == Ci.nsMsgAuthMethod.none;
+  gSmtpUsername.disabled = noUsername;
+  gSmtpUsernameLabel.disabled = noUsername;
 }
 
 /**
- * Resets the default port to SMTP or SMTPS, dependending on |gSmtpTrySSL| value,
- * and sets the port to use to this default, if that's appropriate.
+ * 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 selectProtocol(userAction) {
+function sslChanged(userAction)
+{
   const DEFAULT_SMTP_PORT = "25";
   const DEFAULT_SMTPS_PORT = "465";
-
+  var socketType = gSmtpSocketType.value;
   var otherDefaultPort;
   var prevDefaultPort = gDefaultPort.value;
 
-  if (gSmtpTrySSL.value == 3) {
+  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 == "") ||
       (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");
 }
--- a/mailnews/base/prefs/content/smtpEditOverlay.xul
+++ b/mailnews/base/prefs/content/smtpEditOverlay.xul
@@ -50,85 +50,99 @@
           <caption label="&settings.caption;"/>
           <grid flex="1">
               <columns>
                   <column/>
                   <column flex="1"/>
               </columns>
               <rows>
                   <row align="center">
-                      <hbox pack="end"><label value="&serverDescription.label;" accesskey="&serverDescription.accesskey;"
-                                              control="smtp.description"/></hbox>
+                       <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">
-                      <hbox pack="end"><label value="&serverName.label;" accesskey="&serverName.accesskey;" control="smtp.hostname"/></hbox>
+                      <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">
-                      <hbox pack="end"><label value="&serverPort.label;" accesskey="&serverPort.accesskey;" control="smtp.port"/>
-                      </hbox>
-
+                      <label value="&serverPort.label;"
+                             accesskey="&serverPort.accesskey;"
+                             control="smtp.port"/>
                       <hbox align="center">
                           <textbox id="smtp.port" size="4"
                                    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;"/>
-        <vbox>
-            <!-- This hidden one will hold the integer version
-                 of smtp.useUsername -->
-            <label hidden="true" id="smtp.authMethod"/>
-            <hbox align="center">
-            <checkbox id="smtp.useUsername" label="&alwaysUseUsername.label;"
-                      accesskey="&alwaysUseUsername.accesskey;"
-                      oncommand="onUseUsername(event.target,true);"
-                      prefattribute="value"
-                      prefstring="mail.smtpserver.%serverkey%.use_username"/>
-            </hbox>
-            <vbox class="indent">
-              <hbox align="center">
+
+        <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-anysecure" value="8"/>
+                  <menuitem id="authMethod-any" value="9"/>
+                </menupopup>
+              </menulist>
+            </row>
+            <row id="smtp.username.box" align="center">
+              <hbox class="indent">
                 <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"/>
+                       accesskey="&userName.accesskey;"
+                       control="smtp.username"/>
               </hbox>
-              <checkbox id="smtp.useSecAuth"
-                        label="&useSecAuth.label;"
-                        accesskey="&useSecAuth.accesskey;"
-                        prefattribute="value"
-                        prefstring="mail.smtpserver.%serverkey%.useSecAuth"/>
-            </vbox>
-        </vbox>
-
-        <separator class="thin"/>
-
-        <hbox align="center">
-          <label value="&connectionSecurity.label;"
-                accesskey="&connectionSecurity.accesskey;"
-                control="smtp.trySSL"/>
-          <menulist id="smtp.trySSL" oncommand="selectProtocol(true);"
-                    prefstring="mail.smtpserver.%serverkey%.try_ssl">
-            <menupopup id="smtp.trySSLPopup">
-              <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>
-        </hbox>
-      </groupbox>
+              <textbox id="smtp.username" flex="1"
+                       preftype="string"
+                       prefstring="mail.smtpserver.%serverkey%.username"/>
+            </row>
+          </rows>
+        </grid>
+     </groupbox>
   </vbox>
 </overlay>
--- a/mailnews/base/public/MailNewsTypes2.idl
+++ b/mailnews/base/public/MailNewsTypes2.idl
@@ -36,16 +36,18 @@
  * ***** END LICENSE BLOCK ***** */
 
 typedef unsigned long nsMsgKey;
 typedef unsigned long nsMsgViewIndex;
 
 typedef long nsMsgSearchScopeValue;
 
 typedef long nsMsgPriorityValue;
+typedef long nsMsgSocketTypeValue;
+typedef long nsMsgAuthMethodValue;
 
 typedef unsigned long nsMsgJunkStatus;
 
 typedef unsigned long nsMsgJunkScore;
 
 [scriptable, uuid(94C0D8D8-2045-11d3-8A8F-0060B0FC04D2)]
 interface nsMsgPriority {
     const nsMsgPriorityValue notSet = 0;
@@ -54,14 +56,65 @@ interface nsMsgPriority {
     const nsMsgPriorityValue low = 3;
     const nsMsgPriorityValue normal = 4;
     const nsMsgPriorityValue high = 5;
     const nsMsgPriorityValue highest = 6;
     // the default for a priority picker
     const nsMsgPriorityValue Default = 4;
 };
 
+/**
+ * Defines whether to use SSL or STARTTLS or not.
+ * Used by @see nsIMsgIncomingServer.socketType
+ * and @see nsISmtpServer.socketType
+ */
+[scriptable, uuid(bc78bc74-1b34-48e8-ac2b-968e8dff1aeb)]
+interface nsMsgSocketType {
+    /// No SSL or STARTTLS
+    const nsMsgSocketTypeValue plain = 0;
+    /// Use TLS via STARTTLS, but only if server offers it.
+    /// @deprecated This is vulnerable to MITM attacks
+    const nsMsgSocketTypeValue trySTARTTLS = 1;
+    /// Insist on TLS via STARTTLS.
+    /// Uses normal port.
+    const nsMsgSocketTypeValue alwaysSTARTTLS = 2;
+    /// Connect via SSL.
+    /// Needs special SSL port.
+    const nsMsgSocketTypeValue SSL = 3;
+};
+
+/**
+ * Defines which authentication schemes we should try.
+ * Used by @see nsIMsgIncomingServer.authMethod
+ * and @see nsISmtpServer.authMethod
+ */
+[scriptable, uuid(4a10e647-d179-4a53-b7ef-df575ff5f405)]
+interface nsMsgAuthMethod {
+    // 0 is intentionally undefined and invalid
+    /// No login needed. E.g. IP-address-based.
+    const nsMsgAuthMethodValue none = 1;
+    /// Do not use AUTH commands (e.g. AUTH=PLAIN),
+    /// but the original login commands that the protocol specified
+    /// (POP: "USER"/"PASS", IMAP: "login", not valid for SMTP)
+    const nsMsgAuthMethodValue old = 2;
+    /// password in the clear. AUTH=PLAIN/LOGIN or old-style login.
+    const nsMsgAuthMethodValue passwordCleartext = 3;
+    /// hashed password. CRAM-MD5, DIGEST-MD5
+    const nsMsgAuthMethodValue passwordEncrypted = 4;
+    /// Kerberos / GSSAPI (Unix single-signon)
+    const nsMsgAuthMethodValue GSSAPI = 5;
+    /// NTLM is a Windows single-singon scheme.
+    /// Includes MSN / Passport.net, which is the same with a different name.
+    const nsMsgAuthMethodValue NTLM = 6;
+    /// Encrypted password or Kerberos / GSSAPI or NTLM.
+    /// @deprecated - for migration only.
+    const nsMsgAuthMethodValue secure = 8;
+    /// Let us pick any of the auth types supported by the server.
+    /// Discouraged, because vulnerable to MITM attacks, even if server offers secure auth.
+    const nsMsgAuthMethodValue anything = 9;
+};
+
 typedef unsigned long nsMsgLabelValue;
 
 typedef long nsMsgViewSortOrderValue;
 typedef long nsMsgViewSortTypeValue;
 typedef long nsMsgViewTypeValue;
 typedef long nsMsgViewFlagsTypeValue;
--- a/mailnews/base/public/nsIMsgIncomingServer.idl
+++ b/mailnews/base/public/nsIMsgIncomingServer.idl
@@ -54,17 +54,17 @@ interface nsILocalFile;
 interface nsIURI;
 
 /*
  * Interface for incoming mail/news host
  * this is the base interface for all mail server types (imap, pop, nntp, etc)
  * often you will want to add extra interfaces that give you server-specific
  * attributes and methods.
  */
-[scriptable, uuid(cca9b826-24d8-4b76-b229-b8b12f1ecbd5)]
+[scriptable, uuid(798c89ed-2c25-4eaa-b34d-5b2c2ab62286)]
 interface nsIMsgIncomingServer : nsISupports {
 
   /**
    * internal pref key - guaranteed to be unique across all servers
    */
   attribute ACString key;
 
   /**
@@ -183,31 +183,31 @@ interface nsIMsgIncomingServer : nsISupp
      going off at the same time. */
   attribute boolean serverBusy;
 
   /**
    * Is the server using a secure channel (SSL or STARTTLS).
    */
   readonly attribute boolean isSecure;
 
-  /* should we use secure authentication? */
-  attribute boolean useSecAuth;
-
-  const long defaultSocket = 0;
-  const long tryTLS = 1;
-  const long alwaysUseTLS = 2;
-  const long useSSL = 3;
+  /**
+   * Authentication mechanism.
+   *
+   * @see nsMsgAuthMethod (in MailNewsTypes2.idl)
+   * Same as "mail.server...authMethod" pref
+   */
+  attribute nsMsgAuthMethodValue authMethod;
 
-  /* use above values */
-  attribute long socketType;
-
-  /* if a logon mechanism fails, should we fallback to a different
-     mechanism?
-  */
-  attribute boolean logonFallback;
+  /**
+   * Whether to SSL or STARTTLS or not
+   *
+   * @see nsMsgSocketType (in MailNewsTypes2.idl)
+   * Same as "mail.server...socketType" pref
+   */
+  attribute nsMsgSocketTypeValue socketType;
 
   /* dead code. */
   readonly attribute boolean isSecureServer;
 
   /* empty trash on exit */
   attribute boolean emptyTrashOnExit;
 
   /**
--- a/mailnews/base/util/Makefile.in
+++ b/mailnews/base/util/Makefile.in
@@ -133,16 +133,17 @@ EXTRA_JS_MODULES = \
 		errUtils.js \
 		iteratorUtils.jsm \
 		jsTreeSelection.js \
 		traceHelper.js \
 		autoconfigUtils.jsm \
 		StringBundle.js \
 		templateUtils.js \
 		IOUtils.js \
+		migration.jsm \
 		$(NULL)
 
 ifndef MOZ_STATIC_MAIL_BUILD
 
 ifdef MOZILLA_INTERNAL_API
 EXTRA_DSO_LDOPTS = \
 	$(LIBS_DIR) \
 	$(MOZDEPTH)/rdf/util/src/internal/$(LIB_PREFIX)rdfutil_s.$(LIB_SUFFIX) \
new file mode 100644
--- /dev/null
+++ b/mailnews/base/util/migration.jsm
@@ -0,0 +1,131 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is autoconfig code.
+ *
+ * The Initial Developer of the Original Code is
+ *   Ben Bucksch.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * Migrate profile (prefs and other files) from older versions of Mailnews to
+ * current.
+ * This should be run at startup. It migrates as needed: each migration
+ * function should be written to be a no-op when the value is already migrated
+ * or was never used in the old version.
+ */
+
+var EXPORTED_SYMBOLS = [ "migrateMailnews" ];
+
+Components.utils.import("resource://app/modules/errUtils.js");
+//Components.utils.import("resource://app/modules/Services.js");
+const Ci = Components.interfaces;
+var gPrefs;
+
+function migrateMailnews()
+{
+  try {
+    //gPrefs = Services.prefs; -- Gecko 1.9.3+
+    gPrefs = Components.classes["@mozilla.org/preferences-service;1"]
+        .getService(Ci.nsIPrefBranch);
+
+    MigrateServerAuthPref();
+  } catch (e) { logException(e); }
+}
+
+/**
+ * Migrates from pref useSecAuth to pref authMethod
+ */
+function MigrateServerAuthPref()
+{
+  try {
+    // comma-separated list of all accounts.
+    var accounts = gPrefs.getCharPref("mail.accountmanager.accounts")
+        .split(",");
+    for (let i = 0; i < accounts.length; i++)
+    {
+      let accountKey = accounts[i]; // e.g. "account1"
+      let serverKey = gPrefs.getCharPref("mail.account." + accountKey +
+         ".server");
+      let server = "mail.server." + serverKey + ".";
+      if (gPrefs.prefHasUserValue(server + "authMethod"))
+        continue;
+      if (!gPrefs.prefHasUserValue(server + "useSecAuth") &&
+          !gPrefs.prefHasUserValue(server + "auth_login"))
+        continue;
+      // auth_login = false => old-style auth
+      // else: useSecAuth = true => "secure auth"
+      // else: cleartext pw
+      let auth_login = true;
+      let useSecAuth = false; // old default, default pref now removed
+      try {
+        auth_login = gPrefs.getBoolPref(server + "auth_login");
+      } catch (e) {}
+      try {
+        useSecAuth = gPrefs.getBoolPref(server + "useSecAuth");
+      } catch (e) {}
+
+      gPrefs.setIntPref(server + "authMethod",
+          auth_login ? (useSecAuth ?
+                           Ci.nsMsgAuthMethod.secure :
+                           Ci.nsMsgAuthMethod.passwordCleartext) :
+                       Ci.nsMsgAuthMethod.old);
+    }
+
+    // same again for SMTP servers
+    var smtpservers = gPrefs.getCharPref("mail.smtpservers").split(",");
+    for (let i = 0; i < smtpservers.length; i++)
+    {
+      let server = "mail.smtpserver." + smtpservers[i] + ".";
+      if (gPrefs.prefHasUserValue(server + "authMethod"))
+        continue;
+      if (!gPrefs.prefHasUserValue(server + "useSecAuth") &&
+          !gPrefs.prefHasUserValue(server + "auth_method"))
+        continue;
+      // auth_method = 0 => no auth
+      // else: useSecAuth = true => "secure auth"
+      // else: cleartext pw
+      let auth_method = 1;
+      let useSecAuth = false;
+      try {
+        auth_method = gPrefs.getIntPref(server + "auth_method");
+      } catch (e) {}
+      try {
+        useSecAuth = gPrefs.getBoolPref(server + "useSecAuth");
+      } catch (e) {}
+
+      gPrefs.setIntPref(server + "authMethod",
+          auth_method ? (useSecAuth ?
+                            Ci.nsMsgAuthMethod.secure :
+                            Ci.nsMsgAuthMethod.passwordCleartext) :
+                        Ci.nsMsgAuthMethod.none);
+    }
+  } catch(e) { logException(e); }
+}
--- a/mailnews/base/util/nsMsgIncomingServer.cpp
+++ b/mailnews/base/util/nsMsgIncomingServer.cpp
@@ -1370,33 +1370,33 @@ nsMsgIncomingServer::GetPort(PRInt32 *aP
   // port based on the protocol
   nsCOMPtr<nsIMsgProtocolInfo> protocolInfo;
   rv = getProtocolInfo(getter_AddRefs(protocolInfo));
   NS_ENSURE_SUCCESS(rv, rv);
 
   PRInt32 socketType;
   rv = GetSocketType(&socketType);
   NS_ENSURE_SUCCESS(rv, rv);
-  PRBool useSSLPort = (socketType == nsIMsgIncomingServer::useSSL);
+  PRBool useSSLPort = (socketType == nsMsgSocketType::SSL);
   return protocolInfo->GetDefaultServerPort(useSSLPort, aPort);
 }
 
 NS_IMETHODIMP
 nsMsgIncomingServer::SetPort(PRInt32 aPort)
 {
   nsresult rv;
 
   nsCOMPtr<nsIMsgProtocolInfo> protocolInfo;
   rv = getProtocolInfo(getter_AddRefs(protocolInfo));
   NS_ENSURE_SUCCESS(rv, rv);
 
   PRInt32 socketType;
   rv = GetSocketType(&socketType);
   NS_ENSURE_SUCCESS(rv, rv);
-  PRBool useSSLPort = (socketType == nsIMsgIncomingServer::useSSL);
+  PRBool useSSLPort = (socketType == nsMsgSocketType::SSL);
 
   PRInt32 defaultPort;
   protocolInfo->GetDefaultServerPort(useSSLPort, &defaultPort);
   return SetIntValue("port", aPort == defaultPort ? PORT_NOT_SET : aPort);
 }
 
 nsresult
 nsMsgIncomingServer::getProtocolInfo(nsIMsgProtocolInfo **aResult)
@@ -1637,25 +1637,24 @@ nsMsgIncomingServer::GetSearchScope(nsMs
 
 NS_IMETHODIMP
 nsMsgIncomingServer::GetIsSecure(PRBool *aIsSecure)
 {
   NS_ENSURE_ARG_POINTER(aIsSecure);
   PRInt32 socketType;
   nsresult rv = GetSocketType(&socketType);
   NS_ENSURE_SUCCESS(rv,rv);
-  *aIsSecure = (socketType == nsIMsgIncomingServer::alwaysUseTLS ||
-                socketType == nsIMsgIncomingServer::useSSL);
+  *aIsSecure = (socketType == nsMsgSocketType::alwaysSTARTTLS ||
+                socketType == nsMsgSocketType::SSL);
   return NS_OK;
 }
 
 // use the convenience macros to implement the accessors
 NS_IMPL_SERVERPREF_STR(nsMsgIncomingServer, Username, "userName")
-NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer, UseSecAuth, "useSecAuth")
-NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer, LogonFallback, "logon_fallback")
+NS_IMPL_SERVERPREF_INT(nsMsgIncomingServer, AuthMethod, "authMethod")
 NS_IMPL_SERVERPREF_INT(nsMsgIncomingServer, BiffMinutes, "check_time")
 NS_IMPL_SERVERPREF_STR(nsMsgIncomingServer, Type, "type")
 // in 4.x, this was "mail.pop3_gets_new_mail" for pop and
 // "mail.imap.new_mail_get_headers" for imap (it was global)
 // in 5.0, this will be per server, and it will be "download_on_biff"
 NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer, DownloadOnBiff, "download_on_biff")
 NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer, Valid, "valid")
 NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer, EmptyTrashOnExit,
@@ -1695,47 +1694,47 @@ NS_IMETHODIMP nsMsgIncomingServer::GetSo
 
   // socketType is set to default value. Look at isSecure setting
   if (NS_FAILED(rv))
   {
     PRBool isSecure;
     rv = mPrefBranch->GetBoolPref("isSecure", &isSecure);
     if (NS_SUCCEEDED(rv) && isSecure)
     {
-      *aSocketType = nsIMsgIncomingServer::useSSL;
+      *aSocketType = nsMsgSocketType::SSL;
       // don't call virtual method in case overrides call GetSocketType
       nsMsgIncomingServer::SetSocketType(*aSocketType);
     }
     else
     {
       if (!mDefPrefBranch)
         return NS_ERROR_NOT_INITIALIZED;
       rv = mDefPrefBranch->GetIntPref("socketType", aSocketType);
       if (NS_FAILED(rv))
-        *aSocketType = nsIMsgIncomingServer::defaultSocket;
+        *aSocketType = nsMsgSocketType::plain;
     }
   }
   return rv;
 }
 
 NS_IMETHODIMP nsMsgIncomingServer::SetSocketType(PRInt32 aSocketType)
 {
   if (!mPrefBranch)
     return NS_ERROR_NOT_INITIALIZED;
 
-  PRInt32 socketType = nsIMsgIncomingServer::defaultSocket;
+  PRInt32 socketType = nsMsgSocketType::plain;
   mPrefBranch->GetIntPref("socketType", &socketType);
 
   nsresult rv = mPrefBranch->SetIntPref("socketType", aSocketType);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  PRBool isSecureOld = (socketType == nsIMsgIncomingServer::alwaysUseTLS ||
-                        socketType == nsIMsgIncomingServer::useSSL);
-  PRBool isSecureNew = (aSocketType == nsIMsgIncomingServer::alwaysUseTLS ||
-                        aSocketType == nsIMsgIncomingServer::useSSL);
+  PRBool isSecureOld = (socketType == nsMsgSocketType::alwaysSTARTTLS ||
+                        socketType == nsMsgSocketType::SSL);
+  PRBool isSecureNew = (aSocketType == nsMsgSocketType::alwaysSTARTTLS ||
+                        aSocketType == nsMsgSocketType::SSL);
   if ((isSecureOld != isSecureNew) && m_rootFolder)
     m_rootFolder->NotifyBoolPropertyChanged(NS_NewAtom("isSecure"),
                                             isSecureOld, isSecureNew);
   return NS_OK;
 }
 
 // Check if the password is available and return a boolean indicating whether
 // it is being authenticated or not.
--- a/mailnews/base/util/nsMsgProtocol.cpp
+++ b/mailnews/base/util/nsMsgProtocol.cpp
@@ -830,16 +830,19 @@ nsresult nsMsgProtocol::PostMessage(nsIU
   } while (more);
 
   return NS_OK;
 }
 
 nsresult nsMsgProtocol::DoGSSAPIStep1(const char *service, const char *username, nsCString &response)
 {
     nsresult rv;
+#ifdef DEBUG_BenB
+    printf("GSSAPI step 1 for service %s, username %s\n", service, username);
+#endif
 
     // if this fails, then it means that we cannot do GSSAPI SASL.
     m_authModule = do_CreateInstance(NS_AUTH_MODULE_CONTRACTID_PREFIX "sasl-gssapi", &rv);
     NS_ENSURE_SUCCESS(rv,rv);
 
     m_authModule->Init(service, nsIAuthModule::REQ_DEFAULT, nsnull, NS_ConvertUTF8toUTF16(username).get(), nsnull);
 
     void *outBuf;
@@ -850,21 +853,27 @@ nsresult nsMsgProtocol::DoGSSAPIStep1(co
         char *base64Str = PL_Base64Encode((char *)outBuf, outBufLen, nsnull);
         if (base64Str)
             response.Adopt(base64Str);
         else
             rv = NS_ERROR_OUT_OF_MEMORY;
         nsMemory::Free(outBuf);
     }
 
+#ifdef DEBUG_BenB
+    printf("GSSAPI step 1 succeeded\n");
+#endif
     return rv;
 }
 
 nsresult nsMsgProtocol::DoGSSAPIStep2(nsCString &commandResponse, nsCString &response)
 {
+#ifdef DEBUG_BenB
+    printf("GSSAPI step 2\n");
+#endif
     nsresult rv;
     void *inBuf, *outBuf;
     PRUint32 inBufLen, outBufLen;
     PRUint32 len = commandResponse.Length();
 
     // Cyrus SASL may send us zero length tokens (grrrr)
     if (len > 0) {
         // decode into the input secbuffer
@@ -908,16 +917,19 @@ nsresult nsMsgProtocol::DoGSSAPIStep2(ns
                 response.Adopt(base64Str);
             else
                 rv = NS_ERROR_OUT_OF_MEMORY;
         }
         else
             response.Adopt((char *)nsMemory::Clone("",1));
     }
 
+#ifdef DEBUG_BenB
+    printf(NS_SUCCEEDED(rv) ? "GSSAPI step 2 succeeded\n" : "GSSAPI step 2 failed\n");
+#endif
     return rv;
 }
 
 nsresult nsMsgProtocol::DoNtlmStep1(const char *username, const char *password, nsCString &response)
 {
     nsresult rv;
 
     m_authModule = do_CreateInstance(NS_AUTH_MODULE_CONTRACTID_PREFIX "ntlm", &rv);
--- a/mailnews/compose/public/nsISmtpServer.idl
+++ b/mailnews/compose/public/nsISmtpServer.idl
@@ -32,30 +32,31 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
+#include "MailNewsTypes2.idl"
 
 interface nsIAuthPrompt;
 interface nsIUrlListener;
 interface nsIURI;
 interface nsIMsgWindow;
 
 /**
  * This interface represents a single SMTP Server. A SMTP server instance may be
  * created/obtained from nsIMsgAccountManager.
  *
  * Most of the attributes will set/get preferences from the main preferences
  * file.
  */
-[scriptable, uuid(cf300e82-9def-43b0-b663-be08437960eb)]
+[scriptable, uuid(a53dce6c-cd81-495c-83bc-45a65df1f08e)]
 interface nsISmtpServer : nsISupports {
 
   /// A unique identifier for the server.
   attribute string key;
 
   /// A user supplied description for the server.
   attribute AUTF8String description;
 
@@ -76,37 +77,32 @@ interface nsISmtpServer : nsISupports {
    * the sending password.
    */
   attribute ACString password;
 
   /// Returns a displayname of the format hostname:port or just hostname
   readonly attribute string displayname;
 
   /**
-   * Whether or not to use authentication for this server.
-   * 0 = no authentication, 1 = use authentication.
-   * Reflects the mail.smtpserver.*.auth_method pref (default has value 1).
+   * Authentication mechanism.
+   *
+   * @see nsMsgAuthMethod (in MailNewsTypes2.idl)
+   * Same as "mail.smtpserver...authMethod" pref
+   *
+   * Compatibility note: This attribute had a different meaning in TB < 3.1
    */
-  attribute long authMethod;
-
-  /// Should we always use secure authentication?
-  attribute boolean useSecAuth;
-
-  /// Should we attempt to use secure authentication if the server supports it?
-  attribute boolean trySecAuth;
+  attribute nsMsgAuthMethodValue authMethod;
 
   /**
-   * Should we use SSL for this connection?
-   * 0 = never
-   * 1 = STARTTLS, if available (discouraged, insecure)
-   * 2 = TLS (STARTTLS) always
-   * 3 = SSL (SMTPS) always
-   * @see nsSmtpProtocol.h line 115 and nsSmtpProtocol.cpp line 331
+   * Whether to SSL or STARTTLS or not
+   *
+   * @see nsMsgSocketType (in MailNewsTypes2.idl)
+   * Same as "mail.smtpserver...try_ssl" pref
    */
-  attribute long trySSL;
+  attribute nsMsgSocketTypeValue socketType;
 
   /**
    * May contain an alternative argument to EHLO or HELO to provide to the
    * server. Reflects the value of the mail.smtpserver.*.hello_argument pref.
    * This is mainly useful where ISPs don't bother providing PTR records for
    * their servers and therefore users get an error on sending. See bug 244030
    * for more discussion.
    */
--- a/mailnews/compose/src/nsComposeStrings.h
+++ b/mailnews/compose/src/nsComposeStrings.h
@@ -69,27 +69,31 @@
 
 #define NS_MSG_ERROR_ATTACHING_FILE                 NS_MSG_GENERATE_FAILURE(12570)
 #define NS_MSG_ERROR_DOING_FCC                      12571
 
 #define NS_ERROR_SMTP_GREETING                      NS_MSG_GENERATE_FAILURE(12572)
 
 #define NS_ERROR_SENDING_RCPT_COMMAND               NS_MSG_GENERATE_FAILURE(12575)
 
-#define NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER_INSECAUTH   NS_MSG_GENERATE_FAILURE(12579)
-#define NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER_SECAUTH     NS_MSG_GENERATE_FAILURE(12580)
-#define NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER_AUTH_NONE   NS_MSG_GENERATE_FAILURE(12581)
+#define NS_ERROR_SMTP_AUTH_FAILURE                  NS_MSG_GENERATE_FAILURE(12576)
+#define NS_ERROR_SMTP_AUTH_GSSAPI                   NS_MSG_GENERATE_FAILURE(12579)
+#define NS_ERROR_SMTP_AUTH_MECH_NOT_SUPPORTED       NS_MSG_GENERATE_FAILURE(12580)
+#define NS_ERROR_SMTP_AUTH_NOT_SUPPORTED            NS_MSG_GENERATE_FAILURE(12581)
 
 #define NS_ERROR_STARTTLS_FAILED_EHLO_STARTTLS      NS_MSG_GENERATE_FAILURE(12582)
 
-#define NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER     NS_MSG_GENERATE_FAILURE(12583)
 #define NS_ERROR_SMTP_PASSWORD_UNDEFINED            NS_MSG_GENERATE_FAILURE(12584)
 #define NS_ERROR_SMTP_TEMP_SIZE_EXCEEDED            NS_MSG_GENERATE_FAILURE(12586)
 #define NS_ERROR_SMTP_PERM_SIZE_EXCEEDED_1          NS_MSG_GENERATE_FAILURE(12587)
 #define NS_ERROR_SMTP_PERM_SIZE_EXCEEDED_2          NS_MSG_GENERATE_FAILURE(12588)
 
 #define NS_ERROR_SMTP_SEND_FAILED_UNKNOWN_SERVER    NS_MSG_GENERATE_FAILURE(12589)
 #define NS_ERROR_SMTP_SEND_FAILED_REFUSED           NS_MSG_GENERATE_FAILURE(12590)
 #define NS_ERROR_SMTP_SEND_FAILED_INTERRUPTED       NS_MSG_GENERATE_FAILURE(12591)
 #define NS_ERROR_SMTP_SEND_FAILED_TIMEOUT           NS_MSG_GENERATE_FAILURE(12592)
 #define NS_ERROR_SMTP_SEND_FAILED_UNKNOWN_REASON    NS_MSG_GENERATE_FAILURE(12593)
 
+#define NS_ERROR_SMTP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_NO_SSL  NS_MSG_GENERATE_FAILURE(12594)
+#define NS_ERROR_SMTP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_SSL     NS_MSG_GENERATE_FAILURE(12595)
+#define NS_ERROR_SMTP_AUTH_CHANGE_PLAIN_TO_ENCRYPT         NS_MSG_GENERATE_FAILURE(12596)
+
 #endif /* _nsComposeStrings_H__ */
--- a/mailnews/compose/src/nsMsgSend.cpp
+++ b/mailnews/compose/src/nsMsgSend.cpp
@@ -3870,21 +3870,24 @@ nsMsgComposeAndSend::DoDeliveryExitProce
 
     nsString eMsg;
     if (aExitCode == NS_ERROR_SMTP_SEND_FAILED_UNKNOWN_SERVER ||
         aExitCode == NS_ERROR_SMTP_SEND_FAILED_UNKNOWN_REASON ||
         aExitCode == NS_ERROR_SMTP_SEND_FAILED_REFUSED ||
         aExitCode == NS_ERROR_SMTP_SEND_FAILED_INTERRUPTED ||
         aExitCode == NS_ERROR_SMTP_SEND_FAILED_TIMEOUT ||
         aExitCode == NS_ERROR_SMTP_PASSWORD_UNDEFINED ||
-        aExitCode == NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER ||
-        aExitCode == NS_ERROR_STARTTLS_FAILED_EHLO_STARTTLS ||
-        aExitCode == NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER_INSECAUTH ||
-        aExitCode == NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER_SECAUTH ||
-        aExitCode == NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER_AUTH_NONE)
+        aExitCode == NS_ERROR_SMTP_AUTH_FAILURE ||
+        aExitCode == NS_ERROR_SMTP_AUTH_GSSAPI ||
+        aExitCode == NS_ERROR_SMTP_AUTH_MECH_NOT_SUPPORTED ||
+        aExitCode == NS_ERROR_SMTP_AUTH_NOT_SUPPORTED ||
+        aExitCode == NS_ERROR_SMTP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_NO_SSL ||
+        aExitCode == NS_ERROR_SMTP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_SSL ||
+        aExitCode == NS_ERROR_SMTP_AUTH_CHANGE_PLAIN_TO_ENCRYPT ||
+        aExitCode == NS_ERROR_STARTTLS_FAILED_EHLO_STARTTLS)
       FormatStringWithSMTPHostNameByID(aExitCode, getter_Copies(eMsg));
     else
       mComposeBundle->GetStringFromID(NS_ERROR_GET_CODE(aExitCode), getter_Copies(eMsg));
 
     Fail(aExitCode, eMsg.get(), &aExitCode);
     NotifyListenerOnStopSending(nsnull, aExitCode, nsnull, nsnull);
     return;
   }
--- a/mailnews/compose/src/nsSmtpProtocol.cpp
+++ b/mailnews/compose/src/nsSmtpProtocol.cpp
@@ -18,16 +18,17 @@
  * Netscape Communications Corporation.
  * Portions created by the Initial Developer are Copyright (C) 1998
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Christian Eyrich <ch.ey@gmx.net>
  *   Olivier Parniere BT Global Services / Etat francais Ministere de la Defense
  *   Eric Ballet Baz BT Global Services / Etat francais Ministere de la Defense
+ *   Ben Bucksch <ben.bucksch beonex.com> of Beonex <http://business.beonex.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -74,16 +75,17 @@
 #include "nsNetUtil.h"
 #include "nsIPrefService.h"
 #include "nsISignatureVerifier.h"
 #include "nsISSLSocketControl.h"
 #include "nsComposeStrings.h"
 #include "nsIStringBundle.h"
 #include "nsMsgCompUtils.h"
 #include "nsIMsgWindow.h"
+#include "MailNewsTypes2.h" // for nsMsgSocketType and nsMsgAuthMethod
 
 
 #ifndef XP_UNIX
 #include <stdarg.h>
 #endif /* !XP_UNIX */
 
 static PRLogModuleInfo *SMTPLogModule = nsnull;
 
@@ -252,22 +254,21 @@ nsSmtpProtocol::~nsSmtpProtocol()
 }
 
 void nsSmtpProtocol::Initialize(nsIURI * aURL)
 {
     NS_PRECONDITION(aURL, "invalid URL passed into Smtp Protocol");
     nsresult rv = NS_OK;
 
     m_flags = 0;
-    m_origAuthFlags = 0;
-    m_prefAuthMethod = PREF_AUTH_NONE;
+    m_prefAuthMethods = 0;
+    m_failedAuthMethods = 0;
+    m_currentAuthMethod = 0;
     m_usernamePrompted = PR_FALSE;
-    m_prefTrySSL = PREF_SECURE_TRY_STARTTLS;
-    m_prefUseSecAuth = PR_TRUE;
-    m_prefTrySecAuth = PR_FALSE;
+    m_prefSocketType = nsMsgSocketType::trySTARTTLS;
     m_tlsInitiated = PR_FALSE;
 
     m_urlErrorState = NS_ERROR_FAILURE;
 
     if (!SMTPLogModule)
         SMTPLogModule = PR_NewLogModule("SMTP");
 
     if (aURL)
@@ -305,57 +306,53 @@ void nsSmtpProtocol::Initialize(nsIURI *
         file->GetFileSize(&m_totalMessageSize);
 
     m_originalContentLength = 0;
     m_totalAmountRead = 0;
 
     m_lineStreamBuffer = new nsMsgLineStreamBuffer(OUTPUT_BUFFER_SIZE, PR_TRUE);
     // ** may want to consider caching the server capability to save lots of
     // round trip communication between the client and server
+    PRInt32 authMethod = 0;
     nsCOMPtr<nsISmtpServer> smtpServer;
     m_runningURL->GetSmtpServer(getter_AddRefs(smtpServer));
     if (smtpServer) {
-        smtpServer->GetAuthMethod(&m_prefAuthMethod);
-        smtpServer->GetTrySSL(&m_prefTrySSL);
-        smtpServer->GetUseSecAuth(&m_prefUseSecAuth);
-        // Uncomment out the following line to turn back on sec auth probing
-        // smtpServer->GetTrySecAuth(&m_prefTrySecAuth);
+        smtpServer->GetAuthMethod(&authMethod);
+        smtpServer->GetSocketType(&m_prefSocketType);
         smtpServer->GetHelloArgument(getter_Copies(m_helloArgument));
     }
+    InitPrefAuthMethods(authMethod);
 
 #if defined(PR_LOGGING)
     nsCAutoString hostName;
     aURL->GetAsciiHost(hostName);
     PR_LOG(SMTPLogModule, PR_LOG_ALWAYS, ("SMTP Connecting to: %s", hostName.get()));
 #endif
 
     // When we are making a secure connection, we need to make sure that we
     // pass an interface requestor down to the socket transport so that PSM can
     // retrieve a nsIPrompt instance if needed.
     nsCOMPtr<nsIInterfaceRequestor> callbacks;
     nsCOMPtr<nsISmtpUrl> smtpUrl(do_QueryInterface(aURL));
     if (smtpUrl)
         smtpUrl->GetNotificationCallbacks(getter_AddRefs(callbacks));
 
-    if (m_prefTrySSL == PREF_SECURE_ALWAYS_SMTPS)
+    if (m_prefSocketType == nsMsgSocketType::SSL)
         rv = OpenNetworkSocket(aURL, "ssl", callbacks);
-    else if (m_prefTrySSL != PREF_SECURE_NEVER)
+    else if (m_prefSocketType != nsMsgSocketType::plain)
     {
         rv = OpenNetworkSocket(aURL, "starttls", callbacks);
-        if (NS_FAILED(rv) && m_prefTrySSL == PREF_SECURE_TRY_STARTTLS)
+        if (NS_FAILED(rv) && m_prefSocketType == nsMsgSocketType::trySTARTTLS)
         {
-            m_prefTrySSL = PREF_SECURE_NEVER;
+            m_prefSocketType = nsMsgSocketType::plain;
             rv = OpenNetworkSocket(aURL, nsnull, callbacks);
         }
     }
     else
         rv = OpenNetworkSocket(aURL, nsnull, callbacks);
-
-    if (NS_FAILED(rv))
-        return;
 }
 
 void nsSmtpProtocol::AppendHelloArgument(nsACString& aResult)
 {
   nsresult rv;
 
   // is a custom EHLO/HELO argument configured for the transport to be used?
   if (!m_helloArgument.IsEmpty())
@@ -539,17 +536,17 @@ PRInt32 nsSmtpProtocol::ExtensionLoginRe
 #ifdef DEBUG
     nsresult rv =
 #endif
     nsExplainErrorDetails(m_runningURL, NS_ERROR_SMTP_GREETING,
                           m_responseText.get());
     NS_ASSERTION(NS_SUCCEEDED(rv), "failed to explain SMTP error");
 
     m_urlErrorState = NS_ERROR_BUT_DONT_SHOW_ALERT;
-    return(NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER);
+    return NS_ERROR_SMTP_AUTH_FAILURE;
   }
 
   nsCAutoString buffer("EHLO ");
   AppendHelloArgument(buffer);
   buffer += CRLF;
 
   nsCOMPtr<nsIURI> url = do_QueryInterface(m_runningURL);
 
@@ -573,17 +570,17 @@ PRInt32 nsSmtpProtocol::SendHeloResponse
 #ifdef DEBUG
     rv =
 #endif
     nsExplainErrorDetails(m_runningURL, NS_ERROR_SMTP_SERVER_ERROR,
                           m_responseText.get());
     NS_ASSERTION(NS_SUCCEEDED(rv), "failed to explain SMTP error");
 
     m_urlErrorState = NS_ERROR_BUT_DONT_SHOW_ALERT;
-    return(NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER);
+    return NS_ERROR_SMTP_AUTH_FAILURE;
   }
 
   // check if we're just verifying the ability to logon
   nsCOMPtr<nsISmtpUrl> smtpUrl = do_QueryInterface(m_runningURL, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
   PRBool verifyingLogon = PR_FALSE;
   smtpUrl->GetVerifyLogon(&verifyingLogon);
   if (verifyingLogon)
@@ -683,30 +680,23 @@ PRInt32 nsSmtpProtocol::SendEhloResponse
         /* EHLO must not be implemented by the server, so fall back to the HELO case
          * if command is unrecognized or unimplemented.
          */
         if (m_responseCode == 500 || m_responseCode == 502)
         {
             /* If STARTTLS is requested by the user, EHLO is required to advertise it.
              * But only if TLS handshake is not already accomplished.
              */
-            if (m_prefTrySSL == PREF_SECURE_ALWAYS_STARTTLS && !m_tlsEnabled)
+            if (m_prefSocketType == nsMsgSocketType::alwaysSTARTTLS &&
+                !m_tlsEnabled)
             {
                 m_nextState = SMTP_ERROR_DONE;
                 m_urlErrorState = NS_ERROR_STARTTLS_FAILED_EHLO_STARTTLS;
                 return(NS_ERROR_STARTTLS_FAILED_EHLO_STARTTLS);
             }
-            else
-                // EHLO is always needed if authentication is requested.
-                if (m_prefAuthMethod == PREF_AUTH_ANY)
-                {
-                    m_nextState = SMTP_ERROR_DONE;
-                    m_urlErrorState = NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER_AUTH_NONE;
-                    return(NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER);
-                }
 
             nsCAutoString buffer("HELO ");
             AppendHelloArgument(buffer);
             buffer += CRLF;
 
             status = SendData(url, buffer.get());
 
             m_nextState = SMTP_RESPONSE;
@@ -722,17 +712,17 @@ PRInt32 nsSmtpProtocol::SendEhloResponse
 #ifdef DEBUG
             nsresult rv =
 #endif
             nsExplainErrorDetails(m_runningURL, NS_ERROR_SMTP_SERVER_ERROR,
                                   m_responseText.get());
             NS_ASSERTION(NS_SUCCEEDED(rv), "failed to explain SMTP error");
 
             m_urlErrorState = NS_ERROR_BUT_DONT_SHOW_ALERT;
-            return(NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER);
+            return NS_ERROR_SMTP_AUTH_FAILURE;
         }
     }
 
     PRInt32 responseLength = m_responseText.Length();
     PRInt32 startPos = 0;
     PRInt32 endPos;
     do
     {
@@ -749,71 +739,42 @@ PRInt32 nsSmtpProtocol::SendEhloResponse
         else if (responseLine.Compare("DSN", PR_TRUE) == 0)
         {
             SetFlag(SMTP_EHLO_DSN_ENABLED);
         }
         else if (responseLine.Compare("AUTH", PR_TRUE, 4) == 0)
         {
             SetFlag(SMTP_AUTH);
 
-            if (m_prefUseSecAuth || m_prefTrySecAuth)
-            {
-                if (responseLine.Find("GSSAPI", PR_TRUE, 5) >= 0)
-                    SetFlag(SMTP_AUTH_GSSAPI_ENABLED);
-
-                nsresult rv;
-                nsCOMPtr<nsISignatureVerifier> verifier = do_GetService(SIGNATURE_VERIFIER_CONTRACTID, &rv);
-                // this checks if psm is installed...
-                if (NS_SUCCEEDED(rv))
-                {
-                    if (responseLine.Find("CRAM-MD5", PR_TRUE, 5) >= 0)
-                        SetFlag(SMTP_AUTH_CRAM_MD5_ENABLED);
-
-                    if (responseLine.Find("NTLM", PR_TRUE, 5) >= 0)
-                        SetFlag(SMTP_AUTH_NTLM_ENABLED);
-
-                    if (responseLine.Find("MSN", PR_TRUE, 5) >= 0)
-                        SetFlag(SMTP_AUTH_MSN_ENABLED);
-                }
+            if (responseLine.Find("GSSAPI", PR_TRUE, 5) >= 0)
+                SetFlag(SMTP_AUTH_GSSAPI_ENABLED);
 
-                if (m_prefTrySecAuth)
-                {
-                  // don't adopt value for m_prefTrySecAuth instantly
-                  // so that we reprobe in case of STARTTLS
+            nsresult rv;
+            nsCOMPtr<nsISignatureVerifier> verifier = do_GetService(SIGNATURE_VERIFIER_CONTRACTID, &rv);
+            // this checks if psm is installed...
+            if (NS_SUCCEEDED(rv))
+            {
+                if (responseLine.Find("CRAM-MD5", PR_TRUE, 5) >= 0)
+                    SetFlag(SMTP_AUTH_CRAM_MD5_ENABLED);
 
-                  nsCOMPtr<nsISmtpServer> smtpServer;
-                  m_runningURL->GetSmtpServer(getter_AddRefs(smtpServer));
-                  if (smtpServer)
-                  {
-                    // If we are in probe mode, save what we found out for the future.
-                    // Don't trust GSSAPI since the server can advertise it 
-                    // but the client may not be set up for it.
-                    m_prefUseSecAuth = TestFlag(SMTP_AUTH_SEC_ENABLED &
-                                                ~SMTP_AUTH_GSSAPI_ENABLED);
-                    smtpServer->SetUseSecAuth(m_prefUseSecAuth);
-                    // then disable probing for next run
-                    smtpServer->SetTrySecAuth(PR_FALSE);
-                  }
-                }
+                if (responseLine.Find("NTLM", PR_TRUE, 5) >= 0)
+                    SetFlag(SMTP_AUTH_NTLM_ENABLED);
+
+                if (responseLine.Find("MSN", PR_TRUE, 5) >= 0)
+                    SetFlag(SMTP_AUTH_MSN_ENABLED);
             }
 
-            if (!m_prefUseSecAuth)
-            {
-                if (responseLine.Find("PLAIN", PR_TRUE, 5) >= 0)
-                    SetFlag(SMTP_AUTH_PLAIN_ENABLED);
+            if (responseLine.Find("PLAIN", PR_TRUE, 5) >= 0)
+                SetFlag(SMTP_AUTH_PLAIN_ENABLED);
 
-                if (responseLine.Find("LOGIN", PR_TRUE, 5) >= 0)
-                    SetFlag(SMTP_AUTH_LOGIN_ENABLED);
+            if (responseLine.Find("LOGIN", PR_TRUE, 5) >= 0)
+                SetFlag(SMTP_AUTH_LOGIN_ENABLED);
 
-                if (responseLine.Find("EXTERNAL", PR_TRUE, 5) >= 0)
-                    SetFlag(SMTP_AUTH_EXTERNAL_ENABLED);
-            }
-
-            // for use after mechs disabled fallbacks when login failed
-            BackupAuthFlags();
+            if (responseLine.Find("EXTERNAL", PR_TRUE, 5) >= 0)
+                SetFlag(SMTP_AUTH_EXTERNAL_ENABLED);
         }
         else if (responseLine.Compare("SIZE", PR_TRUE, 4) == 0)
         {
             SetFlag(SMTP_EHLO_SIZE_ENABLED);
 
             m_sizelimit = atol((responseLine.get()) + 4);
         }
 
@@ -860,237 +821,364 @@ PRInt32 nsSmtpProtocol::SendTLSResponse(
       }
 
       if (NS_SUCCEEDED(rv))
       {
           m_nextState = SMTP_EXTN_LOGIN_RESPONSE;
           m_nextStateAfterResponse = SMTP_EXTN_LOGIN_RESPONSE;
           m_tlsEnabled = PR_TRUE;
           m_flags = 0; // resetting the flags
-          BackupAuthFlags();
           return rv;
       }
   }
 
   ClearFlag(SMTP_EHLO_STARTTLS_ENABLED);
   m_tlsInitiated = PR_FALSE;
   m_nextState = SMTP_AUTH_PROCESS_STATE;
 
   return rv;
 }
 
+void nsSmtpProtocol::InitPrefAuthMethods(PRInt32 authMethodPrefValue)
+{
+  // for m_prefAuthMethods, using the same flags as server capablities.
+  switch (authMethodPrefValue)
+  {
+    case nsMsgAuthMethod::none:
+      m_prefAuthMethods = SMTP_AUTH_NONE_ENABLED;
+      break;
+    //case nsMsgAuthMethod::old -- no such thing for SMTP
+    case nsMsgAuthMethod::passwordCleartext:
+      m_prefAuthMethods = SMTP_AUTH_LOGIN_ENABLED |
+        SMTP_AUTH_PLAIN_ENABLED;
+      break;
+    case nsMsgAuthMethod::passwordEncrypted:
+      m_prefAuthMethods = SMTP_AUTH_CRAM_MD5_ENABLED;
+      break;
+    case nsMsgAuthMethod::NTLM:
+      m_prefAuthMethods = SMTP_AUTH_NTLM_ENABLED |
+          SMTP_AUTH_MSN_ENABLED;
+      break;
+    case nsMsgAuthMethod::GSSAPI:
+      m_prefAuthMethods = SMTP_AUTH_GSSAPI_ENABLED;
+      break;
+    case nsMsgAuthMethod::secure:
+      m_prefAuthMethods = SMTP_AUTH_CRAM_MD5_ENABLED |
+          SMTP_AUTH_GSSAPI_ENABLED |
+          SMTP_AUTH_NTLM_ENABLED | SMTP_AUTH_MSN_ENABLED |
+          SMTP_AUTH_EXTERNAL_ENABLED; // TODO: Expose EXTERNAL? How?
+      break;
+    default:
+      NS_ASSERTION(false, "SMTP: authMethod pref invalid");
+      // TODO log to error console
+      PR_LOG(SMTPLogModule, PR_LOG_ERROR,
+          ("SMTP: bad pref authMethod = %d\n", authMethodPrefValue));
+      // fall to any
+    case nsMsgAuthMethod::anything:
+      m_prefAuthMethods =
+          SMTP_AUTH_LOGIN_ENABLED | SMTP_AUTH_PLAIN_ENABLED |
+          SMTP_AUTH_CRAM_MD5_ENABLED | SMTP_AUTH_GSSAPI_ENABLED |
+          SMTP_AUTH_NTLM_ENABLED | SMTP_AUTH_MSN_ENABLED |
+          SMTP_AUTH_EXTERNAL_ENABLED;
+      break;
+  }
+  NS_ASSERTION(m_prefAuthMethods != 0, "SMTP:InitPrefAuthMethods() failed");
+}
+
+/**
+ * Changes m_currentAuthMethod to pick the next-best one
+ * which is allowed by server and prefs and not marked failed.
+ * The order of preference and trying of auth methods is encoded here.
+ */
+nsresult nsSmtpProtocol::ChooseAuthMethod()
+{
+  PRInt32 serverCaps = m_flags; // from nsMsgProtocol::TestFlag()
+  PRInt32 availCaps = serverCaps & m_prefAuthMethods & ~m_failedAuthMethods;
+
+  PR_LOG(SMTPLogModule, PR_LOG_DEBUG,
+        ("SMTP auth: server caps 0x%X, pref 0x%X, failed 0x%X, avail caps 0x%X",
+        serverCaps, m_prefAuthMethods, m_failedAuthMethods, availCaps));
+  PR_LOG(SMTPLogModule, PR_LOG_DEBUG,
+        ("(GSSAPI = 0x%X, CRAM = 0x%X, NTLM = 0x%X, "
+        "MSN =  0x%X, PLAIN = 0x%X, LOGIN = 0x%X, EXTERNAL = 0x%X)",
+        SMTP_AUTH_GSSAPI_ENABLED, SMTP_AUTH_CRAM_MD5_ENABLED,
+        SMTP_AUTH_NTLM_ENABLED, SMTP_AUTH_MSN_ENABLED, SMTP_AUTH_PLAIN_ENABLED,
+        SMTP_AUTH_LOGIN_ENABLED, SMTP_AUTH_EXTERNAL_ENABLED));
+
+  if (SMTP_AUTH_GSSAPI_ENABLED & availCaps)
+    m_currentAuthMethod = SMTP_AUTH_GSSAPI_ENABLED;
+  else if (SMTP_AUTH_CRAM_MD5_ENABLED & availCaps)
+    m_currentAuthMethod = SMTP_AUTH_CRAM_MD5_ENABLED;
+  else if (SMTP_AUTH_NTLM_ENABLED & availCaps)
+    m_currentAuthMethod = SMTP_AUTH_NTLM_ENABLED;
+  else if (SMTP_AUTH_MSN_ENABLED & availCaps)
+    m_currentAuthMethod = SMTP_AUTH_MSN_ENABLED;
+  else if (SMTP_AUTH_PLAIN_ENABLED & availCaps)
+    m_currentAuthMethod = SMTP_AUTH_PLAIN_ENABLED;
+  else if (SMTP_AUTH_LOGIN_ENABLED & availCaps)
+    m_currentAuthMethod = SMTP_AUTH_LOGIN_ENABLED;
+  else if (SMTP_AUTH_EXTERNAL_ENABLED & availCaps)
+    m_currentAuthMethod = SMTP_AUTH_EXTERNAL_ENABLED;
+  else
+  {
+    PR_LOG(SMTPLogModule, PR_LOG_ERROR, ("no auth method remaining"));
+    m_currentAuthMethod = 0;
+    return NS_ERROR_SMTP_AUTH_FAILURE;
+  }
+  PR_LOG(SMTPLogModule, PR_LOG_DEBUG, ("trying auth method 0x%X", m_currentAuthMethod));
+  return NS_OK;
+}
+
+void nsSmtpProtocol::MarkAuthMethodAsFailed(PRInt32 failedAuthMethod)
+{
+  PR_LOG(SMTPLogModule, PR_LOG_DEBUG,
+      ("marking auth method 0x%X failed", failedAuthMethod));
+  m_failedAuthMethods |= failedAuthMethod;
+}
+
+/**
+ * Start over, trying all auth methods again
+ */
+void nsSmtpProtocol::ResetAuthMethods()
+{
+  m_currentAuthMethod = 0;
+  m_failedAuthMethods = 0;
+}
+
 PRInt32 nsSmtpProtocol::ProcessAuth()
 {
     PRInt32 status = 0;
     nsCAutoString buffer;
     nsCOMPtr<nsIURI> url = do_QueryInterface(m_runningURL);
 
     if (!m_tlsEnabled)
     {
         if (TestFlag(SMTP_EHLO_STARTTLS_ENABLED))
         {
             // Do not try to combine SMTPS with STARTTLS.
-            // If PREF_SECURE_ALWAYS_SMTPS is set,
+            // If nsMsgSocketType::SSL is set,
             // we are alrady using a secure connection.
             // Do not attempt to do STARTTLS,
             // even if server offers it.
-            if (m_prefTrySSL == PREF_SECURE_TRY_STARTTLS ||
-                m_prefTrySSL == PREF_SECURE_ALWAYS_STARTTLS)
+            if (m_prefSocketType == nsMsgSocketType::trySTARTTLS ||
+                m_prefSocketType == nsMsgSocketType::alwaysSTARTTLS)
             {
                 buffer = "STARTTLS";
                 buffer += CRLF;
 
                 status = SendData(url, buffer.get());
 
                 m_tlsInitiated = PR_TRUE;
 
                 m_nextState = SMTP_RESPONSE;
                 m_nextStateAfterResponse = SMTP_TLS_RESPONSE;
                 SetFlag(SMTP_PAUSE_FOR_READ);
                 return status;
             }
         }
-        else if (m_prefTrySSL == PREF_SECURE_ALWAYS_STARTTLS)
+        else if (m_prefSocketType == nsMsgSocketType::alwaysSTARTTLS)
         {
             m_nextState = SMTP_ERROR_DONE;
             m_urlErrorState = NS_ERROR_STARTTLS_FAILED_EHLO_STARTTLS;
-            return NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER;
+            return NS_ERROR_STARTTLS_FAILED_EHLO_STARTTLS;
         }
     }
+  // (wrong indention until here)
 
-    if (TestFlag(SMTP_AUTH_EXTERNAL_ENABLED))
-    {
-        buffer = "AUTH EXTERNAL =";
-        buffer += CRLF;
-        SendData(url, buffer.get());
-        m_nextState = SMTP_RESPONSE;
-        m_nextStateAfterResponse = SMTP_AUTH_EXTERNAL_RESPONSE;
-        SetFlag(SMTP_PAUSE_FOR_READ);
-        return NS_OK;
-    }
-    else
-    if (m_prefAuthMethod == PREF_AUTH_ANY)
-    {
-        // did the server advertise authentication capability at all?
-        if (!TestFlag(SMTP_AUTH))
-        {
-            m_nextState = SMTP_ERROR_DONE;
-            m_urlErrorState = NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER_AUTH_NONE;
-            return NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER;
-        }
+  (void) ChooseAuthMethod(); // advance m_currentAuthMethod
 
-        /* check if the server supports at least one of the mechanisms
-           in the class the user wants us to use */
-        if (m_prefUseSecAuth)
-        {
-            if (!TestFlag(SMTP_AUTH_SEC_ENABLED))
-                m_urlErrorState = NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER_SECAUTH;
-        }
-        else
-        {
-            if (!TestFlag(SMTP_AUTH_INSEC_ENABLED))
-                m_urlErrorState = NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER_INSECAUTH;
-        }
+  if (m_prefAuthMethods == SMTP_AUTH_NONE_ENABLED) // No auth needed
+  {
+    m_nextState = SMTP_SEND_HELO_RESPONSE;
+    // fake to 250 because SendHeloResponse() tests for this
+    m_responseCode = 250;
+  }
+  // did the server advertise authentication capability at all,
+  // but we wanted to auth?
+  else if (!TestFlag(SMTP_AUTH))
+  {
+    m_urlErrorState = NS_ERROR_SMTP_AUTH_NOT_SUPPORTED;
+    m_nextState = SMTP_ERROR_DONE;
+    return NS_ERROR_SMTP_AUTH_FAILURE;
+  }
+  else if (m_currentAuthMethod == SMTP_AUTH_EXTERNAL_ENABLED)
+  {
+    buffer = "AUTH EXTERNAL =";
+    buffer += CRLF;
+    SendData(url, buffer.get());
+    m_nextState = SMTP_RESPONSE;
+    m_nextStateAfterResponse = SMTP_AUTH_EXTERNAL_RESPONSE;
+    SetFlag(SMTP_PAUSE_FOR_READ);
+    return NS_OK;
+  }
+  else if (m_currentAuthMethod == SMTP_AUTH_GSSAPI_ENABLED)
+  {
+    m_nextState = SMTP_SEND_AUTH_GSSAPI_FIRST;
+  }
+  else if (m_currentAuthMethod == SMTP_AUTH_CRAM_MD5_ENABLED ||
+           m_currentAuthMethod == SMTP_AUTH_PLAIN_ENABLED ||
+           m_currentAuthMethod == SMTP_AUTH_NTLM_ENABLED)
+  {
+    m_nextState = SMTP_SEND_AUTH_LOGIN_STEP1;
+  }
+  else if (m_currentAuthMethod == SMTP_AUTH_LOGIN_ENABLED ||
+           m_currentAuthMethod == SMTP_AUTH_MSN_ENABLED)
+  {
+    m_nextState = SMTP_SEND_AUTH_LOGIN_STEP0;
+  }
+  else // All auth methods failed
+  {
+    // show an appropriate error msg
+    if (m_failedAuthMethods == 0)
+    {
+      // we didn't even try anything, so we had a non-working config:
+      // pref doesn't match server
+      PR_LOG(SMTPLogModule, PR_LOG_ERROR,
+          ("no working auth mech - pref doesn't match server capas"));
 
-        if (m_urlErrorState != NS_ERROR_FAILURE)
-        {
-            m_nextState = SMTP_ERROR_DONE;
-            return NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER;
-        }
-
-
-        if (TestFlag(SMTP_AUTH_GSSAPI_ENABLED))
-            m_nextState = SMTP_SEND_AUTH_GSSAPI_FIRST;
-        else if (TestFlag(SMTP_AUTH_CRAM_MD5_ENABLED) ||
-                 TestFlag(SMTP_AUTH_NTLM_ENABLED) ||
-                 TestFlag(SMTP_AUTH_PLAIN_ENABLED))
-            m_nextState = SMTP_SEND_AUTH_LOGIN_STEP1;
-        else if (TestFlag(SMTP_AUTH_MSN_ENABLED) ||
-                 TestFlag(SMTP_AUTH_LOGIN_ENABLED))
-            m_nextState = SMTP_SEND_AUTH_LOGIN_STEP0;
+      // pref has encrypted pw & server claims to support plaintext pw
+      if (m_prefAuthMethods == SMTP_AUTH_CRAM_MD5_ENABLED &&
+          m_flags & (SMTP_AUTH_LOGIN_ENABLED | SMTP_AUTH_PLAIN_ENABLED))
+      {
+        // have SSL
+        if (m_prefSocketType == nsMsgSocketType::SSL ||
+            m_prefSocketType == nsMsgSocketType::alwaysSTARTTLS)
+          // tell user to change to plaintext pw
+          m_urlErrorState = NS_ERROR_SMTP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_SSL;
+        else
+          // tell user to change to plaintext pw, with big warning
+          m_urlErrorState = NS_ERROR_SMTP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_NO_SSL;
+      }
+      // pref has plaintext pw & server claims to support encrypted pw
+      else if (m_prefAuthMethods == (SMTP_AUTH_LOGIN_ENABLED |
+                   SMTP_AUTH_PLAIN_ENABLED) &&
+               m_flags & SMTP_AUTH_CRAM_MD5_ENABLED)
+        // tell user to change to encrypted pw
+        m_urlErrorState = NS_ERROR_SMTP_AUTH_CHANGE_PLAIN_TO_ENCRYPT;
+      else
+      {
+        // just "change auth method"
+        m_urlErrorState = NS_ERROR_SMTP_AUTH_MECH_NOT_SUPPORTED;
+      }
+    }
+    else if (m_failedAuthMethods == SMTP_AUTH_GSSAPI_ENABLED)
+    {
+      // We have only GSSAPI, and it failed, so nothing left to do.
+      PR_LOG(SMTPLogModule, PR_LOG_ERROR, ("GSSAPI only and it failed"));
+      m_urlErrorState = NS_ERROR_SMTP_AUTH_GSSAPI;
     }
     else
     {
-        m_nextState = SMTP_SEND_HELO_RESPONSE;
-        // fake to 250 because SendHeloResponse() tests for this
-        m_responseCode = 250;
+      // we tried to login, but it all failed
+      PR_LOG(SMTPLogModule, PR_LOG_ERROR, ("All auth attempts failed"));
+      m_urlErrorState = NS_ERROR_SMTP_AUTH_FAILURE;
     }
+    m_nextState = SMTP_ERROR_DONE;
+    return NS_ERROR_SMTP_AUTH_FAILURE;
+  }
 
-    return NS_OK;
+  return NS_OK;
 }
 
 
-void nsSmtpProtocol::BackupAuthFlags()
-{
-  m_origAuthFlags = m_flags & SMTP_AUTH_ANY_ENABLED;
-}
-
-void nsSmtpProtocol::RestoreAuthFlags()
-{
-  m_flags |= m_origAuthFlags;
-}
-
 
 PRInt32 nsSmtpProtocol::AuthLoginResponse(nsIInputStream * stream, PRUint32 length)
 {
+  PR_LOG(SMTPLogModule, PR_LOG_DEBUG, ("SMTP Login response, code %d", m_responseCode));
   PRInt32 status = 0;
-  nsCOMPtr<nsISmtpServer> smtpServer;
-  m_runningURL->GetSmtpServer(getter_AddRefs(smtpServer));
 
   switch (m_responseCode/100)
   {
     case 2:
       m_nextState = SMTP_SEND_HELO_RESPONSE;
       // fake to 250 because SendHeloResponse() tests for this
       m_responseCode = 250;
       break;
     case 3:
       m_nextState = SMTP_SEND_AUTH_LOGIN_STEP2;
       break;
     case 5:
     default:
+      nsCOMPtr<nsISmtpServer> smtpServer;
+      m_runningURL->GetSmtpServer(getter_AddRefs(smtpServer));
       if (smtpServer)
       {
-        // If one authentication failed, we're going to
+        // If one authentication failed, mark it failed, so that we're going to
         // fall back on a less secure login method.
-        if(TestFlag(SMTP_AUTH_GSSAPI_ENABLED))
-          ClearFlag(SMTP_AUTH_GSSAPI_ENABLED);
-        else if(TestFlag(SMTP_AUTH_DIGEST_MD5_ENABLED))
-          // if DIGEST-MD5 enabled, clear it if we failed.
-          ClearFlag(SMTP_AUTH_DIGEST_MD5_ENABLED);
-        else if(TestFlag(SMTP_AUTH_CRAM_MD5_ENABLED))
-          // if CRAM-MD5 enabled, clear it if we failed.
-          ClearFlag(SMTP_AUTH_CRAM_MD5_ENABLED);
-        else if(TestFlag(SMTP_AUTH_NTLM_ENABLED))
-          // if NTLM enabled, clear it if we failed.
-          ClearFlag(SMTP_AUTH_NTLM_ENABLED);
-        else if(TestFlag(SMTP_AUTH_MSN_ENABLED))
-          // if MSN enabled, clear it if we failed.
-          ClearFlag(SMTP_AUTH_MSN_ENABLED);
-        else if(TestFlag(SMTP_AUTH_PLAIN_ENABLED))
-          // if PLAIN enabled, clear it if we failed.
-          ClearFlag(SMTP_AUTH_PLAIN_ENABLED);
-        else if(TestFlag(SMTP_AUTH_LOGIN_ENABLED))
-          // if LOGIN enabled, clear it if we failed.
-          ClearFlag(SMTP_AUTH_LOGIN_ENABLED);
+        MarkAuthMethodAsFailed(m_currentAuthMethod);
 
-        // Only forget the password if we've no mechanism left.
-        if (!TestFlag(SMTP_AUTH_ANY_ENABLED))
+        PRBool allFailed = NS_FAILED(ChooseAuthMethod());
+        if (allFailed && m_failedAuthMethods > 0 &&
+            m_failedAuthMethods != SMTP_AUTH_GSSAPI_ENABLED &&
+            m_failedAuthMethods != SMTP_AUTH_EXTERNAL_ENABLED)
         {
+          // We've tried all avail. methods, and they all failed, and we have no mechanism left.
+          // Ask user to try with a new password.
+          PR_LOG(SMTPLogModule, PR_LOG_WARN,
+              ("SMTP: ask user what to do (after login failed): new password, retry or cancel"));
+
           nsCOMPtr<nsISmtpServer> smtpServer;
           nsresult rv = m_runningURL->GetSmtpServer(getter_AddRefs(smtpServer));
           NS_ENSURE_SUCCESS(rv, rv);
 
           nsCString hostname;
           rv = smtpServer->GetHostname(hostname);
           NS_ENSURE_SUCCESS(rv, rv);
 
-          PRInt32 buttonPressed = 0;
+          PRInt32 buttonPressed = 1;
           if (NS_SUCCEEDED(MsgPromptLoginFailed(nsnull, hostname,
                                                 &buttonPressed)))
           {
-            if (buttonPressed == 1)
+            if (buttonPressed == 1) // Cancel button
             {
-              // Cancel button pressed, so we need to abort.
-              status = NS_ERROR_FAILURE;
-
-              // and just get out of here.
+              PR_LOG(SMTPLogModule, PR_LOG_WARN, ("cancel button pressed"));
+              // abort and get out of here
+              status = NS_ERROR_ABORT;
               break;
             }
-            if (buttonPressed == 2)
+            else if (buttonPressed == 2) // 'New password' button
             {
+              PR_LOG(SMTPLogModule, PR_LOG_WARN, ("new password button pressed"));
               // Change password was pressed. For now, forget the stored
               // password and we'll prompt for a new one next time around.
               smtpServer->ForgetPassword();
+              if (m_usernamePrompted)
+                smtpServer->SetUsername(EmptyCString());
+
+              // Let's restore the original auth flags from SendEhloResponse
+              // so we can try them again with new password and username
+              ResetAuthMethods();
+              // except for GSSAPI and EXTERNAL, which don't care about passwords.
+              MarkAuthMethodAsFailed(SMTP_AUTH_GSSAPI_ENABLED);
+              MarkAuthMethodAsFailed(SMTP_AUTH_EXTERNAL_ENABLED);
+            }
+            else if (buttonPressed == 0) // Retry button
+            {
+              PR_LOG(SMTPLogModule, PR_LOG_WARN, ("retry button pressed"));
+              // try all again, including GSSAPI
+              ResetAuthMethods();
             }
           }
-          if (m_usernamePrompted)
-            smtpServer->SetUsername(EmptyCString());
+        }
+        PR_LOG(SMTPLogModule, PR_LOG_ERROR,
+            ("SMTP: login failed: failed %X, current %X", m_failedAuthMethods, m_currentAuthMethod));
 
-          // Let's restore the original auth flags from SendEhloResponse
-          // so we can try them again with new password and username
-          RestoreAuthFlags();
-          // except for gssapi, which doesn't care about the new password.
-          ClearFlag(SMTP_AUTH_GSSAPI_ENABLED);
-        }
-
-        m_nextState = SMTP_AUTH_PROCESS_STATE;
+        m_nextState = SMTP_AUTH_PROCESS_STATE; // try auth (ProcessAuth()) again, with other method
       }
       else
           status = NS_ERROR_SMTP_PASSWORD_UNDEFINED;
       break;
   }
 
   return (status);
 }
 
-// GSSAPI may consist of multiple round trips
-
 PRInt32 nsSmtpProtocol::AuthGSSAPIFirst()
 {
+  NS_ASSERTION(m_currentAuthMethod == SMTP_AUTH_GSSAPI_ENABLED, "called in invalid state");
   nsCAutoString command("AUTH GSSAPI ");
   nsCAutoString resp;
   nsCAutoString service("smtp@");
   nsCString hostName;
   nsCString userName;
   nsresult rv;
   nsCOMPtr<nsISmtpServer> smtpServer;
   rv = m_runningURL->GetSmtpServer(getter_AddRefs(smtpServer));
@@ -1099,37 +1187,44 @@ PRInt32 nsSmtpProtocol::AuthGSSAPIFirst(
 
   rv = smtpServer->GetUsername(userName);
   if (NS_FAILED(rv))
     return NS_ERROR_FAILURE;
 
   rv = smtpServer->GetHostname(hostName);
   if (NS_FAILED(rv))
     return NS_ERROR_FAILURE;
+  service.Append(hostName);
+  PR_LOG(SMTPLogModule, PR_LOG_DEBUG, ("SMTP: GSSAPI step 1 for user %s at server %s, service %s",
+      userName.get(), hostName.get(), service.get()));
 
- service.Append(hostName);
   rv = DoGSSAPIStep1(service.get(), userName.get(), resp);
   if (NS_FAILED(rv))
   {
+    PR_LOG(SMTPLogModule, PR_LOG_ERROR, ("SMTP: GSSAPI step 1 failed early"));
+    MarkAuthMethodAsFailed(SMTP_AUTH_GSSAPI_ENABLED);
     m_nextState = SMTP_AUTH_PROCESS_STATE;
-    ClearFlag(SMTP_AUTH_GSSAPI_ENABLED);
     return 0;
   }
   else
     command.Append(resp);
   command.Append(CRLF);
   m_nextState = SMTP_RESPONSE;
   m_nextStateAfterResponse = SMTP_SEND_AUTH_GSSAPI_STEP;
   SetFlag(SMTP_PAUSE_FOR_READ);
   nsCOMPtr<nsIURI> url = do_QueryInterface(m_runningURL);
   return SendData(url, command.get());
 }
 
+// GSSAPI may consist of multiple round trips
+
 PRInt32 nsSmtpProtocol::AuthGSSAPIStep()
 {
+  PR_LOG(SMTPLogModule, PR_LOG_DEBUG, ("SMTP: GSSAPI auth step 2"));
+  NS_ASSERTION(m_currentAuthMethod == SMTP_AUTH_GSSAPI_ENABLED, "called in invalid state");
   nsresult rv;
   nsCAutoString cmd;
 
   // Check to see what the server said
   if (m_responseCode / 100 != 3) {
     m_nextState = SMTP_AUTH_LOGIN_RESPONSE;
     return 0;
   }
@@ -1149,38 +1244,45 @@ PRInt32 nsSmtpProtocol::AuthGSSAPIStep()
 
 
 // LOGIN and MSN consist of three steps (MSN not through the mechanism
 // but by non-RFC2821 compliant implementation in MS servers) not two as
 // PLAIN or CRAM-MD5, so we've to start here and continue with AuthStep1
 // if the server responds with with a 3xx code to "AUTH LOGIN" or "AUTH MSN"
 PRInt32 nsSmtpProtocol::AuthLoginStep0()
 {
-    nsCAutoString command(TestFlag(SMTP_AUTH_MSN_ENABLED) ? "AUTH MSN" CRLF :
-                                                            "AUTH LOGIN" CRLF);
+    NS_ASSERTION(m_currentAuthMethod == SMTP_AUTH_MSN_ENABLED ||
+        m_currentAuthMethod == SMTP_AUTH_LOGIN_ENABLED,
+        "called in invalid state");
+    PR_LOG(SMTPLogModule, PR_LOG_DEBUG, ("SMTP: MSN or LOGIN auth, step 0"));
+    nsCAutoString command(m_currentAuthMethod == SMTP_AUTH_MSN_ENABLED
+        ? "AUTH MSN" CRLF : "AUTH LOGIN" CRLF);
     m_nextState = SMTP_RESPONSE;
     m_nextStateAfterResponse = SMTP_AUTH_LOGIN_STEP0_RESPONSE;
     SetFlag(SMTP_PAUSE_FOR_READ);
 
     return SendData(m_url, command.get());
 }
 
 PRInt32 nsSmtpProtocol::AuthLoginStep0Response()
 {
+    NS_ASSERTION(m_currentAuthMethod == SMTP_AUTH_MSN_ENABLED ||
+        m_currentAuthMethod == SMTP_AUTH_LOGIN_ENABLED,
+        "called in invalid state");
     // need the test to be here instead in AuthLoginResponse() to
     // continue with step 1 instead of 2 in case of a code 3xx
     m_nextState = (m_responseCode/100 == 3) ?
                   SMTP_SEND_AUTH_LOGIN_STEP1 : SMTP_AUTH_LOGIN_RESPONSE;
 
     return 0;
 }
 
 PRInt32 nsSmtpProtocol::AuthLoginStep1()
 {
-  char buffer[512];
+  char buffer[512]; // TODO nsCAutoString
   nsresult rv;
   PRInt32 status = 0;
   nsCString username;
   char *base64Str = nsnull;
   nsCAutoString password;
   nsCOMPtr<nsISmtpServer> smtpServer;
   rv = m_runningURL->GetSmtpServer(getter_AddRefs(smtpServer));
   if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
@@ -1188,54 +1290,61 @@ PRInt32 nsSmtpProtocol::AuthLoginStep1()
   rv = smtpServer->GetUsername(username);
   if (username.IsEmpty())
   {
     rv = GetUsernamePassword(username, password);
     m_usernamePrompted = PR_TRUE;
     if (username.IsEmpty() || password.IsEmpty())
       return NS_ERROR_SMTP_PASSWORD_UNDEFINED;
   }
+  PR_LOG(SMTPLogModule, PR_LOG_DEBUG, ("SMTP AuthLoginStep1() for %s@%s",
+      username.get(), smtpServer.get()));
 
   GetPassword(password);
   if (password.IsEmpty())
   {
+    PR_LOG(SMTPLogModule, PR_LOG_ERROR, ("SMTP: password undefined"));
     m_urlErrorState = NS_ERROR_SMTP_PASSWORD_UNDEFINED;
     return NS_ERROR_SMTP_PASSWORD_UNDEFINED;
   }
 
-  if (TestFlag(SMTP_AUTH_CRAM_MD5_ENABLED))
+  if (m_currentAuthMethod == SMTP_AUTH_CRAM_MD5_ENABLED)
+  {
+    PR_LOG(SMTPLogModule, PR_LOG_ERROR, ("CRAM auth, step 1"));
     PR_snprintf(buffer, sizeof(buffer), "AUTH CRAM-MD5" CRLF);
-  else
-  if (TestFlag(SMTP_AUTH_NTLM_ENABLED) || TestFlag(SMTP_AUTH_MSN_ENABLED))
+  }
+  else if (m_currentAuthMethod == SMTP_AUTH_NTLM_ENABLED ||
+           m_currentAuthMethod == SMTP_AUTH_MSN_ENABLED)
   {
+    PR_LOG(SMTPLogModule, PR_LOG_DEBUG, ("NTLM/MSN auth, step 1"));
     nsCAutoString response;
     rv = DoNtlmStep1(username.get(), password.get(), response);
     PR_snprintf(buffer, sizeof(buffer), TestFlag(SMTP_AUTH_NTLM_ENABLED) ?
                                         "AUTH NTLM %.256s" CRLF :
                                         "%.256s" CRLF, response.get());
   }
-  else
-  if (TestFlag(SMTP_AUTH_PLAIN_ENABLED))
+  else if (m_currentAuthMethod == SMTP_AUTH_PLAIN_ENABLED)
   {
+    PR_LOG(SMTPLogModule, PR_LOG_DEBUG, ("PLAIN auth"));
     char plain_string[512];
     int len = 1; /* first <NUL> char */
 
     memset(plain_string, 0, 512);
     PR_snprintf(&plain_string[1], 510, "%s", username.get());
     len += username.Length();
     len++; /* second <NUL> char */
     PR_snprintf(&plain_string[len], 511-len, "%s", password.get());
     len += password.Length();
 
     base64Str = PL_Base64Encode(plain_string, len, nsnull);
     PR_snprintf(buffer, sizeof(buffer), "AUTH PLAIN %.256s" CRLF, base64Str);
   }
-  else
-  if (TestFlag(SMTP_AUTH_LOGIN_ENABLED))
+  else if (m_currentAuthMethod == SMTP_AUTH_LOGIN_ENABLED)
   {
+    PR_LOG(SMTPLogModule, PR_LOG_DEBUG, ("LOGIN auth"));
     base64Str = PL_Base64Encode(username.get(),
         username.Length(), nsnull);
     PR_snprintf(buffer, sizeof(buffer), "%.256s" CRLF, base64Str);
   }
   else
     return (NS_ERROR_COMMUNICATIONS_ERROR);
 
   nsCOMPtr<nsIURI> url = do_QueryInterface(m_runningURL);
@@ -1260,33 +1369,35 @@ PRInt32 nsSmtpProtocol::AuthLoginStep2()
   nsCAutoString password;
 
   GetPassword(password);
   if (password.IsEmpty())
   {
     m_urlErrorState = NS_ERROR_SMTP_PASSWORD_UNDEFINED;
     return NS_ERROR_SMTP_PASSWORD_UNDEFINED;
   }
+  PR_LOG(SMTPLogModule, PR_LOG_MAX, ("SMTP AuthLoginStep2"));
 
   if (!password.IsEmpty())
   {
     char buffer[512];
-    if (TestFlag(SMTP_AUTH_CRAM_MD5_ENABLED))
+    if (m_currentAuthMethod == SMTP_AUTH_CRAM_MD5_ENABLED)
     {
+      PR_LOG(SMTPLogModule, PR_LOG_DEBUG, ("CRAM auth, step 2"));
       unsigned char digest[DIGEST_LENGTH];
       char * decodedChallenge = PL_Base64Decode(m_responseText.get(),
         m_responseText.Length(), nsnull);
 
       if (decodedChallenge)
         rv = MSGCramMD5(decodedChallenge, strlen(decodedChallenge), password.get(), password.Length(), digest);
       else
         rv = NS_ERROR_FAILURE;
 
       PR_Free(decodedChallenge);
-      if (NS_SUCCEEDED(rv) && digest)
+      if (NS_SUCCEEDED(rv))
       {
         nsCAutoString encodedDigest;
         char hexVal[8];
 
         for (PRUint32 j=0; j<16; j++)
         {
           PR_snprintf (hexVal,8, "%.2x", 0x0ff & (unsigned short)digest[j]);
           encodedDigest.Append(hexVal);
@@ -1302,29 +1413,34 @@ PRInt32 nsSmtpProtocol::AuthLoginStep2()
         PR_snprintf(buffer, sizeof(buffer), "%s %s", userName.get(), encodedDigest.get());
         char *base64Str = PL_Base64Encode(buffer, strlen(buffer), nsnull);
         PR_snprintf(buffer, sizeof(buffer), "%s" CRLF, base64Str);
         NS_Free(base64Str);
       }
       if (NS_FAILED(rv))
         PR_snprintf(buffer, sizeof(buffer), "*" CRLF);
     }
-    else
-    if (TestFlag(SMTP_AUTH_NTLM_ENABLED) || TestFlag(SMTP_AUTH_MSN_ENABLED))
+    else if (m_currentAuthMethod == SMTP_AUTH_NTLM_ENABLED ||
+             m_currentAuthMethod == SMTP_AUTH_MSN_ENABLED)
     {
+      PR_LOG(SMTPLogModule, PR_LOG_DEBUG, ("NTLM/MSN auth, step 2"));
       nsCAutoString response;
       rv = DoNtlmStep2(m_responseText, response);
       PR_snprintf(buffer, sizeof(buffer), "%.256s" CRLF, response.get());
     }
-    else
+    else if (m_currentAuthMethod == SMTP_AUTH_PLAIN_ENABLED ||
+             m_currentAuthMethod == SMTP_AUTH_LOGIN_ENABLED)
     {
+      PR_LOG(SMTPLogModule, PR_LOG_DEBUG, ("PLAIN/LOGIN auth, step 2"));
       char *base64Str = PL_Base64Encode(password.get(), password.Length(), nsnull);
       PR_snprintf(buffer, sizeof(buffer), "%.256s" CRLF, base64Str);
       NS_Free(base64Str);
     }
+    else
+      return NS_ERROR_COMMUNICATIONS_ERROR;
 
     nsCOMPtr<nsIURI> url = do_QueryInterface(m_runningURL);
     status = SendData(url, buffer, PR_TRUE);
     m_nextState = SMTP_RESPONSE;
     m_nextStateAfterResponse = SMTP_AUTH_LOGIN_RESPONSE;
     SetFlag(SMTP_PAUSE_FOR_READ);
     return (status);
   }
@@ -1621,17 +1737,17 @@ nsresult nsSmtpProtocol::LoadUrl(nsIURI 
   if (hostName.IsEmpty())
   {
     nsCOMPtr <nsIMsgMailNewsUrl> aMsgUrl = do_QueryInterface(aURL);
     if (aMsgUrl)
     {
       aMsgUrl->SetUrlState(PR_TRUE, NS_OK);
       // set the url as a url currently being run...
       aMsgUrl->SetUrlState(PR_FALSE /* we aren't running the url */,
-                           NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER); 
+                           NS_ERROR_SMTP_AUTH_FAILURE);
     }
     return NS_ERROR_BUT_DONT_SHOW_ALERT;
   }
 
   PRBool postMessage = PR_FALSE;
   m_runningURL->GetPostMessage(&postMessage);
 
   if (postMessage)
--- a/mailnews/compose/src/nsSmtpProtocol.h
+++ b/mailnews/compose/src/nsSmtpProtocol.h
@@ -39,16 +39,17 @@
 #define nsSmtpProtocol_h___
 
 #include "nsMsgProtocol.h"
 #include "nsIStreamListener.h"
 #include "nsISmtpUrl.h"
 #include "nsIMsgStatusFeedback.h"
 #include "nsMsgLineBuffer.h"
 #include "nsIAuthModule.h"
+#include "MailNewsTypes2.h" // for nsMsgSocketType
 
 #include "nsCOMPtr.h"
 
  /* states of the machine
  */
 typedef enum _SmtpState {
 SMTP_RESPONSE = 0,                                  // 0
 SMTP_START_CONNECT,                                 // 1
@@ -85,42 +86,28 @@ SMTP_SEND_AUTH_GSSAPI_STEP              
 #define SMTP_EHLO_DSN_ENABLED           0x00000004
 #define SMTP_EHLO_STARTTLS_ENABLED      0x00000008
 #define SMTP_EHLO_SIZE_ENABLED          0x00000010
 
 // insecure mechanisms follow
 #define SMTP_AUTH_LOGIN_ENABLED         0x00000100
 #define SMTP_AUTH_PLAIN_ENABLED         0x00000200
 #define SMTP_AUTH_EXTERNAL_ENABLED      0x00000400
-// sum of above insecure mechanisms
-#define SMTP_AUTH_INSEC_ENABLED         0x00000700
 // secure mechanisms follow
 #define SMTP_AUTH_GSSAPI_ENABLED        0x00000800
 #define SMTP_AUTH_DIGEST_MD5_ENABLED    0x00001000
 #define SMTP_AUTH_CRAM_MD5_ENABLED      0x00002000
 #define SMTP_AUTH_NTLM_ENABLED          0x00004000
 #define SMTP_AUTH_MSN_ENABLED           0x00008000
-// sum of above secure mechanisms
-#define SMTP_AUTH_SEC_ENABLED           0x0000F800
-// sum of all above mechanisms
-#define SMTP_AUTH_ANY_ENABLED           0x0000FF00
+// sum of all above auth mechanisms
+#define SMTP_AUTH_ANY                   0x0000FF00
 // indicates that AUTH has been advertised
 #define SMTP_AUTH                       0x00010000
-
-typedef enum _PrefAuthMethod {
-    PREF_AUTH_NONE = 0,
-    PREF_AUTH_ANY = 1
-} PrefAuthMethod;
-
-typedef enum _PrefTrySSL {
-    PREF_SECURE_NEVER = 0,
-    PREF_SECURE_TRY_STARTTLS = 1,
-    PREF_SECURE_ALWAYS_STARTTLS = 2,
-    PREF_SECURE_ALWAYS_SMTPS = 3
-} PrefTrySSL;
+// No login necessary (pref)
+#define SMTP_AUTH_NONE_ENABLED          0x00020000
 
 class nsSmtpProtocol : public nsMsgAsyncWriteProtocol
 {
 public:
     NS_DECL_ISUPPORTS_INHERITED
 
     // Creating a protocol instance requires the URL which needs to be run.
     nsSmtpProtocol(nsIURI * aURL);
@@ -164,21 +151,18 @@ private:
     char           *m_addresses;
     PRUint32       m_addressesLeft;
     nsCString m_mailAddr;
     nsCString m_helloArgument;
     PRInt32        m_sizelimit;
 
     // *** the following should move to the smtp server when we support
     // multiple smtp servers
-    PRInt32 m_prefAuthMethod;
-    PRBool m_prefUseSecAuth;
-    PRBool m_prefTrySecAuth;
     PRBool m_usernamePrompted;
-    PRInt32 m_prefTrySSL;
+    PRInt32 m_prefSocketType;
     PRBool m_tlsEnabled;
 
     PRBool m_tlsInitiated;
 
     PRBool m_sendDone;
 
     PRInt32 m_totalAmountRead;
 #ifdef UNREADY_CODE 
@@ -242,14 +226,18 @@ private:
 
     void AppendHelloArgument(nsACString& aResult);
     nsresult GetPassword(nsCString &aPassword);
     nsresult GetUsernamePassword(nsACString &aUsername, nsACString &aPassword);
     nsresult PromptForPassword(nsISmtpServer *aSmtpServer, nsISmtpUrl *aSmtpUrl, 
                                const PRUnichar **formatStrings, 
                                nsACString &aPassword);
 
-    void BackupAuthFlags();
-    void RestoreAuthFlags();
-    PRInt32 m_origAuthFlags;
+    void    InitPrefAuthMethods(PRInt32 authMethodPrefValue);
+    nsresult ChooseAuthMethod();
+    void    MarkAuthMethodAsFailed(PRInt32 failedAuthMethod);
+    void    ResetAuthMethods();
+    PRInt32 m_prefAuthMethods; // set of capability flags for auth methods
+    PRInt32 m_failedAuthMethods; // ditto
+    PRInt32 m_currentAuthMethod; // exactly one capability flag, or 0
 };
 
 #endif  // nsSmtpProtocol_h___
--- a/mailnews/compose/src/nsSmtpServer.cpp
+++ b/mailnews/compose/src/nsSmtpServer.cpp
@@ -199,61 +199,27 @@ nsSmtpServer::GetDisplayname(char * *aDi
         hostname.AppendInt(port);
     }
 
     *aDisplayname = ToNewCString(hostname);
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSmtpServer::GetTrySSL(PRInt32 *trySSL)
+nsSmtpServer::GetSocketType(PRInt32 *socketType)
 {
-  NS_ENSURE_ARG_POINTER(trySSL);
-  getIntPrefWithDefault("try_ssl", trySSL, 0);
+  NS_ENSURE_ARG_POINTER(socketType);
+  getIntPrefWithDefault("try_ssl", socketType, 0);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSmtpServer::SetTrySSL(PRInt32 trySSL)
-{
-    return mPrefBranch->SetIntPref("try_ssl", trySSL);
-}
-
-NS_IMETHODIMP
-nsSmtpServer::GetUseSecAuth(PRBool *useSecAuth)
-{
-    nsresult rv;
-    NS_ENSURE_ARG_POINTER(useSecAuth);
-    rv = mPrefBranch->GetBoolPref("useSecAuth", useSecAuth);
-    if (NS_FAILED(rv))
-        mDefPrefBranch->GetBoolPref("useSecAuth", useSecAuth);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSmtpServer::SetUseSecAuth(const PRBool useSecAuth)
+nsSmtpServer::SetSocketType(PRInt32 socketType)
 {
-    return mPrefBranch->SetBoolPref("useSecAuth", useSecAuth);
-}
-
-NS_IMETHODIMP
-nsSmtpServer::GetTrySecAuth(PRBool *trySecAuth)
-{
-    nsresult rv;
-    NS_ENSURE_ARG_POINTER(trySecAuth);
-    rv = mPrefBranch->GetBoolPref("trySecAuth", trySecAuth);
-    if (NS_FAILED(rv))
-        mDefPrefBranch->GetBoolPref("trySecAuth", trySecAuth);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSmtpServer::SetTrySecAuth(const PRBool trySecAuth)
-{
-    return mPrefBranch->SetBoolPref("trySecAuth", trySecAuth);
+    return mPrefBranch->SetIntPref("try_ssl", socketType);
 }
 
 NS_IMETHODIMP
 nsSmtpServer::GetHelloArgument(char * *aHelloArgument)
 {
     nsresult rv;
     NS_ENSURE_ARG_POINTER(aHelloArgument);
     rv = mPrefBranch->GetCharPref("hello_argument", aHelloArgument);
@@ -265,17 +231,17 @@ nsSmtpServer::GetHelloArgument(char * *a
     }
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSmtpServer::GetAuthMethod(PRInt32 *authMethod)
 {
   NS_ENSURE_ARG_POINTER(authMethod);
-  getIntPrefWithDefault("auth_method", authMethod, 1);
+  getIntPrefWithDefault("authMethod", authMethod, 3);
   return NS_OK;
 }
 
 void
 nsSmtpServer::getIntPrefWithDefault(const char *prefName,
                                     PRInt32 *val,
                                     PRInt32 defVal)
 {
@@ -287,17 +253,17 @@ nsSmtpServer::getIntPrefWithDefault(cons
   if (NS_FAILED(rv))
     // last resort
     *val = defVal;
 }
 
 NS_IMETHODIMP
 nsSmtpServer::SetAuthMethod(PRInt32 authMethod)
 {
-    return mPrefBranch->SetIntPref("auth_method", authMethod);
+    return mPrefBranch->SetIntPref("authMethod", authMethod);
 }
 
 NS_IMETHODIMP
 nsSmtpServer::GetUsername(nsACString &aUsername)
 {
   nsCString result;
   nsresult rv = mPrefBranch->GetCharPref("username", getter_Copies(result));
   if (NS_FAILED(rv))
@@ -455,17 +421,17 @@ nsSmtpServer::GetPasswordWithUI(const PR
                                nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
                                getter_Copies(uniPassword), &okayValue);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If the user pressed cancel, just return an empty string.
   if (!okayValue)
   {
     aPassword.Truncate();
-    return rv;
+    return NS_MSG_PASSWORD_PROMPT_CANCELLED;
   }
 
   NS_LossyConvertUTF16toASCII password(uniPassword);
 
   rv = SetPassword(password);
   NS_ENSURE_SUCCESS(rv, rv);
 
   aPassword = password;
--- a/mailnews/compose/src/nsSmtpService.cpp
+++ b/mailnews/compose/src/nsSmtpService.cpp
@@ -165,25 +165,25 @@ nsresult NS_MsgBuildSmtpUrl(nsIFile * aF
   // mscott: this function is a convience hack until netlib actually dispatches
   // smtp urls. in addition until we have a session to get a password, host and
   // other stuff from, we need to use default values....
   // ..for testing purposes....
 
     nsCString smtpHostName;
     nsCString smtpUserName;
     PRInt32 smtpPort;
-    PRInt32 trySSL;
+    PRInt32 socketType;
 
     aSmtpServer->GetHostname(smtpHostName);
     aSmtpServer->GetUsername(smtpUserName);
     aSmtpServer->GetPort(&smtpPort);
-    aSmtpServer->GetTrySSL(&trySSL);
+    aSmtpServer->GetSocketType(&socketType);
 
     if (!smtpPort)
-      smtpPort = (trySSL == PREF_SECURE_ALWAYS_SMTPS) ? 
+      smtpPort = (socketType == nsMsgSocketType::SSL) ?
         nsISmtpUrl::DEFAULT_SMTPS_PORT :  nsISmtpUrl::DEFAULT_SMTP_PORT;
 
   nsresult rv;
   nsCOMPtr<nsISmtpUrl> smtpUrl(do_CreateInstance(kCSmtpUrlCID, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCAutoString urlSpec("smtp://");
 
--- a/mailnews/compose/test/unit/head_compose.js
+++ b/mailnews/compose/test/unit/head_compose.js
@@ -22,17 +22,17 @@ function getBasicSmtpServer() {
                       .getService(Ci.nsISmtpService);
 
   // Create an smtp server and fill in the details.
   var smtpServer = smtpService.createSmtpServer();
 
   smtpServer.hostname = "localhost";
   smtpServer.port = SMTP_PORT;
   // Set the authentication method to "none"
-  smtpServer.authMethod = 0;
+  smtpServer.authMethod = 1;
 
   // Override the default greeting so we get something predicitable
   // in the ELHO message
   var prefSvc = Components.classes["@mozilla.org/preferences-service;1"]
     .getService(Components.interfaces.nsIPrefBranch);
 
   prefSvc.setCharPref("mail.smtpserver.default.hello_argument", "test");
 
--- a/mailnews/compose/test/unit/test_bug155172.js
+++ b/mailnews/compose/test/unit/test_bug155172.js
@@ -64,20 +64,18 @@ function run_test() {
   // the server if something fails.
   try {
     // Start the fake SMTP server
     server.start(SMTP_PORT);
 
     // This time with auth
     test = "Auth sendMailMessage";
 
-    smtpServer.authMethod = 1;
-    smtpServer.useSecAuth = false;
-    smtpServer.trySecAuth = false;
-    smtpServer.trySSL = false;
+    smtpServer.authMethod = Ci.nsMsgAuthMethod.passwordCleartext;
+    smtpServer.socketType = Ci.nsMsgSocketType.plain;
     smtpServer.username = kUsername;
 
     smtpService.sendMailMessage(testFile, kTo, identity,
                                 null, null, null, null,
                                 false, {}, {});
 
     // Set the new password for when we get a prompt
     gNewPassword = kPassword1;
--- a/mailnews/compose/test/unit/test_sendMailMessage.js
+++ b/mailnews/compose/test/unit/test_sendMailMessage.js
@@ -49,20 +49,18 @@ function test_RFC2821() {
                                        "RCPT TO:<" + kTo + ">",
                                        "DATA"]);
 
     server.resetTest();
 
     // This time with auth
     test = "Auth sendMailMessage";
 
-    smtpServer.authMethod = 1;
-    smtpServer.useSecAuth = false;
-    smtpServer.trySecAuth = false;
-    smtpServer.trySSL = false;
+    smtpServer.authMethod = Ci.nsMsgAuthMethod.passwordCleartext;
+    smtpServer.socketType = Ci.nsMsgSocketType.plain;
     smtpServer.username = kUsername;
     smtpServer.password = kPassword;
 
     smtpService.sendMailMessage(testFile, kTo, identity,
                                 null, null, null, null,
                                 false, {}, {});
 
     server.performTest();
new file mode 100644
--- /dev/null
+++ b/mailnews/compose/test/unit/test_smtpAuthMethods.js
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/**
+ * Authentication tests for SMTP.
+ *
+ * Test code <copied from="test_pop3AuthMethods.js">
+ */
+
+var server;
+var handler;
+var smtpServer;
+var smtpService;
+var testFile;
+var identity;
+
+const kUsername = "fred";
+const kPassword = "wilma";
+const kSender = "from@invalid.com";
+const kTo = "to@invalid.com";
+const MAILFROM = "MAIL FROM:<" + kSender + "> SIZE=155";
+const RCPTTO = "RCPT TO:<" + kTo + ">";
+const AUTHPLAIN = "AUTH PLAIN " + AuthPLAIN.encodeLine(kUsername, kPassword);
+
+var tests = [
+  { title: "Cleartext password, with server supporting AUTH PLAIN, LOGIN, and CRAM",
+    clientAuthMethod : Ci.nsMsgAuthMethod.passwordCleartext,
+    serverAuthMethods : [ "PLAIN", "LOGIN", "CRAM-MD5" ],
+    expectSuccess : true,
+    transaction: [ "EHLO test", AUTHPLAIN, MAILFROM, RCPTTO, "DATA" ] },
+  { title: "Cleartext password, with server only supporting AUTH LOGIN",
+    clientAuthMethod : Ci.nsMsgAuthMethod.passwordCleartext,
+    serverAuthMethods : [ "LOGIN" ],
+    expectSuccess : true,
+    transaction: [ "EHLO test", "AUTH LOGIN", MAILFROM, RCPTTO, "DATA" ] },
+  { title: "Encrypted password, with server supporting AUTH PLAIN, LOGIN and CRAM",
+    clientAuthMethod : Ci.nsMsgAuthMethod.passwordEncrypted,
+    serverAuthMethods : [ "PLAIN", "LOGIN", "CRAM-MD5" ],
+    expectSuccess : true,
+    transaction: [ "EHLO test", "AUTH CRAM-MD5", MAILFROM, RCPTTO, "DATA" ] },
+  { title: "Encrypted password, with server only supporting AUTH PLAIN (must fail)",
+    clientAuthMethod : Ci.nsMsgAuthMethod.passwordEncrypted,
+    serverAuthMethods : [ "PLAIN" ],
+    expectSuccess : false,
+    transaction: [ "EHLO test"] },
+  { title: "Any secure method, with server supporting AUTH PLAIN, LOGIN and CRAM",
+    clientAuthMethod : Ci.nsMsgAuthMethod.secure,
+    serverAuthMethods : [ "PLAIN" , "LOGIN", "CRAM-MD5" ],
+    expectSuccess : true,
+    transaction: [ "EHLO test", "AUTH CRAM-MD5", MAILFROM, RCPTTO, "DATA" ] },
+  { title: "Any secure method, with server only supporting AUTH PLAIN (must fail)",
+    clientAuthMethod : Ci.nsMsgAuthMethod.secure,
+    serverAuthMethods : [ "PLAIN" ],
+    expectSuccess : false,
+    transaction: [ "EHLO test" ] },
+];
+
+
+
+function nextTest() {
+  if (tests.length == 0)
+  {
+    // this is sync, so we run into endTest() at the end of run_test() now
+    return;
+  }
+  server.resetTest();
+
+  var curTest = tests.shift();
+  test = curTest.title;
+  dump("NEXT test: " + curTest.title + "\n");
+
+
+  // Adapt to curTest
+  handler.kAuthSchemes = curTest.serverAuthMethods;
+  smtpServer.authMethod = curTest.clientAuthMethod;
+
+  // Run test
+  smtpService.sendMailMessage(testFile, kTo, identity,
+                              null, null, null, null,
+                              false, {}, {});
+  server.performTest();
+
+  do_check_transaction(server.playTransaction(), curTest.transaction);
+
+  nextTest();
+}
+
+function run_test() {
+  // Handle the server in a try/catch/finally loop so that we always will stop
+  // the server if something fails.
+  try {
+    handler = new SMTP_RFC2821_handler(new smtpDaemon());
+    server = new nsMailServer(handler);
+    handler.kUsername = kUsername;
+    handler.kPassword = kPassword;
+    handler.kAuthRequired = true;
+    dump("AUTH PLAIN = " + AUTHPLAIN + "\n");
+    server.start(SMTP_PORT);
+
+    loadLocalMailAccount();
+    smtpServer = getBasicSmtpServer();
+    smtpServer.socketType = Ci.nsMsgSocketType.plain;
+    smtpServer.username = handler.kUsername;
+    smtpServer.password = handler.kPassword;
+    identity = getSmtpIdentity(kSender, smtpServer);
+    smtpService = Cc["@mozilla.org/messengercompose/smtp;1"]
+                        .getService(Ci.nsISmtpService);
+
+    testFile = do_get_file("data/message1.eml");
+
+    nextTest();
+
+  } catch (e) {
+    do_throw(e);
+  } finally {
+    endTest();
+  }
+}
+
+function endTest() {
+    dump("endTest()\n");
+    server.stop();
+
+    dump("emptying event loop\n");
+    var thread = gThreadManager.currentThread;
+    while (thread.hasPendingEvents()) {
+        dump("next event\n");
+      thread.processNextEvent(true);
+    }
+}
--- a/mailnews/compose/test/unit/test_smtpPassword.js
+++ b/mailnews/compose/test/unit/test_smtpPassword.js
@@ -41,20 +41,18 @@ function run_test() {
   // the server if something fails.
   try {
     // Start the fake SMTP server
     server.start(SMTP_PORT);
 
     // This time with auth
     test = "Auth sendMailMessage";
 
-    smtpServer.authMethod = 1;
-    smtpServer.useSecAuth = false;
-    smtpServer.trySecAuth = false;
-    smtpServer.trySSL = false;
+    smtpServer.authMethod = Ci.nsMsgAuthMethod.passwordCleartext;
+    smtpServer.socketType = Ci.nsMsgSocketType.plain;
     smtpServer.username = kUsername;
 
     smtpService.sendMailMessage(testFile, kTo, identity,
                                 null, null, null, null,
                                 false, {}, {});
 
     server.performTest();
 
--- a/mailnews/compose/test/unit/test_smtpPassword2.js
+++ b/mailnews/compose/test/unit/test_smtpPassword2.js
@@ -21,19 +21,19 @@ function run_test()
   signons.copyTo(gProfileDir, "signons.txt");
 
   // Set up the basic accounts and folders.
   loadLocalMailAccount();
 
   var smtpServer1 = getBasicSmtpServer();
   var smtpServer2 = getBasicSmtpServer();
 
-  smtpServer1.authMethod = 1;
+  smtpServer1.authMethod = 3;
   smtpServer1.username = kUser1;
-  smtpServer2.authMethod = 1;
+  smtpServer2.authMethod = 3;
   smtpServer2.username = kUser2;
 
   var i;
   var count = {};
 
   // Test - Check there are two logins to begin with.
   var logins = loginMgr.findLogins(count, kServerUrl, null, kServerUrl);
 
--- a/mailnews/compose/test/unit/test_smtpPasswordFailure1.js
+++ b/mailnews/compose/test/unit/test_smtpPasswordFailure1.js
@@ -108,20 +108,18 @@ function run_test() {
   // the server if something fails.
   try {
     // Start the fake SMTP server
     server.start(SMTP_PORT);
 
     // This time with auth
     test = "Auth sendMailMessage";
 
-    smtpServer.authMethod = 1;
-    smtpServer.useSecAuth = false;
-    smtpServer.trySecAuth = false;
-    smtpServer.trySSL = false;
+    smtpServer.authMethod = Ci.nsMsgAuthMethod.passwordCleartext;
+    smtpServer.socketType = Ci.nsMsgSocketType.plain;
     smtpServer.username = kUsername;
 
     dump("Send\n");
 
     smtpService.sendMailMessage(testFile, kTo, identity,
                                 null, null, null, null,
                                 false, {}, {});
 
--- a/mailnews/compose/test/unit/test_smtpPasswordFailure2.js
+++ b/mailnews/compose/test/unit/test_smtpPasswordFailure2.js
@@ -119,20 +119,18 @@ function run_test() {
   // the server if something fails.
   try {
     // Start the fake SMTP server
     server.start(SMTP_PORT);
 
     // This time with auth
     test = "Auth sendMailMessage";
 
-    smtpServer.authMethod = 1;
-    smtpServer.useSecAuth = false;
-    smtpServer.trySecAuth = false;
-    smtpServer.trySSL = false;
+    smtpServer.authMethod = Ci.nsMsgAuthMethod.passwordCleartext;
+    smtpServer.socketType = Ci.nsMsgSocketType.plain;
     smtpServer.username = kUsername;
 
     dump("Send\n");
 
     smtpService.sendMailMessage(testFile, kTo, identity,
                                 null, null, null, null,
                                 false, {}, {});
 
--- a/mailnews/imap/src/nsImapCore.h
+++ b/mailnews/imap/src/nsImapCore.h
@@ -118,18 +118,18 @@ typedef enum {
     kPublicNamespace,
     kDefaultNamespace,
     kUnknownNamespace
 } EIMAPNamespaceType;
 
 typedef enum {
     kCapabilityUndefined = 0x00000000,
     kCapabilityDefined = 0x00000001,
-    kHasAuthLoginCapability = 0x00000002,
-    kHasXNetscapeCapability = 0x00000004,
+    kHasAuthLoginCapability = 0x00000002, /* AUTH LOGIN (not the same as kHasAuthOldLoginCapability) */
+    kHasAuthOldLoginCapability = 0x00000004, /* original IMAP login method */
     kHasXSenderCapability = 0x00000008,
     kIMAP4Capability = 0x00000010,          /* RFC1734 */
     kIMAP4rev1Capability = 0x00000020,      /* RFC2060 */
     kIMAP4other = 0x00000040,                       /* future rev?? */
     kNoHierarchyRename = 0x00000080,                        /* no hierarchy rename */
     kACLCapability = 0x00000100,          /* ACL extension */
     kNamespaceCapability = 0x00000200,    /* IMAP4 Namespace Extension */
     kMailboxDataCapability = 0x00000400,  /* MAILBOXDATA SMTP posting extension */
@@ -140,18 +140,18 @@ typedef enum {
     kAOLImapCapability = 0x00008000,     /* aol imap extensions */
     kHasLanguageCapability = 0x00010000, /* language extensions */
     kHasCRAMCapability     = 0x00020000, /* CRAM auth extension */
     kQuotaCapability       = 0x00040000, /* RFC 2087 quota extension */
     kHasIdleCapability       = 0x00080000,  /* RFC 2177 idle extension */
     kHasAuthNTLMCapability = 0x00100000,  /* AUTH NTLM extension */
     kHasAuthMSNCapability = 0x00200000,   /* AUTH MSN extension */
     kHasStartTLSCapability = 0x00400000,   /* STARTTLS support */
-    kLoginDisabled = 0x00800000,        /* login disabled */
-    kHasAuthGssApiCapability = 0x01000000, /* GSSAPI AUTH */ 
+    kHasAuthNoneCapability = 0x00800000, /* needs no login */
+    kHasAuthGssApiCapability = 0x01000000, /* GSSAPI AUTH */
     kHasCondStoreCapability =  0x02000000, /* RFC 3551 CondStore extension */
     kHasEnableCapability    =  0x04000000, /* RFC 5161 ENABLE extension */
     kHasXListCapability    =  0x08000000,  /* XLIST extension */
     kHasCompressDeflateCapability  =  0x10000000  /* RFC 4978 COMPRESS extension */
 } eIMAPCapabilityFlag;
 
 // this used to be part of the connection object class - maybe we should move it into 
 // something similar
--- a/mailnews/imap/src/nsImapIncomingServer.cpp
+++ b/mailnews/imap/src/nsImapIncomingServer.cpp
@@ -829,24 +829,33 @@ nsImapIncomingServer::GetImapConnection(
 nsresult
 nsImapIncomingServer::CreateProtocolInstance(nsIEventTarget *aEventTarget,
                                              nsIImapProtocol ** aImapConnection)
 {
   // create a new connection and add it to the connection cache
   // we may need to flag the protocol connection as busy so we don't get
   // a race condition where someone else goes through this code
 
-  PRBool useSecAuth;
-  GetUseSecAuth(&useSecAuth);
+  PRInt32 authMethod;
+  GetAuthMethod(&authMethod);
   nsresult rv;
-  // pre-flight that we have nss - on the ui thread
-  if (useSecAuth)
+  // pre-flight that we have nss - on the ui thread - for MD5 etc.
+  switch (authMethod)
   {
-    nsCOMPtr<nsISignatureVerifier> verifier = do_GetService(SIGNATURE_VERIFIER_CONTRACTID, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
+    case nsMsgAuthMethod::passwordEncrypted:
+    case nsMsgAuthMethod::secure:
+    case nsMsgAuthMethod::anything:
+      {
+        nsCOMPtr<nsISignatureVerifier> verifier =
+            do_GetService(SIGNATURE_VERIFIER_CONTRACTID, &rv);
+        NS_ENSURE_SUCCESS(rv, rv);
+      }
+      break;
+    default:
+      break;
   }
   nsIImapProtocol * protocolInstance;
   rv = CallCreateInstance(kImapProtocolCID, &protocolInstance);
   if (NS_SUCCEEDED(rv) && protocolInstance)
   {
     nsCOMPtr<nsIImapHostSessionList> hostSession =
       do_GetService(kCImapHostSessionListCID, &rv);
     if (NS_SUCCEEDED(rv))
@@ -2751,17 +2760,17 @@ nsImapIncomingServer::GeneratePrettyName
   PRInt32 serverPort = PORT_NOT_SET;
   rv = GetPort(&serverPort);
   NS_ENSURE_SUCCESS(rv,rv);
 
   // Is the server secure ?
   PRInt32 socketType;
   rv = GetSocketType(&socketType);
   NS_ENSURE_SUCCESS(rv,rv);
-  PRBool isSecure = (socketType == nsIMsgIncomingServer::useSSL);
+  PRBool isSecure = (socketType == nsMsgSocketType::SSL);
 
   // Is server port a default port ?
   PRBool isItDefaultPort = PR_FALSE;
   if (((serverPort == defaultServerPort) && !isSecure)||
       ((serverPort == defaultSecureServerPort) && isSecure))
       isItDefaultPort = PR_TRUE;
 
   // Construct pretty name from username and hostname
--- a/mailnews/imap/src/nsImapProtocol.cpp
+++ b/mailnews/imap/src/nsImapProtocol.cpp
@@ -18,16 +18,17 @@
  * Netscape Communications Corporation.
  * Portions created by the Initial Developer are Copyright (C) 1999
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Pierre Phaneuf <pp@ludusdesign.com>
  *   Henry Jia <Henry.Jia@sun.com>
  *   Lorenzo Colitti <lorenzo@colitti.com>
+ *   Ben Bucksch <ben.bucksch beonex.com> <http://business.beonex.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -371,24 +372,25 @@ nsImapProtocol::nsImapProtocol() : nsMsg
 {
   m_urlInProgress = PR_FALSE;
   m_idle = PR_FALSE;
   m_retryUrlOnError = PR_FALSE;
   m_useIdle = PR_TRUE; // by default, use it
   m_useCondStore = PR_TRUE;
   m_useCompressDeflate = PR_TRUE;
   m_ignoreExpunges = PR_FALSE;
-  m_useSecAuth = PR_FALSE;
-  m_socketType = nsIMsgIncomingServer::tryTLS;
+  m_prefAuthMethods = kCapabilityUndefined;
+  m_failedAuthMethods = 0;
+  m_currentAuthMethod = kCapabilityUndefined;
+  m_socketType = nsMsgSocketType::trySTARTTLS;
   m_connectionStatus = 0;
   m_safeToCloseConnection = PR_FALSE;
   m_hostSessionList = nsnull;
   m_flagState = nsnull;
   m_fetchBodyIdList = nsnull;
-  m_authLogin = PR_TRUE;
 
   nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
   NS_ASSERTION(prefBranch, "FAILED to create the preference service");
 
   // read in the accept languages preference
   if (prefBranch)
   {
     if (!gInitialized)
@@ -524,19 +526,17 @@ nsresult nsImapProtocol::Initialize(nsII
 
   m_sinkEventTarget = aSinkEventTarget;
   m_hostSessionList = aHostSessionList; // no ref count...host session list has life time > connection
   m_parser.SetHostSessionList(aHostSessionList);
   m_parser.SetFlagState(m_flagState);
 
   // one of the initializations that should be done in UI thread
   nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
-  if (NS_SUCCEEDED(rv) && prefBranch)
-    prefBranch->GetBoolPref("mail.auth_login", &m_authLogin);
-    
+
   // Now initialize the thread for the connection and create appropriate monitors
   if (m_thread == nsnull)
   {
     m_dataAvailableMonitor = PR_NewMonitor();
     m_urlReadyToRunMonitor = PR_NewMonitor();
     m_pseudoInterruptMonitor = PR_NewMonitor();
     m_dataMemberMonitor = PR_NewMonitor();
     m_threadDeathMonitor = PR_NewMonitor();
@@ -791,19 +791,21 @@ nsresult nsImapProtocol::SetupWithUrl(ns
                                 getter_AddRefs(m_channelListener));
       if (NS_FAILED(rv)) return rv;
     }
 
     PRUint32 capability = kCapabilityUndefined;
 
     m_hostSessionList->GetCapabilityForHost(GetImapServerKey(), capability);
 
+    PRInt32 authMethod;
+    (void) server->GetAuthMethod(&authMethod);
+    InitPrefAuthMethods(authMethod);
+    (void) server->GetSocketType(&m_socketType);
     PRBool shuttingDown;
-    (void) server->GetUseSecAuth(&m_useSecAuth);
-    (void) server->GetSocketType(&m_socketType);
     (void) imapServer->GetShuttingDown(&shuttingDown);
     if (!shuttingDown)
       (void) imapServer->GetUseIdle(&m_useIdle);
     else
       m_useIdle = PR_FALSE;
     if (imapServer)
       imapServer->GetFetchByChunks(&m_fetchByChunks);
 
@@ -813,35 +815,36 @@ nsresult nsImapProtocol::SetupWithUrl(ns
       PRInt32 port=-1;
       server->GetPort(&port);
 
       if (port <= 0)
       {
         PRInt32 socketType;
         // Be a bit smarter about setting the default port
         port = (NS_SUCCEEDED(server->GetSocketType(&socketType)) &&
-                socketType == nsIMsgIncomingServer::useSSL) ?
+                socketType == nsMsgSocketType::SSL) ?
                nsIImapUrl::DEFAULT_IMAPS_PORT : nsIImapUrl::DEFAULT_IMAP_PORT;
       }
       nsCAutoString hostName;
       nsCOMPtr<nsISocketTransportService> socketService = 
                do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
       if (NS_SUCCEEDED(rv) && aURL)
       {
         aURL->GetPort(&port);
         server->GetRealHostName(hostName);
 
         Log("SetupWithUrl", nsnull, "clearing IMAP_CONNECTION_IS_OPEN");
         ClearFlag(IMAP_CONNECTION_IS_OPEN);
         const char *connectionType = nsnull;
 
-        if (m_socketType == nsIMsgIncomingServer::useSSL)
+        if (m_socketType == nsMsgSocketType::SSL)
           connectionType = "ssl";
-        else if ((m_socketType == nsIMsgIncomingServer::tryTLS && (capability & kHasStartTLSCapability))
-          || m_socketType == nsIMsgIncomingServer::alwaysUseTLS)
+        else if ((m_socketType == nsMsgSocketType::trySTARTTLS &&
+                 (capability & kHasStartTLSCapability))
+                 || m_socketType == nsMsgSocketType::alwaysSTARTTLS)
           connectionType = "starttls";
 
         nsCOMPtr<nsIProxyInfo> proxyInfo;
         rv = NS_ExamineForProxy("imap", hostName.get(), port, getter_AddRefs(proxyInfo));
         if (NS_FAILED(rv)) proxyInfo = nsnull;
 
         const nsACString *socketHost;
         PRUint16 socketPort;
@@ -854,20 +857,20 @@ nsresult nsImapProtocol::SetupWithUrl(ns
         else
         {
           socketHost = &hostName;
           socketPort = port;
         }
         rv = socketService->CreateTransport(&connectionType, connectionType != nsnull,
                                             *socketHost, socketPort, proxyInfo,
                                             getter_AddRefs(m_transport));
-        if (NS_FAILED(rv) && m_socketType == nsIMsgIncomingServer::tryTLS)
+        if (NS_FAILED(rv) && m_socketType == nsMsgSocketType::trySTARTTLS)
         {
           connectionType = nsnull;
-          m_socketType = nsIMsgIncomingServer::defaultSocket;
+          m_socketType = nsMsgSocketType::plain;
           rv = socketService->CreateTransport(&connectionType, connectionType != nsnull,
                                               *socketHost, socketPort, proxyInfo,
                                               getter_AddRefs(m_transport));
         }
         // remember so we can know whether we can issue a start tls or not...
         m_connectionType = connectionType;
         if (m_transport && m_mockChannel)
         {
@@ -1626,19 +1629,19 @@ PRBool nsImapProtocol::ProcessCurrentURL
         if (!DeathSignalReceived() && GetConnectionStatus() >= 0)
           AlertUserEventUsingId(IMAP_SERVER_NOT_IMAP4);
 
         SetConnectionStatus(-1);        // stop netlib
       }
       else
       {
         if (m_connectionType.Equals("starttls")
-            && (m_socketType == nsIMsgIncomingServer::tryTLS
+            && (m_socketType == nsMsgSocketType::trySTARTTLS
             && (GetServerStateParser().GetCapabilityFlag() & kHasStartTLSCapability))
-          || m_socketType == nsIMsgIncomingServer::alwaysUseTLS)
+          || m_socketType == nsMsgSocketType::alwaysSTARTTLS)
         {
           StartTLS();
           if (GetServerStateParser().LastCommandSuccessful())
           {
             nsCOMPtr<nsISupports> secInfo;
             nsCOMPtr<nsISocketTransport> strans = do_QueryInterface(m_transport, &rv);
             if (NS_FAILED(rv)) return rv;
 
@@ -1648,16 +1651,19 @@ PRBool nsImapProtocol::ProcessCurrentURL
             {
               nsCOMPtr<nsISSLSocketControl> sslControl = do_QueryInterface(secInfo, &rv);
 
               if (NS_SUCCEEDED(rv) && sslControl)
               {
                 rv = sslControl->StartTLS();
                 if (NS_SUCCEEDED(rv))
                 {
+                  // force re-issue of "capability", because servers may
+                  // enable other auth features (e.g. remove LOGINDISABLED
+                  // and add AUTH=PLAIN) after we upgraded to SSL.
                   Capability();
                   PRInt32 capabilityFlag = GetServerStateParser().GetCapabilityFlag();
                   // Courier imap doesn't return STARTTLS capability if we've done
                   // a STARTTLS! But we need to remember this capability so we'll
                   // try to use STARTTLS next time.
                   if (!(capabilityFlag & kHasStartTLSCapability))
                   {
                     capabilityFlag |= kHasStartTLSCapability;
@@ -1668,34 +1674,34 @@ PRBool nsImapProtocol::ProcessCurrentURL
                 }
               }
             }
             if (NS_FAILED(rv))
             {
               nsCAutoString logLine("STARTTLS negotiation failed. Error 0x");
               logLine.AppendInt(rv, 16);
               Log("ProcessCurrentURL", nsnull, logLine.get());
-              if (m_socketType == nsIMsgIncomingServer::alwaysUseTLS)
+              if (m_socketType == nsMsgSocketType::alwaysSTARTTLS)
               {
                 SetConnectionStatus(-1);        // stop netlib
                 m_transport->Close(rv);
               }
             }
           }
-          else if (m_socketType == nsIMsgIncomingServer::alwaysUseTLS)
+          else if (m_socketType == nsMsgSocketType::alwaysSTARTTLS)
           {
             SetConnectionStatus(-1);        // stop netlib
             if (m_transport)
               m_transport->Close(rv);
           }
         }
         // in this case, we didn't know the server supported TLS when
         // we created the socket, so we're going to retry with
         // STARTTLS.
-        else if (m_socketType == nsIMsgIncomingServer::tryTLS
+        else if (m_socketType == nsMsgSocketType::trySTARTTLS
             && (GetServerStateParser().GetCapabilityFlag() & kHasStartTLSCapability))
         {
           ClearFlag(IMAP_CONNECTION_IS_OPEN);
           TellThreadToDie();
           SetConnectionStatus(-1);
           return RetryUrl();
         }
         logonFailed = !TryToLogon();
@@ -5407,119 +5413,203 @@ void nsImapProtocol::EscapeUserNamePassw
         {
             resultStr->Append('\\');
         }
         resultStr->Append(strToEscape[i]);
     }
   }
 }
 
-void nsImapProtocol::InsecureLogin(const char *userName, const nsCString &password)
-{
-  ProgressEventFunctionUsingId (IMAP_STATUS_SENDING_LOGIN);
-  IncrementCommandTagNumber();
-  nsCString command (GetServerCommandTag());
-  nsCAutoString escapedUserName;
-  command.Append(" login \"");
-  EscapeUserNamePasswordString(userName, &escapedUserName);
-  command.Append(escapedUserName);
-  command.Append("\" \"");
-
-  // if the password contains a \, login will fail
-  // turn foo\bar into foo\\bar
-  nsCAutoString correctedPassword;
-  EscapeUserNamePasswordString(password.get(), &correctedPassword);
-  command.Append(correctedPassword);
-  command.Append("\""CRLF);
-
-  nsresult rv = SendData(command.get(), PR_TRUE /* suppress logging */);
-
-  if (NS_SUCCEEDED(rv))
-     ParseIMAPandCheckForNewMail();
+void nsImapProtocol::InitPrefAuthMethods(PRInt32 authMethodPrefValue)
+{
+    // for m_prefAuthMethods, using the same flags as server capablities.
+    switch (authMethodPrefValue)
+    {
+      case nsMsgAuthMethod::none:
+        m_prefAuthMethods = kHasAuthNoneCapability;
+        break;
+      case nsMsgAuthMethod::old:
+        m_prefAuthMethods = kHasAuthOldLoginCapability;
+        break;
+      case nsMsgAuthMethod::passwordCleartext:
+        m_prefAuthMethods = kHasAuthOldLoginCapability |
+            kHasAuthLoginCapability | kHasAuthPlainCapability;
+        break;
+      case nsMsgAuthMethod::passwordEncrypted:
+        m_prefAuthMethods = kHasCRAMCapability;
+        break;
+      case nsMsgAuthMethod::NTLM:
+        m_prefAuthMethods = kHasAuthNTLMCapability | kHasAuthMSNCapability;
+        break;
+      case nsMsgAuthMethod::GSSAPI:
+        m_prefAuthMethods = kHasAuthGssApiCapability;
+        break;
+      case nsMsgAuthMethod::secure:
+        m_prefAuthMethods = kHasCRAMCapability |
+            kHasAuthGssApiCapability |
+            kHasAuthNTLMCapability | kHasAuthMSNCapability;
+        break;
+      default:
+        NS_ASSERTION(false, "IMAP: authMethod pref invalid");
+        // TODO log to error console
+        PR_LOG(IMAP, PR_LOG_ERROR,
+            ("IMAP: bad pref authMethod = %d\n", authMethodPrefValue));
+        // fall to any
+      case nsMsgAuthMethod::anything:
+        m_prefAuthMethods = kHasAuthOldLoginCapability |
+            kHasAuthLoginCapability | kHasAuthPlainCapability |
+            kHasCRAMCapability | kHasAuthGssApiCapability |
+            kHasAuthNTLMCapability | kHasAuthMSNCapability;
+        break;
+    }
+    NS_ASSERTION(m_prefAuthMethods != kCapabilityUndefined,
+         "IMAP: InitPrefAuthMethods() didn't work");
+}
+
+/**
+ * Changes m_currentAuthMethod to pick the best remaining one
+ * which is allowed by server and prefs and not marked failed.
+ * The order of preference and trying of auth methods is encoded here.
+ */
+nsresult nsImapProtocol::ChooseAuthMethod()
+{
+  PRInt32 serverCaps = GetServerStateParser().GetCapabilityFlag();
+  PRInt32 availCaps = serverCaps & m_prefAuthMethods & ~m_failedAuthMethods;
+
+  PR_LOG(IMAP, PR_LOG_DEBUG, ("IMAP auth: server caps 0x%X, pref 0x%X, failed 0x%X, avail caps 0x%X",
+        serverCaps, m_prefAuthMethods, m_failedAuthMethods, availCaps));
+  PR_LOG(IMAP, PR_LOG_DEBUG, ("(GSSAPI = 0x%X, CRAM = 0x%X, NTLM = 0x%X, "
+        "MSN =  0x%X, PLAIN = 0x%X, LOGIN = 0x%X, old-style IMAP login = 0x%X)",
+        kHasAuthGssApiCapability, kHasCRAMCapability, kHasAuthNTLMCapability,
+        kHasAuthMSNCapability, kHasAuthPlainCapability, kHasAuthLoginCapability,
+        kHasAuthOldLoginCapability));
+
+  if (kHasAuthGssApiCapability & availCaps)
+    m_currentAuthMethod = kHasAuthGssApiCapability;
+  else if (kHasCRAMCapability & availCaps)
+    m_currentAuthMethod = kHasCRAMCapability;
+  else if (kHasAuthNTLMCapability & availCaps)
+    m_currentAuthMethod = kHasAuthNTLMCapability;
+  else if (kHasAuthMSNCapability & availCaps)
+    m_currentAuthMethod = kHasAuthMSNCapability;
+  else if (kHasAuthPlainCapability & availCaps)
+    m_currentAuthMethod = kHasAuthPlainCapability;
+  else if (kHasAuthLoginCapability & availCaps)
+    m_currentAuthMethod = kHasAuthLoginCapability;
+  else if (kHasAuthOldLoginCapability & availCaps)
+    m_currentAuthMethod = kHasAuthOldLoginCapability;
+  else
+  {
+    PR_LOG(IMAP, PR_LOG_DEBUG, ("no remaining auth method"));
+    m_currentAuthMethod = kCapabilityUndefined;
+    return NS_ERROR_FAILURE;
+  }
+  PR_LOG(IMAP, PR_LOG_DEBUG, ("trying auth method 0x%X", m_currentAuthMethod));
+  return NS_OK;
+}
+
+void nsImapProtocol::MarkAuthMethodAsFailed(PRInt32 failedAuthMethod)
+{
+  PR_LOG(IMAP, PR_LOG_DEBUG, ("marking auth method 0x%X failed", failedAuthMethod));
+  m_failedAuthMethods |= failedAuthMethod;
+}
+
+/**
+ * Start over, trying all auth methods again
+ */
+void nsImapProtocol::ResetAuthMethods()
+{
+  PR_LOG(IMAP, PR_LOG_DEBUG, ("resetting (failed) auth methods"));
+  m_currentAuthMethod = kCapabilityUndefined;
+  m_failedAuthMethods = 0;
 }
 
 nsresult nsImapProtocol::AuthLogin(const char *userName, const nsCString &password, eIMAPCapabilityFlag flag)
 {
   ProgressEventFunctionUsingId (IMAP_STATUS_SENDING_AUTH_LOGIN);
   IncrementCommandTagNumber();
 
   char * currentCommand=nsnull;
   nsresult rv;
 
+  PR_LOG(IMAP, PR_LOG_DEBUG, ("IMAP: trying auth method 0x%X", m_currentAuthMethod));
+
   if (flag & kHasCRAMCapability)
   {
-      // inform the server that we want to begin a CRAM authentication procedure...
-      nsCAutoString command (GetServerCommandTag());
-      command.Append(" authenticate CRAM-MD5" CRLF);
-      rv = SendData(command.get());
-      ParseIMAPandCheckForNewMail();
-      if (GetServerStateParser().LastCommandSuccessful())
+    NS_ENSURE_TRUE(m_imapServerSink, NS_ERROR_NULL_POINTER);
+    PR_LOG(IMAP, PR_LOG_DEBUG, ("MD5 auth"));
+    // inform the server that we want to begin a CRAM authentication procedure...
+    nsCAutoString command (GetServerCommandTag());
+    command.Append(" authenticate CRAM-MD5" CRLF);
+    rv = SendData(command.get());
+    NS_ENSURE_SUCCESS(rv, rv);
+    ParseIMAPandCheckForNewMail();
+    if (GetServerStateParser().LastCommandSuccessful())
+    {
+      char *digest = nsnull;
+      char *cramDigest = GetServerStateParser().fAuthChallenge;
+      char *decodedChallenge = PL_Base64Decode(cramDigest,
+                                                strlen(cramDigest), nsnull);
+      rv = m_imapServerSink->CramMD5Hash(decodedChallenge, password.get(), &digest);
+      PR_Free(decodedChallenge);
+      NS_ENSURE_SUCCESS(rv, rv);
+      NS_ENSURE_TRUE(digest, NS_ERROR_NULL_POINTER);
+      nsCAutoString encodedDigest;
+      char hexVal[8];
+
+      for (PRUint32 j=0; j<16; j++)
       {
-        char *digest = nsnull;
-        char *cramDigest = GetServerStateParser().fAuthChallenge;
-        char * decodedChallenge = PL_Base64Decode(cramDigest,
-                                                  strlen(cramDigest), nsnull);
-        if (m_imapServerSink)
-          rv = m_imapServerSink->CramMD5Hash(decodedChallenge, password.get(), &digest);
-
-        PR_Free(decodedChallenge);
-        if (NS_SUCCEEDED(rv) && digest)
-        {
-          nsCAutoString encodedDigest;
-          char hexVal[8];
-
-          for (PRUint32 j=0; j<16; j++)
-          {
-            PR_snprintf (hexVal,8, "%.2x", 0x0ff & (unsigned short)(digest[j]));
-            encodedDigest.Append(hexVal);
-          }
-
-          PR_snprintf(m_dataOutputBuf, OUTPUT_BUFFER_SIZE, "%s %s", userName, encodedDigest.get());
-          char *base64Str = PL_Base64Encode(m_dataOutputBuf, strlen(m_dataOutputBuf), nsnull);
-          PR_snprintf(m_dataOutputBuf, OUTPUT_BUFFER_SIZE, "%s" CRLF, base64Str);
-          PR_Free(base64Str);
-          PR_Free(digest);
-          rv = SendData(m_dataOutputBuf);
-          if (NS_SUCCEEDED(rv))
-            ParseIMAPandCheckForNewMail(command.get());
-          if (GetServerStateParser().LastCommandSuccessful())
-            return NS_OK;
-          GetServerStateParser().SetCapabilityFlag(GetServerStateParser().GetCapabilityFlag() & ~kHasCRAMCapability);
-
-        }
+        PR_snprintf (hexVal,8, "%.2x", 0x0ff & (unsigned short)(digest[j]));
+        encodedDigest.Append(hexVal);
+      }
+
+      PR_snprintf(m_dataOutputBuf, OUTPUT_BUFFER_SIZE, "%s %s", userName, encodedDigest.get());
+      char *base64Str = PL_Base64Encode(m_dataOutputBuf, strlen(m_dataOutputBuf), nsnull);
+      PR_snprintf(m_dataOutputBuf, OUTPUT_BUFFER_SIZE, "%s" CRLF, base64Str);
+      PR_Free(base64Str);
+      PR_Free(digest);
+      rv = SendData(m_dataOutputBuf);
+      NS_ENSURE_SUCCESS(rv, rv);
+      ParseIMAPandCheckForNewMail(command.get());
     }
   } // if CRAM response was received
   else if (flag & kHasAuthGssApiCapability)
   {
+    PR_LOG(IMAP, PR_LOG_DEBUG, ("MD5 auth"));
+
     // Only try GSSAPI once - if it fails, its going to be because we don't
     // have valid credentials
-    GetServerStateParser().SetCapabilityFlag(GetServerStateParser().GetCapabilityFlag() & ~(kHasAuthGssApiCapability));
+    //MarkAuthMethodAsFailed(kHasAuthGssApiCapability);
 
     // We do step1 first, so we don't try GSSAPI against a server which
     // we can't get credentials for.
     nsCAutoString response;
-    nsresult gssrv;
-
+
+    // realHostname != GetImapHostName() when hostname was changed
+    nsCAutoString realHostname;
+    nsCOMPtr<nsIMsgIncomingServer> server = do_QueryReferent(m_server);
+    server->GetRealHostName(realHostname);
     nsCAutoString service("imap@");
-    service.Append(GetImapHostName());
-    gssrv = DoGSSAPIStep1(service.get(), userName, response);
-    NS_ENSURE_SUCCESS(gssrv, gssrv);
+    service.Append(realHostname);
+    rv = DoGSSAPIStep1(service.get(), userName, response);
+    NS_ENSURE_SUCCESS(rv, rv);
 
     nsCAutoString command (GetServerCommandTag());
     command.Append(" authenticate GSSAPI" CRLF);
     rv = SendData(command.get());
     NS_ENSURE_SUCCESS(rv, rv);
 
     ParseIMAPandCheckForNewMail("AUTH GSSAPI");
     if (GetServerStateParser().LastCommandSuccessful())
     {
       response += CRLF;
       rv = SendData(response.get());
       NS_ENSURE_SUCCESS(rv, rv);
       ParseIMAPandCheckForNewMail(command.get());
+      nsresult gssrv = NS_OK;
 
       while (GetServerStateParser().LastCommandSuccessful() &&
              NS_SUCCEEDED(gssrv) && gssrv != NS_SUCCESS_AUTH_FINISHED)
       {
         nsCString challengeStr(GetServerStateParser().fAuthChallenge);
         gssrv = DoGSSAPIStep2(challengeStr, response);
         if (NS_SUCCEEDED(gssrv))
         {
@@ -5527,132 +5617,142 @@ nsresult nsImapProtocol::AuthLogin(const
           rv = SendData(response.get());
         }
         else
           rv = SendData("*" CRLF);
 
         NS_ENSURE_SUCCESS(rv, rv);
         ParseIMAPandCheckForNewMail(command.get());
       }
-      rv = gssrv;
-    }
-    return rv;
-  }
-  else if (flag & (kHasAuthNTLMCapability|kHasAuthMSNCapability))
-  {
+      // TODO: whether it worked or not is shown by LastCommandSuccessful(), not gssrv, right?
+    }
+  }
+  else if (flag & (kHasAuthNTLMCapability | kHasAuthMSNCapability))
+  {
+    PR_LOG(IMAP, PR_LOG_DEBUG, ("NTLM auth"));
     nsCAutoString command (GetServerCommandTag());
     command.Append((flag & kHasAuthNTLMCapability) ? " authenticate NTLM" CRLF
                                                    : " authenticate MSN" CRLF);
     rv = SendData(command.get());
     ParseIMAPandCheckForNewMail("AUTH NTLM"); // this just waits for ntlm step 1
     if (GetServerStateParser().LastCommandSuccessful())
     {
       nsCAutoString cmd;
       rv = DoNtlmStep1(userName, password.get(), cmd);
-      if (NS_SUCCEEDED(rv))
+      NS_ENSURE_SUCCESS(rv, rv);
+      cmd += CRLF;
+      rv = SendData(cmd.get());
+      NS_ENSURE_SUCCESS(rv, rv);
+      ParseIMAPandCheckForNewMail(command.get());
+      if (GetServerStateParser().LastCommandSuccessful())
       {
-        cmd += CRLF;
-        rv = SendData(cmd.get());
-        if (NS_SUCCEEDED(rv))
-        {
-          ParseIMAPandCheckForNewMail(command.get());
-          if (GetServerStateParser().LastCommandSuccessful())
-          {
-            nsCString challengeStr(GetServerStateParser().fAuthChallenge);
-            nsCString response;
-            rv = DoNtlmStep2(challengeStr, response);
-            if (NS_SUCCEEDED(rv))
-            {
-              response += CRLF;
-              rv = SendData(response.get());
-              ParseIMAPandCheckForNewMail(command.get());
-              if (!GetServerStateParser().LastCommandSuccessful())
-                GetServerStateParser().SetCapabilityFlag(GetServerStateParser().GetCapabilityFlag() & ~(kHasAuthNTLMCapability|kHasAuthMSNCapability));
-            }
-          }
-        }
+        nsCString challengeStr(GetServerStateParser().fAuthChallenge);
+        nsCString response;
+        rv = DoNtlmStep2(challengeStr, response);
+        NS_ENSURE_SUCCESS(rv, rv);
+        response += CRLF;
+        rv = SendData(response.get());
+        ParseIMAPandCheckForNewMail(command.get());
       }
     }
   }
   else if (flag & kHasAuthPlainCapability)
   {
+    PR_LOG(IMAP, PR_LOG_DEBUG, ("PLAIN auth"));
     PR_snprintf(m_dataOutputBuf, OUTPUT_BUFFER_SIZE, "%s authenticate plain" CRLF, GetServerCommandTag());
     rv = SendData(m_dataOutputBuf);
     NS_ENSURE_SUCCESS(rv, rv);
     currentCommand = PL_strdup(m_dataOutputBuf); /* StrAllocCopy(currentCommand, GetOutputBuffer()); */
     ParseIMAPandCheckForNewMail();
     if (GetServerStateParser().LastCommandSuccessful())
     {
-      char plainstr[512]; // placeholder for "<NUL>userName<NUL>password"
+      // RFC 4616
+      char plainstr[512]; // placeholder for "<NUL>userName<NUL>password" TODO nsCAutoString
       int len = 1; // count for first <NUL> char
       memset(plainstr, 0, 512);
       PR_snprintf(&plainstr[1], 510, "%s", userName);
       len += PL_strlen(userName);
       len++;  // count for second <NUL> char
       PR_snprintf(&plainstr[len], 511-len, "%s", password.get());
       len += password.Length();
       char *base64Str = PL_Base64Encode(plainstr, len, nsnull);
-      if (base64Str)
-      {
-        PR_snprintf(m_dataOutputBuf, OUTPUT_BUFFER_SIZE, "%s" CRLF, base64Str);
-        PR_Free(base64Str);
-        rv = SendData(m_dataOutputBuf, PR_TRUE /* suppress logging */);
-        if (NS_SUCCEEDED(rv))
-            ParseIMAPandCheckForNewMail(currentCommand);
-        if (GetServerStateParser().LastCommandSuccessful())
-        {
-          PR_Free(currentCommand);
-          return NS_OK;
-        } // if the last command succeeded
-      } // if we got a base 64 encoded string
+      PR_snprintf(m_dataOutputBuf, OUTPUT_BUFFER_SIZE, "%s" CRLF, base64Str);
+      PR_Free(base64Str);
+      rv = SendData(m_dataOutputBuf, PR_TRUE /* suppress logging */);
+      if (NS_SUCCEEDED(rv))
+        ParseIMAPandCheckForNewMail(currentCommand);
     } // if the last command succeeded
   } // if auth plain capability
-
   else if (flag & kHasAuthLoginCapability)
   {
+    PR_LOG(IMAP, PR_LOG_DEBUG, ("LOGIN auth"));
     PR_snprintf(m_dataOutputBuf, OUTPUT_BUFFER_SIZE, "%s authenticate login" CRLF, GetServerCommandTag());
     rv = SendData(m_dataOutputBuf);
     NS_ENSURE_SUCCESS(rv, rv);
     currentCommand = PL_strdup(m_dataOutputBuf);
     ParseIMAPandCheckForNewMail();
 
     if (GetServerStateParser().LastCommandSuccessful())
     {
       char *base64Str = PL_Base64Encode(userName, PL_strlen(userName), nsnull);
-      if(base64Str)
+      PR_snprintf(m_dataOutputBuf, OUTPUT_BUFFER_SIZE, "%s" CRLF, base64Str);
+      PR_Free(base64Str);
+      rv = SendData(m_dataOutputBuf, PR_TRUE /* suppress logging */);
+      if (NS_SUCCEEDED(rv))
       {
-        PR_snprintf(m_dataOutputBuf, OUTPUT_BUFFER_SIZE, "%s" CRLF, base64Str);
-        PR_Free(base64Str);
-        rv = SendData(m_dataOutputBuf, PR_TRUE /* suppress logging */);
-        if (NS_SUCCEEDED(rv))
-            ParseIMAPandCheckForNewMail(currentCommand);
-      }
-      if (GetServerStateParser().LastCommandSuccessful())
-      {
-        base64Str = PL_Base64Encode(password.get(), password.Length(), nsnull);
-        PR_snprintf(m_dataOutputBuf, OUTPUT_BUFFER_SIZE, "%s" CRLF, base64Str);
-        PR_Free(base64Str);
-        rv = SendData(m_dataOutputBuf, PR_TRUE /* suppress logging */);
-        if (NS_SUCCEEDED(rv))
-           ParseIMAPandCheckForNewMail(currentCommand);
+        ParseIMAPandCheckForNewMail(currentCommand);
         if (GetServerStateParser().LastCommandSuccessful())
         {
-          PR_Free(currentCommand);
-          return NS_OK;
-        }
+          base64Str = PL_Base64Encode(password.get(), password.Length(), nsnull);
+          PR_snprintf(m_dataOutputBuf, OUTPUT_BUFFER_SIZE, "%s" CRLF, base64Str);
+          PR_Free(base64Str);
+          rv = SendData(m_dataOutputBuf, PR_TRUE /* suppress logging */);
+          if (NS_SUCCEEDED(rv))
+            ParseIMAPandCheckForNewMail(currentCommand);
+        } // if last command successful
       } // if last command successful
     } // if last command successful
   } // if has auth login capability
-
-  // Fall back to InsecureLogin() if the user did not request secure authentication
-  if (!m_useSecAuth && ! (GetServerStateParser().GetCapabilityFlag() & kLoginDisabled))
-    InsecureLogin(userName, password);
+  else if (flag & kHasAuthOldLoginCapability)
+  {
+    PR_LOG(IMAP, PR_LOG_DEBUG, ("old-style auth"));
+    ProgressEventFunctionUsingId (IMAP_STATUS_SENDING_LOGIN);
+    IncrementCommandTagNumber();
+    nsCString command (GetServerCommandTag());
+    nsCAutoString escapedUserName;
+    command.Append(" login \"");
+    EscapeUserNamePasswordString(userName, &escapedUserName);
+    command.Append(escapedUserName);
+    command.Append("\" \"");
+
+    // if the password contains a \, login will fail
+    // turn foo\bar into foo\\bar
+    nsCAutoString correctedPassword;
+    EscapeUserNamePasswordString(password.get(), &correctedPassword);
+    command.Append(correctedPassword);
+    command.Append("\""CRLF);
+    rv = SendData(command.get(), PR_TRUE /* suppress logging */);
+    NS_ENSURE_SUCCESS(rv, rv);
+    ParseIMAPandCheckForNewMail();
+  }
+  else if (flag & kHasAuthNoneCapability)
+  {
+    // TODO What to do? "login <username>" like POP?
+    return NS_ERROR_NOT_IMPLEMENTED;
+  }
+  else
+  {
+    PR_LOG(IMAP, PR_LOG_ERROR, ("flags param has no auth scheme selected"));
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
 
   PR_Free(currentCommand);
-  return NS_OK;
+  NS_ENSURE_SUCCESS(rv, rv);
+  return GetServerStateParser().LastCommandSuccessful() ?
+        NS_OK : NS_ERROR_FAILURE;
 }
 
 void nsImapProtocol::OnLSubFolders()
 {
   // **** use to find out whether Drafts, Sent, & Templates folder
   // exists or not even the user didn't subscribe to it
   char *mailboxName = OnCreateServerSourceFolderPathString();
   if (mailboxName)
@@ -7943,243 +8043,266 @@ nsresult nsImapProtocol::GetMsgWindow(ns
 {
     nsresult rv = NS_OK;
     nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl =
         do_QueryInterface(m_runningUrl, &rv);
     if (NS_FAILED(rv)) return rv;
     return mailnewsUrl->GetMsgWindow(aMsgWindow);
 }
 
+/**
+ * Get password from RAM, disk (password manager) or user (dialog)
+ * @return NS_MSG_PASSWORD_PROMPT_CANCELLED
+ *    (which is NS_SUCCEEDED!) when user cancelled
+ *    NS_FAILED(rv) for other errors
+ */
 nsresult nsImapProtocol::GetPassword(nsCString &password)
 {
-  if (password.IsEmpty() && m_imapServerSink &&
-      !(m_useSecAuth && GetServerStateParser().GetCapabilityFlag() & kHasAuthGssApiCapability))
+  // we are in the imap thread so *NEVER* try to extract the password with UI
+  // if logon redirection has changed the password, use the cookie as the password
+  if (m_overRideUrlConnectionInfo)
+  {
+    password.Assign(m_logonCookie);
+    return NS_OK;
+  }
+
+  NS_ENSURE_TRUE(m_imapServerSink, NS_ERROR_NULL_POINTER);
+  NS_ENSURE_TRUE(m_server, NS_ERROR_NULL_POINTER);
+  nsresult rv;
+  nsCOMPtr<nsIMsgIncomingServer> server = do_QueryReferent(m_server, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Get the password already stored in mem
+  rv = server->GetPassword(password);
+  if (NS_FAILED(rv) || password.IsEmpty())
   {
     nsCOMPtr<nsIMsgWindow> msgWindow;
-
     GetMsgWindow(getter_AddRefs(msgWindow));
-    // need to copy password, because in the case of Cancel,
-    // GetPasswordWithUI will truncate the password.
-    nsCString pwd = m_lastPasswordSent;
-    nsresult rv = m_imapServerSink->PromptForPassword(pwd, msgWindow);
-
-    if (NS_FAILED(rv) || rv == NS_MSG_PASSWORD_PROMPT_CANCELLED)
+    NS_ENSURE_TRUE(msgWindow, NS_ERROR_NOT_AVAILABLE); // biff case
+
+    // Get the password from pw manager (harddisk) or user (dialog)
+    nsCAutoString pwd; // GetPasswordWithUI truncates the password on Cancel
+    rv = m_imapServerSink->PromptForPassword(pwd, msgWindow);
+    NS_ENSURE_SUCCESS(rv, rv);
+    if (rv == NS_MSG_PASSWORD_PROMPT_CANCELLED) // (this is a success code)
       return NS_ERROR_ABORT;
-
+    NS_ENSURE_TRUE(!pwd.IsEmpty(), NS_ERROR_ABORT);
     password.Assign(pwd);
   }
+
   m_lastPasswordSent = password;
   return NS_OK;
 }
 
 PRBool nsImapProtocol::TryToLogon()
 {
-  PRInt32 logonTries = 0;
-  const PRInt32 maxLogonTries = 4;
+  PR_LOG(IMAP, PR_LOG_DEBUG, ("try to log in"));
+  NS_ENSURE_TRUE(m_imapServerSink, false);
   PRBool loginSucceeded = PR_FALSE;
-  PRBool clientSucceeded = PR_TRUE;
+  PRBool skipLoop = PR_FALSE;
   nsCAutoString password;
   nsCAutoString userName;
-  nsresult rv = NS_OK;
-
-  // get the password and user name for the current incoming server...
-  nsCOMPtr<nsIMsgIncomingServer> server = do_QueryReferent(m_server);
-  if (!m_imapServerSink)
-    return NS_ERROR_FAILURE;
-
-  if (server)
-  {
-    // we are in the imap thread so *NEVER* try to extract the password with UI
-    // if logon redirection has changed the password, use the cookie as the password
-    if (m_overRideUrlConnectionInfo)
-      password.Assign(m_logonCookie);
+
+  nsresult rv = ChooseAuthMethod();
+  if (NS_FAILED(rv)) // all methods failed
+  {
+    // are there any matching login schemes at all?
+    if (!(GetServerStateParser().GetCapabilityFlag() & m_prefAuthMethods))
+    {
+      // Pref doesn't match server. Now, find an appropriate error msg.
+
+      // pref has plaintext pw & server claims to support encrypted pw
+      if (m_prefAuthMethods == (kHasAuthOldLoginCapability |
+              kHasAuthLoginCapability | kHasAuthPlainCapability) &&
+          GetServerStateParser().GetCapabilityFlag() & kHasCRAMCapability)
+        // tell user to change to encrypted pw
+        AlertUserEventUsingId(IMAP_AUTH_CHANGE_PLAIN_TO_ENCRYPT);
+      // pref has encrypted pw & server claims to support plaintext pw
+      else if (m_prefAuthMethods == kHasCRAMCapability &&
+               GetServerStateParser().GetCapabilityFlag() &
+                   (kHasAuthOldLoginCapability | kHasAuthLoginCapability |
+                    kHasAuthPlainCapability))
+      {
+        // have SSL
+        if (m_socketType == nsMsgSocketType::SSL ||
+            m_socketType == nsMsgSocketType::alwaysSTARTTLS)
+          // tell user to change to plaintext pw
+          AlertUserEventUsingId(IMAP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_SSL);
+        else
+          // tell user to change to plaintext pw, with big warning
+          AlertUserEventUsingId(IMAP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_NO_SSL);
+      }
+      else
+        // just "change auth method"
+        AlertUserEventUsingId(IMAP_AUTH_MECH_NOT_SUPPORTED);
+
+      skipLoop = PR_TRUE;
+    }
     else
-      rv = server->GetPassword(password);
-    rv = m_imapServerSink->GetLoginUsername(userName);
-  }
-
-  do
-  {
-      PRBool imapPasswordIsNew = PR_FALSE;
-      if (!userName.IsEmpty())
-      {
-      PRBool lastReportingErrors = GetServerStateParser().GetReportingErrors();
-      GetServerStateParser().SetReportingErrors(PR_FALSE);  // turn off errors - we'll put up our own.
-
-      if (GetServerStateParser().GetCapabilityFlag() == kCapabilityUndefined)
-        Capability();
-
-      if (m_authLogin)
+    {
+      // try to reset failed methods and try them again
+      ResetAuthMethods();
+      rv = ChooseAuthMethod();
+      if (NS_FAILED(rv)) // all methods failed
       {
-        // If secure auth is configured, don't proceed unless the server
-        // supports it. This avoids fallback to insecure login in case
-        // authentication fails.
-        if(m_useSecAuth && !(GetServerStateParser().GetCapabilityFlag()
-            & (kHasCRAMCapability|kHasAuthNTLMCapability|kHasAuthMSNCapability|kHasAuthGssApiCapability)))
-        {
-          AlertUserEventUsingId(IMAP_AUTH_SECURE_NOTSUPPORTED);
-          break;
-        }
-
-        // If secure auth is disabled, ensure that server supports plaintext auth
-        if (!m_useSecAuth && !(GetServerStateParser().GetCapabilityFlag()
-             & (kLoginDisabled|kHasAuthLoginCapability|kHasAuthPlainCapability)
-             ^  kLoginDisabled))
-        {
-          AlertUserEventUsingId(IMAP_LOGIN_DISABLED);
-          // force re-issue of Capability() to make sure login still disabled.
-          m_hostSessionList->SetCapabilityForHost(GetImapServerKey(), kCapabilityUndefined);
-          break;
-        }
-
-        clientSucceeded = PR_TRUE;
-        rv = GetPassword(password);
-        if (NS_FAILED(rv)) break;
-        
-        // Use CRAM/NTLM/MSN only if secure auth is enabled. This is for servers that
-        // say they support CRAM but are so badly broken that trying it causes
-        // all subsequent login attempts to fail (bug 231303, bug 227560)
-        if (m_useSecAuth && GetServerStateParser().GetCapabilityFlag() & kHasAuthGssApiCapability)
-        {
-          clientSucceeded = NS_SUCCEEDED(AuthLogin(userName.get(), password, kHasAuthGssApiCapability));
-        }
-        else if (m_useSecAuth && GetServerStateParser().GetCapabilityFlag() & kHasCRAMCapability)
+        PR_LOG(IMAP, PR_LOG_ERROR, ("huch? there are auth methods, and we resetted failed ones, but ChooseAuthMethod still fails."));
+        return false;
+      }
+    }
+  }
+
+  // Get username, either the stored one or from user
+  rv = m_imapServerSink->GetLoginUsername(userName);
+  if (NS_FAILED(rv) || userName.IsEmpty())
+  {
+    // The user hit "Cancel" on the dialog box
+    skipLoop = PR_TRUE;
+  }
+
+  /*
+   * Login can fail for various reasons:
+   * 1. Server claims to support GSSAPI, but it really doesn't.
+   *    Or the client doesn't support GSSAPI, or is not logged in yet.
+   *    (GSSAPI is a mechanism without password in apps).
+   * 2. Server claims to support CRAM-MD5, but it's broken and will fail despite correct password.
+   * 2.1. Some servers say they support CRAM but are so badly broken that trying it causes
+   *    all subsequent login attempts to fail during this connection (bug 231303).
+   *    So we use CRAM/NTLM/MSN only if enabled in prefs.
+   *    Update: if it affects only some ISPs, we can maybe use the ISP DB
+   *    and disable CRAM specifically for these.
+   * 3. Prefs are set to require auth methods which the server doesn't support
+   *     (per CAPS or we tried and they failed).
+   * 4. User provided wrong password.
+   * 5. We tried too often and the server shut us down, so even a correct attempt
+   *    will now (currently) fail.
+   * The above problems may overlap, e.g. 3. with 1. and 2., and we can't differentiate
+   * between 2. and 4., which is really unfortunate.
+   */
+
+  // This loops over 1) auth methods (only one per loop) and 2) password tries (with UI)
+  while (!loginSucceeded && !skipLoop && !DeathSignalReceived())
+  {
+      // Get password
+      if (m_currentAuthMethod != kHasAuthGssApiCapability && // GSSAPI uses no pw in apps
+          m_currentAuthMethod != kHasAuthNoneCapability)
+      {
+          rv = GetPassword(password);
+          if (rv == NS_MSG_PASSWORD_PROMPT_CANCELLED || NS_FAILED(rv))
+          {
+            PR_LOG(IMAP, PR_LOG_ERROR, ("IMAP: password prompt failed or user canceled it"));
+            break;
+          }
+          PR_LOG(IMAP, PR_LOG_DEBUG, ("got new password"));
+      }
+
+      PRBool lastReportingErrors = GetServerStateParser().GetReportingErrors();
+      GetServerStateParser().SetReportingErrors(PR_FALSE); // turn off errors - we'll put up our own.
+
+      rv = AuthLogin(userName.get(), password, m_currentAuthMethod);
+
+      GetServerStateParser().SetReportingErrors(lastReportingErrors); // restore error reports
+      loginSucceeded = NS_SUCCEEDED(rv);
+
+      if (!loginSucceeded)
+      {
+        PR_LOG(IMAP, PR_LOG_DEBUG, ("authlogin failed"));
+        MarkAuthMethodAsFailed(m_currentAuthMethod);
+        rv = ChooseAuthMethod(); // change m_currentAuthMethod to try other one next round
+
+        if (NS_FAILED(rv)) // all methods failed
         {
-          AuthLogin (userName.get(), password, kHasCRAMCapability);
-          logonTries++;
-        }
-        else if (m_useSecAuth && GetServerStateParser().GetCapabilityFlag() & kHasAuthNTLMCapability)
-        {
-          AuthLogin (userName.get(), password, kHasAuthNTLMCapability);
-          logonTries++;
-        }
-        else if (m_useSecAuth && GetServerStateParser().GetCapabilityFlag() & kHasAuthMSNCapability)
-        {
-          AuthLogin (userName.get(), password, kHasAuthMSNCapability);
-          logonTries++;
-        }
-        else if (GetServerStateParser().GetCapabilityFlag() & kHasAuthPlainCapability)
-        {
-          AuthLogin (userName.get(), password, kHasAuthPlainCapability);
-          logonTries++;
-        }
-        else if (GetServerStateParser().GetCapabilityFlag() & kHasAuthLoginCapability)
-        {
-          AuthLogin (userName.get(), password,  kHasAuthLoginCapability);
-          logonTries++; // This counts as a logon try for most servers
-        }
-        else if (! (GetServerStateParser().GetCapabilityFlag() & kLoginDisabled))
-          InsecureLogin(userName.get(), password);
-      } // if prefbool
-      else if (! (GetServerStateParser().GetCapabilityFlag() & kLoginDisabled))
-      {
-        rv = GetPassword(password);
-        if (NS_FAILED(rv)) break;
-        InsecureLogin(userName.get(), password);
-      }
-
-      if (!clientSucceeded || !GetServerStateParser().LastCommandSuccessful())
-      {
-        if (!DeathSignalReceived() && clientSucceeded)
-        {
-          // login failed!
-          // if we failed because of an interrupt, then do not bother the user
-          // similarly - if we failed due to a local error, don't bug them
-          if (m_imapServerSink)
+          if (m_prefAuthMethods == kHasAuthGssApiCapability)
+          {
+            // GSSAPI failed, and it's the only available method,
+            // and it's password-less, so nothing left to do.
+            AlertUserEventUsingId(IMAP_AUTH_GSSAPI_FAILED);
+            break;
+          }
+
+          // The reason that we failed might be a wrong password, so
+          // ask user what to do
+          PR_LOG(IMAP, PR_LOG_WARN, ("IMAP: ask user what to do (after login failed): new passwort, retry, cancel"));
+          if (!m_imapServerSink)
+            break;
+          nsCOMPtr<nsIMsgWindow> msgWindow;
+          GetMsgWindow(getter_AddRefs(msgWindow));
+          // if there's no msg window, don't forget the password
+          if (!msgWindow)
+            break;
+          PRInt32 buttonPressed = 1;
+          rv = m_imapServerSink->PromptLoginFailed(msgWindow,
+                                                    &buttonPressed);
+          if (NS_FAILED(rv))
+            break;
+          if (buttonPressed == 2) // 'New password' button
           {
-            nsCOMPtr<nsIMsgWindow> msgWindow;
-            GetMsgWindow(getter_AddRefs(msgWindow));
-            // if there's no msg window, don't forget the password
-            if (msgWindow)
-            {
-              PRInt32 buttonPressed = 0;
-              rv = m_imapServerSink->PromptLoginFailed(msgWindow,
-                                                       &buttonPressed);
-              if (NS_SUCCEEDED(rv))
-              {
-                if (buttonPressed == 2)
-                {
-                  // Change password was pressed. For now, forget the
-                  // stored password and we'll prompt for a new one next time
-                  // around.
-                  m_imapServerSink->ForgetPassword();
-                  // Reset logon tries to allow the user to have some failed
-                  // attempts even if they have already pressed retry a few
-                  // times.
-                  logonTries = 0;
-                }
-                else if (buttonPressed == 1)
-                  // Cancel button pressed, abort quickly by exiting the loop
-                  // this time.
-                  logonTries = maxLogonTries;
-              }
-            }
+            PR_LOG(IMAP, PR_LOG_WARN, ("new password button pressed."));
+            // Forget the current password
+            password.Truncate();
+            m_hostSessionList->SetPasswordForHost(GetImapServerKey(), nsnull);
+            m_imapServerSink->ForgetPassword();
+            PR_LOG(IMAP, PR_LOG_WARN, ("password resetted (nulled)"));
+            // Will call GetPassword() in beginning of next loop
+
+            // Try all possible auth methods again with the new password.
+            ResetAuthMethods();
           }
-
-          m_hostSessionList->SetPasswordForHost(GetImapServerKey(), nsnull);
+          else if (buttonPressed == 0) // Retry button
+          {
+            PR_LOG(IMAP, PR_LOG_WARN, ("retry button pressed"));
+            // Try all possible auth methods again
+            ResetAuthMethods();
+          }
+          else if (buttonPressed == 1) // Cancel button
+          {
+            PR_LOG(IMAP, PR_LOG_WARN, ("cancel button pressed"));
+            break; // Abort quickly
+          }
+
+          // TODO what is this for? When does it get set to != unknown again?
           m_currentBiffState = nsIMsgFolder::nsMsgBiffState_Unknown;
           SendSetBiffIndicatorEvent(m_currentBiffState);
-          password.Truncate();
-        } // if we didn't receive the death signal...
-      } // if login failed
-      else  // login succeeded
-      {
-        PRBool passwordAlreadyVerified;
-        rv = m_hostSessionList->SetPasswordForHost(GetImapServerKey(), password.get());
-        rv = m_hostSessionList->GetPasswordVerifiedOnline(GetImapServerKey(), passwordAlreadyVerified);
-        if (NS_SUCCEEDED(rv) && !passwordAlreadyVerified)
-          m_hostSessionList->SetPasswordVerifiedOnline(GetImapServerKey());
-        imapPasswordIsNew = !passwordAlreadyVerified;
-        if (imapPasswordIsNew)
-        {
-          if (m_currentBiffState == nsIMsgFolder::nsMsgBiffState_Unknown)
-          {
-              m_currentBiffState = nsIMsgFolder::nsMsgBiffState_NoMail;
-              SendSetBiffIndicatorEvent(m_currentBiffState);
-          }
-        }
-
-        loginSucceeded = PR_TRUE;
-      } // else if login succeeded
-
-      GetServerStateParser().SetReportingErrors(lastReportingErrors);  // restore it
-
-      if (loginSucceeded && imapPasswordIsNew)
+        } // all methods failed
+      } // login failed
+  } // while
+
+  if (loginSucceeded)
+  {
+    PR_LOG(IMAP, PR_LOG_DEBUG, ("login succeeded"));
+    PRBool passwordAlreadyVerified;
+    m_hostSessionList->SetPasswordForHost(GetImapServerKey(), password.get());
+    rv = m_hostSessionList->GetPasswordVerifiedOnline(GetImapServerKey(), passwordAlreadyVerified);
+    if (NS_SUCCEEDED(rv) && !passwordAlreadyVerified)
+      m_hostSessionList->SetPasswordVerifiedOnline(GetImapServerKey());
+    PRBool imapPasswordIsNew = !passwordAlreadyVerified;
+    if (imapPasswordIsNew)
+    {
+      if (m_currentBiffState == nsIMsgFolder::nsMsgBiffState_Unknown)
       {
-        // let's record the user as authenticated.
-        m_imapServerSink->SetUserAuthenticated(PR_TRUE);
-      }
-
-      if (loginSucceeded)
-      {
-        nsImapAction imapAction;
-        m_runningUrl->GetImapAction(&imapAction);
-        // We don't want to do any more processing if we're just
-        // verifying the ability to logon because it can leave us in
-        // a half-constructed state.
-        if (imapAction != nsIImapUrl::nsImapVerifylogon)
-          ProcessAfterAuthenticated();
+          m_currentBiffState = nsIMsgFolder::nsMsgBiffState_NoMail;
+          SendSetBiffIndicatorEvent(m_currentBiffState);
       }
-    }
-    else
-    {
-      // The user hit "Cancel" on the dialog box
-      HandleCurrentUrlError();
-      break;
-    }
-  }
-
-  while (!loginSucceeded && ++logonTries < maxLogonTries);
-
-  if (!loginSucceeded)
-  {
+      m_imapServerSink->SetUserAuthenticated(PR_TRUE);
+    }
+
+    nsImapAction imapAction;
+    m_runningUrl->GetImapAction(&imapAction);
+    // We don't want to do any more processing if we're just
+    // verifying the ability to logon because it can leave us in
+    // a half-constructed state.
+    if (imapAction != nsIImapUrl::nsImapVerifylogon)
+      ProcessAfterAuthenticated();
+  }
+  else // login failed
+  {
+    PR_LOG(IMAP, PR_LOG_ERROR, ("login failed entirely"));
     m_currentBiffState = nsIMsgFolder::nsMsgBiffState_Unknown;
     SendSetBiffIndicatorEvent(m_currentBiffState);
     HandleCurrentUrlError();
-    SetConnectionStatus(-1);        // stop netlib
+    SetConnectionStatus(-1); // stop netlib
   }
 
   return loginSucceeded;
 }
 
 void nsImapProtocol::UpdateFolderQuotaData(nsCString& aQuotaRoot, PRUint32 aUsed, PRUint32 aMax)
 {
   NS_ASSERTION(m_imapMailFolderSink, "m_imapMailFolderSink is null!");
--- a/mailnews/imap/src/nsImapProtocol.h
+++ b/mailnews/imap/src/nsImapProtocol.h
@@ -346,17 +346,16 @@ private:
   nsCString             m_userName;
   nsCString             m_serverKey;
   char                  *m_dataOutputBuf;
   nsMsgLineStreamBuffer * m_inputStreamBuffer;
   PRUint32              m_allocatedSize; // allocated size
   PRUint32        m_totalDataSize; // total data size
   PRUint32        m_curReadIndex;  // current read index
   nsCString       m_trashFolderName;
-  PRBool          m_authLogin;
 
   // Ouput stream for writing commands to the socket
   nsCOMPtr<nsISocketTransport>  m_transport;
 
   nsCOMPtr<nsIAsyncInputStream>   m_channelInputStream;
   nsCOMPtr<nsIAsyncOutputStream>  m_channelOutputStream;
   nsCOMPtr<nsIImapMockChannel>    m_mockChannel;   // this is the channel we should forward to people
   //nsCOMPtr<nsIRequest> mAsyncReadRequest; // we're going to cancel this when we're done with the conn.
@@ -470,16 +469,20 @@ private:
   int  m_currentServerCommandTagNumber;
   void IncrementCommandTagNumber();
   char *GetServerCommandTag();
 
   void StartTLS();
 
   // login related methods.
   nsresult GetPassword(nsCString &password);
+  void InitPrefAuthMethods(PRInt32 authMethodPrefValue);
+  nsresult ChooseAuthMethod();
+  void MarkAuthMethodAsFailed(PRInt32 failedAuthMethod);
+  void ResetAuthMethods();
 
   // All of these methods actually issue protocol
   void Capability(); // query host for capabilities.
   void EnableCondStore(); 
   void StartCompressDeflate();
   nsresult BeginCompressing();
   void Language(); // set the language on the server if it supports it
   void Namespace();
@@ -590,17 +593,19 @@ private:
   PRTime  m_lastActiveTime;
   PRInt32 m_tooFastTime;
   PRInt32 m_idealTime;
   PRInt32 m_chunkAddSize;
   PRInt32 m_chunkStartSize;
   PRBool  m_fetchByChunks;
   PRInt32 m_curFetchSize;
   PRBool  m_ignoreExpunges;
-  PRBool  m_useSecAuth;
+  PRInt32 m_prefAuthMethods; // set of capability flags (in nsImapCore.h) for auth methods
+  PRInt32 m_failedAuthMethods; // ditto
+  eIMAPCapabilityFlag m_currentAuthMethod; // exactly one capability flag, or 0
   PRInt32 m_socketType;
   PRInt32 m_chunkSize;
   PRInt32 m_chunkThreshold;
   nsRefPtr <nsMsgImapLineDownloadCache> m_downloadLineCache;
   nsRefPtr <nsMsgImapHdrXferInfo> m_hdrDownloadCache;
   nsCOMPtr <nsIImapHeaderInfo> m_curHdrInfo;
   // mapping between special xlist mailboxes and the corresponding folder flag
   nsDataHashtable<nsCStringHashKey, PRInt32> m_specialXListMailboxes;
--- a/mailnews/imap/src/nsImapServerResponseParser.cpp
+++ b/mailnews/imap/src/nsImapServerResponseParser.cpp
@@ -2189,17 +2189,17 @@ void nsImapServerResponseParser::msg_obs
   else
     SetSyntaxError(PR_TRUE);
   
 }
 
 void nsImapServerResponseParser::capability_data()
 {
   PRInt32 endToken = -1;
-  fCapabilityFlag = kCapabilityDefined;
+  fCapabilityFlag = kCapabilityDefined | kHasAuthOldLoginCapability;
   do {
     AdvanceToNextToken();
     if (fNextToken) {
       nsCString token(fNextToken);
       endToken = token.FindChar(']');
       if (endToken >= 0)
         token.Truncate(endToken);
 
@@ -2213,19 +2213,17 @@ void nsImapServerResponseParser::capabil
         fCapabilityFlag |= kHasAuthNTLMCapability;
       else if (token.Equals("AUTH=GSSAPI", nsCaseInsensitiveCStringComparator()))
         fCapabilityFlag |= kHasAuthGssApiCapability;
       else if (token.Equals("AUTH=MSN", nsCaseInsensitiveCStringComparator()))
         fCapabilityFlag |= kHasAuthMSNCapability;
       else if (token.Equals("STARTTLS", nsCaseInsensitiveCStringComparator()))
         fCapabilityFlag |= kHasStartTLSCapability;
       else if (token.Equals("LOGINDISABLED", nsCaseInsensitiveCStringComparator()))
-        fCapabilityFlag |= kLoginDisabled;
-      else if (token.Equals("X-NETSCAPE", nsCaseInsensitiveCStringComparator()))
-        fCapabilityFlag |= kHasXNetscapeCapability;
+        fCapabilityFlag &= ~kHasAuthOldLoginCapability; // remove flag
       else if (token.Equals("XSENDER", nsCaseInsensitiveCStringComparator()))
         fCapabilityFlag |= kHasXSenderCapability;
       else if (token.Equals("IMAP4", nsCaseInsensitiveCStringComparator()))
         fCapabilityFlag |= kIMAP4Capability;
       else if (token.Equals("IMAP4rev1", nsCaseInsensitiveCStringComparator()))
         fCapabilityFlag |= kIMAP4rev1Capability;
       else if (Substring(token,0,5).Equals("IMAP4", nsCaseInsensitiveCStringComparator()))
         fCapabilityFlag |= kIMAP4other;
--- a/mailnews/imap/src/nsImapStringBundle.h
+++ b/mailnews/imap/src/nsImapStringBundle.h
@@ -109,17 +109,21 @@ PR_END_EXTERN_C
 #define IMAP_SERVER_DOESNT_SUPPORT_ACL              5084
 #define IMAP_ACL_EXPUNGE_RIGHT                      5085
 #define IMAP_SERVER_DISCONNECTED                    5090
 #define IMAP_SUBSCRIBE_PROMPT                       5092
 #define IMAP_SERVER_DROPPED_CONNECTION              5093
 #define IMAP_QUOTA_STATUS_FOLDERNOTOPEN             5095
 #define IMAP_QUOTA_STATUS_NOTSUPPORTED              5096
 #define IMAP_QUOTA_STATUS_NOQUOTA                   5097
-#define	IMAP_OUT_OF_MEMORY                          5100
-#define IMAP_AUTH_SECURE_NOTSUPPORTED               5102
+#define IMAP_OUT_OF_MEMORY                          5100
+#define IMAP_AUTH_MECH_NOT_SUPPORTED                5101
+#define IMAP_AUTH_MECH_FAILED                       5102
 #define IMAP_COPYING_MESSAGE_OF                     5103
+#define IMAP_AUTH_GSSAPI_FAILED                     5104
 #define IMAP_MOVE_FOLDER_TO_TRASH                   5105
 #define IMAP_DELETE_NO_TRASH                        5106
 #define IMAP_DELETE_FOLDER_DIALOG_TITLE             5107
 #define IMAP_DELETE_FOLDER_BUTTON_LABEL             5108
-#define IMAP_LOGIN_DISABLED                         5109
+#define IMAP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_NO_SSL    5109
+#define IMAP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_SSL       5110
+#define IMAP_AUTH_CHANGE_PLAIN_TO_ENCRYPT           5111
 #endif /* _nsImapStringBundle_H__ */
new file mode 100644
--- /dev/null
+++ b/mailnews/imap/test/unit/test_imapAuthMethods.js
@@ -0,0 +1,163 @@
+/**
+ * Login tests for IMAP
+ *
+ * Test code <copied from="test_mailboxes.js">
+ * and <copied from="test_pop3AuthMethods.js">
+ *
+ * BUGS:
+ * - cleanup after each test doesn't seem to work correctly. Effects:
+ *    - one more "lsub" per test, e.g. "capability", "auth...", "lsub", "lsub", "lsub", "list" in the 3. test.,
+ *    - root folder check succeeds although login failed
+ * - removeIncomingServer(..., true); (cleanup files) fails.
+ */
+
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+load("../../mailnews/resources/alertTestUtils.js");
+
+//const kUsername = "fred";
+//const kPassword = "wilma";
+
+var acctMgr;
+var thisTest;
+var test = null;
+
+var tests = [
+  { title: "Cleartext password, with server only supporting old-style login",
+    clientAuthMethod : Ci.nsMsgAuthMethod.passwordCleartext,
+    serverAuthMethods : [],
+    expectSuccess : true,
+    transaction: [ "capability", "login", "lsub" ] },
+  // Just to make sure we clean up properly - in the test and in TB, e.g. don't cache stuff
+  { title: "Second time Cleartext password, with server only supporting old-style login",
+    clientAuthMethod : Ci.nsMsgAuthMethod.passwordCleartext,
+    serverAuthMethods : [],
+    expectSuccess : true,
+    transaction: [ "capability", "login", "lsub" ] },
+ { title: "Cleartext password, with server supporting AUTH PLAIN, LOGIN and CRAM",
+    clientAuthMethod : Ci.nsMsgAuthMethod.passwordCleartext,
+    serverAuthMethods : [ "PLAIN", "LOGIN", "CRAM-MD5" ],
+    expectSuccess : true,
+    transaction: [ "capability", "authenticate PLAIN", "lsub" ] },
+  { title: "Cleartext password, with server supporting only AUTH LOGIN",
+    clientAuthMethod : Ci.nsMsgAuthMethod.passwordCleartext,
+    serverAuthMethods : [ "LOGIN" ],
+    expectSuccess : true,
+    transaction: [ "capability", "authenticate LOGIN", "lsub" ] },
+  { title: "Encrypted password, with server supporting PLAIN and CRAM",
+    clientAuthMethod : Ci.nsMsgAuthMethod.passwordEncrypted,
+    serverAuthMethods : [ "PLAIN", "LOGIN", "CRAM-MD5" ],
+    expectSuccess : true,
+    transaction: [ "capability", "authenticate CRAM-MD5", "lsub" ] },
+  { title: "Encrypted password, with server only supporting AUTH PLAIN and LOGIN (must fail)",
+    clientAuthMethod : Ci.nsMsgAuthMethod.passwordEncrypted,
+    serverAuthMethods : [ "PLAIN", "LOGIN" ],
+    expectSuccess : false,
+    transaction: [ "capability" ] },
+  { title: "Any secure method, with server supporting AUTH PLAIN and CRAM",
+    clientAuthMethod : Ci.nsMsgAuthMethod.secure,
+    serverAuthMethods : [ "PLAIN" , "LOGIN", "CRAM-MD5" ],
+    expectSuccess : true,
+    transaction: [ "capability", "authenticate CRAM-MD5", "lsub" ] },
+  { title: "Any secure method, with server only supporting AUTH PLAIN and LOGIN (must fail)",
+    clientAuthMethod : Ci.nsMsgAuthMethod.secure,
+    serverAuthMethods : [ "PLAIN" ],
+    expectSuccess : false,
+    transaction: [ "capability" ] },
+];
+
+function nextTest() {
+  try {
+    thisTest = tests.shift();
+    if (!thisTest)
+    {
+        endTest();
+        return;
+    }
+    /* doesn't work, hangs on first performTest(...)
+    {
+      dump("resetTest()\n");
+      server.resetTest();
+      dump("server.performTest()\n");
+      server.performTest();
+    }*/
+
+    test = thisTest.title;
+    dump("NEXT test: " + thisTest.title + "\n");
+
+    // (re)create fake server
+    var daemon = new imapDaemon();
+    var server = makeServer(daemon, "");
+    server.setDebugLevel(fsDebugAll);
+    var handler = server._handler;
+    //handler.kUsername = kUsername;
+    //handler.kPassword = kPassword;
+    //daemon.createMailbox("somemailbox");
+
+    handler.kAuthSchemes = thisTest.serverAuthMethods;
+
+    // If Mailnews ever caches server capabilities, delete and re-create the incomingServer here
+    var incomingServer = createLocalIMAPServer();
+
+    let msgServer = incomingServer;
+    msgServer.QueryInterface(Ci.nsIMsgIncomingServer);
+    msgServer.authMethod = thisTest.clientAuthMethod;
+
+    // connect
+    incomingServer.performExpand(null);
+    server.performTest("LSUB");
+
+    dump("should " + (thisTest.expectSuccess ? "":"not ") + "be logged in\n");
+    do_check_eq(true, incomingServer instanceof Ci.nsIImapServerSink);
+    //do_check_eq(thisTest.expectSuccess, incomingServer.userAuthenticated); TODO fails second time
+    //var rootFolder = incomingServer.rootFolder;
+    // Client creates fake Inbox, so check other folder
+    //do_check_eq(thisTest.expectSuccess,
+    //    rootFolder.containsChildNamed("somemailbox")); TODO
+    do_check_transaction(server.playTransaction(), thisTest.transaction, false);
+
+    do {
+      incomingServer.closeCachedConnections();
+    } while (incomingServer.serverBusy)
+    incomingServer.shutdown();
+    incomingServer.clearAllValues();
+    deleteIMAPServer(incomingServer);
+    acctMgr.closeCachedConnections();
+    acctMgr.shutdownServers();
+    acctMgr.UnloadAccounts();
+    server.stop();
+
+  } catch (e) {
+    //server.stop();
+    //endTest();
+    do_throw(e);
+  }
+
+  nextTest();
+}
+
+function deleteIMAPServer(incomingServer) {
+  if (!incomingServer)
+    return;
+  acctMgr.removeIncomingServer(incomingServer, false); // TODO cleanup files = true fails
+  //incomingServer = null;
+  acctMgr.removeAccount(acctMgr.defaultAccount);
+}
+
+
+function run_test() {
+  do_test_pending();
+
+  registerAlertTestUtils();
+  acctMgr = Cc["@mozilla.org/messenger/account-manager;1"]
+                  .getService(Ci.nsIMsgAccountManager);
+
+  nextTest();
+}
+
+function endTest() {
+  var thread = gThreadManager.currentThread;
+  while (thread.hasPendingEvents())
+    thread.processNextEvent(true);
+
+  do_test_finished();
+}
--- a/mailnews/import/oexpress/nsOESettings.cpp
+++ b/mailnews/import/oexpress/nsOESettings.cpp
@@ -73,19 +73,19 @@ public:
 
   static PRBool DoImport( nsIMsgAccount **ppAccount);
 
   static PRBool DoIMAPServer( nsIMsgAccountManager *pMgr, HKEY hKey, char *pServerName, nsIMsgAccount **ppAccount);
   static PRBool DoPOP3Server( nsIMsgAccountManager *pMgr, HKEY hKey, char *pServerName, nsIMsgAccount **ppAccount);
   static PRBool DoNNTPServer( nsIMsgAccountManager *pMgr, HKEY hKey, char *pServerName, nsIMsgAccount **ppAccount);
 
   static void SetIdentities( nsIMsgAccountManager *pMgr, nsIMsgAccount *pAcc, HKEY hKey,
-                             char *pIncomgUserName, PRBool useSecAuth, PRBool isNNTP);
+                             char *pIncomgUserName, PRInt32 authMethodIncoming, PRBool isNNTP);
   static void SetSmtpServer( char *pSmtpServer, HKEY hKey, nsIMsgIdentity *id,
-                             char *pIncomgUserName, PRBool useSecAuth);
+                             char *pIncomgUserName, PRInt32 authMethodIncoming);
   static nsresult GetAccountName(HKEY hKey, char *defaultName, nsString &acctName);
 };
 
 static PRInt32 checkNewMailTime;// OE global setting, let's default to 30
 static PRBool  checkNewMail;    // OE global setting, let's default to PR_FALSE
                                 // This won't cause unwanted autodownloads-
                                 // user can set prefs after import
 
@@ -396,17 +396,17 @@ nsresult OESettings::GetAccountName(HKEY
   }
   else
     acctName.AssignASCII(defaultName);
   return rv;
 }
 
 PRBool OESettings::DoIMAPServer( nsIMsgAccountManager *pMgr, HKEY hKey, char *pServerName, nsIMsgAccount **ppAccount)
 {
-  PRBool useSecAuth;    // Secure Password Authentication
+  PRInt32 authMethod;
   if (ppAccount)
     *ppAccount = nsnull;
 
   char * pUserName;
   pUserName = (char *)nsOERegUtil::GetValueBytes(hKey, "IMAP User Name");
   if (!pUserName)
     return( PR_FALSE);
 
@@ -432,38 +432,39 @@ PRBool OESettings::DoIMAPServer( nsIMsgA
         imapServer->SetServerDirectory(nsDependentCString((const char *) pRootFolder));
         nsOERegUtil::FreeValueBytes(pRootFolder);
       }
 
       BYTE * pSecureConnection = nsOERegUtil::GetValueBytes(hKey, "IMAP Secure Connection");
       if (pSecureConnection)
       {
         if (*pSecureConnection)
-          in->SetSocketType(nsIMsgIncomingServer::useSSL);
+          in->SetSocketType(nsMsgSocketType::SSL);
         nsOERegUtil::FreeValueBytes(pSecureConnection);
       }
 
       BYTE * pPort = nsOERegUtil::GetValueBytes(hKey, "IMAP Port");
       if (pPort)
       {
         in->SetPort(*(PRInt32 *) pPort);
         nsOERegUtil::FreeValueBytes(pPort);
       }
 
       BYTE * pBytesTemp = nsOERegUtil::GetValueBytes(hKey, "IMAP Use Sicily");
       if (pBytesTemp)
       {
-        in->SetUseSecAuth(*(PRBool *)pBytesTemp);
-        useSecAuth = *(PRBool *)pBytesTemp;
+        PRBool secAuth = *(PRBool *)pBytesTemp;
         nsOERegUtil::FreeValueBytes(pBytesTemp);
+        authMethod = secAuth ? nsMsgAuthMethod::secure
+            : nsMsgAuthMethod::passwordCleartext;
       }
       else {
-        in->SetUseSecAuth(PR_FALSE);
-        useSecAuth = PR_FALSE;
+        authMethod = nsMsgAuthMethod::passwordCleartext;
       }
+      in->SetAuthMethod(authMethod);
 
       in->SetDoBiff(checkNewMail);
       in->SetBiffMinutes(checkNewMailTime);
 
       IMPORT_LOG2("Created IMAP server named: %s, userName: %s\n",
                    pServerName, pUserName);
 
       nsString prettyName;
@@ -474,48 +475,48 @@ PRBool OESettings::DoIMAPServer( nsIMsgA
       nsCOMPtr<nsIMsgAccount> account;
       rv = pMgr->CreateAccount(getter_AddRefs( account));
       if (NS_SUCCEEDED( rv) && account) {
         rv = account->SetIncomingServer(in);
 
         IMPORT_LOG0("Created an account and set the IMAP server as the incoming server\n");
 
         // Fiddle with the identities
-        SetIdentities(pMgr, account, hKey, pUserName, useSecAuth, PR_FALSE);
+        SetIdentities(pMgr, account, hKey, pUserName, authMethod, PR_FALSE);
         result = PR_TRUE;
         if (ppAccount)
           account->QueryInterface(NS_GET_IID(nsIMsgAccount), (void **)ppAccount);
       }
     }
   }
   else if (NS_SUCCEEDED(rv) && in) {
     // for an existing server we create another identity,
     //  TB lists under 'manage identities'
     nsCOMPtr<nsIMsgAccount> account;
     rv = pMgr->FindAccountForServer(in, getter_AddRefs( account));
     if (NS_SUCCEEDED( rv) && account) {
       IMPORT_LOG0("Created an identity and added to existing IMAP incoming server\n");
       // Fiddle with the identities
-      in->GetUseSecAuth(&useSecAuth);
-      SetIdentities(pMgr, account, hKey, pUserName, useSecAuth, PR_FALSE);
+      in->GetAuthMethod(&authMethod);
+      SetIdentities(pMgr, account, hKey, pUserName, authMethod, PR_FALSE);
       result = PR_TRUE;
       if (ppAccount)
         account->QueryInterface(NS_GET_IID(nsIMsgAccount),
                                  (void **)ppAccount);
     }
   }
   else
     result = PR_TRUE;
   nsOERegUtil::FreeValueBytes((BYTE *) pUserName);
   return( result);
 }
 
 PRBool OESettings::DoPOP3Server( nsIMsgAccountManager *pMgr, HKEY hKey, char *pServerName, nsIMsgAccount **ppAccount)
 {
-  PRBool useSecAuth;    // Secure Password Authentication
+  PRInt32 authMethod;    // Secure Password Authentication
   if (ppAccount)
     *ppAccount = nsnull;
 
   char * pUserName;
   pUserName = (char *)nsOERegUtil::GetValueBytes( hKey, "POP3 User Name");
   if (!pUserName)
     return( PR_FALSE);
 
@@ -533,38 +534,39 @@ PRBool OESettings::DoPOP3Server( nsIMsgA
                                     nsDependentCString(pServerName),
                                     NS_LITERAL_CSTRING("pop3"),
                                     getter_AddRefs( in));
     if (NS_SUCCEEDED( rv) && in) {
       BYTE * pSecureConnection = nsOERegUtil::GetValueBytes( hKey, "POP3 Secure Connection");
       if (pSecureConnection)
       {
         if (*pSecureConnection)
-          in->SetSocketType(nsIMsgIncomingServer::useSSL);
+          in->SetSocketType(nsMsgSocketType::SSL);
         nsOERegUtil::FreeValueBytes(pSecureConnection);
       }
 
       BYTE * pPort = nsOERegUtil::GetValueBytes( hKey, "POP3 Port");
       if (pPort)
       {
         in->SetPort(*(PRInt32 *) pPort);
         nsOERegUtil::FreeValueBytes(pPort);
       }
 
       BYTE * pBytesTemp = nsOERegUtil::GetValueBytes( hKey, "POP3 Use Sicily");
       if (pBytesTemp)
       {
-        in->SetUseSecAuth(*(PRBool *)pBytesTemp );
-        useSecAuth = *(PRBool *)pBytesTemp;
+        PRBool secAuth = *(PRBool *)pBytesTemp;
         nsOERegUtil::FreeValueBytes(pBytesTemp);
+        authMethod = secAuth ? nsMsgAuthMethod::secure
+            : nsMsgAuthMethod::passwordCleartext;
       }
       else {
-        in->SetUseSecAuth( PR_FALSE);
-        useSecAuth = PR_FALSE;
+        authMethod = nsMsgAuthMethod::passwordCleartext;
       }
+      in->SetAuthMethod(authMethod);
 
       in->SetDoBiff(checkNewMail);
       in->SetBiffMinutes(checkNewMailTime);
       nsCOMPtr<nsIPop3IncomingServer> pop3Server = do_QueryInterface(in);
       if (pop3Server) {
         // set local folders as the Inbox to use for this POP3 server
         nsCOMPtr<nsIMsgIncomingServer> localFoldersServer;
         pMgr->GetLocalFoldersServer(getter_AddRefs(localFoldersServer));
@@ -635,17 +637,17 @@ PRBool OESettings::DoPOP3Server( nsIMsgA
       // We have a server, create an account.
       nsCOMPtr<nsIMsgAccount>  account;
       rv = pMgr->CreateAccount(getter_AddRefs( account));
       if (NS_SUCCEEDED( rv) && account) {
         rv = account->SetIncomingServer(in);
         IMPORT_LOG0("Created a new account and set the incoming server to the POP3 server.\n");
 
         // Fiddle with the identities
-        SetIdentities(pMgr, account, hKey, pUserName, useSecAuth, PR_FALSE);
+        SetIdentities(pMgr, account, hKey, pUserName, authMethod, PR_FALSE);
         result = PR_TRUE;
         if (ppAccount)
           account->QueryInterface(NS_GET_IID(nsIMsgAccount),
                                    (void **)ppAccount);
       }
     }
   } 
   else if (NS_SUCCEEDED(rv) && in) {
@@ -653,18 +655,18 @@ PRBool OESettings::DoPOP3Server( nsIMsgA
                 pServerName, pUserName);
     // for an existing server we create another identity,
     // TB listed under 'manage identities'
     nsCOMPtr<nsIMsgAccount>  account;
     rv = pMgr->FindAccountForServer(in, getter_AddRefs( account));
     if (NS_SUCCEEDED(rv) && account) {
       IMPORT_LOG0("Created identity and added to existing POP3 incoming server.\n");
       // Fiddle with the identities
-      in->GetUseSecAuth(&useSecAuth);
-      SetIdentities(pMgr, account, hKey, pUserName, useSecAuth, PR_FALSE);
+      in->GetAuthMethod(&authMethod);
+      SetIdentities(pMgr, account, hKey, pUserName, authMethod, PR_FALSE);
       result = PR_TRUE;
       if (ppAccount)
         account->QueryInterface(NS_GET_IID(nsIMsgAccount), (void **)ppAccount);
     }
   }
   else
     result = PR_TRUE;
   nsOERegUtil::FreeValueBytes((BYTE *) pUserName);
@@ -749,17 +751,17 @@ PRBool OESettings::DoNNTPServer( nsIMsgA
   else
     result = PR_TRUE;
   nsOERegUtil::FreeValueBytes((BYTE *) pUserName);
   return result;
 }
 
 void OESettings::SetIdentities(nsIMsgAccountManager *pMgr, nsIMsgAccount *pAcc,
                                HKEY hKey, char *pIncomgUserName,
-                               PRBool useSecAuth, PRBool isNNTP )
+                               PRInt32 authMethodIncoming, PRBool isNNTP )
 {
   // Get the relevant information for an identity
   char *pSmtpServer = (char *)nsOERegUtil::GetValueBytes(hKey, "SMTP Server");
   char *pName = (char *)nsOERegUtil::GetValueBytes(hKey, isNNTP ? "NNTP Display Name" : "SMTP Display Name");
   char *pEmail = (char *)nsOERegUtil::GetValueBytes(hKey, isNNTP ? "NNTP Email Address" : "SMTP Email Address");
   char *pReply = (char *)nsOERegUtil::GetValueBytes(hKey, isNNTP ? "NNTP Reply To Email Address" : "SMTP Reply To Email Address");
   char *pOrgName = (char *)nsOERegUtil::GetValueBytes(hKey, isNNTP ? "NNTP Organization Name" : "SMTP Organization Name");
 
@@ -789,27 +791,27 @@ void OESettings::SetIdentities(nsIMsgAcc
       pAcc->AddIdentity(id);
 
       IMPORT_LOG0("Created identity and added to the account\n");
       IMPORT_LOG1("\tname: %s\n", pName);
       IMPORT_LOG1("\temail: %s\n", pEmail);
     }
 
   if (!isNNTP)  // NNTP does not use SMTP in OE or TB
-    SetSmtpServer( pSmtpServer, hKey, id, pIncomgUserName, useSecAuth);
+    SetSmtpServer(pSmtpServer, hKey, id, pIncomgUserName, authMethodIncoming);
 
   nsOERegUtil::FreeValueBytes((BYTE *)pName);
   nsOERegUtil::FreeValueBytes((BYTE *)pSmtpServer);
   nsOERegUtil::FreeValueBytes((BYTE *)pEmail);
   nsOERegUtil::FreeValueBytes((BYTE *)pReply);
 }
 
 void OESettings::SetSmtpServer(char *pSmtpServer, HKEY hKey,
                                nsIMsgIdentity *id, char *pIncomgUserName,
-                               PRBool useSecAuth)
+                               PRInt32 authMethodIncoming)
 {
   // set the id.smtpserver accordingly
   // first we have to calculate the smtp user name which is based on sicily
   if (!hKey || !id || !pIncomgUserName || !pSmtpServer)
     return;
   nsCString smtpServerKey, userName;
   BYTE *pBytes;
   // smtp user name depends on sicily which may or not exist
@@ -858,38 +860,34 @@ void OESettings::SetSmtpServer(char *pSm
         {
           smtpServer->SetPort(*(PRInt32 *) pBytes);
           nsOERegUtil::FreeValueBytes(pBytes);
         }
         pBytes = nsOERegUtil::GetValueBytes(hKey,"SMTP Secure Connection");
         if (pBytes)
         {
           if (*(PRInt32 *)pBytes == 1)
-            smtpServer->SetTrySSL(nsIMsgIncomingServer::useSSL);
+            smtpServer->SetSocketType(nsMsgSocketType::SSL);
           else
-            smtpServer->SetTrySSL(nsIMsgIncomingServer::defaultSocket);
+            smtpServer->SetSocketType(nsMsgSocketType::plain);
           nsOERegUtil::FreeValueBytes(pBytes);
         }
         smtpServer->SetUsername(userName);
         switch (useSicily) {
           case 1 :
-            smtpServer->SetAuthMethod(1);
-            smtpServer->SetUseSecAuth(PR_TRUE);  // useSecAuth
+            smtpServer->SetAuthMethod(nsMsgAuthMethod::secure);
             break;
-          case 2 : // requires authentication use incoming settings
-            smtpServer->SetAuthMethod(1);
-            smtpServer->SetUseSecAuth(useSecAuth);
+          case 2 : // requires SMTP authentication to use the incoming server settings
+            smtpServer->SetAuthMethod(authMethodIncoming);
             break;
           case 3 :
-            smtpServer->SetAuthMethod(1);
-            smtpServer->SetUseSecAuth(PR_FALSE);
+            smtpServer->SetAuthMethod(nsMsgAuthMethod::passwordCleartext);
             break;
           default:
-            smtpServer->SetAuthMethod(0);
-            smtpServer->SetUseSecAuth(PR_FALSE);
+            smtpServer->SetAuthMethod(nsMsgAuthMethod::none);
         }
 
         smtpServer->SetHostname(nsDependentCString(pSmtpServer));
 
         smtpServer->GetKey(getter_Copies(smtpServerKey));
         id->SetSmtpServerKey(smtpServerKey);
 
         IMPORT_LOG1("Created new SMTP server: %s\n", pSmtpServer);
--- a/mailnews/import/outlook/src/nsOutlookSettings.cpp
+++ b/mailnews/import/outlook/src/nsOutlookSettings.cpp
@@ -303,18 +303,17 @@ PRBool OutlookSettings::DoIMAPServer( ns
   // I now have a user name/server name pair, find out if it already exists?
   nsCOMPtr<nsIMsgIncomingServer> in;
   nsresult rv = pMgr->FindServer( nsDependentCString((const char *)pBytes), nsDependentCString(pServerName), NS_LITERAL_CSTRING("imap"), getter_AddRefs( in));
   if (NS_FAILED( rv) || (in == nsnull)) {
     // Create the incoming server and an account for it?
     rv = pMgr->CreateIncomingServer( nsDependentCString((const char *)pBytes), nsDependentCString(pServerName), NS_LITERAL_CSTRING("imap"), getter_AddRefs( in));
     if (NS_SUCCEEDED( rv) && in) {
       rv = in->SetType(NS_LITERAL_CSTRING("imap"));
-      // rv = in->SetHostName( pServerName);
-      // rv = in->SetUsername( (char *)pBytes);
+      // TODO SSL, auth method
 
       IMPORT_LOG2( "Created IMAP server named: %s, userName: %s\n", pServerName, (char *)pBytes);
 
       nsString prettyName;
       if (NS_SUCCEEDED(GetAccountName(hKey, pServerName, prettyName)))
         rv = in->SetPrettyName( prettyName);
       // We have a server, create an account.
       nsCOMPtr<nsIMsgAccount>  account;
@@ -356,16 +355,18 @@ PRBool OutlookSettings::DoPOP3Server( ns
   nsCOMPtr<nsIMsgIncomingServer> in;
   nsresult rv = pMgr->FindServer( nsDependentCString((const char *)pBytes), nsDependentCString(pServerName), NS_LITERAL_CSTRING("pop3"), getter_AddRefs( in));
   if (NS_FAILED( rv) || (in == nsnull)) {
     // Create the incoming server and an account for it?
     rv = pMgr->CreateIncomingServer(nsDependentCString((const char *)pBytes), nsDependentCString(pServerName), NS_LITERAL_CSTRING("pop3"), getter_AddRefs( in));
     if (NS_SUCCEEDED( rv) && in) {
       rv = in->SetType(NS_LITERAL_CSTRING("pop3"));
 
+      // TODO SSL, auth method
+
         nsCOMPtr<nsIPop3IncomingServer> pop3Server = do_QueryInterface(in);
         if (pop3Server) {
             // set local folders as the Inbox to use for this POP3 server
             nsCOMPtr<nsIMsgIncomingServer> localFoldersServer;
             pMgr->GetLocalFoldersServer(getter_AddRefs(localFoldersServer));
 
             if (!localFoldersServer)
             {
@@ -537,13 +538,14 @@ void OutlookSettings::SetSmtpServer(nsIM
       return;
     }
     nsCOMPtr<nsISmtpServer> smtpServer;
     rv = smtpService->CreateSmtpServer( getter_AddRefs( smtpServer));
     if (NS_SUCCEEDED( rv) && smtpServer) {
       smtpServer->SetHostname(nsDependentCString(pServer));
       if (!user.IsEmpty())
         smtpServer->SetUsername(user);
+      // TODO SSL, auth method
       IMPORT_LOG1( "Ceated new SMTP server: %s\n", pServer);
     }
   }
 }
 
--- a/mailnews/local/public/nsIPop3IncomingServer.idl
+++ b/mailnews/local/public/nsIPop3IncomingServer.idl
@@ -38,22 +38,21 @@
 #include "nsISupports.idl"
 
 interface nsIPop3Protocol;
 interface nsISupportsArray;
 interface nsIMsgFolder;
 interface nsIUrlListener;
 interface nsIMsgWindow;
 
-[scriptable, uuid(FC67F5C9-C8BB-46c1-90CB-1E752ECCEB19)]
+[scriptable, uuid(98d50234-6c8a-4875-815b-40e0178a13bd)]
 interface nsIPop3IncomingServer : nsISupports {
   attribute boolean leaveMessagesOnServer;
   attribute boolean headersOnly;
   attribute boolean deleteMailLeftOnServer;
-  attribute boolean authLogin;
   attribute boolean dotFix;
   attribute unsigned long pop3CapabilityFlags;
   attribute boolean deleteByAgeFromServer;
   attribute long numDaysToLeaveOnServer;
   attribute nsIPop3Protocol runningProtocol;
   // client adds uidls to mark one by one, then calls markMessages
   void addUidlToMark(in string aUidl, in PRInt32 newStatus);
   void markMessages();
--- a/mailnews/local/src/nsLocalStrings.h
+++ b/mailnews/local/src/nsLocalStrings.h
@@ -21,24 +21,28 @@
 #define POP3_USERNAME_UNDEFINED                               4014
 #define POP3_LIST_FAILURE                                     4015
 #define POP3_DELE_FAILURE                                     4016
 #define POP3_STAT_FAILURE                                     4024
 #define POP3_SERVER_SAID                                      4025
 #define COPYING_MSGS_STATUS                                   4027
 #define MOVING_MSGS_STATUS                                    4028
 #define POP3_MESSAGE_FOLDER_BUSY                              4029
-#define CANNOT_PROCESS_SECURE_AUTH                            4030
+#define POP3_AUTH_MECH_NOT_SUPPORTED                          4030
+#define POP3_GSSAPI_FAILURE                                   4031
 #define MOVEMAIL_CANT_OPEN_SPOOL_FILE                         4033
 #define MOVEMAIL_CANT_CREATE_LOCK                             4034
 #define MOVEMAIL_CANT_DELETE_LOCK                             4035
 #define MOVEMAIL_CANT_TRUNCATE_SPOOL_FILE                     4036
 #define MOVEMAIL_SPOOL_FILE_NOT_FOUND                         4037
 #define POP3_TMP_DOWNLOAD_FAILED                              4038
 #define POP3_SERVER_DOES_NOT_SUPPORT_UIDL_ETC                 4040
 #define POP3_SERVER_DOES_NOT_SUPPORT_THE_TOP_COMMAND          4041
-#define CANNOT_PROCESS_APOP_AUTH                              4042
 #define NS_ERROR_COULD_NOT_CONNECT_VIA_TLS                    4043
 #define POP3_MOVE_FOLDER_TO_TRASH                             4044
 #define POP3_DELETE_FOLDER_DIALOG_TITLE                       4045
 #define POP3_DELETE_FOLDER_BUTTON_LABEL                       4046
+#define POP3_AUTH_INTERNAL_ERROR                              4047
+#define POP3_AUTH_CHANGE_ENCRYPT_TO_PLAIN_NO_SSL              4048
+#define POP3_AUTH_CHANGE_ENCRYPT_TO_PLAIN_SSL                 4049
+#define POP3_AUTH_CHANGE_PLAIN_TO_ENCRYPT                     4050
 
 #endif /* _nsLocalStrings_H__ */
--- a/mailnews/local/src/nsPop3IncomingServer.cpp
+++ b/mailnews/local/src/nsPop3IncomingServer.cpp
@@ -108,20 +108,16 @@ NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingSe
                         HeadersOnly,
                         "headers_only")
 
 NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingServer,
                         DeleteMailLeftOnServer,
                         "delete_mail_left_on_server")
 
 NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingServer,
-                        AuthLogin,
-                        "auth_login")
-
-NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingServer,
                         DotFix,
                         "dot_fix")
 
 NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingServer,
                         DeleteByAgeFromServer,
                         "delete_by_age_from_server")
 
 NS_IMPL_SERVERPREF_INT(nsPop3IncomingServer,
--- a/mailnews/local/src/nsPop3Protocol.cpp
+++ b/mailnews/local/src/nsPop3Protocol.cpp
@@ -19,16 +19,17 @@
  * Netscape Communications Corporation.
  * Portions created by the Initial Developer are Copyright (C) 1998
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Howard Chu <hyc@highlandsun.com>
  *   David Bienvenu <bienvenu@nventure.com>
  *   Christian Eyrich <ch.ey@gmx.net>
+ *   Ben Bucksch <ben.bucksch beonex.com> <http://business.beonex.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -67,19 +68,16 @@
 #include "nsIMsgIncomingServer.h"
 #include "nsTextFormatter.h"
 #include "nsCOMPtr.h"
 #include "nsIMsgWindow.h"
 #include "nsIMsgFolder.h" // TO include biffState enum. Change to bool later...
 #include "nsIDocShell.h"
 #include "nsMsgUtils.h"
 #include "nsISignatureVerifier.h"
-#include "nsIPrefBranch.h"
-#include "nsIPrefService.h"
-#include "nsIPrefLocalizedString.h"
 #include "nsISocketTransport.h"
 #include "nsISSLSocketControl.h"
 #include "nsILineInputStream.h"
 #include "nsLocalStrings.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsMsgMessageFlags.h"
 
 #define EXTRA_SAFETY_SPACE 3096
@@ -489,58 +487,65 @@ nsPop3Protocol::nsPop3Protocol(nsIURI* a
   m_pop3ConData(nsnull),
   m_password_already_sent(PR_FALSE)
 {
 }
 
 nsresult nsPop3Protocol::Initialize(nsIURI * aURL)
 {
   nsresult rv = NS_OK;
+  if (!POP3LOGMODULE)
+    POP3LOGMODULE = PR_NewLogModule("POP3");
 
   m_pop3ConData = (Pop3ConData *)PR_NEWZAP(Pop3ConData);
   if(!m_pop3ConData)
     return NS_ERROR_OUT_OF_MEMORY;
 
   m_totalBytesReceived = 0;
   m_bytesInMsgReceived = 0;
   m_totalFolderSize = 0;
   m_totalDownloadSize = 0;
   m_totalBytesReceived = 0;
   m_tlsEnabled = PR_FALSE;
-  m_socketType = nsIMsgIncomingServer::tryTLS;
+  m_socketType = nsMsgSocketType::trySTARTTLS;
+  m_prefAuthMethods = POP3_AUTH_MECH_UNDEFINED;
+  m_failedAuthMethods = 0;
+  m_currentAuthMethod = POP3_AUTH_MECH_UNDEFINED;
 
   if (aURL)
   {
     // extract out message feedback if there is any.
     nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(aURL);
     if (mailnewsUrl)
     {
       nsCOMPtr<nsIMsgIncomingServer> server;
       mailnewsUrl->GetStatusFeedback(getter_AddRefs(m_statusFeedback));
       mailnewsUrl->GetServer(getter_AddRefs(server));
       NS_ENSURE_TRUE(server, NS_MSG_INVALID_OR_MISSING_SERVER);
 
       rv = server->GetSocketType(&m_socketType);
       NS_ENSURE_SUCCESS(rv,rv);
 
-      rv = server->GetUseSecAuth(&m_useSecAuth);
+      PRInt32 authMethod = 0;
+      rv = server->GetAuthMethod(&authMethod);
       NS_ENSURE_SUCCESS(rv,rv);
+      InitPrefAuthMethods(authMethod);
 
       m_pop3Server = do_QueryInterface(server);
       if (m_pop3Server)
         m_pop3Server->GetPop3CapabilityFlags(&m_pop3ConData->capability_flags);
     }
 
     m_url = do_QueryInterface(aURL);
 
     // When we are making a secure connection, we need to make sure that we
     // pass an interface requestor down to the socket transport so that PSM can
     // retrieve a nsIPrompt instance if needed.
     nsCOMPtr<nsIInterfaceRequestor> ir;
-    if (m_socketType != nsIMsgIncomingServer::defaultSocket)
+    if (m_socketType != nsMsgSocketType::plain)
     {
       nsCOMPtr<nsIMsgWindow> msgwin;
       mailnewsUrl->GetMsgWindow(getter_AddRefs(msgwin));
       if (!msgwin)
         GetTopmostMsgWindow(getter_AddRefs(msgwin));
       if (msgwin)
       {
         nsCOMPtr<nsIDocShell> docshell;
@@ -564,36 +569,33 @@ nsresult nsPop3Protocol::Initialize(nsIU
     if (server)
       server->GetRealHostName(hostName);
 
     nsCOMPtr<nsIProxyInfo> proxyInfo;
     rv = MsgExamineForProxy("pop", hostName.get(), port, getter_AddRefs(proxyInfo));
     if (NS_FAILED(rv)) proxyInfo = nsnull;
 
     const char *connectionType = nsnull;
-    if (m_socketType == nsIMsgIncomingServer::useSSL)
+    if (m_socketType == nsMsgSocketType::SSL)
       connectionType = "ssl";
-    else if (m_socketType == nsIMsgIncomingServer::tryTLS ||
-          m_socketType == nsIMsgIncomingServer::alwaysUseTLS)
+    else if (m_socketType == nsMsgSocketType::trySTARTTLS ||
+          m_socketType == nsMsgSocketType::alwaysSTARTTLS)
         connectionType = "starttls";
 
     rv = OpenNetworkSocketWithInfo(hostName.get(), port, connectionType, proxyInfo, ir);
-    if (NS_FAILED(rv) && m_socketType == nsIMsgIncomingServer::tryTLS)
+    if (NS_FAILED(rv) && m_socketType == nsMsgSocketType::trySTARTTLS)
     {
-      m_socketType = nsIMsgIncomingServer::defaultSocket;
+      m_socketType = nsMsgSocketType::plain;
       rv = OpenNetworkSocketWithInfo(hostName.get(), port, nsnull, proxyInfo, ir);
     }
 
     if(NS_FAILED(rv))
       return rv;
   } // if we got a url...
 
-  if (!POP3LOGMODULE)
-      POP3LOGMODULE = PR_NewLogModule("POP3");
-
   m_lineStreamBuffer = new nsMsgLineStreamBuffer(OUTPUT_BUFFER_SIZE, PR_TRUE);
   if(!m_lineStreamBuffer)
     return NS_ERROR_OUT_OF_MEMORY;
 
   nsCOMPtr<nsIStringBundleService> bundleService(do_GetService("@mozilla.org/intl/stringbundle;1", &rv));
   NS_ENSURE_SUCCESS(rv, rv);
   return bundleService->CreateBundle("chrome://messenger/locale/localMsgs.properties", getter_AddRefs(mLocalBundle));
 }
@@ -622,16 +624,21 @@ void nsPop3Protocol::ClearCapFlag(PRUint
     m_pop3ConData->capability_flags &= ~flag;
 }
 
 PRBool nsPop3Protocol::TestCapFlag(PRUint32 flag)
 {
     return m_pop3ConData->capability_flags & flag;
 }
 
+PRUint32 nsPop3Protocol::GetCapFlags()
+{
+    return m_pop3ConData->capability_flags;
+}
+
 void nsPop3Protocol::UpdateStatus(PRInt32 aStatusID)
 {
   if (m_statusFeedback)
   {
     nsString statusString;
     mLocalBundle->GetStringFromID(aStatusID, getter_Copies(statusString));
     UpdateStatusWithString(statusString.get());
   }
@@ -660,125 +667,121 @@ void nsPop3Protocol::SetUsername(const c
 {
   NS_ASSERTION(name, "no name specified!");
     if (name)
       m_username = name;
 }
 
 nsresult nsPop3Protocol::GetPassword(nsCString& aPassword)
 {
+  PR_LOG(POP3LOGMODULE, PR_LOG_MAX, ("GetPassword()"));
   nsresult rv = NS_OK;
   nsCOMPtr<nsIMsgIncomingServer> server = do_QueryInterface(m_pop3Server);
-
-  if (server)
+  NS_ENSURE_TRUE(server, NS_MSG_INVALID_OR_MISSING_SERVER);
+
+  PRBool isAuthenticated;
+  m_nsIPop3Sink->GetUserAuthenticated(&isAuthenticated);
+
+  // pass the failed password into the password prompt so that
+  // it will be pre-filled, in case it failed because of a
+  // server problem and not because it was wrong.
+  if (!m_lastPasswordSent.IsEmpty())
+    aPassword = m_lastPasswordSent;
+
+  // Set up some items that we're going to need for the prompting.
+  nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(m_url, &rv);
+  nsCOMPtr<nsIMsgWindow> msgWindow;
+  if (mailnewsUrl)
+    mailnewsUrl->GetMsgWindow(getter_AddRefs(msgWindow));
+
+  nsCString userName;
+  server->GetRealUsername(userName);
+
+  nsCString hostName;
+  server->GetRealHostName(hostName);
+
+  nsString passwordPrompt;
+  NS_ConvertUTF8toUTF16 userNameUTF16(userName);
+  NS_ConvertUTF8toUTF16 hostNameUTF16(hostName);
+  const PRUnichar* passwordParams[] = { userNameUTF16.get(),
+                                        hostNameUTF16.get() };
+
+  // if the last prompt got us a bad password then show a special dialog
+  if (TestFlag(POP3_PASSWORD_FAILED))
   {
-    PRBool isAuthenticated;
-    m_nsIPop3Sink->GetUserAuthenticated(&isAuthenticated);
-
-    // pass the failed password into the password prompt so that
-    // it will be pre-filled, in case it failed because of a
-    // server problem and not because it was wrong.
-    if (!m_lastPasswordSent.IsEmpty())
-      aPassword = m_lastPasswordSent;
-
-    // clear the password if the last one failed
-    if (TestFlag(POP3_PASSWORD_FAILED))
+    // Biff case (no msgWindow) shouldn't cause prompts or passwords to get forgotten at all
+    // TODO shouldn't we skip the new password prompt below as well for biff? Just exit here?
+    if (msgWindow)
     {
-      // if we've already gotten a password and it wasn't correct..clear
-      // out the password and try again.
-      rv = server->SetPassword(EmptyCString());
-    }
-
-    // Set up some items that we're going to need for the prompting.
-    nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(m_url, &rv);
-    nsCOMPtr<nsIMsgWindow> msgWindow;
-    if (mailnewsUrl)
-      mailnewsUrl->GetMsgWindow(getter_AddRefs(msgWindow));
-
-    nsCString userName;
-    server->GetRealUsername(userName);
-
-    nsCString hostName;
-    server->GetRealHostName(hostName);
-
-    nsString passwordPrompt;
-    NS_ConvertUTF8toUTF16 userNameUTF16(userName);
-    NS_ConvertUTF8toUTF16 hostNameUTF16(hostName);
-    const PRUnichar* passwordParams[] = { userNameUTF16.get(),
-                                          hostNameUTF16.get() };
-
-    // if the last prompt got us a bad password then show a special dialog
-    if (TestFlag(POP3_PASSWORD_FAILED))
-    {
-      // if we haven't successfully logged onto the server in this session
-      // and tried at least twice or if the server threw the specific error,
-      // forget the password.
-      // Only do this if it's not check for new mail, since biff shouldn't
-      // cause passwords to get forgotten at all.
-      if ((!isAuthenticated || m_pop3ConData->logonFailureCount > 2) && msgWindow)
+      PR_LOG(POP3LOGMODULE, PR_LOG_WARN,
+          ("POP: ask user what to do (after password failed): new password, retry or cancel"));
+
+      PRInt32 buttonPressed = 0;
+      if (NS_SUCCEEDED(MsgPromptLoginFailed(msgWindow, hostName,
+                                            &buttonPressed)))
       {
-        PRInt32 buttonPressed = 0;
-        if (NS_SUCCEEDED(MsgPromptLoginFailed(msgWindow, hostName,
-                                              &buttonPressed)))
+        if (buttonPressed == 1) // Cancel button
+        {
+          PR_LOG(POP3LOGMODULE, PR_LOG_WARN, ("cancel button pressed"));
+          // About quickly and stop trying for now.
+          m_pop3ConData->next_state = POP3_ERROR_DONE;
+
+          // Clear the password we're going to return to force failure in
+          // the get mail instance.
+          aPassword.Truncate();
+
+          // We also have to clear the password failed flag, otherwise we'll
+          // automatically try again.
+          ClearFlag(POP3_PASSWORD_FAILED);
+          return NS_ERROR_ABORT;
+        }
+        else if (buttonPressed == 2) // "New password" button
         {
-          if (buttonPressed == 1)
-          {
-            // Cancel button pressed, about quickly and stop trying for now.
-            m_pop3ConData->next_state = POP3_ERROR_DONE;
-
-            // Clear the password we're going to return to force failure in
-            // the get mail instance.
-            aPassword.Truncate();
-
-            // We also have to clear the password failed flag, otherwise we'll
-            // automatically try again.
-            ClearFlag(POP3_PASSWORD_FAILED);
-            return NS_ERROR_FAILURE;
-          }
-          if (buttonPressed == 2)
-          {
-            // Change password was pressed. For now, forget the stored password
-            // and we'll prompt for a new one next time around.
-            rv = server->ForgetPassword();
-            NS_ENSURE_SUCCESS(rv, rv);
-          }
-          // Reset the logon failure count now that we've prompted the user
-          m_pop3ConData->logonFailureCount = 0;
+          PR_LOG(POP3LOGMODULE, PR_LOG_WARN, ("new password button pressed"));
+          // Forget the stored password
+          // and we'll prompt for a new one next time around.
+          rv = server->ForgetPassword();
+          NS_ENSURE_SUCCESS(rv, rv);
+
+          // try all methods again with new password
+          ResetAuthMethods();
+          // ... apart from GSSAPI, which doesn't care about passwords
+          MarkAuthMethodAsFailed(POP3_HAS_AUTH_GSSAPI);
+        }
+        else if (buttonPressed == 0) // "Retry" button
+        {
+          PR_LOG(POP3LOGMODULE, PR_LOG_WARN, ("retry button pressed"));
+          // try all methods again, including GSSAPI
+          ResetAuthMethods();
+          ClearFlag(POP3_PASSWORD_FAILED|POP3_AUTH_FAILURE);
+          return NS_OK;
         }
       }
-      mLocalBundle->FormatStringFromName(
-        NS_LITERAL_STRING("pop3PreviouslyEnteredPasswordIsInvalidPrompt").get(),
-        passwordParams, 2, getter_Copies(passwordPrompt));
     }
-    else
-      // Otherwise this is the first time we've asked about the server's
-      // password so show a first time prompt.
-      mLocalBundle->FormatStringFromName(
-        NS_LITERAL_STRING("pop3EnterPasswordPrompt").get(),
-        passwordParams, 2, getter_Copies(passwordPrompt));
-
-    nsString passwordTitle;
-    mLocalBundle->GetStringFromName(
-      NS_LITERAL_STRING("pop3EnterPasswordPromptTitle").get(),
-      getter_Copies(passwordTitle));
-
-    // Now go and get the password.
-    if (!passwordPrompt.IsEmpty() && !passwordTitle.IsEmpty())
-      rv = server->GetPasswordWithUI(passwordPrompt, passwordTitle,
-                                     msgWindow, aPassword);
-    ClearFlag(POP3_PASSWORD_FAILED|POP3_AUTH_FAILURE);
-
-    // If it failed, then user pressed the cancel button (or some other
-    // failure).
-    if (NS_FAILED(rv))
-      m_pop3ConData->next_state = POP3_ERROR_DONE;
+    mLocalBundle->FormatStringFromName(
+      NS_LITERAL_STRING("pop3PreviouslyEnteredPasswordIsInvalidPrompt").get(),
+      passwordParams, 2, getter_Copies(passwordPrompt));
   }
   else
-    // No server present :-(
-    rv = NS_MSG_INVALID_OR_MISSING_SERVER;
+    // Otherwise this is the first time we've asked about the server's
+    // password so show a first time prompt.
+    mLocalBundle->FormatStringFromName(
+      NS_LITERAL_STRING("pop3EnterPasswordPrompt").get(),
+      passwordParams, 2, getter_Copies(passwordPrompt));
+
+  nsString passwordTitle;
+  mLocalBundle->GetStringFromName(
+    NS_LITERAL_STRING("pop3EnterPasswordPromptTitle").get(),
+    getter_Copies(passwordTitle));
+
+  // Now go and get the password.
+  if (!passwordPrompt.IsEmpty() && !passwordTitle.IsEmpty())
+    rv = server->GetPasswordWithUI(passwordPrompt, passwordTitle,
+                                    msgWindow, aPassword);
+  ClearFlag(POP3_PASSWORD_FAILED|POP3_AUTH_FAILURE);
 
   return rv;
 }
 
 NS_IMETHODIMP nsPop3Protocol::OnTransportStatus(nsITransport *aTransport, nsresult aStatus, PRUint64 aProgress, PRUint64 aProgressMax)
 {
   return nsMsgProtocol::OnTransportStatus(aTransport, aStatus, aProgress, aProgressMax);
 }
@@ -974,17 +977,17 @@ nsPop3Protocol::WaitForStartOfConnection
   if(*line == '+')
   {
     m_pop3ConData->command_succeeded = PR_TRUE;
     if(PL_strlen(line) > 4)
       m_commandResponse = line + 4;
     else
       m_commandResponse = line;
 
-    if (m_useSecAuth)
+    if (m_prefAuthMethods & POP3_HAS_AUTH_APOP)
     {
         nsresult rv;
         nsCOMPtr<nsISignatureVerifier> verifier = do_GetService(SIGNATURE_VERIFIER_CONTRACTID, &rv);
         // this checks if psm is installed...
         if (NS_SUCCEEDED(rv))
         {
           if (NS_SUCCEEDED(GetApopTimestamp()))
             SetCapFlag(POP3_HAS_AUTH_APOP);
@@ -1045,17 +1048,20 @@ nsPop3Protocol::WaitForResponse(nsIInput
     else
       m_commandResponse  = line;
 
     // search for the response codes (RFC 2449, chapter 8 and RFC 3206)
     if(TestCapFlag(POP3_HAS_RESP_CODES | POP3_HAS_AUTH_RESP_CODE))
     {
         // code for authentication failure due to the user's credentials
         if(m_commandResponse.Find("[AUTH", PR_TRUE) >= 0)
+        {
+          PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("setting auth failure"));
           SetFlag(POP3_AUTH_FAILURE);
+        }
 
         // codes for failures due to other reasons
         if(m_commandResponse.Find("[LOGIN-DELAY", PR_TRUE) >= 0 ||
            m_commandResponse.Find("[IN-USE", PR_TRUE) >= 0 ||
            m_commandResponse.Find("[SYS", PR_TRUE) >= 0)
       SetFlag(POP3_STOPLOGIN);
 
       // remove the codes from the response string presented to the user
@@ -1246,24 +1252,20 @@ PRInt32 nsPop3Protocol::AuthResponse(nsI
 }
 
 /*
  * POP3 CAPA extension, see RFC 2449, chapter 5
  */
 
 PRInt32 nsPop3Protocol::SendCapa()
 {
+    PR_LOG(POP3LOGMODULE, PR_LOG_MAX, ("SendCapa()"));
     if(!m_pop3ConData->command_succeeded)
         return(Error(POP3_SERVER_ERROR));
 
-    // for use after mechs disabled fallbacks when login failed
-    // should better live in AuthResponse(), but it would only
-    // be called the first time then
-    BackupAuthFlags();
-
     nsCAutoString command("CAPA" CRLF);
 
     m_pop3ConData->next_state_after_response = POP3_CAPA_RESPONSE;
     return SendData(m_url, command.get());
 }
 
 PRInt32 nsPop3Protocol::CapaResponse(nsIInputStream* inputStream,
                              PRUint32 length)
@@ -1361,21 +1363,20 @@ PRInt32 nsPop3Protocol::CapaResponse(nsI
             if (responseLine.Find("NTLM", PR_TRUE) >= 0)
                 SetCapFlag(POP3_HAS_AUTH_NTLM);
 
             if (responseLine.Find("MSN", PR_TRUE) >= 0)
                 SetCapFlag(POP3_HAS_AUTH_NTLM|POP3_HAS_AUTH_MSN);
         }
 
         m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
-        // for use after mechs disabled fallbacks when login failed
-        BackupAuthFlags();
     }
 
     PR_Free(line);
+    PR_LOG(POP3LOGMODULE, PR_LOG_MAX, ("capa processed"));
     return 0;
 }
 
 PRInt32 nsPop3Protocol::SendTLSResponse()
 {
   // only tear down our existing connection and open a new one if we received
   // a +OK response from the pop server after we issued the STLS command
   nsresult rv = NS_OK;
@@ -1417,203 +1418,331 @@ PRInt32 nsPop3Protocol::SendTLSResponse(
   }
 
   ClearFlag(POP3_HAS_STLS);
   m_pop3ConData->next_state = POP3_PROCESS_AUTH;
 
   return rv;
 }
 
+void nsPop3Protocol::InitPrefAuthMethods(PRInt32 authMethodPrefValue)
+{
+  // for m_prefAuthMethods, using the same flags as server capablities.
+  switch (authMethodPrefValue)
+  {
+    case nsMsgAuthMethod::none:
+      m_prefAuthMethods = POP3_HAS_AUTH_NONE;
+      break;
+    case nsMsgAuthMethod::old:
+      m_prefAuthMethods = POP3_HAS_AUTH_USER;
+      break;
+    case nsMsgAuthMethod::passwordCleartext:
+      m_prefAuthMethods = POP3_HAS_AUTH_USER |
+          POP3_HAS_AUTH_LOGIN | POP3_HAS_AUTH_PLAIN;
+      break;
+    case nsMsgAuthMethod::passwordEncrypted:
+      m_prefAuthMethods = POP3_HAS_AUTH_CRAM_MD5 |
+          POP3_HAS_AUTH_APOP;
+      break;
+    case nsMsgAuthMethod::NTLM:
+      m_prefAuthMethods = POP3_HAS_AUTH_NTLM | POP3_HAS_AUTH_MSN;
+      break;
+    case nsMsgAuthMethod::GSSAPI:
+      m_prefAuthMethods = POP3_HAS_AUTH_GSSAPI;
+      break;
+    case nsMsgAuthMethod::secure:
+      m_prefAuthMethods = POP3_HAS_AUTH_APOP |
+          POP3_HAS_AUTH_CRAM_MD5 | POP3_HAS_AUTH_GSSAPI |
+          POP3_HAS_AUTH_NTLM | POP3_HAS_AUTH_MSN;
+      break;
+    default:
+      NS_ASSERTION(false, "POP: authMethod pref invalid");
+      // TODO log to error console
+      PR_LOG(POP3LOGMODULE, PR_LOG_ERROR,
+          ("POP: bad pref authMethod = %d\n", authMethodPrefValue));
+      // fall to any
+    case nsMsgAuthMethod::anything:
+      m_prefAuthMethods = POP3_HAS_AUTH_USER |
+          POP3_HAS_AUTH_LOGIN | POP3_HAS_AUTH_PLAIN |
+          POP3_HAS_AUTH_CRAM_MD5 | POP3_HAS_AUTH_APOP |
+          POP3_HAS_AUTH_GSSAPI |
+          POP3_HAS_AUTH_NTLM | POP3_HAS_AUTH_MSN;
+      // TODO needed?
+      break;
+  }
+  NS_ASSERTION(m_prefAuthMethods != POP3_AUTH_MECH_UNDEFINED,
+      "POP: InitPrefAuthMethods() didn't work");
+}
+
+/**
+ * Changes m_currentAuthMethod to pick the best one
+ * which is allowed by server and prefs and not marked failed.
+ * The order of preference and trying of auth methods is encoded here.
+ */
+nsresult nsPop3Protocol::ChooseAuthMethod()
+{
+  PRInt32 availCaps = GetCapFlags() & m_prefAuthMethods & ~m_failedAuthMethods;
+
+  PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG,
+        ("POP auth: server caps 0x%X, pref 0x%X, failed 0x%X, avail caps 0x%X",
+        GetCapFlags(), m_prefAuthMethods, m_failedAuthMethods, availCaps));
+  PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG,
+        ("(GSSAPI = 0x%X, CRAM = 0x%X, APOP = 0x%X, NTLM = 0x%X, "
+        "MSN =  0x%X, PLAIN = 0x%X, LOGIN = 0x%X, USER/PASS = 0x%X)",
+        POP3_HAS_AUTH_GSSAPI, POP3_HAS_AUTH_CRAM_MD5, POP3_HAS_AUTH_APOP,
+        POP3_HAS_AUTH_NTLM, POP3_HAS_AUTH_MSN, POP3_HAS_AUTH_PLAIN,
+        POP3_HAS_AUTH_LOGIN, POP3_HAS_AUTH_USER));
+
+  if (POP3_HAS_AUTH_GSSAPI & availCaps)
+    m_currentAuthMethod = POP3_HAS_AUTH_GSSAPI;
+  else if (POP3_HAS_AUTH_CRAM_MD5 & availCaps)
+    m_currentAuthMethod = POP3_HAS_AUTH_CRAM_MD5;
+  else if (POP3_HAS_AUTH_APOP & availCaps)
+    m_currentAuthMethod = POP3_HAS_AUTH_APOP;
+  else if (POP3_HAS_AUTH_NTLM & availCaps)
+    m_currentAuthMethod = POP3_HAS_AUTH_NTLM;
+  else if (POP3_HAS_AUTH_MSN & availCaps)
+    m_currentAuthMethod = POP3_HAS_AUTH_MSN;
+  else if (POP3_HAS_AUTH_PLAIN & availCaps)
+    m_currentAuthMethod = POP3_HAS_AUTH_PLAIN;
+  else if (POP3_HAS_AUTH_LOGIN & availCaps)
+    m_currentAuthMethod = POP3_HAS_AUTH_LOGIN;
+  else if (POP3_HAS_AUTH_USER & availCaps)
+    m_currentAuthMethod = POP3_HAS_AUTH_USER;
+  else
+  {
+    // there are no matching login schemes at all, per server and prefs
+    m_currentAuthMethod = POP3_AUTH_MECH_UNDEFINED;
+    PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("no auth method remaining"));
+    return NS_ERROR_FAILURE;
+  }
+  PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("trying auth method 0x%X", m_currentAuthMethod));
+  return NS_OK;
+}
+
+void nsPop3Protocol::MarkAuthMethodAsFailed(PRInt32 failedAuthMethod)
+{
+  PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG,
+      ("marking auth method 0x%X failed", failedAuthMethod));
+  m_failedAuthMethods |= failedAuthMethod;
+}
+
+/**
+ * Start over, trying all auth methods again
+ */
+void nsPop3Protocol::ResetAuthMethods()
+{
+  PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("resetting (failed) auth methods"));
+  m_currentAuthMethod = POP3_AUTH_MECH_UNDEFINED;
+  m_failedAuthMethods = 0;
+}
+
+/**
+ * state POP3_PROCESS_AUTH
+ * Called when we should try to authenticate to the server.
+ * Also called when one auth method fails and we want to try and start
+ * the next best auth method.
+ */
 PRInt32 nsPop3Protocol::ProcessAuth()
 {
+    PR_LOG(POP3LOGMODULE, PR_LOG_MAX, ("ProcessAuth()"));
+
+    // Try to upgrade to STARTTLS -- TODO move into its own function
     if (!m_tlsEnabled)
     {
       if(TestCapFlag(POP3_HAS_STLS))
       {
-        if (m_socketType == nsIMsgIncomingServer::tryTLS ||
-            m_socketType == nsIMsgIncomingServer::alwaysUseTLS)
+        if (m_socketType == nsMsgSocketType::trySTARTTLS ||
+            m_socketType == nsMsgSocketType::alwaysSTARTTLS)
         {
             nsCAutoString command("STLS" CRLF);
 
             m_pop3ConData->next_state_after_response = POP3_TLS_RESPONSE;
             return SendData(m_url, command.get());
         }
       }
-      else if (m_socketType == nsIMsgIncomingServer::alwaysUseTLS)
+      else if (m_socketType == nsMsgSocketType::alwaysSTARTTLS)
       {
           m_pop3ConData->next_state = POP3_ERROR_DONE;
           return(Error(NS_ERROR_COULD_NOT_CONNECT_VIA_TLS));
       }
     }
 
     m_password_already_sent = PR_FALSE;
 
-    if(m_useSecAuth)
+    nsresult rv = ChooseAuthMethod();
+    if (NS_FAILED(rv))
     {
-      if (TestCapFlag(POP3_HAS_AUTH_GSSAPI))
-          m_pop3ConData->next_state = POP3_AUTH_GSSAPI;
-      else if (TestCapFlag(POP3_HAS_AUTH_CRAM_MD5))
-          m_pop3ConData->next_state = POP3_SEND_USERNAME;
-      else
-        if (TestCapFlag(POP3_HAS_AUTH_NTLM))
-            m_pop3ConData->next_state = POP3_AUTH_NTLM;
-        else
-        if (TestCapFlag(POP3_HAS_AUTH_APOP))
-            m_pop3ConData->next_state = POP3_SEND_PASSWORD;
+      // Pref doesn't match server. Now, find an appropriate error msg.
+      PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG,
+           ("ProcessAuth() early exit because no auth methods"));
+
+      // AuthGSSAPI* falls in here in case of an auth failure.
+      // If Kerberos was the only method, assume that
+      // the user is just not logged in yet, and show an appropriate error.
+      if (m_prefAuthMethods == POP3_HAS_AUTH_GSSAPI &&
+          m_failedAuthMethods == POP3_HAS_AUTH_GSSAPI)
+        return Error(POP3_GSSAPI_FAILURE);
+
+      // pref has plaintext pw & server claims to support encrypted pw
+      if (m_prefAuthMethods == (POP3_HAS_AUTH_USER | POP3_HAS_AUTH_LOGIN |
+              POP3_HAS_AUTH_PLAIN) &&
+          GetCapFlags() & (POP3_HAS_AUTH_CRAM_MD5 | POP3_HAS_AUTH_APOP))
+        // tell user to change to encrypted pw
+        return Error(POP3_AUTH_CHANGE_PLAIN_TO_ENCRYPT);
+      // pref has encrypted pw & server claims to support plaintext pw
+      else if (m_prefAuthMethods == (POP3_HAS_AUTH_CRAM_MD5 |
+                    POP3_HAS_AUTH_APOP) &&
+               GetCapFlags() & (POP3_HAS_AUTH_USER | POP3_HAS_AUTH_LOGIN |
+                    POP3_HAS_AUTH_PLAIN))
+      {
+        // have SSL
+        if (m_socketType == nsMsgSocketType::SSL ||
+            m_socketType == nsMsgSocketType::alwaysSTARTTLS)
+          // tell user to change to plaintext pw
+          return Error(POP3_AUTH_CHANGE_ENCRYPT_TO_PLAIN_SSL);
         else
-          return(Error(CANNOT_PROCESS_SECURE_AUTH));
+          // tell user to change to plaintext pw, with big warning
+          return Error(POP3_AUTH_CHANGE_ENCRYPT_TO_PLAIN_NO_SSL);
+      }
+      else
+        // just "change auth method"
+        return Error(POP3_AUTH_MECH_NOT_SUPPORTED);
     }
-    else
+
+    switch (m_currentAuthMethod)
     {
-        if (TestCapFlag(POP3_HAS_AUTH_PLAIN))
-            m_pop3ConData->next_state = POP3_SEND_USERNAME;
-        else
-        if (TestCapFlag(POP3_HAS_AUTH_LOGIN))
-            m_pop3ConData->next_state = POP3_AUTH_LOGIN;
-        else
-        if (TestCapFlag(POP3_HAS_AUTH_USER))
-            m_pop3ConData->next_state = POP3_SEND_USERNAME;
-        else
-            return(Error(POP3_SERVER_ERROR));
+      case POP3_HAS_AUTH_GSSAPI:
+        PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("POP GSSAPI"));
+        m_pop3ConData->next_state = POP3_AUTH_GSSAPI;
+        break;
+      case POP3_HAS_AUTH_APOP:
+        PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("POP APOP"));
+        m_pop3ConData->next_state = POP3_SEND_PASSWORD;
+        break;
+      case POP3_HAS_AUTH_CRAM_MD5:
+        PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("POP CRAM"));
+      case POP3_HAS_AUTH_PLAIN:
+      case POP3_HAS_AUTH_USER:
+        PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("POP username"));
+        m_pop3ConData->next_state = POP3_SEND_USERNAME;
+        break;
+      case POP3_HAS_AUTH_LOGIN:
+        PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("POP AUTH=LOGIN"));
+        m_pop3ConData->next_state = POP3_AUTH_LOGIN;
+        break;
+      case POP3_HAS_AUTH_NTLM:
+        PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("POP NTLM"));
+        m_pop3ConData->next_state = POP3_AUTH_NTLM;
+        break;
+      case POP3_HAS_AUTH_NONE:
+        PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("POP no auth"));
+        m_pop3ConData->command_succeeded = true;
+        m_pop3ConData->next_state = POP3_NEXT_AUTH_STEP;
+        break;
+      default:
+        PR_LOG(POP3LOGMODULE, PR_LOG_ERROR,
+             ("POP: m_currentAuthMethod has unknown value"));
+        return Error(POP3_AUTH_MECH_NOT_SUPPORTED);
     }
 
     m_pop3ConData->pause_for_read = PR_FALSE;
 
     return 0;
 }
 
-void nsPop3Protocol::BackupAuthFlags()
-{
-  m_origAuthFlags = m_pop3ConData->capability_flags &
-                    (POP3_HAS_AUTH_ANY | POP3_HAS_AUTH_ANY_SEC);
-}
-
-void nsPop3Protocol::RestoreAuthFlags()
+/**
+ * state POP3_NEXT_AUTH_STEP
+ * This is called when we finished one auth step (e.g. sending username
+ * or password are separate steps, similarly for AUTH LOGIN, NTLM etc.)
+ * and want to proceed to the next one.
+ */
+PRInt32 nsPop3Protocol::NextAuthStep()
 {
-  m_pop3ConData->capability_flags |= m_origAuthFlags;
-}
-
-PRInt32 nsPop3Protocol::AuthFallback()
-{
+    PR_LOG(POP3LOGMODULE, PR_LOG_MAX, ("NextAuthStep()"));
     if (m_pop3ConData->command_succeeded)
-        if(m_password_already_sent)
+    {
+        if (m_password_already_sent || // (also true for GSSAPI)
+            m_currentAuthMethod == POP3_HAS_AUTH_NONE)
         {
+            PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("login succeeded"));
             m_nsIPop3Sink->SetUserAuthenticated(PR_TRUE);
             ClearFlag(POP3_PASSWORD_FAILED);
             if (m_pop3ConData->verify_logon)
               m_pop3ConData->next_state = POP3_SEND_QUIT;
             else
               m_pop3ConData->next_state = (m_pop3ConData->get_url)
                                           ? POP3_SEND_GURL : POP3_SEND_STAT;
         }
         else
             m_pop3ConData->next_state = POP3_SEND_PASSWORD;
+    }
     else
     {
+        PR_LOG(POP3LOGMODULE, PR_LOG_MAX, ("command did not succeed"));
         // response code received shows that login failed not because of
         // wrong credential -> stop login without retry or pw dialog, only alert
         if (TestFlag(POP3_STOPLOGIN))
             return(Error((m_password_already_sent)
                          ? POP3_PASSWORD_FAILURE : POP3_USERNAME_FAILURE));
 
         // response code received shows that server is certain about the
-        // credential was wrong, or fallback has been disabled by pref
-        // -> no fallback, show alert and pw dialog
-        PRBool logonFallback = PR_TRUE;
-        nsCOMPtr<nsIMsgIncomingServer> server = do_QueryInterface(m_pop3Server);
-        if (server)
-          server->GetLogonFallback(&logonFallback);
-        if (!logonFallback)
-          SetFlag(POP3_AUTH_FAILURE);
-
+        // credential was wrong -> no fallback, show alert and pw dialog
         if (TestFlag(POP3_AUTH_FAILURE))
         {
+            PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG,
+               ("auth failure, setting password failed"));
             Error((m_password_already_sent)
                          ? POP3_PASSWORD_FAILURE : POP3_USERNAME_FAILURE);
             SetFlag(POP3_PASSWORD_FAILED);
             ClearFlag(POP3_AUTH_FAILURE);
-            m_pop3ConData->logonFailureCount++;
             return 0;
         }
 
-        // we have no certain response code -> fallback and try again
-        if (m_useSecAuth)
-        {
-            // If one authentication failed, we're going to
-            // fall back on a less secure login method.
-            if (TestCapFlag(POP3_HAS_AUTH_GSSAPI))
-                ClearCapFlag(POP3_HAS_AUTH_GSSAPI);
-            else if (TestCapFlag(POP3_HAS_AUTH_CRAM_MD5))
-                // if CRAM-MD5 enabled, disable it
-                ClearCapFlag(POP3_HAS_AUTH_CRAM_MD5);
-            else if (TestCapFlag(POP3_HAS_AUTH_NTLM))
-                // if NTLM enabled, disable it
-                ClearCapFlag(POP3_HAS_AUTH_NTLM|POP3_HAS_AUTH_MSN);
-            else if (TestCapFlag(POP3_HAS_AUTH_APOP))
-            {
-                // if APOP enabled, disable it
-                ClearCapFlag(POP3_HAS_AUTH_APOP);
-                // unsure because APOP failed and we can't determine why
-                Error(CANNOT_PROCESS_APOP_AUTH);
-            }
-        }
-        else
+        // We have no certain response code -> fallback and try again.
+        // Mark the auth method failed, to use a different method next round.
+        MarkAuthMethodAsFailed(m_currentAuthMethod);
+
+        if (m_currentAuthMethod == POP3_HAS_AUTH_USER &&
+            !m_password_already_sent)
         {
-            // If one authentication failed, we're going to
-            // fall back on a less secure login method.
-            if (TestCapFlag(POP3_HAS_AUTH_PLAIN))
-                // if PLAIN enabled, disable it
-                ClearCapFlag(POP3_HAS_AUTH_PLAIN);
-            else if(TestCapFlag(POP3_HAS_AUTH_LOGIN))
-                // if LOGIN enabled, disable it
-                ClearCapFlag(POP3_HAS_AUTH_LOGIN);
-            else if(TestCapFlag(POP3_HAS_AUTH_USER))
-            {
-                if(m_password_already_sent)
-                    // if USER enabled, disable it
-                    ClearCapFlag(POP3_HAS_AUTH_USER);
-                else
-                    // if USER enabled,
-                    // it was the username which was wrong -
-                    // no fallback but return error
-                    return(Error(POP3_USERNAME_FAILURE));
-            }
+            PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("USER username failed"));
+            // if USER auth method failed before sending the password,
+            // the username was wrong.
+            // no fallback but return error
+            return Error(POP3_USERNAME_FAILURE);
         }
 
-        // Only forget the password if we've no mechanism left.
-        if (m_useSecAuth && !TestCapFlag(POP3_HAS_AUTH_ANY_SEC) ||
-            !m_useSecAuth && !TestCapFlag(POP3_HAS_AUTH_ANY))
+        // If we have no auth method left, ask user to try with new password
+        nsresult rv = ChooseAuthMethod();
+        if (NS_FAILED(rv))
         {
-            // Let's restore the original auth flags from AuthResponse so we can
-            // try them again with new password and username
-            RestoreAuthFlags();
-            m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
-
-            Error(POP3_PASSWORD_FAILURE);
-            /* The password failed.
-
-               Sever the connection and go back to the `read password' state,
+            PR_LOG(POP3LOGMODULE, PR_LOG_ERROR,
+                ("POP: no auth methods remaining, setting password failure"));
+            /* Sever the connection and go back to the `read password' state,
                which, upon success, will re-open the connection.  Set a flag
                which causes the prompt to be different that time (to indicate
                that the old password was bogus.)
 
                But if we're just checking for new mail (biff) then don't bother
                prompting the user for a password: just fail silently.
             */
-
             SetFlag(POP3_PASSWORD_FAILED);
-            m_pop3ConData->logonFailureCount++;
+            Error(POP3_PASSWORD_FAILURE);
 
             if (m_nsIPop3Sink)
                 m_nsIPop3Sink->SetMailAccountURL(NULL);
 
             return 0;
         }
-
-        m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
+        PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG,
+           ("still have some auth methods to try"));
+
+        // TODO needed?
+        //m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
 
         m_pop3ConData->command_succeeded = PR_TRUE;
 
         m_pop3ConData->next_state = POP3_PROCESS_AUTH;
     }
 
     if (TestCapFlag(POP3_AUTH_MECH_UNDEFINED))
     {
@@ -1635,69 +1764,68 @@ PRInt32 nsPop3Protocol::AuthLogin()
     m_pop3ConData->next_state_after_response = POP3_AUTH_LOGIN_RESPONSE;
     m_pop3ConData->pause_for_read = PR_TRUE;
 
     return SendData(m_url, command.get());
 }
 
 PRInt32 nsPop3Protocol::AuthLoginResponse()
 {
-    // need the test to be here instead in AuthFallback() to
+    // need the test to be here instead in NextAuthStep() to
     // differentiate between command AUTH LOGIN failed and
     // sending username using LOGIN mechanism failed.
     if (!m_pop3ConData->command_succeeded)
     {
         // we failed with LOGIN, remove it
-        ClearCapFlag(POP3_HAS_AUTH_LOGIN);
-
+        MarkAuthMethodAsFailed(POP3_HAS_AUTH_LOGIN);
         m_pop3ConData->next_state = POP3_PROCESS_AUTH;
     }
     else
         m_pop3ConData->next_state = POP3_SEND_USERNAME;
 
     m_pop3ConData->pause_for_read = PR_FALSE;
 
     return 0;
 }
 
 // NTLM, like LOGIN consists of three steps not two as USER/PASS or CRAM-MD5,
 // so we've to start here and continue in SendUsername if the server
 // responds + to "AUTH NTLM"
 PRInt32 nsPop3Protocol::AuthNtlm()
 {
-    nsCAutoString command (TestCapFlag(POP3_HAS_AUTH_MSN) ? "AUTH MSN" CRLF :
-                                                            "AUTH NTLM" CRLF);
+    nsCAutoString command (m_currentAuthMethod == POP3_HAS_AUTH_MSN
+          ? "AUTH MSN" CRLF : "AUTH NTLM" CRLF);
     m_pop3ConData->next_state_after_response = POP3_AUTH_NTLM_RESPONSE;
     m_pop3ConData->pause_for_read = PR_TRUE;
 
     return SendData(m_url, command.get());
 }
 
 PRInt32 nsPop3Protocol::AuthNtlmResponse()
 {
-    // need the test to be here instead in AuthFallback() to
+    // need the test to be here instead in NextAuthStep() to
     // differentiate between command AUTH NTLM failed and
     // sending username using NTLM mechanism failed.
     if (!m_pop3ConData->command_succeeded)
     {
-        // we failed with NTLM, remove it
-        ClearCapFlag(POP3_HAS_AUTH_NTLM|POP3_HAS_AUTH_MSN);
-
+        MarkAuthMethodAsFailed(POP3_HAS_AUTH_NTLM);
+        MarkAuthMethodAsFailed(POP3_HAS_AUTH_MSN);
         m_pop3ConData->next_state = POP3_PROCESS_AUTH;
     }
     else
         m_pop3ConData->next_state = POP3_SEND_USERNAME;
 
     m_pop3ConData->pause_for_read = PR_FALSE;
 
     return 0;
 }
 
 PRInt32 nsPop3Protocol::AuthGSSAPI()
 {
+    PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("AuthGSSAPI()"));
     nsCOMPtr<nsIMsgIncomingServer> server = do_QueryInterface(m_pop3Server);
     if (server) {
         nsCAutoString cmd;
         nsCAutoString service("pop@");
         nsCString hostName;
         nsresult rv;
         server->GetRealHostName(hostName);
         service.Append(hostName);
@@ -1705,29 +1833,29 @@ PRInt32 nsPop3Protocol::AuthGSSAPI()
         if (NS_SUCCEEDED(rv)) {
             m_GSSAPICache.Assign(cmd);
             m_pop3ConData->next_state_after_response = POP3_AUTH_GSSAPI_FIRST;
             m_pop3ConData->pause_for_read = PR_TRUE;
             return SendData(m_url, "AUTH GSSAPI" CRLF);
         }
     }
 
-    ClearCapFlag(POP3_HAS_AUTH_GSSAPI);
+    MarkAuthMethodAsFailed(POP3_HAS_AUTH_GSSAPI);
     m_pop3ConData->next_state = POP3_PROCESS_AUTH;
     m_pop3ConData->pause_for_read = PR_FALSE;
     return NS_OK;
 }
 
 PRInt32 nsPop3Protocol::AuthGSSAPIResponse(PRBool first)
 {
     if (!m_pop3ConData->command_succeeded)
     {
         if (first)
             m_GSSAPICache.Truncate();
-        ClearCapFlag(POP3_HAS_AUTH_GSSAPI);
+        MarkAuthMethodAsFailed(POP3_HAS_AUTH_GSSAPI);
         m_pop3ConData->next_state = POP3_PROCESS_AUTH;
         m_pop3ConData->pause_for_read = PR_FALSE;
         return NS_OK;
     }
 
     nsresult rv;
 
     m_pop3ConData->next_state_after_response = POP3_AUTH_GSSAPI_STEP;
@@ -1735,220 +1863,248 @@ PRInt32 nsPop3Protocol::AuthGSSAPIRespon
 
     if (first) {
         m_GSSAPICache += CRLF;
         rv = SendData(m_url, m_GSSAPICache.get());
         m_GSSAPICache.Truncate();
     }
     else {
         nsCAutoString cmd;
+        PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("GSSAPI step 2"));
         rv = DoGSSAPIStep2(m_commandResponse, cmd);
         if (NS_FAILED(rv))
             cmd = "*";
         if (rv == NS_SUCCESS_AUTH_FINISHED) {
-            m_pop3ConData->next_state_after_response = POP3_AUTH_FALLBACK;
+            m_pop3ConData->next_state_after_response = POP3_NEXT_AUTH_STEP;
             m_password_already_sent = PR_TRUE;
         }
         cmd += CRLF;
         rv = SendData(m_url, cmd.get());
     }
 
     return rv;
 }
 
 PRInt32 nsPop3Protocol::SendUsername()
 {
+    PR_LOG(POP3LOGMODULE, PR_LOG_MAX, ("SendUsername()"));
     if(m_username.IsEmpty())
       return(Error(POP3_USERNAME_UNDEFINED));
 
+    // <copied from="SendPassword()">
+    // Needed for NTLM
     nsCString password;
     nsresult rv = GetPassword(password);
-    if (NS_SUCCEEDED(rv) && rv == NS_MSG_PASSWORD_PROMPT_CANCELLED)
+    if (rv == NS_MSG_PASSWORD_PROMPT_CANCELLED) // this is a "success" code
     {
       // user has canceled the password prompt
       m_pop3ConData->next_state = POP3_ERROR_DONE;
       return NS_ERROR_ABORT;
     }
     else if (NS_FAILED(rv) || password.IsEmpty())
+    {
+      m_pop3ConData->next_state = POP3_ERROR_DONE;
       return Error(POP3_PASSWORD_UNDEFINED);
+    }
+    // </copied>
 
     nsCAutoString cmd;
 
-    if (m_useSecAuth)
+    if (m_currentAuthMethod == POP3_HAS_AUTH_NTLM)
+        (void) DoNtlmStep1(m_username.get(), password.get(), cmd);
+    else if (m_currentAuthMethod == POP3_HAS_AUTH_CRAM_MD5)
+        cmd = "AUTH CRAM-MD5";
+    else if (m_currentAuthMethod == POP3_HAS_AUTH_PLAIN)
+        cmd = "AUTH PLAIN";
+    else if (m_currentAuthMethod == POP3_HAS_AUTH_LOGIN)
     {
-      if (TestCapFlag(POP3_HAS_AUTH_CRAM_MD5))
-          cmd = "AUTH CRAM-MD5";
-      else if (TestCapFlag(POP3_HAS_AUTH_NTLM))
-          rv = DoNtlmStep1(m_username.get(), password.get(), cmd);
+        char *base64Str = PL_Base64Encode(m_username.get(), m_username.Length(), nsnull);
+        cmd = base64Str;
+        PR_Free(base64Str);
+    }
+    else if (m_currentAuthMethod == POP3_HAS_AUTH_USER)
+    {
+        PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("USER login"));
+        cmd = "USER ";
+        cmd += m_username;
     }
     else
     {
-        if (TestCapFlag(POP3_HAS_AUTH_PLAIN))
-            cmd = "AUTH PLAIN";
-        else if (TestCapFlag(POP3_HAS_AUTH_LOGIN))
-        {
-            char *base64Str = PL_Base64Encode(m_username.get(), m_username.Length(), nsnull);
-            cmd = base64Str;
-            PR_Free(base64Str);
-        }
-        else
-        {
-            cmd = "USER ";
-            cmd += m_username;
-        }
+      PR_LOG(POP3LOGMODULE, PR_LOG_ERROR,
+          ("In nsPop3Protocol::SendUsername(), m_currentAuthMethod is 0x%X, "
+          "but that is unexpected", m_currentAuthMethod));
+      return Error(POP3_AUTH_INTERNAL_ERROR);
     }
+
     cmd += CRLF;
 
-    m_pop3ConData->next_state_after_response = POP3_AUTH_FALLBACK;
+    m_pop3ConData->next_state_after_response = POP3_NEXT_AUTH_STEP;
 
     m_pop3ConData->pause_for_read = PR_TRUE;
 
     return SendData(m_url, cmd.get());
 }
 
 PRInt32 nsPop3Protocol::SendPassword()
 {
-    if (m_username.IsEmpty())
-        return(Error(POP3_USERNAME_UNDEFINED));
-
-    nsCString password;
-    nsresult rv = GetPassword(password);
-    if (NS_SUCCEEDED(rv) && rv == NS_MSG_PASSWORD_PROMPT_CANCELLED)
+  PR_LOG(POP3LOGMODULE, PR_LOG_MAX, ("SendPassword()"));
+  if (m_username.IsEmpty())
+    return(Error(POP3_USERNAME_UNDEFINED));
+
+  // <copied to="SendUsername()">
+  // Needed here, too, because APOP skips SendUsername()
+  nsCString password;
+  nsresult rv = GetPassword(password);
+  if (rv == NS_MSG_PASSWORD_PROMPT_CANCELLED) // this is a "success" code
+  {
+    // user has canceled the password prompt
+    m_pop3ConData->next_state = POP3_ERROR_DONE;
+    return NS_ERROR_ABORT;
+  }
+  else if (NS_FAILED(rv) || password.IsEmpty())
+  {
+    m_pop3ConData->next_state = POP3_ERROR_DONE;
+    return Error(POP3_PASSWORD_UNDEFINED);
+  }
+  // </copied>
+
+  nsCAutoString cmd;
+
+  if (m_currentAuthMethod == POP3_HAS_AUTH_NTLM)
+    rv = DoNtlmStep2(m_commandResponse, cmd);
+  else if (m_currentAuthMethod == POP3_HAS_AUTH_CRAM_MD5)
+  {
+    PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("CRAM login"));
+    char buffer[512]; // TODO nsCAutoString
+    unsigned char digest[DIGEST_LENGTH];
+
+    char *decodedChallenge = PL_Base64Decode(m_commandResponse.get(),
+    m_commandResponse.Length(), nsnull);
+
+    if (decodedChallenge)
+      rv = MSGCramMD5(decodedChallenge, strlen(decodedChallenge),
+                      password.get(), password.Length(), digest);
+    else
+      rv = NS_ERROR_NULL_POINTER;
+
+    if (NS_SUCCEEDED(rv) && digest)
     {
-        // user has canceled the password prompt
-        m_pop3ConData->next_state = POP3_ERROR_DONE;
-        return NS_ERROR_ABORT;
+      nsCAutoString encodedDigest;
+      char hexVal[8];
+
+      for (PRUint32 j = 0; j < 16; j++)
+      {
+        PR_snprintf (hexVal,8, "%.2x", 0x0ff & (unsigned short)digest[j]);
+        encodedDigest.Append(hexVal);
+      }
+
+      PR_snprintf(buffer, sizeof(buffer), "%s %s", m_username.get(),
+                  encodedDigest.get());
+      char *base64Str = PL_Base64Encode(buffer, strlen(buffer), nsnull);
+      cmd = base64Str;
+      PR_Free(base64Str);
     }
-    else if (NS_FAILED(rv) || password.IsEmpty())
-    {
-      return Error(POP3_PASSWORD_UNDEFINED);
-    }
-
-    nsCAutoString cmd;
-    if (m_useSecAuth)
+
+    if (NS_FAILED(rv))
+      cmd = "*";
+  }
+  else if (m_currentAuthMethod == POP3_HAS_AUTH_APOP)
+  {
+    PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("APOP login"));
+    char buffer[512];
+    unsigned char digest[DIGEST_LENGTH];
+
+    rv = MSGApopMD5(m_ApopTimestamp.get(), m_ApopTimestamp.Length(),
+                    password.get(), password.Length(), digest);
+
+    if (NS_SUCCEEDED(rv) && digest)
     {
-        if (TestCapFlag(POP3_HAS_AUTH_CRAM_MD5))
-        {
-            char buffer[512];
-            unsigned char digest[DIGEST_LENGTH];
-
-            char *decodedChallenge = PL_Base64Decode(m_commandResponse.get(),
-            m_commandResponse.Length(), nsnull);
-
-            if (decodedChallenge)
-                rv = MSGCramMD5(decodedChallenge, strlen(decodedChallenge), password.get(), password.Length(), digest);
-            else
-                rv = NS_ERROR_FAILURE;
-
-            if (NS_SUCCEEDED(rv) && digest)
-            {
-                nsCAutoString encodedDigest;
-                char hexVal[8];
-
-                for (PRUint32 j=0; j<16; j++)
-                {
-                    PR_snprintf (hexVal,8, "%.2x", 0x0ff & (unsigned short)digest[j]);
-                    encodedDigest.Append(hexVal);
-                }
-
-                PR_snprintf(buffer, sizeof(buffer), "%s %s", m_username.get(), encodedDigest.get());
-                char *base64Str = PL_Base64Encode(buffer, strlen(buffer), nsnull);
-                cmd = base64Str;
-                PR_Free(base64Str);
-            }
-
-            if (NS_FAILED(rv))
-                cmd = "*";
-        }
-        else if (TestCapFlag(POP3_HAS_AUTH_NTLM))
-            rv = DoNtlmStep2(m_commandResponse, cmd);
-        else if (TestCapFlag(POP3_HAS_AUTH_APOP))
-        {
-            char buffer[512];
-            unsigned char digest[DIGEST_LENGTH];
-
-            rv = MSGApopMD5(m_ApopTimestamp.get(), m_ApopTimestamp.Length(), password.get(), password.Length(), digest);
-
-            if (NS_SUCCEEDED(rv) && digest)
-            {
-                nsCAutoString encodedDigest;
-                char hexVal[8];
-
-                for (PRUint32 j=0; j<16; j++)
-                {
-                    PR_snprintf (hexVal,8, "%.2x", 0x0ff & (unsigned short)digest[j]);
-                    encodedDigest.Append(hexVal);
-                }
-
-                PR_snprintf(buffer, sizeof(buffer), "APOP %s %s", m_username.get(), encodedDigest.get());
-                cmd = buffer;
-            }
-
-            if (NS_FAILED(rv))
-                cmd = "*";
-        }
+      nsCAutoString encodedDigest;
+      char hexVal[8];
+
+      for (PRUint32 j=0; j<16; j++)
+      {
+        PR_snprintf (hexVal,8, "%.2x", 0x0ff & (unsigned short)digest[j]);
+        encodedDigest.Append(hexVal);
+      }
+
+      PR_snprintf(buffer, sizeof(buffer), "APOP %s %s", m_username.get(),
+                  encodedDigest.get());
+      cmd = buffer;
+    }
+
+    if (NS_FAILED(rv))
+      cmd = "*";
+  }
+  else if (m_currentAuthMethod == POP3_HAS_AUTH_PLAIN)
+  {
+    PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("PLAIN login"));
+    // workaround for IPswitch's IMail server software
+    // this server goes into LOGIN mode even if we send "AUTH PLAIN"
+    // "VXNlc" is the beginning of the base64 encoded prompt ("Username:") for LOGIN
+    if (StringBeginsWith(m_commandResponse, NS_LITERAL_CSTRING("VXNlc")))
+    {
+      // disable PLAIN and enable LOGIN (in case it's not already enabled)
+      ClearCapFlag(POP3_HAS_AUTH_PLAIN);
+      SetCapFlag(POP3_HAS_AUTH_LOGIN);
+      m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
+
+      // reenter authentication again at LOGIN response handler
+      m_pop3ConData->next_state = POP3_AUTH_LOGIN_RESPONSE;
+      m_pop3ConData->pause_for_read = PR_FALSE;
+      return 0;
     }
-    else
-    {
-        if (TestCapFlag(POP3_HAS_AUTH_PLAIN))
-        {
-            // workaround for IPswitch's IMail server software
-            // this server goes into LOGIN mode even if we send "AUTH PLAIN"
-            // "VXNlc" is the begin of the base64 encoded prompt for LOGIN
-            if (StringBeginsWith(m_commandResponse, NS_LITERAL_CSTRING("VXNlc")))
-            {
-                // disable PLAIN and enable LOGIN (in case it's not already enabled)
-                ClearCapFlag(POP3_HAS_AUTH_PLAIN);
-                SetCapFlag(POP3_HAS_AUTH_LOGIN);
-                m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
-
-                // reenter authentication again at LOGIN response handler
-                m_pop3ConData->next_state = POP3_AUTH_LOGIN_RESPONSE;
-                m_pop3ConData->pause_for_read = PR_FALSE;
-                return 0;
-            }
-
-            char plain_string[512];
-            int len = 1; /* first <NUL> char */
-
-            memset(plain_string, 0, 512);
-            PR_snprintf(&plain_string[1], 510, "%s", m_username.get());
-            len += m_username.Length();
-            len++; /* second <NUL> char */
-            PR_snprintf(&plain_string[len], 511-len, "%s", password.get());
-            len += password.Length();
-
-            char *base64Str = PL_Base64Encode(plain_string, len, nsnull);
-            cmd = base64Str;
-            PR_Free(base64Str);
-        }
-        else if (TestCapFlag(POP3_HAS_AUTH_LOGIN))
-        {
-            char * base64Str =
-                PL_Base64Encode(password.get(), password.Length(), nsnull);
-            cmd = base64Str;
-            PR_Free(base64Str);
-        }
-        else
-        {
-            cmd = "PASS ";
-            cmd += password;
-        }
-    }
-    cmd += CRLF;
-
-    m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
-
-    m_pop3ConData->next_state_after_response = POP3_AUTH_FALLBACK;
-
-    m_pop3ConData->pause_for_read = PR_TRUE;
-
-    m_password_already_sent = PR_TRUE;
-    m_lastPasswordSent = password;
-    return SendData(m_url, cmd.get(), PR_TRUE);
+
+    char plain_string[512]; // TODO nsCString
+    int len = 1; /* first <NUL> char */
+    memset(plain_string, 0, 512);
+    PR_snprintf(&plain_string[1], 510, "%s", m_username.get());
+    len += m_username.Length();
+    len++; /* second <NUL> char */
+    PR_snprintf(&plain_string[len], 511-len, "%s", password.get());
+    len += password.Length();
+
+    char *base64Str = PL_Base64Encode(plain_string, len, nsnull);
+    cmd = base64Str;
+    PR_Free(base64Str);
+  }
+  else if (m_currentAuthMethod == POP3_HAS_AUTH_LOGIN)
+  {
+    PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("LOGIN password"));
+    char * base64Str =
+        PL_Base64Encode(password.get(), password.Length(), nsnull);
+    cmd = base64Str;
+    PR_Free(base64Str);
+  }
+  else if (m_currentAuthMethod == POP3_HAS_AUTH_USER)
+  {
+    PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG, ("PASS password"));
+    cmd = "PASS ";
+    cmd += password;
+  }
+  else
+  {
+    PR_LOG(POP3LOGMODULE, PR_LOG_ERROR,
+        ("In nsPop3Protocol::SendPassword(), m_currentAuthMethod is %X, "
+        "but that is unexpected", m_currentAuthMethod));
+    return Error(POP3_AUTH_INTERNAL_ERROR);
+  }
+
+  cmd += CRLF;
+
+  // TODO needed?
+  //m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
+
+  m_pop3ConData->next_state_after_response = POP3_NEXT_AUTH_STEP;
+
+  m_pop3ConData->pause_for_read = PR_TRUE;
+
+  m_password_already_sent = PR_TRUE;
+  m_lastPasswordSent = password;
+  return SendData(m_url, cmd.get(), PR_TRUE);
 }
 
 PRInt32 nsPop3Protocol::SendStatOrGurl(PRBool sendStat)
 {
   nsCAutoString cmd;
   if (sendStat)
   {
     cmd  = "STAT" CRLF;
@@ -2703,20 +2859,17 @@ PRInt32 nsPop3Protocol::GetMsg()
   }
 
   /* Look at this message, and decide whether to ignore it, get it, just get
   the TOP of it, or delete it. */
 
   // if this is a message we've seen for the first time, we won't find it in
   // m_pop3ConData-uidlinfo->hash.  By default, we retrieve messages, unless they have a status,
   // or are too big, in which case we figure out what to do.
-  PRBool prefBool = PR_FALSE;
-  m_pop3Server->GetAuthLogin(&prefBool);
-
-  if (prefBool && (TestCapFlag(POP3_HAS_XSENDER)))
+  if (m_prefAuthMethods != POP3_HAS_AUTH_USER && TestCapFlag(POP3_HAS_XSENDER))
     m_pop3ConData->next_state = POP3_SEND_XSENDER;
   else
     m_pop3ConData->next_state = POP3_SEND_RETR;
   m_pop3ConData->truncating_cur_msg = PR_FALSE;
   m_pop3ConData->pause_for_read = PR_FALSE;
   if (m_pop3ConData->msg_info)
   {
     Pop3MsgInfo* info = m_pop3ConData->msg_info + m_pop3ConData->last_accessed_msg;
@@ -3180,36 +3333,33 @@ nsPop3Protocol::TopResponse(nsIInputStre
   if(m_pop3ConData->cur_msg_size == -1 &&  /* first line after TOP command sent */
     !m_pop3ConData->command_succeeded)  /* and TOP command failed */
   {
   /* TOP doesn't work so we can't retrieve the first part of this msg.
   So just go download the whole thing, and warn the user.
 
     Note that the progress bar will not be accurate in this case.
     Oops. #### */
-    PRBool prefBool = PR_FALSE;
     m_pop3ConData->truncating_cur_msg = PR_FALSE;
 
     nsString statusTemplate;
     mLocalBundle->GetStringFromID(POP3_SERVER_DOES_NOT_SUPPORT_THE_TOP_COMMAND, getter_Copies(statusTemplate));
     if (!statusTemplate.IsEmpty())
     {
       nsCAutoString hostName;
       PRUnichar * statusString = nsnull;
       m_url->GetHost(hostName);
 
       statusString = nsTextFormatter::smprintf(statusTemplate.get(), hostName.get());
       UpdateStatusWithString(statusString);
       nsTextFormatter::smprintf_free(statusString);
     }
 
-    m_pop3Server->GetAuthLogin(&prefBool);
-
-    if (prefBool &&
-      (TestCapFlag(POP3_HAS_XSENDER)))
+    if (m_prefAuthMethods != POP3_HAS_AUTH_USER &&
+        TestCapFlag(POP3_HAS_XSENDER))
       m_pop3ConData->next_state = POP3_SEND_XSENDER;
     else
       m_pop3ConData->next_state = POP3_SEND_RETR;
     return(0);
   }
 
   /* If TOP works, we handle it in the same way as RETR. */
   return RetrResponse(inputStream, length);
@@ -3454,37 +3604,29 @@ nsresult nsPop3Protocol::ProcessProtocol
           m_nsIPop3Sink->SetBiffStateAndUpdateFE(m_pop3ConData->biffstate, 0, PR_FALSE);
 
           /* update old style biff */
           m_pop3ConData->next_state = POP3_FREE;
           m_pop3ConData->pause_for_read = PR_FALSE;
           break;
         }
 
-        if (m_username.IsEmpty() || !pwd)
+        m_pop3ConData->pause_for_read = PR_FALSE;
+        // we are already connected so just go on and send the username
+        if (m_prefAuthMethods == POP3_HAS_AUTH_USER)
         {
-          m_pop3ConData->next_state = POP3_ERROR_DONE;
-          m_pop3ConData->pause_for_read = PR_FALSE;
+          m_currentAuthMethod = POP3_HAS_AUTH_USER;
+          m_pop3ConData->next_state = POP3_SEND_USERNAME;
         }
         else
         {
-          // we are already connected so just go on and send the username
-          PRBool prefBool = PR_FALSE;
-          m_pop3ConData->pause_for_read = PR_FALSE;
-          m_pop3Server->GetAuthLogin(&prefBool);
-
-          if (prefBool)
-          {
-            if (TestCapFlag(POP3_AUTH_MECH_UNDEFINED))
-              m_pop3ConData->next_state = POP3_SEND_AUTH;
-            else
-              m_pop3ConData->next_state = POP3_SEND_CAPA;
-          }
+          if (TestCapFlag(POP3_AUTH_MECH_UNDEFINED))
+            m_pop3ConData->next_state = POP3_SEND_AUTH;
           else
-            m_pop3ConData->next_state = POP3_SEND_USERNAME;
+            m_pop3ConData->next_state = POP3_SEND_CAPA;
         }
         break;
       }
 
 
     case POP3_START_CONNECT:
       {
         m_pop3ConData->next_state = POP3_FINISH_CONNECT;
@@ -3504,28 +3646,28 @@ nsresult nsPop3Protocol::ProcessProtocol
       break;
 
     case POP3_WAIT_FOR_START_OF_CONNECTION_RESPONSE:
       {
         status = WaitForStartOfConnectionResponse(aInputStream, aLength);
 
         if(status)
         {
-          PRBool prefBool = PR_FALSE;
-          m_pop3Server->GetAuthLogin(&prefBool);
-
-          if (prefBool)
+          if (m_prefAuthMethods == POP3_HAS_AUTH_USER)
+          {
+            m_currentAuthMethod = POP3_HAS_AUTH_USER;
+            m_pop3ConData->next_state = POP3_SEND_USERNAME;
+          }
+          else
           {
             if (TestCapFlag(POP3_AUTH_MECH_UNDEFINED))
               m_pop3ConData->next_state = POP3_SEND_AUTH;
             else
               m_pop3ConData->next_state = POP3_SEND_CAPA;
           }
-          else
-            m_pop3ConData->next_state = POP3_SEND_USERNAME;
         }
 
         break;
       }
 
     case POP3_SEND_AUTH:
       status = SendAuth();
       break;
@@ -3545,18 +3687,18 @@ nsresult nsPop3Protocol::ProcessProtocol
     case POP3_TLS_RESPONSE:
       status = SendTLSResponse();
       break;
 
     case POP3_PROCESS_AUTH:
       status = ProcessAuth();
       break;
 
-    case POP3_AUTH_FALLBACK:
-      status = AuthFallback();
+    case POP3_NEXT_AUTH_STEP:
+      status = NextAuthStep();
       break;
 
     case POP3_AUTH_LOGIN:
       status = AuthLogin();
       break;
 
     case POP3_AUTH_LOGIN_RESPONSE:
       status = AuthLoginResponse();
@@ -3763,17 +3905,17 @@ nsresult nsPop3Protocol::ProcessProtocol
           UpdateStatusWithString(statusString);
           nsTextFormatter::smprintf_free(statusString);
         }
 
         NS_ASSERTION (!TestFlag(POP3_PASSWORD_FAILED), "POP3_PASSWORD_FAILED set when del_started");
         m_nsIPop3Sink->AbortMailDelivery(this);
       }
 
-      if (TestFlag(POP3_PASSWORD_FAILED) && m_pop3ConData->logonFailureCount < 6)
+      if (TestFlag(POP3_PASSWORD_FAILED))
       {
       /* We got here because the password was wrong, so go
         read a new one and re-open the connection. */
         m_pop3ConData->next_state = POP3_READ_PASSWORD;
         m_pop3ConData->command_succeeded = PR_TRUE;
         status = 0;
         break;
       }
--- a/mailnews/local/src/nsPop3Protocol.h
+++ b/mailnews/local/src/nsPop3Protocol.h
@@ -109,16 +109,18 @@ enum Pop3CapabilityEnum {
     POP3_HAS_AUTH_NTLM          = 0x00008000,
     POP3_HAS_AUTH_MSN           = 0x00010000,
     POP3_HAS_RESP_CODES         = 0x00020000,
     POP3_HAS_AUTH_RESP_CODE     = 0x00040000,
     POP3_HAS_STLS               = 0x00080000,
     POP3_HAS_AUTH_GSSAPI        = 0x00100000
 };
 
+// TODO use value > 0?
+#define POP3_HAS_AUTH_NONE        0
 #define POP3_HAS_AUTH_ANY         0x00001C00
 #define POP3_HAS_AUTH_ANY_SEC     0x0011E000
 
 enum Pop3StatesEnum {
     POP3_READ_PASSWORD,                         // 0
                                                 //
     POP3_START_CONNECT,                         // 1
     POP3_FINISH_CONNECT,                        // 2
@@ -149,17 +151,17 @@ enum Pop3StatesEnum {
     POP3_DONE,                                  // 23
     POP3_ERROR_DONE,                            // 24
     POP3_FREE,                                  // 25
     POP3_SEND_AUTH,                             // 26
     POP3_AUTH_RESPONSE,                         // 27
     POP3_SEND_CAPA,                             // 28
     POP3_CAPA_RESPONSE,                         // 29
     POP3_PROCESS_AUTH,                          // 30
-    POP3_AUTH_FALLBACK,                         // 31
+    POP3_NEXT_AUTH_STEP,                        // 31
 
     POP3_AUTH_LOGIN,                            // 32
     POP3_AUTH_LOGIN_RESPONSE,                   // 33
     POP3_AUTH_NTLM,                             // 34
     POP3_AUTH_NTLM_RESPONSE,                    // 35
     POP3_SEND_XSENDER,                          // 36
     POP3_XSENDER_RESPONSE,                      // 37
     POP3_SEND_GURL,                             // 38
@@ -249,17 +251,16 @@ typedef struct _Pop3ConData {
     char *only_uidl;              /* If non-NULL, then load only this UIDL. */
 
     PRBool get_url;
     PRBool seenFromHeader;
     PRInt32 parsed_bytes;
     PRInt32 pop3_size;
     PRBool dot_fix;
     PRBool assumed_end;
-    PRInt32 logonFailureCount;
     nsresult urlStatus;
 } Pop3ConData;
 
 // State Flags (Note, I use the word state in terms of storing
 // state information about the connection (authentication, have we sent
 // commands, etc. I do not intend it to refer to protocol state)
 #define POP3_PAUSE_FOR_READ      0x00000001  /* should we pause for the next read */
 #define POP3_PASSWORD_FAILED    0x00000002
@@ -327,26 +328,31 @@ private:
 
   nsMsgLineStreamBuffer   * m_lineStreamBuffer; // used to efficiently extract lines from the incoming data stream
   Pop3ConData* m_pop3ConData;
   void FreeMsgInfo();
   void Abort();
 
   PRBool m_tlsEnabled;
   PRInt32 m_socketType;
-  PRBool m_useSecAuth;
   PRBool m_password_already_sent;
 
   void SetCapFlag(PRUint32 flag);
   void ClearCapFlag(PRUint32 flag);
   PRBool TestCapFlag(PRUint32 flag);
+  PRUint32 GetCapFlags();
 
-  void BackupAuthFlags();
-  void RestoreAuthFlags();
-  PRInt32 m_origAuthFlags;
+  void    InitPrefAuthMethods(PRInt32 authMethodPrefValue);
+  nsresult ChooseAuthMethod();
+  void    MarkAuthMethodAsFailed(PRInt32 failedAuthMethod);
+  void    ResetAuthMethods();
+  PRInt32 m_prefAuthMethods; // set of capability flags for auth methods
+  PRInt32 m_failedAuthMethods; // ditto
+  PRInt32 m_currentAuthMethod; // exactly one capability flag, or 0
+
   PRInt32 m_listpos;
 
   nsresult HandleLine(char *line, PRUint32 line_length);
 
   nsresult GetApopTimestamp();
 
   //////////////////////////////////////////////////////////////////////////////////////////
       // Begin Pop3 protocol state handlers
@@ -357,17 +363,17 @@ private:
                           PRUint32 length);
   PRInt32 Error(PRInt32 err_code);
   PRInt32 SendAuth();
   PRInt32 AuthResponse(nsIInputStream* inputStream, PRUint32 length);
   PRInt32 SendCapa();
   PRInt32 CapaResponse(nsIInputStream* inputStream, PRUint32 length);
   PRInt32 SendTLSResponse();
   PRInt32 ProcessAuth();
-  PRInt32 AuthFallback();
+  PRInt32 NextAuthStep();
   PRInt32 AuthLogin();
   PRInt32 AuthLoginResponse();
   PRInt32 AuthNtlm();
   PRInt32 AuthNtlmResponse();
   PRInt32 AuthGSSAPI();
   PRInt32 AuthGSSAPIResponse(PRBool first);
   PRInt32 SendUsername();
   PRInt32 SendPassword();
new file mode 100644
--- /dev/null
+++ b/mailnews/local/test/unit/test_pop3AuthMethods.js
@@ -0,0 +1,188 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/**
+ * Login tests for POP3
+ *
+ * Test code <copied from="test_pop3GetNewMail.js">
+ */
+var server;
+var daemon;
+var handler;
+var incomingServer;
+var pop3Service;
+var acctMgr;
+var thisTest;
+var test = null;
+
+var tests = [
+  { title: "Cleartext password, with server only supporting USER/PASS",
+    clientAuthMethod : Ci.nsMsgAuthMethod.passwordCleartext,
+    serverAuthMethods : [],
+    expectSuccess : true,
+    transaction: [ "AUTH", "CAPA", "USER fred", "PASS wilma", "STAT" ] },
+  // Just to make sure we clear the auth flags and re-issue "AUTH"
+  { title: "Second time Cleartext password, with server only supporting USER/PASS",
+    clientAuthMethod : Ci.nsMsgAuthMethod.passwordCleartext,
+    serverAuthMethods : [],
+    expectSuccess : true,
+    transaction: [ "AUTH", "CAPA", "USER fred", "PASS wilma", "STAT" ] },
+  { title: "Cleartext password, with server supporting AUTH PLAIN, LOGIN and CRAM",
+    clientAuthMethod : Ci.nsMsgAuthMethod.passwordCleartext,
+    serverAuthMethods : [ "PLAIN", "LOGIN", "CRAM-MD5" ],
+    expectSuccess : true,
+    transaction: [ "AUTH", "CAPA", "AUTH PLAIN", "STAT" ] },
+  { title: "Cleartext password, with server supporting only AUTH LOGIN",
+    clientAuthMethod : Ci.nsMsgAuthMethod.passwordCleartext,
+    serverAuthMethods : [ "LOGIN" ],
+    expectSuccess : true,
+    transaction: [ "AUTH", "CAPA", "AUTH LOGIN", "STAT" ] },
+  { title: "Encrypted password, with server supporting PLAIN and CRAM",
+    clientAuthMethod : Ci.nsMsgAuthMethod.passwordEncrypted,
+    serverAuthMethods : [ "PLAIN", "LOGIN", "CRAM-MD5" ],
+    expectSuccess : true,
+    transaction: [ "AUTH", "CAPA", "AUTH CRAM-MD5", "STAT" ] },
+  { title: "Encrypted password, with server only supporting AUTH PLAIN and LOGIN (must fail)",
+    clientAuthMethod : Ci.nsMsgAuthMethod.passwordEncrypted,
+    serverAuthMethods : [ "PLAIN", "LOGIN" ],
+    expectSuccess : false,
+    transaction: [ "AUTH", "CAPA"] },
+  { title: "Any secure method, with server supporting AUTH PLAIN and CRAM",
+    clientAuthMethod : Ci.nsMsgAuthMethod.secure,
+    serverAuthMethods : [ "PLAIN" , "LOGIN", "CRAM-MD5" ],
+    expectSuccess : true,
+    transaction: [ "AUTH", "CAPA", "AUTH CRAM-MD5", "STAT" ] },
+  { title: "Any secure method, with server only supporting AUTH PLAIN and LOGIN (must fail)",
+    clientAuthMethod : Ci.nsMsgAuthMethod.secure,
+    serverAuthMethods : [ "PLAIN" ],
+    expectSuccess : false,
+    transaction: [ "AUTH", "CAPA" ] }
+];
+
+var urlListener =
+{
+  OnStartRunningUrl: function (url) {
+  },
+  OnStopRunningUrl: function (url, result) {
+    try {
+      if (thisTest.expectSuccess)
+        do_check_eq(result, 0);
+      else
+        do_check_neq(result, 0);
+
+      var transaction = server.playTransaction();
+      do_check_transaction(transaction, thisTest.transaction);
+
+      do_timeout(0, checkBusy);
+    } catch (e) {
+      server.stop();
+      var thread = gThreadManager.currentThread;
+      while (thread.hasPendingEvents())
+        thread.processNextEvent(true);
+
+      do_throw(e);
+    }
+  }
+};
+
+function checkBusy() {
+  if (tests.length == 0) {
+    incomingServer.closeCachedConnections();
+
+    // No more tests, let everything finish
+    server.stop();
+
+    var thread = gThreadManager.currentThread;
+    while (thread.hasPendingEvents())
+      thread.processNextEvent(true);
+
+    do_test_finished();
+    return;
+  }
+
+  // If the server hasn't quite finished, just delay a little longer.
+  if (incomingServer.serverBusy ||
+      (incomingServer instanceof Ci.nsIPop3IncomingServer &&
+       incomingServer.runningProtocol)) {
+    do_timeout(20, checkBusy);
+    return;
+  }
+
+  testNext();
+}
+
+function testNext() {
+  thisTest = tests.shift();
+
+  // Handle the server in a try/catch/finally loop so that we always will stop
+  // the server if something fails.
+  try {
+    server.resetTest();
+
+    test = thisTest.title;
+    dump("NEXT test: " + thisTest.title + "\n");
+
+    handler.kAuthSchemes = thisTest.serverAuthMethods;
+
+    // Mailnews caches server capabilities, so try to reset it
+    // (alternative would be .pop3CapabilityFlags = 0, but this is safer)
+    deletePop3Server();
+    incomingServer = createPop3Server();
+
+    let msgServer = incomingServer;
+    msgServer.QueryInterface(Ci.nsIMsgIncomingServer);
+    msgServer.authMethod = thisTest.clientAuthMethod;
+
+    pop3Service.GetNewMail(null, urlListener, gLocalInboxFolder,
+                           incomingServer);
+    server.performTest();
+  } catch (e) {
+    server.stop();
+    do_throw(e);
+  }
+}
+
+// <copied from="head_maillocal.js::createPop3ServerAndLocalFolders()">
+function createPop3Server()
+{
+  var incoming = acctMgr.createIncomingServer("fred", "localhost", "pop3");
+  incoming.port = POP3_PORT;
+  incoming.password = "wilma";
+  return incoming;
+}
+//</copied>
+
+function deletePop3Server()
+{
+  if (!incomingServer)
+    return;
+  acctMgr.removeIncomingServer(incomingServer, true);
+  incomingServer = null;
+}
+
+function run_test() {
+  // Disable new mail notifications
+  var prefSvc = Components.classes["@mozilla.org/preferences-service;1"]
+    .getService(Components.interfaces.nsIPrefBranch);
+
+  prefSvc.setBoolPref("mail.biff.play_sound", false);
+  prefSvc.setBoolPref("mail.biff.show_alert", false);
+  prefSvc.setBoolPref("mail.biff.show_tray_icon", false);
+  prefSvc.setBoolPref("mail.biff.animate_dock_icon", false);
+
+  ssd = setupServerDaemon();
+  daemon = ssd[0];
+  server = ssd[1];
+  handler = ssd[2];
+  server.start(POP3_PORT);
+
+  //incomingServer = createPop3ServerAndLocalFolders();
+  loadLocalMailAccount();
+
+  pop3Service = Cc["@mozilla.org/messenger/popservice;1"]
+                      .getService(Ci.nsIPop3Service);
+  acctMgr = Cc["@mozilla.org/messenger/account-manager;1"]
+                  .getService(Ci.nsIMsgAccountManager);
+
+  do_test_pending();
+
+  testNext();
+}
new file mode 100644
--- /dev/null
+++ b/mailnews/local/test/unit/test_pop3GSSAPIFail.js
@@ -0,0 +1,218 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/**
+ * A server offers GSSAPI (Kerberos), but auth fails, due to client or server.
+ *
+ * This mainly tests whether we use the correct login mode.
+ *
+ * Whether it fails due to
+ * - client not set up
+ * - client ticket expired / not logged in
+ * - server not being set up properly
+ * makes no difference to Thunderbird, as that's all hidden in the gssapi-Library
+ * from the OS. So, the server here just returning err is a good approximation
+ * of reality of the above cases.
+ *
+ * Actually, we (more precisely the OS GSSAPI lib) fail out of band
+ * in the Kerberos protocol, before the AUTH GSSAPI command is even issued.
+ *
+ * @author Ben Bucksch
+ */
+
+var server;
+var daemon;
+var handler;
+var incomingServer;
+var pop3Service;
+var acctMgr;
+var thisTest;
+var test = null;
+
+var tests = [
+  { title: "GSSAPI auth, server with GSSAPI only",
+    clientAuthMethod : Ci.nsMsgAuthMethod.GSSAPI,
+    serverAuthMethods : [ "GSSAPI" ],
+    expectSuccess : false,
+    transaction: [ "AUTH", "CAPA" ] },
+    // First GSSAPI step happens and fails out of band, thus no "AUTH GSSAPI"
+  { title: "GSSAPI auth, server with GSSAPI and CRAM-MD5",
+    clientAuthMethod : Ci.nsMsgAuthMethod.GSSAPI,
+    serverAuthMethods : [ "GSSAPI", "CRAM-MD5" ],
+    expectSuccess : false,
+    transaction: [ "AUTH", "CAPA" ] },
+  { title: "Any secure auth, server with GSSAPI only",
+    clientAuthMethod : Ci.nsMsgAuthMethod.secure,
+    serverAuthMethods : [ "GSSAPI" ],
+    expectSuccess : false,
+    transaction: [ "AUTH", "CAPA" ] },
+  { title: "Any secure auth, server with GSSAPI and CRAM-MD5",
+    clientAuthMethod : Ci.nsMsgAuthMethod.secure,
+    serverAuthMethods : [ "GSSAPI", "CRAM-MD5" ],
+    expectSuccess : true,
+    transaction: [ "AUTH", "CAPA", "AUTH CRAM-MD5", "STAT" ] },
+  { title: "Encrypted password, server with GSSAPI and CRAM-MD5",
+    clientAuthMethod : Ci.nsMsgAuthMethod.passwordEncrypted,
+    serverAuthMethods : [ "GSSAPI", "CRAM-MD5" ],
+    expectSuccess : true,
+    transaction: [ "AUTH", "CAPA", "AUTH CRAM-MD5", "STAT" ] },
+];
+
+var urlListener =
+{
+  OnStartRunningUrl: function (url) {
+  },
+  OnStopRunningUrl: function (url, result) {
+    try {
+      if (thisTest.expectSuccess)
+        do_check_eq(result, 0);
+      else
+        do_check_neq(result, 0);
+
+      var transaction = server.playTransaction();
+      do_check_transaction(transaction, thisTest.transaction);
+
+      do_timeout(0, checkBusy);
+    } catch (e) {
+      server.stop();
+      var thread = gThreadManager.currentThread;
+      while (thread.hasPendingEvents())
+        thread.processNextEvent(true);
+
+      do_throw(e);
+    }
+  }
+};
+
+function checkBusy() {
+  if (tests.length == 0) {
+    incomingServer.closeCachedConnections();
+
+    // No more tests, let everything finish
+    server.stop();
+
+    var thread = gThreadManager.currentThread;
+    while (thread.hasPendingEvents())
+      thread.processNextEvent(true);
+
+    do_test_finished();
+    return;
+  }
+
+  // If the server hasn't quite finished, just delay a little longer.
+  if (incomingServer.serverBusy ||
+      (incomingServer instanceof Ci.nsIPop3IncomingServer &&
+       incomingServer.runningProtocol)) {
+    do_timeout(20, checkBusy);
+    return;
+  }
+
+  testNext();
+}
+
+function testNext() {
+  thisTest = tests.shift();
+
+  // Handle the server in a try/catch/finally loop so that we always will stop
+  // the server if something fails.
+  try {
+    server.resetTest();
+
+    test = thisTest.title;
+    dump("NEXT test is: " + thisTest.title + "\n");
+
+    handler.kAuthSchemes = thisTest.serverAuthMethods;
+
+    // Mailnews caches server capabilities, so try to reset it
+    deletePop3Server();
+    incomingServer = createPop3Server();
+
+    let msgServer = incomingServer;
+    msgServer.QueryInterface(Ci.nsIMsgIncomingServer);
+    msgServer.authMethod = thisTest.clientAuthMethod;
+
+    pop3Service.GetNewMail(null, urlListener, gLocalInboxFolder,
+                           incomingServer);
+    server.performTest();
+  } catch (e) {
+    server.stop();
+    do_throw(e);
+  }
+}
+
+// <copied from="head_maillocal.js::createPop3ServerAndLocalFolders()">
+function createPop3Server()
+{
+  var incoming = acctMgr.createIncomingServer("fred", "localhost", "pop3");
+  incoming.port = POP3_PORT;
+  incoming.password = "wilma";
+  return incoming;
+}
+//</copied>
+
+function deletePop3Server()
+{
+  if (!incomingServer)
+    return;
+  acctMgr.removeIncomingServer(incomingServer, true);
+  incomingServer = null;
+}
+
+function GSSAPIFail_handler(daemon)
+{
+  POP3_RFC5034_handler.call(this, daemon);
+}
+GSSAPIFail_handler.prototype = {
+  __proto__ : POP3_RFC5034_handler.prototype, // inherit
+  _needGSSAPI : false,
+  // kAuthSchemes will be set by test
+
+  AUTH: function(restLine)
+  {
+    var scheme = restLine.split(" ")[0];
+    if (scheme == "GSSAPI")
+    {
+      this._multiline = true;
+      this._needGSSAPI = true;
+      return "+";
+    }
+    return POP3_RFC5034_handler.prototype.AUTH.call(this, restLine); // call parent
+  },
+  onMultiline: function(line) {
+    if (this._needGSSAPI) {
+      this._multiline = false;
+      this._needGSSAPI = false;
+      return "-ERR hm.... shall I allow you? hm... NO.";
+    }
+
+    if (POP3_RFC5034_handler.prototype.onMultiline)
+      return POP3_RFC5034_handler.prototype.onMultiline.call(this, line); // call parent
+    return undefined;
+  }
+}
+
+function run_test() {
+  // Disable new mail notifications
+  var prefSvc = Components.classes["@mozilla.org/preferences-service;1"]
+    .getService(Components.interfaces.nsIPrefBranch);
+
+  prefSvc.setBoolPref("mail.biff.play_sound", false);
+  prefSvc.setBoolPref("mail.biff.show_alert", false);
+  prefSvc.setBoolPref("mail.biff.show_tray_icon", false);
+  prefSvc.setBoolPref("mail.biff.animate_dock_icon", false);
+
+  daemon = new pop3Daemon();
+  handler = new GSSAPIFail_handler(daemon);
+  server = new nsMailServer(handler);
+  server.start(POP3_PORT);
+
+  //incomingServer = createPop3ServerAndLocalFolders();
+  loadLocalMailAccount();
+
+  pop3Service = Cc["@mozilla.org/messenger/popservice;1"]
+                      .getService(Ci.nsIPop3Service);
+  acctMgr = Cc["@mozilla.org/messenger/account-manager;1"]
+                  .getService(Ci.nsIMsgAccountManager);
+
+  do_test_pending();
+
+  testNext();
+}
new file mode 100644
--- /dev/null
+++ b/mailnews/local/test/unit/test_pop3ServerBrokenCRAMDisconnect.js
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/**
+ * Server which advertises CRAM-MD5, but is impolite enough to just
+ * disconnect (close the TCP connection) when we try it.
+ *
+ * This is a tough one, because we may lose state on which auth schemes
+ * are allowed and which ones failed and may restart from scratch, and
+ * retry, never skipping the failed scheme.
+ * Dear server implementors, NEVER DO THAT! Be polite, give an error
+ * with explanation and by all means keep the connection open.
+ *
+ * I don't know if real servers do that, but bienvenu says they exist.
+ *
+ * TODO:
+ * This test shows that the current situation is not good.
+ * Problems:
+ * - We should reopen the connection, remember which auth scheme failed
+ *    and start with the next in list, not trying the broken one again.
+ *    We currently neither retry nor remember.
+ * - OnStopRunningUrl() returns success although the server closed the connection
+ *    and it's clearly not successful.
+ * - incomingServer thinks it is still running/busy although the connection is
+ *    clearly done and over.
+ *
+ * @author Ben Bucksch
+ */
+
+var server;
+var daemon;
+var handler;
+var incomingServer;
+var pop3Service;
+const test = "Server which advertises CRAM-MD5, but closes the connection when it's tried";
+// that's how it currently looks like (we fail to log in):
+const expectedTransaction = [ "AUTH", "CAPA", "AUTH CRAM-MD5" ];
+// TODO that's how it should look like (we start a new connection and try another scheme):
+//const expectedTransaction = [ "AUTH", "CAPA", "AUTH CRAM-MD5", "CAPA", "AUTH PLAIN", "STAT" ];
+
+var urlListener =
+{
+  OnStartRunningUrl: function (url) {
+  },
+  OnStopRunningUrl: function (url, result) {
+    try {
+      // TODO we should be getting an error here, if we couldn't log in, but we don't.
+      do_check_eq(result, 0);
+
+      var transaction = server.playTransaction();
+      do_check_transaction(transaction, expectedTransaction);
+
+      do_timeout(0, endTest);
+    } catch (e) {
+      server.stop();
+      var thread = gThreadManager.currentThread;
+      while (thread.hasPendingEvents())
+        thread.processNextEvent(true);
+
+      do_throw(e);
+    }
+  }
+};
+
+function checkBusy() {
+  // If the server hasn't quite finished, just delay a little longer.
+  if (incomingServer.serverBusy ||
+      (incomingServer instanceof Ci.nsIPop3IncomingServer &&
+       incomingServer.runningProtocol)) {
+    do_timeout(20, checkBusy);
+    return;
+  }
+
+  endTest();
+}
+
+function endTest() {
+  incomingServer.closeCachedConnections();
+
+  // No more tests, let everything finish
+  server.stop();
+
+  var thread = gThreadManager.currentThread;
+  while (thread.hasPendingEvents())
+    thread.processNextEvent(true);
+
+  do_test_finished();
+}
+
+function CRAMFail_handler(daemon)
+{
+  POP3_RFC5034_handler.call(this, daemon);
+
+  this._kAuthSchemeStartFunction["CRAM-MD5"] = this.killConn;
+}
+CRAMFail_handler.prototype = {
+  __proto__ : POP3_RFC5034_handler.prototype, // inherit
+
+  killConn : function()
+  {
+     server._readers.forEach(function (reader) {
+        //reader.closeSocket(); doesn't close right away
+        reader._realCloseSocket();
+    });
+    return "-ERR I don't feel like it";
+  }
+}
+
+function run_test() {
+  try {
+    do_test_pending();
+
+    // Disable new mail notifications
+    var prefSvc = Components.classes["@mozilla.org/preferences-service;1"]
+      .getService(Components.interfaces.nsIPrefBranch);
+
+    prefSvc.setBoolPref("mail.biff.play_sound", false);
+    prefSvc.setBoolPref("mail.biff.show_alert", false);
+    prefSvc.setBoolPref("mail.biff.show_tray_icon", false);
+    prefSvc.setBoolPref("mail.biff.animate_dock_icon", false);
+
+    daemon = new pop3Daemon();
+    handler = new CRAMFail_handler(daemon);
+    server = new nsMailServer(handler);
+    server.start(POP3_PORT);
+
+    incomingServer = createPop3ServerAndLocalFolders();
+    let msgServer = incomingServer;
+    msgServer.QueryInterface(Ci.nsIMsgIncomingServer);
+    // Need to allow any auth here, although that's not use in TB really,
+    // because we need to fall back to something after CRAM-MD5 and
+    // check that login works after we fell back.
+    msgServer.authMethod = Ci.nsMsgAuthMethod.anything;
+
+    pop3Service = Cc["@mozilla.org/messenger/popservice;1"]
+                        .getService(Ci.nsIPop3Service);
+    pop3Service.GetNewMail(null, urlListener, gLocalInboxFolder,
+                           incomingServer);
+    server.performTest();
+  } catch (e) {
+    server.stop();
+
+    do_throw(e);
+  } finally {
+    var thread = gThreadManager.currentThread;
+    while (thread.hasPendingEvents())
+      thread.processNextEvent(true);
+  }
+}
new file mode 100644
--- /dev/null
+++ b/mailnews/local/test/unit/test_pop3ServerBrokenCRAMFail.js
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/**
+ * Server which advertises CRAM-MD5, but fails when it's tried.
+ * This reportedly happens for some misconfigured servers.
+ */
+var server;
+var daemon;
+var handler;
+var incomingServer;
+var pop3Service;
+const test = "Server which advertises CRAM-MD5, but fails when it's tried";
+const expectedTransaction = [ "AUTH", "CAPA", "AUTH CRAM-MD5", "AUTH PLAIN", "STAT" ];
+
+var urlListener =
+{
+  OnStartRunningUrl: function (url) {
+  },
+  OnStopRunningUrl: function (url, result) {
+    try {
+      do_check_eq(result, 0);
+
+      var transaction = server.playTransaction();
+      do_check_transaction(transaction, expectedTransaction);
+
+      do_timeout(0, checkBusy);
+    } catch (e) {
+      server.stop();
+      var thread = gThreadManager.currentThread;
+      while (thread.hasPendingEvents())
+        thread.processNextEvent(true);
+
+      do_throw(e);
+    }
+  }
+};
+
+function checkBusy() {
+  // If the server hasn't quite finished, just delay a little longer.
+  if (incomingServer.serverBusy ||
+      (incomingServer instanceof Ci.nsIPop3IncomingServer &&
+       incomingServer.runningProtocol)) {
+    do_timeout(20, checkBusy);
+    return;
+  }
+
+  endTest();
+}
+
+function endTest() {
+  incomingServer.closeCachedConnections();
+
+  // No more tests, let everything finish
+  server.stop();
+
+  var thread = gThreadManager.currentThread;
+  while (thread.hasPendingEvents())
+    thread.processNextEvent(true);
+
+  do_test_finished();
+}
+
+function CRAMFail_handler(daemon)
+{
+  POP3_RFC5034_handler.call(this, daemon);
+
+  this._kAuthSchemeStartFunction["CRAM-MD5"] = this.killConn;
+}
+CRAMFail_handler.prototype = {
+  __proto__ : POP3_RFC5034_handler.prototype, // inherit
+
+  killConn : function()
+  {
+    this._multiline = false;
+    this._state = kStateAuthNeeded;
+    return "-ERR I just pretended to implement CRAM-MD5";
+  }
+}
+
+function run_test() {
+  try {
+    do_test_pending();
+
+    // Disable new mail notifications
+    var prefSvc = Components.classes["@mozilla.org/preferences-service;1"]
+      .getService(Components.interfaces.nsIPrefBranch);
+
+    prefSvc.setBoolPref("mail.biff.play_sound", false);
+    prefSvc.setBoolPref("mail.biff.show_alert", false);
+    prefSvc.setBoolPref("mail.biff.show_tray_icon", false);
+    prefSvc.setBoolPref("mail.biff.animate_dock_icon", false);
+
+    daemon = new pop3Daemon();
+    handler = new CRAMFail_handler(daemon);
+    server = new nsMailServer(handler);
+    server.start(POP3_PORT);
+
+    incomingServer = createPop3ServerAndLocalFolders();
+    let msgServer = incomingServer;
+    msgServer.QueryInterface(Ci.nsIMsgIncomingServer);
+    // Need to allow any auth here, although that's not use in TB really,
+    // because we need to fall back to something after CRAM-MD5 and
+    // check that login works after we fell back.
+    msgServer.authMethod = Ci.nsMsgAuthMethod.anything;
+
+    pop3Service = Cc["@mozilla.org/messenger/popservice;1"]
+                        .getService(Ci.nsIPop3Service);
+    pop3Service.GetNewMail(null, urlListener, gLocalInboxFolder,
+                           incomingServer);
+    server.performTest();
+  } catch (e) {
+    server.stop();
+
+    do_throw(e);
+  } finally {
+    var thread = gThreadManager.currentThread;
+    while (thread.hasPendingEvents())
+      thread.processNextEvent(true);
+  }
+}
--- a/mailnews/mailnews.js
+++ b/mailnews/mailnews.js
@@ -120,17 +120,16 @@ pref("mail.delete_matches_sort_order", f
 // mailnews tcp read+write timeout in seconds.
 pref("mailnews.tcptimeout", 100);
 
 pref("mailnews.headers.showSender", false);
 
 // Mail server preferences, pop by default
 // 0 pop, 1 imap; (Unix only:) 2 movemail, 3 inbox.
 pref("mail.server_type", 0);
-pref("mail.auth_login", true);
 
 pref("mail.default_drafts", "");    // empty string use default Drafts name;
 pref("mail.default_templates", ""); // empty string use default Templates name
 
 // set to 0 if you don't want to ignore timestamp differences between
 // local mail folders and the value stored in the corresponding .msf file.
 // 0 was the default up to and including 1.5. I've made the default
 // be greater than one hour so daylight savings time changes don't affect us.
@@ -226,17 +225,16 @@ pref("mail.html_compose",               
 // this will show up in the address picker in the compose window
 // examples: "X-Face" or "Approved,X-No-Archive"
 pref("mail.compose.other.header", "");
 pref("mail.compose.autosave", true);
 pref("mail.compose.autosaveinterval", 5); // in minutes
 pref("mail.fcc_folder",                     "");
 
 pref("mail.default_html_action", 0);          // 0=ask, 1=plain, 2=html, 3=both
-pref("mail.smtp.ssl", 0);                     // 0 = no, 1 = try, 2 = must use SSL
 
 pref("mail.mdn.report.not_in_to_cc", 2);               // 0: Never 1: Always 2: Ask me
 pref("mail.mdn.report.outside_domain", 2);             // 0: Never 1: Always 2: Ask me
 pref("mail.mdn.report.other", 2);                      // 0: Never 1: Always 2: Ask me 3: Denial
 
 pref("mail.incorporate.return_receipt", 0);            // 0: Inbox/filter 1: Sent folder
 pref("mail.request.return_receipt", 2);                // 1: DSN 2: MDN 3: Both
 pref("mail.receipt.request_header_type", 0);           // 0: MDN-DNT header  1: RRT header 2: Both (MC)
@@ -456,23 +454,22 @@ pref("mail.server.default.offline_suppor
 pref("mail.server.default.leave_on_server", false);
 pref("mail.server.default.download_on_biff", false);
 pref("mail.server.default.check_time", 10);
 pref("mail.server.default.delete_by_age_from_server", false);
 pref("mail.server.default.num_days_to_leave_on_server", 7);
 pref("mail.server.default.dot_fix", true);
 pref("mail.server.default.limit_offline_message_size", false);
 pref("mail.server.default.max_size", 50);
-pref("mail.server.default.auth_login", true);
 pref("mail.server.default.delete_mail_left_on_server", false);
 pref("mail.server.default.valid", true);
 pref("mail.server.default.abbreviate", true);
 pref("mail.server.default.isSecure", false);
-pref("mail.server.default.useSecAuth", false);
-pref("mail.server.default.socketType", 0);
+pref("mail.server.default.authMethod", 3); // cleartext password. @see nsIMsgIncomingServer.authMethod.
+pref("mail.server.default.socketType", 0); // @see nsIMsgIncomingServer.socketType
 pref("mail.server.default.override_namespaces", true);
 pref("mail.server.default.deferred_to_account", "");
 
 pref("mail.server.default.delete_model", 1);
 pref("mail.server.default.fetch_by_chunks", true);
 pref("mail.server.default.mime_parts_on_demand", true);
 
 pref("mail.server.default.always_authenticate", false);
@@ -490,17 +487,16 @@ pref("mail.server.default.hidden", false
 
 pref("mail.server.default.using_subscription", true);
 pref("mail.server.default.dual_use_folders", true);
 pref("mail.server.default.canDelete", false);
 pref("mail.server.default.login_at_startup", false);
 pref("mail.server.default.allows_specialfolders_usage", true);
 pref("mail.server.default.canCreateFolders", true);
 pref("mail.server.default.canFileMessages", true);
-pref("mail.server.default.logon_fallback", true);
 
 // special enhancements for IMAP servers
 pref("mail.server.default.is_gmail", false);
 pref("mail.server.default.use_idle", true);
 // in case client or server has bugs in condstore implementation
 pref("mail.server.default.use_condstore", true);
 // in case client or server has bugs in compress implementation
 pref("mail.server.default.use_compress_deflate", true);
@@ -561,20 +557,18 @@ pref("mail.autoComplete.highlightNonMatc
 // if true, we'll use the password from an incoming server with
 // matching username and domain
 pref("mail.smtp.useMatchingDomainServer", false);
 
 // if true, we'll use the password from an incoming server with
 // matching username and host name
 pref("mail.smtp.useMatchingHostNameServer", false);
 
-pref("mail.smtpserver.default.auth_method", 1); // auth any
-pref("mail.smtpserver.default.useSecAuth", false);
-pref("mail.smtpserver.default.trySecAuth", true);
-pref("mail.smtpserver.default.try_ssl", 0);
+pref("mail.smtpserver.default.authMethod", 3); // cleartext password. @see nsIMsgIncomingServer.authMethod.
+pref("mail.smtpserver.default.try_ssl", 0); // @see nsISmtpServer.socketType
 
 // For the next 3 prefs, see <http://www.bucksch.org/1/projects/mozilla/16507>
 pref("mail.display_glyph", true);   // TXT->HTML :-) etc. in viewer
 pref("mail.display_struct", true);  // TXT->HTML *bold* etc. in viewer; ditto
 pref("mail.send_struct", false);   // HTML->HTML *bold* etc. during Send; ditto
 // display time and date in message pane using senders timezone
 pref("mailnews.display.date_senders_timezone", false);
 // For the next 4 prefs, see <http://www.bucksch.org/1/projects/mozilla/108153>
--- a/mailnews/mapi/mapihook/src/msgMapiMain.cpp
+++ b/mailnews/mapi/mapihook/src/msgMapiMain.cpp
@@ -256,17 +256,23 @@ HRESULT nsMAPIConfiguration::GetMAPIErro
   switch (res)
   {
     case NS_MSG_NO_RECIPIENTS :
       hr = MAPI_E_BAD_RECIPTYPE;
       break;
     case NS_ERROR_COULD_NOT_GET_USERS_MAIL_ADDRESS :
       hr = MAPI_E_INVALID_RECIPS;
       break;
-    case NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER :
+    case NS_ERROR_SMTP_AUTH_FAILURE :
+    case NS_ERROR_SMTP_AUTH_GSSAPI :
+    case NS_ERROR_SMTP_AUTH_MECH_NOT_SUPPORTED :
+    case NS_ERROR_SMTP_AUTH_NOT_SUPPORTED :
+    case NS_ERROR_SMTP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_NO_SSL :
+    case NS_ERROR_SMTP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_SSL :
+    case NS_ERROR_SMTP_AUTH_CHANGE_PLAIN_TO_ENCRYPT :
       hr = MAPI_E_LOGIN_FAILURE;
       break;
     case NS_MSG_UNABLE_TO_OPEN_FILE :
     case NS_MSG_UNABLE_TO_OPEN_TMP_FILE :
     case NS_MSG_COULDNT_OPEN_FCC_FOLDER :
     case NS_ERROR_FILE_INVALID_PATH :
       hr = MAPI_E_ATTACHMENT_OPEN_FAILURE;
       break;
--- a/mailnews/news/src/nsNNTPProtocol.cpp
+++ b/mailnews/news/src/nsNNTPProtocol.cpp
@@ -425,17 +425,17 @@ NS_IMETHODIMP nsNNTPProtocol::Initialize
 
   PRInt32 port = 0;
   rv = m_url->GetPort(&port);
   if (NS_FAILED(rv) || (port<=0)) {
     rv = server->GetPort(&port);
     if (NS_FAILED(rv)) return rv;
 
     if (port<=0) {
-      port = (socketType == nsIMsgIncomingServer::useSSL) ?
+      port = (socketType == nsMsgSocketType::SSL) ?
              nsINntpUrl::DEFAULT_NNTPS_PORT : nsINntpUrl::DEFAULT_NNTP_PORT;
     }
 
     rv = m_url->SetPort(port);
     if (NS_FAILED(rv)) return rv;
   }
 
   NS_PRECONDITION(m_url , "invalid URL passed into NNTP Protocol");
@@ -495,17 +495,17 @@ NS_IMETHODIMP nsNNTPProtocol::Initialize
   }
 
   if (!m_socketIsOpen)
   {
     // When we are making a secure connection, we need to make sure that we
     // pass an interface requestor down to the socket transport so that PSM can
     // retrieve a nsIPrompt instance if needed.
     nsCOMPtr<nsIInterfaceRequestor> ir;
-    if (socketType != nsIMsgIncomingServer::defaultSocket && aMsgWindow)
+    if (socketType != nsMsgSocketType::plain && aMsgWindow)
     {
       nsCOMPtr<nsIDocShell> docShell;
       aMsgWindow->GetRootDocShell(getter_AddRefs(docShell));
       ir = do_QueryInterface(docShell);
     }
 
     PR_LOG(NNTP,PR_LOG_ALWAYS,("(%p) opening connection to %s on port %d",this, hostName.get(), port));
     // call base class to set up the transport
@@ -517,17 +517,17 @@ NS_IMETHODIMP nsNNTPProtocol::Initialize
     rv = server->GetRealHostName(hostName);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIProxyInfo> proxyInfo;
     rv = NS_ExamineForProxy("nntp", hostName.get(), port, getter_AddRefs(proxyInfo));
     if (NS_FAILED(rv)) proxyInfo = nsnull;
 
     rv = OpenNetworkSocketWithInfo(hostName.get(), port,
-           (socketType == nsIMsgIncomingServer::useSSL) ? "ssl" : nsnull,
+           (socketType == nsMsgSocketType::SSL) ? "ssl" : nsnull,
            proxyInfo, ir);
 
     NS_ENSURE_SUCCESS(rv,rv);
     m_nextState = NNTP_LOGIN_RESPONSE;
   }
   else {
     m_nextState = SEND_FIRST_NNTP_COMMAND;
   }
--- a/mailnews/news/src/nsNewsFolder.cpp
+++ b/mailnews/news/src/nsNewsFolder.cpp
@@ -463,17 +463,17 @@ NS_IMETHODIMP nsMsgNewsFolder::GetFolder
 
   PRInt32 socketType;
   rv = server->GetSocketType(&socketType);
   NS_ENSURE_SUCCESS(rv, rv);
 
   PRInt32 port;
   rv = server->GetPort(&port);
   NS_ENSURE_SUCCESS(rv, rv);
-  const char *newsScheme = (socketType == nsIMsgIncomingServer::useSSL) ?
+  const char *newsScheme = (socketType == nsMsgSocketType::SSL) ?
                            SNEWS_SCHEME : NEWS_SCHEME;
   nsCString escapedName;
   rv = NS_MsgEscapeEncodeURLPath(groupName, escapedName);
   NS_ENSURE_SUCCESS(rv, rv);
   nsCString tmpStr;
   tmpStr.Adopt(PR_smprintf("%s//%s:%ld/%s", newsScheme, hostName.get(), port,
                            escapedName.get()));
   aUrl.Assign(tmpStr);
@@ -1128,17 +1128,17 @@ nsresult nsMsgNewsFolder::CreateNewsgrou
 
     PRInt32 socketType;
     nsresult rv = server->GetSocketType(&socketType);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Only set this for ssl newsgroups as for non-ssl connections, we don't
     // need to specify the port as it is the default for the protocol and
     // password manager "blanks" those out.
-    if (socketType == nsIMsgIncomingServer::useSSL)
+    if (socketType == nsMsgSocketType::SSL)
     {
       rv = url->SetPort(nsINntpUrl::DEFAULT_NNTPS_PORT);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   if (ref)
   {
--- a/mailnews/news/src/nsNntpIncomingServer.cpp
+++ b/mailnews/news/src/nsNntpIncomingServer.cpp
@@ -2086,32 +2086,32 @@ nsNntpIncomingServer::GetSocketType(PRIn
 
   nsresult rv = mPrefBranch->GetIntPref("socketType", aSocketType);
   if (NS_FAILED(rv))
   {
     if (!mDefPrefBranch)
       return NS_ERROR_NOT_INITIALIZED;
     rv = mDefPrefBranch->GetIntPref("socketType", aSocketType);
     if (NS_FAILED(rv))
-      *aSocketType = nsIMsgIncomingServer::defaultSocket;
+      *aSocketType = nsMsgSocketType::plain;
   }
 
   // nsMsgIncomingServer::GetSocketType migrates old isSecure to socketType
   // style for mail. Unfortunately, a bug caused news socketType 0 to be stored
   // in the prefs even for isSecure true, so the migration wouldn't happen :(
 
   // Now that we know the socket, make sure isSecure true + socketType 0
   // doesn't mix. Migrate if that's the case here.
-  if (*aSocketType == nsIMsgIncomingServer::defaultSocket)
+  if (*aSocketType == nsMsgSocketType::plain)
   {
     PRBool isSecure = PR_FALSE;
     nsresult rv2 = mPrefBranch->GetBoolPref("isSecure", &isSecure);
     if (NS_SUCCEEDED(rv2) && isSecure)
     {
-      *aSocketType = nsIMsgIncomingServer::useSSL;
+      *aSocketType = nsMsgSocketType::SSL;
       // Don't call virtual method in case overrides call GetSocketType.
       nsMsgIncomingServer::SetSocketType(*aSocketType);
     }
   }
   return rv;
 }
 
 NS_IMETHODIMP
@@ -2122,17 +2122,17 @@ nsNntpIncomingServer::SetSocketType(PRIn
   nsresult rv = nsMsgIncomingServer::SetSocketType(aSocketType);
   if (NS_SUCCEEDED(rv))
   {
     PRBool isSecure = PR_FALSE;
     if (NS_SUCCEEDED(mPrefBranch->GetBoolPref("isSecure", &isSecure)))
     {
       // Must keep isSecure in sync since we migrate based on it... if it's set.
       rv = mPrefBranch->SetBoolPref("isSecure",
-                                    aSocketType == nsIMsgIncomingServer::useSSL);
+                                    aSocketType == nsMsgSocketType::SSL);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
   return rv;
 }
 
 NS_IMETHODIMP
 nsNntpIncomingServer::OnUserOrHostNameChanged(const nsACString& oldName, const nsACString& newName)
--- a/mailnews/news/src/nsNntpService.cpp
+++ b/mailnews/news/src/nsNntpService.cpp
@@ -302,17 +302,17 @@ nsNntpService::DisplayMessage(const char
     {
       rv = server->GetPort(&port);
       if (NS_FAILED(rv) || (port <= 0))
       {
         PRInt32 socketType;
         rv = server->GetSocketType(&socketType);
         NS_ENSURE_SUCCESS(rv, rv);
 
-        port = (socketType == nsIMsgIncomingServer::useSSL) ?
+        port = (socketType == nsMsgSocketType::SSL) ?
                nsINntpUrl::DEFAULT_NNTPS_PORT : nsINntpUrl::DEFAULT_NNTP_PORT;
       }
 
       rv = url->SetPort(port);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
     folder->ShouldStoreMsgOffline(key, &shouldStoreMsgOffline);
@@ -1058,17 +1058,17 @@ nsNntpService::CreateNewsAccount(const c
   if (NS_FAILED(rv)) return rv;
 
   // for news, username is always null
   rv = accountManager->CreateIncomingServer(EmptyCString(), nsDependentCString(aHostname), NS_LITERAL_CSTRING("nntp"), aServer);
   if (NS_FAILED(rv)) return rv;
 
   if (aUseSSL)
   {
-    rv = (*aServer)->SetSocketType(nsIMsgIncomingServer::useSSL);
+    rv = (*aServer)->SetSocketType(nsMsgSocketType::SSL);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   rv = (*aServer)->SetPort(aPort);
   if (NS_FAILED(rv)) return rv;
 
   nsCOMPtr <nsIMsgIdentity> identity;
   rv = accountManager->CreateIdentity(getter_AddRefs(identity));
@@ -1602,17 +1602,17 @@ nsNntpService::StreamMessage(const char 
         nsCOMPtr<nsIMsgIncomingServer> server;
         rv = folder->GetServer(getter_AddRefs(server));
         NS_ENSURE_SUCCESS(rv, rv);
 
         PRInt32 socketType;
         rv = server->GetSocketType(&socketType);
         NS_ENSURE_SUCCESS(rv, rv);
 
-        url->SetPort((socketType == nsIMsgIncomingServer::useSSL) ?
+        url->SetPort((socketType == nsMsgSocketType::SSL) ?
                      nsINntpUrl::DEFAULT_NNTPS_PORT : nsINntpUrl::DEFAULT_NNTP_PORT);
 
         rv = IsMsgInMemCache(url, folder, nsnull, &hasMsgOffline);
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
       // Return with an error if we didn't find it in the memory cache either
       if (!hasMsgOffline)
--- a/suite/common/src/nsSuiteGlue.js
+++ b/suite/common/src/nsSuiteGlue.js
@@ -38,16 +38,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 Components.utils.import("resource://app/modules/Sanitizer.jsm");
+Components.utils.import("resource://app/modules/migration.jsm");
 
 // Constructor
 
 function SuiteGlue() {
   this._init();
 }
 
 SuiteGlue.prototype = {
@@ -153,16 +154,17 @@ SuiteGlue.prototype = {
     osvr.removeObserver(this, "session-save");
     osvr.removeObserver(this, "dl-done");
   },
 
   // profile startup handler (contains profile initialization routines)
   _onProfileStartup: function()
   {
     this._updatePrefs();
+    migrateMailnews(); // migration.jsm
 
     Sanitizer.checkAndSanitize();
 
     const prefSvc = Components.classes["@mozilla.org/preferences-service;1"]
                               .getService(Components.interfaces.nsIPrefBranch2);
     if (prefSvc.prefHasUserValue("privacy.sanitize.didShutdownSanitize")) {
       prefSvc.clearUserPref("privacy.sanitize.didShutdownSanitize");
       // We need to persist this preference change, since we want to
--- a/suite/locales/en-US/chrome/mailnews/compose/composeMsgs.properties
+++ b/suite/locales/en-US/chrome/mailnews/compose/composeMsgs.properties
@@ -203,31 +203,31 @@ 12570=There was an error attaching %S. P
 12571=There was an error copying the message to the Sent folder. Retry?
 
 ## @name NS_ERROR_SMTP_GREETING
 12572=An error occurred sending mail: The mail server sent an incorrect greeting:  %s.
 
 ## @name NS_ERROR_SENDING_RCPT_COMMAND
 12575=An error occurred while sending mail. The mail server responded:  %1$s. Please check the message recipient %2$s and try again.
 
-## @name NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER_INSECAUTH
-12579=An error occurred sending mail: Unable to authenticate to SMTP server %S. The server does not support any compatible insecure authentication mechanism but you have chosen insecure authentication. Try switching on secure authentication or contact your service provider.
+## @name NS_ERROR_SMTP_AUTH_FAILURE
+12576=Unable to authenticate to SMTP server %S. Please check the password, and verify the 'Authentication method' in 'Account Settings | Outgoing server (SMTP)'.
+
+## @name NS_ERROR_SMTP_AUTH_GSSAPI
+12579=The Kerberos/GSSAPI ticket was not accepted by the SMTP server %S. Please check that you are logged in to the Kerberos/GSSAPI realm.
 
-## @name NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER_SECAUTH
-12580=An error occurred sending mail: Unable to authenticate to SMTP server %S. The server does not support any compatible secure authentication mechanism but you have chosen secure authentication. Try switching off secure authentication or contact your service provider.
+## @name NS_ERROR_SMTP_AUTH_MECH_NOT_SUPPORTED
+12580=The SMTP server %S does not support the selected authentication method. Please change the 'Authentication method' in the 'Account Settings | Outgoing Server (SMTP)'.
 
-## @name NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER_AUTH_NONE
-12581=An error occurred sending mail: Unable to authenticate to SMTP server %S. It does not support authentication (SMTP-AUTH) but you have chosen to use authentication. Uncheck 'Use name and password' for that server or contact your service provider.
+## @name NS_ERROR_SMTP_AUTH_NOT_SUPPORTED
+12581=Unable to authenticate to SMTP server %S. It does not support authentication (SMTP-AUTH) but you have chosen to use authentication. Please change the 'Authentication method' to 'None' in the 'Account Settings | Outgoing Server (SMTP)' or contact your email service provider for instructions.
 
 ## @name NS_ERROR_STARTTLS_FAILED_EHLO_STARTTLS
 12582=An error occurred sending mail: Unable to establish a secure link with SMTP server %S using STARTTLS since it doesn't advertise that feature. Switch off STARTTLS for that server or contact your service provider.
 
-## @name NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER
-12583=An error occurred sending mail: Unable to log in to SMTP server %S. The server may be incorrectly configured. Please verify that your SMTP server settings are correct and try again.
-
 ## @name NS_ERROR_SMTP_PASSWORD_UNDEFINED
 12584=An error occurred sending mail: Could not get password for %S. The message was not sent.
 
 ## @name NS_ERROR_SMTP_TEMP_SIZE_EXCEEDED
 12586=The size of the message you are trying to send exceeds a temporary size limit of the server. The message was not sent; try to reduce the message size or wait some time and try again. The server responded:  %s.
 
 ## @name NS_ERROR_SMTP_PERM_SIZE_EXCEEDED_1
 12587=The size of the message you are trying to send exceeds the global size limit (%d bytes) of the server. The message was not sent; reduce the message size and try again.
@@ -245,16 +245,26 @@ 12590=The message could not be sent beca
 12591=The message could not be sent because the connection to SMTP server %S was lost in the middle of the transaction. Try again or contact your network administrator.
 
 ## @name NS_ERROR_SMTP_SEND_FAILED_TIMEOUT
 12592=The message could not be sent because the connection to SMTP server %S timed out. Try again or contact your network administrator.
 
 ## @name NS_ERROR_SMTP_SEND_FAILED_UNKNOWN_REASON
 12593=The message could not be sent using SMTP server %S for an unknown reason. Please verify that your SMTP server settings are correct and try again, or contact your network administrator.
 
+## @name NS_ERROR_SMTP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_NO_SSL
+12594=The SMTP server %S does not seem to support encrypted passwords. If you just set up the account, please try changing to 'Password, transmitted insecurely' as the 'Authentication method' in the 'Account Settings | Server settings'. If it used to work and now suddenly fails, this is a common scenario how someone could steal your password.
+
+## @name NS_ERROR_SMTP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_SSL
+12595=The SMTP server %S does not seem to support encrypted passwords. If you just set up this account, please try changing to 'Normal password' as the 'Authentication method' in the 'Account Settings | Server settings'. If it used to work and now suddenly fails, please contact your email administrator or provider.
+
+## @name NS_ERROR_SMTP_AUTH_CHANGE_PLAIN_TO_ENCRYPT
+12596=The SMTP server %S does not allow plaintext passwords. Please try changing to 'Encrypted password' as the 'Authentication method' in the 'Account Settings | Server settings'.
+
+
 ## Strings use for the save message dialog shown when the user close a message compose window
 saveDlogTitle=Save Message
 saveDlogMessage=Message has not been sent. Do you want to save the message in the Drafts folder?
 
 ## generics string
 defaultSubject=(no subject)
 chooseFileToAttach=Attach File(s)
 
--- a/suite/locales/en-US/chrome/mailnews/imapMsgs.properties
+++ b/suite/locales/en-US/chrome/mailnews/imapMsgs.properties
@@ -119,17 +119,17 @@ 5012=Checking mail server capabilitiesâ€
 # Status - logging on
 ## @name IMAP_STATUS_SENDING_LOGIN
 ## @loc None
 5013=Sending login information…
 
 # Status - auth logon
 ## @name IMAP_STATUS_SENDING_AUTH_LOGIN
 ## @loc None
-5014=Sending secure login information…
+5014=Sending login information…
 
 ## @name IMAP_DOWNLOADING_MESSAGE
 ## @loc None
 5015=Downloading message…
 
 ## @name IMAP_GETTING_ACL_FOR_FOLDER
 ## @loc None
 # LOCALIZATION NOTE (Error 5029): Do not translate the word "ACL" below.
@@ -360,28 +360,39 @@ 5096=This server does not support quotas
 ## @loc None
 5097=There are no storage quotas on this folder.
 
 # Out of memory
 ## @name IMAP_OUT_OF_MEMORY
 ## @loc None
 5100=Application is out of memory.
 
-## @name IMAP_AUTH_SECURE_NOTSUPPORTED
+## @name IMAP_AUTH_MECH_NOT_SUPPORTED
 ## @loc None
-5102=You cannot log in to %S because you have enabled secure authentication and this server does not support it.\n\nTo log in, turn off secure authentication for this account.
+# LOCALIZATION NOTE (5101): %S is the server hostname
+5101=The IMAP server %S does not support the selected authentication method. Please change the 'Authentication method' in the 'Account Settings | Server settings'.
+
+## @name IMAP_AUTH_MECH_FAILED
+## @loc None
+# LOCALIZATION NOTE (5102): %S is the server hostname
+5102=All login mechanisms for %S failed. Please check the password or change the 'Authentication method' in the 'Account Settings | Server settings'.
 
 ## @name IMAP_COPYING_MESSAGE_OF
 ## @loc None
 # LOCALIZATION NOTE (Error 5103): Do not translate the word "%S" below.
 # Place the word %3$S in your translation where the name of the destination folder should appear.
 # Place the word %1$S where the currently copying message should appear.
 # Place the word %2$S where the total number of messages should appear.
 5103=Copying Message %1$S of %2$S to %3$S
 
+## @name IMAP_AUTH_GSSAPI_FAILED
+## @loc None
+# LOCALIZATION NOTE (5104): %S is the server hostname
+5104=The Kerberos/GSSAPI ticket was not accepted by the IMAP server %S. Please check that you are logged in to the Kerberos/GSSAPI realm.
+
 ## @name IMAP_MOVE_FOLDER_TO_TRASH
 ## @loc None
 # LOCALIZATION NOTE (5105): Do not translate the word %S below.
 # "%S" is the name of the folder.
 5105=Are you sure you want to delete the folder '%S'?
 
 ## @name IMAP_DELETE_NO_TRASH
 ## @loc None
@@ -392,12 +403,22 @@ 5106=Deleting this folder is not undoabl
 ## @name IMAP_DELETE_FOLDER_DIALOG_TITLE
 ## @loc None
 5107=Delete Folder
 
 ## @name IMAP_DELETE_FOLDER_BUTTON_LABEL
 ## @loc None
 5108=&Delete Folder
 
-## @name IMAP_LOGIN_DISABLED
+## @name IMAP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_NO_SSL
+## @loc None
+# LOCALIZATION NOTE (5109): %S is the server hostname
+5109=The IMAP server %S does not seem to support encrypted passwords. If you just set up the account, please try changing to 'Password, transmitted insecurely' as the 'Authentication method' in the 'Account Settings | Server settings'. If it used to work and now suddenly fails, this is a common scenario how someone could steal your password.
+
+## @name IMAP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_SSL
 ## @loc None
-# LOCALIZATION NOTE (5109): %S is the server address
-5109=You cannot log in to %S because the server doesn't allow plaintext authentication without STARTTLS or SSL/TLS. Try enabling connection security or secure authentication in the account settings.
+# LOCALIZATION NOTE (5110): %S is the server hostname
+5110=The IMAP server %S does not seem to support encrypted passwords. If you just set up this account, please try changing to 'Normal password' as the 'Authentication method' in the 'Account Settings | Server settings'. If it used to work and now suddenly fails, please contact your email administrator or provider.
+
+## @name IMAP_AUTH_CHANGE_PLAIN_TO_ENCRYPT
+## @loc None
+# LOCALIZATION NOTE (5111): %S is the server hostname
+5111=The IMAP server %S does not allow plaintext passwords. Please try changing to 'Encrypted password' as the 'Authentication method' in the 'Account Settings | Server settings'.
--- a/suite/locales/en-US/chrome/mailnews/localMsgs.properties
+++ b/suite/locales/en-US/chrome/mailnews/localMsgs.properties
@@ -160,20 +160,25 @@ 4025= Mail server %S responded:
 ## @name COPYING_MSGS_STATUS
 ## @loc None
 4027=Copying %S of %S messages to %S
 
 ## @name MOVING_MSGS_STATUS
 ## @loc None
 4028=Moving %S of %S messages to %S
 
-# secure authentication failed
-## @name CANNOT_PROCESS_SECURE_AUTH
+# Authentication server caps and pref don't match
+## @name POP3_AUTH_MECH_NOT_SUPPORTED
 ## @loc None
-4030=Mail server does not support secure authentication.
+4030=The server does not support the selected authentication method. Please change the Authentication method in the Account Settings.
+
+# Status - Could not log in to GSSAPI, and it was the only method
+## @name POP3_GSSAPI_FAILURE
+## @loc None
+4031=The Kerberos/GSSAPI ticket was not accepted by the POP server. Please check that you are logged in to the Kerberos/GSSAPI realm.
 
 ## @name MOVEMAIL_CANT_OPEN_SPOOL_FILE
 ## @loc None
 4033=Unable to open mail spool file %S.
 
 ## @name MOVEMAIL_CANT_CREATE_LOCK
 ## @loc None
 4034=Unable to create lock file %S. For movemail to work, it is necessary to create lock files in the mail spool directory. On many systems, this is best accomplished by making the spool directory be mode 01777.
@@ -207,21 +212,16 @@ 4040=The POP3 mail server (%S) does not 
 ## @name POP3_SERVER_DOES_NOT_SUPPORT_THE_TOP_COMMAND
 ## @loc None
 # LOCALIZATION NOTE(4011): The following sentence should be translated in this way:
 # Do not translate "POP3"
 # Do not translate "%S". Place %S in your translation where the name of the server should appear.
 # Do not translate "TOP"
 4041=The POP3 mail server (%S) does not support the TOP command. Without server support for this, we cannot implement the ``Maximum Message Size'' or ``Fetch Headers Only'' preference.  This option has been disabled, and messages will be downloaded regardless of their size.
 
-# secure authentication failed and unsure why
-## @name CANNOT_PROCESS_APOP_AUTH
-## @loc None
-4042=The mail server does not support secure authentication or you have entered an incorrect password. Please check your password, or turn off secure authentication in the Server Settings for your mail server in the Account Settings window.\n
-
 ## @name NS_ERROR_COULD_NOT_CONNECT_VIA_TLS
 ## @loc None
 4043=Unable to establish TLS connection to POP3 server. The server may be down or may be incorrectly configured. Please verify the correct configuration in the Server Settings for your mail server in the Account Settings window and try again.
 
 ## @name POP3_MOVE_FOLDER_TO_TRASH
 ## @loc None
 # LOCALIZATION NOTE (4044): Do not translate the word %S below.
 # "%S" is the name of the folder.
@@ -229,8 +229,24 @@ 4044=Are you sure you want to delete the
 
 ## @name POP3_DELETE_FOLDER_DIALOG_TITLE
 ## @loc None
 4045=Delete Folder
 
 ## @name POP3_DELETE_FOLDER_BUTTON_LABEL
 ## @loc None
 4046=&Delete Folder
+
+## @name POP3_AUTH_INTERNAL_ERROR
+## @loc None
+4047=Internal state error during POP3 server authentication. This is an internal, unexpected error in the application, please report it as bug.
+
+## @name POP3_AUTH_CHANGE_ENCRYPT_TO_PLAIN_NO_SSL
+## @loc None
+4048=This POP3 server does not seem to support encrypted passwords. If you just set up the account, please try changing to 'Password, transmitted insecurely' as the 'Authentication method' in the 'Account Settings | Server settings'. If it used to work and now suddenly fails, this is a common scenario how someone could steal your password.
+
+## @name POP3_AUTH_CHANGE_ENCRYPT_TO_PLAIN_SSL
+## @loc None
+4049=This POP3 server does not seem to support encrypted passwords. If you just set up this account, please try changing to 'Normal password' as the 'Authentication method' in the 'Account Settings | Server settings'. If it used to work and now suddenly fails, please contact your email administrator or provider.
+
+## @name POP3_AUTH_CHANGE_PLAIN_TO_ENCRYPT
+## @loc None
+4050=This POP3 server does not allow plaintext passwords. Please try changing to 'Encrypted password' as the 'Authentication method' in the 'Account Settings | Server settings'.
--- a/suite/locales/en-US/chrome/mailnews/messenger.properties
+++ b/suite/locales/en-US/chrome/mailnews/messenger.properties
@@ -132,16 +132,27 @@ smtpServer-ConnectionSecurityType-0=None
 smtpServer-ConnectionSecurityType-1=STARTTLS, if available
 smtpServer-ConnectionSecurityType-2=STARTTLS
 smtpServer-ConnectionSecurityType-3=SSL/TLS
 smtpServer-SecureAuthentication-Type-false=No
 smtpServer-SecureAuthentication-Type-true=Yes
 smtpServers-confirmServerDeletionTitle=Delete Server
 smtpServers-confirmServerDeletion=Are you sure you want to delete the server: \n %S?
 
+# Account Settings - Both Incoming and SMTP server
+authNo=No authentication
+authOld=Password, original method (insecure)
+authPasswordCleartextInsecurely=Password, transmitted insecurely
+authPasswordCleartextViaSSL=Normal password
+authPasswordEncrypted=Encrypted password
+authKerberos=Kerberos / GSSAPI
+authNTLM=NTLM
+authAnySecure=Any secure method (deprecated)
+authAny=Any method (insecure)
+
 # LOCALIZATION NOTE(serverType-nntp): Do not translate "NNTP" in the line below
 serverType-nntp=News Server (NNTP)
 # LOCALIZATION NOTE(serverType-pop3): Do not translate "POP" in the line below
 serverType-pop3=POP Mail Server
 # LOCALIZATION NOTE(serverType-imap): Do not translate "IMAP" in the line below
 serverType-imap=IMAP Mail Server
 serverType-none=Local Mail Store
 # LOCALIZATION NOTE(serverType-movemail): DONT_TRANSLATE
--- a/suite/locales/en-US/chrome/mailnews/pref/am-advanced.dtd
+++ b/suite/locales/en-US/chrome/mailnews/pref/am-advanced.dtd
@@ -12,9 +12,9 @@
 <!ENTITY smtpListSetDefault.label "Set Default">
 <!ENTITY smtpListSetDefault.accesskey "t">
 
 <!ENTITY serverDescription.label "Description: ">
 <!ENTITY serverName.label "Server Name: ">
 <!ENTITY serverPort.label "Port: ">
 <!ENTITY userName.label   "User Name: ">
 <!ENTITY connectionSecurity.label "Connection Security: ">
-<!ENTITY useSecureAuthentication.label   "Secure Authentication: ">
+<!ENTITY authMethod.label   "Authentication method: ">
--- a/suite/locales/en-US/chrome/mailnews/pref/am-server-top.dtd
+++ b/suite/locales/en-US/chrome/mailnews/pref/am-server-top.dtd
@@ -19,18 +19,18 @@
 <!ENTITY biffStart.accesskey "y">
 <!ENTITY biffEnd.label "minutes">
 <!ENTITY connectionSecurity.label "Connection security:">
 <!ENTITY connectionSecurity.accesskey "u">
 <!ENTITY connectionSecurityType-0.label "None">
 <!ENTITY connectionSecurityType-1.label "STARTTLS, if available">
 <!ENTITY connectionSecurityType-2.label "STARTTLS">
 <!ENTITY connectionSecurityType-3.label "SSL/TLS">
-<!ENTITY useSecAuth.label "Use secure authentication">
-<!ENTITY useSecAuth.accesskey "i">
+<!ENTITY authMethod.label "Authentication method:">
+<!ENTITY authMethod.accesskey "i">
 <!ENTITY leaveOnServer.label "Leave messages on server">
 <!ENTITY leaveOnServer.accesskey "g">
 <!ENTITY headersOnly.label "Fetch headers only">
 <!ENTITY headersOnly.accesskey "e">
 <!ENTITY deleteByAgeFromServer.label "For at most">
 <!ENTITY deleteByAgeFromServer.accesskey "o">
 <!ENTITY daysEnd.label "days">
 <!ENTITY deleteOnServer2.label "Until I delete them">
--- a/suite/locales/en-US/chrome/mailnews/pref/smtpEditOverlay.dtd
+++ b/suite/locales/en-US/chrome/mailnews/pref/smtpEditOverlay.dtd
@@ -1,22 +1,20 @@
 <!ENTITY settings.caption "Settings">
 <!ENTITY security.caption "Security and Authentication">
 <!ENTITY serverName.label "Server Name:">
 <!ENTITY serverName.accesskey "S">
 <!ENTITY serverDescription.label "Description:">
 <!ENTITY serverDescription.accesskey "D">
 <!ENTITY serverPort.label "Port:">
 <!ENTITY serverPort.accesskey "P">
-<!ENTITY alwaysUseUsername.label "Use name and password">
-<!ENTITY alwaysUseUsername.accesskey "U">
 <!ENTITY userName.label "User Name:">
 <!ENTITY userName.accesskey "m">
-<!ENTITY useSecAuth.label "Use secure authentication">
-<!ENTITY useSecAuth.accesskey "i">
 <!ENTITY connectionSecurity.label "Connection security:">
 <!ENTITY connectionSecurity.accesskey "n">
 <!ENTITY connectionSecurityType-0.label "None">
 <!ENTITY connectionSecurityType-1.label "STARTTLS, if available">
 <!ENTITY connectionSecurityType-2.label "STARTTLS">
 <!ENTITY connectionSecurityType-3.label "SSL/TLS">
 <!ENTITY smtpEditTitle.label "SMTP Server">
 <!ENTITY serverPortDefault.label "Default:">
+<!ENTITY authMethod.label "Authentication method:">
+<!ENTITY authMethod.accesskey "i">