backend work for auto config verify logon, r=standard8, sr=neil, 422814
authorDavid Bienvenu <bienvenu@nventure.com>
Wed, 10 Sep 2008 14:23:15 -0700
changeset 310 77d59259d30251b0d6021348fec6a7607b1f2471
parent 309 5dcdfc0e376b5be6e1e082a354f977dcb91e80e7
child 311 572833185ccf2ca6f7d063ebe5e822333bd8d907
push idunknown
push userunknown
push dateunknown
reviewersstandard8, neil, 422814
bugs422814
backend work for auto config verify logon, r=standard8, sr=neil, 422814
mailnews/base/public/nsIMsgAccountManager.idl
mailnews/base/public/nsIMsgIncomingServer.idl
mailnews/base/src/nsMsgAccountManager.cpp
mailnews/base/src/nsMsgAccountManager.h
mailnews/base/util/nsMsgIncomingServer.cpp
mailnews/base/util/nsMsgMailNewsUrl.cpp
mailnews/compose/public/nsISmtpServer.idl
mailnews/compose/public/nsISmtpService.idl
mailnews/compose/public/nsISmtpUrl.idl
mailnews/compose/src/nsSmtpProtocol.cpp
mailnews/compose/src/nsSmtpProtocol.h
mailnews/compose/src/nsSmtpServer.cpp
mailnews/compose/src/nsSmtpService.cpp
mailnews/compose/src/nsSmtpUrl.cpp
mailnews/compose/src/nsSmtpUrl.h
mailnews/imap/public/nsIImapService.idl
mailnews/imap/public/nsIImapUrl.idl
mailnews/imap/src/nsImapIncomingServer.cpp
mailnews/imap/src/nsImapIncomingServer.h
mailnews/imap/src/nsImapProtocol.cpp
mailnews/imap/src/nsImapService.cpp
mailnews/imap/src/nsImapUrl.cpp
mailnews/local/public/nsIPop3Service.idl
mailnews/local/src/nsPop3IncomingServer.cpp
mailnews/local/src/nsPop3IncomingServer.h
mailnews/local/src/nsPop3Protocol.cpp
mailnews/local/src/nsPop3Protocol.h
mailnews/local/src/nsPop3Service.cpp
--- a/mailnews/base/public/nsIMsgAccountManager.idl
+++ b/mailnews/base/public/nsIMsgAccountManager.idl
@@ -42,17 +42,17 @@
 #include "nsIMsgIncomingServer.idl"
 #include "nsIIncomingServerListener.idl"
 #include "nsIMsgFolder.idl"
 
 interface nsISupportsArray;
 interface nsIMsgFolderCache;
 interface nsIFolderListener;
 
-[scriptable, uuid(8129D2AD-6093-479D-884C-D8E79FA29B46)]
+[scriptable, uuid(d0e03f59-ee44-40ab-a444-3d61aaf6da59)]
 interface nsIMsgAccountManager : nsISupports {
 
   nsIMsgAccount createAccount();
   /*
    * Return the account with the provided key, or null if none found.
    */
   nsIMsgAccount getAccount(in ACString key);
     
@@ -63,21 +63,34 @@ interface nsIMsgAccountManager : nsISupp
   /*
    * creates a new identity and assigns it a new, unique "key"
    */
   nsIMsgIdentity createIdentity();
 
   /*
    * creates a new server and assigns it a new, unique "key"
    * the given type will be used to construct a ContractID
+   *
+   *  @param type "imap", "pop3", "nntp", "movemail", "none", "rss", "generic"
+   * (suffix of contract ID @mozilla.org/messenger/server;1?type= )
    */
   nsIMsgIncomingServer createIncomingServer(in ACString username,
                                             in ACString hostname,
                                             in ACString type);
-  
+
+  /**
+   * Removes the server from the list of servers
+   * 
+   * @param aServer        server to remove
+   * @param aCleanupFiles  remove directory from profile
+   *
+   * @throws NS_ERROR_FAILURE if server not found 
+   */
+  void removeIncomingServer(in nsIMsgIncomingServer aServer, 
+                            in boolean aCleanupFiles);
   /*
    * get the identity with the given key
    * if the identity does not exist, it will be created
    */
   nsIMsgIdentity getIdentity(in ACString key);
 
   /*
    * Gets the existing incoming server with the given key
--- a/mailnews/base/public/nsIMsgIncomingServer.idl
+++ b/mailnews/base/public/nsIMsgIncomingServer.idl
@@ -52,17 +52,17 @@ interface nsIMsgDBHdr;
 interface nsILocalFile;
 
 /*
  * 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(15087bf7-f63f-42c3-8f60-a0cd11aaca53)]
+[scriptable, uuid(e84541a9-98a7-47b3-8037-2cf83b4c242b)]
 interface nsIMsgIncomingServer : nsISupports {
 
   /**
    * internal pref key - guaranteed to be unique across all servers
    */
   attribute ACString key;
 
   /**
@@ -168,17 +168,21 @@ interface nsIMsgIncomingServer : nsISupp
      - if account is deferred, root folder of deferred-to account */
   readonly attribute nsIMsgFolder rootMsgFolder;
 
   /* are we already getting new Messages on the current server..
      This is used to help us prevent multiple get new msg commands from
      going off at the same time. */
   attribute boolean serverBusy;
 
-  /* should we use a secure channel? */
+  /**
+   * Should we use a SSL/TLS?
+   * If not, set this to false and socketType to defaultSocket.
+   * If SSL/TLS, set this to true and socketType to the right SSL type.
+   */
   attribute boolean isSecure;
 
   /* should we use secure authentication? */
   attribute boolean useSecAuth;
 
   const long defaultSocket = 0;
   const long tryTLS = 1;
   const long alwaysUseTLS = 2;
@@ -187,31 +191,39 @@ interface nsIMsgIncomingServer : nsISupp
   /* use above values */
   attribute long socketType;
 
   /* if a logon mechanism fails, should we fallback to a different
      mechanism?
   */
   attribute boolean logonFallback;
 
-  /* can server support a secure channel? */
+  /* dead code. */
   readonly attribute boolean isSecureServer;
 
   /* empty trash on exit */
   attribute boolean emptyTrashOnExit;
 
   /* get filter list */
   nsIMsgFilterList getFilterList(in nsIMsgWindow aMsgWindow);
 
   /* set filter list */
   void setFilterList(in nsIMsgFilterList aFilterList);
 
   /* we use this to set the default local path.  we use this when migrating prefs */
   void setDefaultLocalPath(in nsILocalFile aDefaultLocalPath);
 
+  /**
+   * Verify that we can logon 
+   * 
+   * @param  aUrlListener - gets called back with success or failure.
+   *
+   */
+  void verifyLogon(in nsIUrlListener aUrlListener);
+
   /* do a biff */
   void performBiff(in nsIMsgWindow aMsgWindow);
   
   /* get new messages */
   void getNewMessages(in nsIMsgFolder aFolder, in nsIMsgWindow aMsgWindow, 
                       in nsIUrlListener aUrlListener);
   /* this checks if a server needs a password to do biff */
   readonly attribute boolean serverRequiresPasswordForBiff;
--- a/mailnews/base/src/nsMsgAccountManager.cpp
+++ b/mailnews/base/src/nsMsgAccountManager.cpp
@@ -451,16 +451,67 @@ nsMsgAccountManager::GetIncomingServer(c
   nsCString hostname;
   rv = m_prefs->GetCharPref(serverPref.get(), getter_Copies(hostname));
   NS_ENSURE_SUCCESS(rv, NS_ERROR_NOT_INITIALIZED);
 
     // the server type doesn't exist. That's bad.
   return createKeyedServer(key, username, hostname, serverType, _retval);
 }
 
+NS_IMETHODIMP
+nsMsgAccountManager::RemoveIncomingServer(nsIMsgIncomingServer *aServer, 
+                                          PRBool aCleanupFiles)
+{
+  nsCString serverKey;
+  nsresult rv = aServer->GetKey(serverKey);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  LogoutOfServer(aServer); // close cached connections and forget session password
+
+  // invalidate the FindServer() cache if we are removing the cached server
+  if (m_lastFindServerResult == aServer)
+    SetLastServerFound(nsnull, EmptyCString(), EmptyCString(), 0, EmptyCString());
+
+  m_incomingServers.Remove(serverKey);
+
+  nsCOMPtr<nsIMsgFolder> rootFolder;
+  nsCOMPtr<nsISupportsArray> allDescendents;
+
+  rv = aServer->GetRootFolder(getter_AddRefs(rootFolder));
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = NS_NewISupportsArray(getter_AddRefs(allDescendents));
+  NS_ENSURE_SUCCESS(rv, rv);
+  rootFolder->ListDescendents(allDescendents);
+
+  PRUint32 cnt = 0;
+  rv = allDescendents->Count(&cnt);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  for (PRUint32 i = 0; i < cnt; i++)
+  {
+    nsCOMPtr<nsIMsgFolder> folder = do_QueryElementAt(allDescendents, i);
+    if (folder)
+      folder->ForceDBClosed();
+  }
+
+  mFolderListeners->EnumerateForwards(removeListenerFromFolder, (void*)rootFolder);
+  NotifyServerUnloaded(aServer);
+  if (aCleanupFiles)
+  {
+    rv = aServer->RemoveFiles();
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  // now clear out the server once and for all.
+  // watch out! could be scary
+  aServer->ClearAllValues();
+  rootFolder->Shutdown(PR_TRUE);
+  return rv;
+}
+
 /*
  * create a server when you know the key and the type
  */
 nsresult
 nsMsgAccountManager::createKeyedServer(const nsACString& key,
                                        const nsACString& username,
                                        const nsACString& hostname,
                                        const nsACString& type,
@@ -560,59 +611,18 @@ nsMsgAccountManager::RemoveAccount(nsIMs
     SetDefaultAccount(nsnull);
 
   // XXX - need to figure out if this is the last time this server is
   // being used, and only send notification then.
   // (and only remove from hashtable then too!)
   nsCOMPtr<nsIMsgIncomingServer> server;
   rv = aAccount->GetIncomingServer(getter_AddRefs(server));
   if (NS_SUCCEEDED(rv) && server) {
-    nsCString serverKey;
-    rv = server->GetKey(serverKey);
-    NS_ENSURE_SUCCESS(rv,rv);
-
-    LogoutOfServer(server); // close cached connections and forget session password
-
-    // invalidate the FindServer() cache if we are removing the cached server
-    if (m_lastFindServerResult) {
-      nsCString cachedServerKey;
-      rv = m_lastFindServerResult->GetKey(cachedServerKey);
-      NS_ENSURE_SUCCESS(rv,rv);
-
-      if (serverKey.Equals(cachedServerKey)) {
-        rv = SetLastServerFound(nsnull, EmptyCString(), EmptyCString(), 0, EmptyCString());
-        NS_ENSURE_SUCCESS(rv,rv);
-      }
-    }
-
-    m_incomingServers.Remove(serverKey);
-
-    nsCOMPtr<nsIMsgFolder> rootFolder;
-    server->GetRootFolder(getter_AddRefs(rootFolder));
-    nsCOMPtr<nsISupportsArray> allDescendents;
-    NS_NewISupportsArray(getter_AddRefs(allDescendents));
-    rootFolder->ListDescendents(allDescendents);
-    PRUint32 cnt =0;
-    rv = allDescendents->Count(&cnt);
+    rv = RemoveIncomingServer(server, PR_FALSE);
     NS_ENSURE_SUCCESS(rv, rv);
-    for (PRUint32 i = 0; i < cnt;i++)
-    {
-      nsCOMPtr<nsIMsgFolder> folder = do_QueryElementAt(allDescendents, i, &rv);
-      folder->ForceDBClosed();
-    }
-
-    mFolderListeners->EnumerateForwards(removeListenerFromFolder, (void*)rootFolder);
-    NotifyServerUnloaded(server);
-    rv = server->RemoveFiles();
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    // now clear out the server once and for all.
-    // watch out! could be scary
-    server->ClearAllValues();
-    rootFolder->Shutdown(PR_TRUE);
   }
 
   nsCOMPtr<nsISupportsArray> identityArray;
   rv = aAccount->GetIdentities(getter_AddRefs(identityArray));
   if (NS_SUCCEEDED(rv)) {
     PRUint32 count=0;
     identityArray->Count(&count);
     PRUint32 i;
@@ -1681,18 +1691,17 @@ nsMsgAccountManager::FindServerByURI(nsI
   serverInfo.useRealSetting = aRealFlag;
   serverInfo.server = *aResult = nsnull;
   servers->EnumerateForwards(findServerUrl, (void *)&serverInfo);
 
   if (!serverInfo.server)
     return NS_ERROR_UNEXPECTED;
 
   // cache for next time
-  rv = SetLastServerFound(serverInfo.server, hostname, username, port, type);
-  NS_ENSURE_SUCCESS(rv, rv);
+  SetLastServerFound(serverInfo.server, hostname, username, port, type);
   NS_ADDREF(*aResult = serverInfo.server);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMsgAccountManager::FindServer(const nsACString& username,
                                 const nsACString& hostname,
                                 const nsACString& type,
@@ -1727,18 +1736,17 @@ nsMsgAccountManager::FindServer(const ns
   serverInfo.server = *aResult = nsnull;
 
   servers->EnumerateForwards(findServer, (void *)&serverInfo);
 
   if (!serverInfo.server)
     return NS_ERROR_UNEXPECTED;
 
   // cache for next time
-  rv = SetLastServerFound(serverInfo.server, hostname, username, 0, type);
-  NS_ENSURE_SUCCESS(rv,rv);
+  SetLastServerFound(serverInfo.server, hostname, username, 0, type);
 
   NS_ADDREF(*aResult = serverInfo.server);
   return NS_OK;
 }
 
 // Interface called by UI js only (always return true).
 NS_IMETHODIMP
 nsMsgAccountManager::FindRealServer(const nsACString& username,
@@ -2309,26 +2317,25 @@ nsMsgAccountManager::SetFolderDoingClean
 NS_IMETHODIMP
 nsMsgAccountManager::GetCleanupInboxInProgress(PRBool *bVal)
 {
   NS_ENSURE_ARG_POINTER(bVal);
   *bVal = m_cleanupInboxInProgress;
   return NS_OK;
 }
 
-nsresult
+void
 nsMsgAccountManager::SetLastServerFound(nsIMsgIncomingServer *server, const nsACString& hostname, 
                                         const nsACString& username, const PRInt32 port, const nsACString& type)
 {
   m_lastFindServerResult = server;
   m_lastFindServerHostName = hostname;
   m_lastFindServerUserName = username;
   m_lastFindServerPort = port;
   m_lastFindServerType = type;
-  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMsgAccountManager::SaveAccountInfo()
 {
   nsresult rv;
   nsCOMPtr<nsIPrefService> pref(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
   NS_ENSURE_SUCCESS(rv,rv);
--- a/mailnews/base/src/nsMsgAccountManager.h
+++ b/mailnews/base/src/nsMsgAccountManager.h
@@ -109,18 +109,18 @@ private:
 
   /* we call FindServer() a lot.  so cache the last server found */
   nsCOMPtr <nsIMsgIncomingServer> m_lastFindServerResult;
   nsCString m_lastFindServerHostName;
   nsCString m_lastFindServerUserName;
   PRInt32 m_lastFindServerPort;
   nsCString m_lastFindServerType;
 
-  nsresult SetLastServerFound(nsIMsgIncomingServer *server, const nsACString& hostname,
-                              const nsACString& username, const PRInt32 port, const nsACString& type);
+  void SetLastServerFound(nsIMsgIncomingServer *server, const nsACString& hostname,
+                          const nsACString& username, const PRInt32 port, const nsACString& type);
 
   /* internal creation routines - updates m_identities and m_incomingServers */
   nsresult createKeyedAccount(const nsCString& key,
                               nsIMsgAccount **_retval);
   nsresult createKeyedServer(const nsACString& key,
                              const nsACString& username,
                              const nsACString& password,
                              const nsACString& type,
--- a/mailnews/base/util/nsMsgIncomingServer.cpp
+++ b/mailnews/base/util/nsMsgIncomingServer.cpp
@@ -181,16 +181,22 @@ nsMsgIncomingServer::GetRootMsgFolder(ns
 NS_IMETHODIMP
 nsMsgIncomingServer::PerformExpand(nsIMsgWindow *aMsgWindow)
 {
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
+nsMsgIncomingServer::VerifyLogon(nsIUrlListener *aUrlListener)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
 nsMsgIncomingServer::PerformBiff(nsIMsgWindow* aMsgWindow)
 {
   //This has to be implemented in the derived class, but in case someone doesn't implement it
   //just return not implemented.
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
@@ -742,24 +748,16 @@ nsMsgIncomingServer::GetPasswordWithUI(c
     {
       // prompt the user for the password
       nsCOMPtr<nsIDocShell> docShell;
       rv = aMsgWindow->GetRootDocShell(getter_AddRefs(docShell));
       NS_ENSURE_SUCCESS(rv, rv);
       dialog = do_GetInterface(docShell, &rv);
       NS_ENSURE_SUCCESS(rv, rv);
     }
-    else
-    {
-      nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
-      if (wwatch)
-        wwatch->GetNewAuthPrompter(0, getter_AddRefs(dialog));
-      NS_ENSURE_TRUE(dialog, NS_ERROR_FAILURE);
-    }
-    
     if (dialog)
     {
       nsCString serverUri;
       rv = GetServerURI(serverUri);
       NS_ENSURE_SUCCESS(rv, rv);
 
       // we pass in the previously used password, if any, into PromptPassword
       // so that it will appear as ******. This means we can't use an nsString
@@ -995,17 +993,29 @@ NS_IMETHODIMP
 nsMsgIncomingServer::RemoveFiles()
 {
   // IMPORTANT, see bug #77652
   // don't turn this code on yet.  we don't inform the user that
   // we are going to be deleting the directory, and they might have
   // tweaked their localPath pref for this server to point to
   // somewhere they didn't want deleted.
   // until we tell them, we shouldn't do the delete.
-  return NS_OK;
+  nsCString deferredToAccount;
+  GetCharValue("deferred_to_account", deferredToAccount);
+  PRBool isDeferredTo = PR_TRUE;
+  GetIsDeferredTo(&isDeferredTo);
+  if (!deferredToAccount.IsEmpty() || isDeferredTo)
+  {
+    NS_ASSERTION(PR_FALSE, "shouldn't remove files for a deferred account");
+    return NS_ERROR_FAILURE;
+  }
+  nsCOMPtr <nsILocalFile> localPath;
+  nsresult rv = GetLocalPath(getter_AddRefs(localPath));
+  NS_ENSURE_SUCCESS(rv, rv);
+  return localPath->Remove(PR_TRUE);
 }
 
 NS_IMETHODIMP
 nsMsgIncomingServer::SetFilterList(nsIMsgFilterList *aFilterList)
 {
   mFilterList = aFilterList;
   return NS_OK;
 }
--- a/mailnews/base/util/nsMsgMailNewsUrl.cpp
+++ b/mailnews/base/util/nsMsgMailNewsUrl.cpp
@@ -197,21 +197,19 @@ NS_IMETHODIMP nsMsgMailNewsUrl::GetServe
     return rv;
 }
 
 NS_IMETHODIMP nsMsgMailNewsUrl::GetMsgWindow(nsIMsgWindow **aMsgWindow)
 {
   NS_ENSURE_ARG_POINTER(aMsgWindow);
   *aMsgWindow = nsnull;
   
-  // note: it is okay to return a null msg window and not return an error
-  // it's possible the url really doesn't have msg window
   nsCOMPtr<nsIMsgWindow> msgWindow(do_QueryReferent(m_msgWindowWeak));
   msgWindow.swap(*aMsgWindow);
-  return NS_OK;
+  return *aMsgWindow ? NS_OK : NS_ERROR_NULL_POINTER;
 }
 
 NS_IMETHODIMP nsMsgMailNewsUrl::SetMsgWindow(nsIMsgWindow *aMsgWindow)
 {
   if (aMsgWindow)
     m_msgWindowWeak = do_GetWeakReference(aMsgWindow);
   return NS_OK;
 }
--- a/mailnews/compose/public/nsISmtpServer.idl
+++ b/mailnews/compose/public/nsISmtpServer.idl
@@ -34,25 +34,26 @@
  * 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"
 
 interface nsIAuthPrompt;
+interface nsIUrlListener;
 
 /**
  * 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(1d449933-b0b7-4bbf-a8a4-cc4bb9b545c5)]
+[scriptable, uuid(71f5d415-094d-4a32-899b-2256c2de6876)]
 interface nsISmtpServer : nsISupports {
 
   /// A unique identifier for the server.
   attribute string key;
 
   /// A user supplied description for the server.
   attribute AUTF8String description;
 
@@ -67,17 +68,17 @@ interface nsISmtpServer : nsISupports {
 
   /**
    * The password to access the server with (if required).
    *
    * @note this is stored within the server instance but not within preferences.
    * It can be specified/saved here to avoid prompting the user constantly for
    * the sending password.
    */
-  attribute string 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).
@@ -85,17 +86,24 @@ interface nsISmtpServer : nsISupports {
   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;
 
-  /// Should we try to use SSL for this connection?
+  /**
+   * 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
+   */
   attribute long trySSL;
 
   /**
    * 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.
@@ -111,38 +119,48 @@ interface nsISmtpServer : nsISupports {
    * @param promptString  The string to prompt the user with when asking for
    *                      the password.
    * @param promptTitle   The title of the prompt.
    * @param netPrompt     An nsIAuthPrompt instance to use for the password
    *                      prompt.
    * @return              The password to use (may be null if no password was
    *                      obtained).
    */  
-  string getPasswordWithUI(in wstring promptString, in wstring promptTitle,
+  ACString getPasswordWithUI(in wstring promptString, in wstring promptTitle,
                            in nsIAuthPrompt netPrompt);
 
   /**
    * Gets a username and password for this server, using a UI prompt if
    * necessary.
    *
    * @param promptString  The string to prompt the user with when asking for
    *                      the password.
    * @param promptTitle   The title of the prompt.
    * @param netPrompt     An nsIAuthPrompt instance to use for the password
    *                      prompt.
    * @param userid        The username to use (may be null if no password was
    *                      obtained).
-   * @param password      The password to use (may be null if no password was
+   * @param password      The password to use (may be empty if no password was
    *                      obtained).
    */  
   void getUsernamePasswordWithUI(in wstring promptString, in wstring promptTitle,
                                  in nsIAuthPrompt netPrompt, out string userid,
-                                 out string password);
+                                 out ACString password);
 
   /**
    * Calling this will *remove* the saved password for this server from the
    * password manager and from the stored value.
    */
   void forgetPassword();
 
+    /**
+   * Verify that we can logon 
+   * 
+   * @param  aPassword - password to use
+   * @param  aUrlListener - gets called back with success or failure.
+   *
+   */
+  void verifyLogon(in nsIUrlListener aUrlListener);
+
+
   /// Call this to clear all preference values for this server.
   void clearAllValues();
 };
--- a/mailnews/compose/public/nsISmtpService.idl
+++ b/mailnews/compose/public/nsISmtpService.idl
@@ -43,17 +43,17 @@ interface nsIURI;
 interface nsIUrlListener;
 interface nsIMsgIdentity;
 interface nsIInterfaceRequestor;
 interface nsIFile;
 interface nsIMsgStatusFeedback;
 interface nsIRequest;
 interface nsISimpleEnumerator;
 
-[scriptable, uuid(8e9a7c57-cee1-46f2-a03b-14fac3086706)]
+[scriptable, uuid(7b1c1604-7aad-451e-ae55-a7984c1fd0d9)]
 interface nsISmtpService : nsISupports {
   /**
    * Sends a mail message via the given parameters. This function builds an
    * SMTP URL and makes an SMTP connection, and then runs the url.
    * The SMTP server defined
    * in the aSenderIdentity object (see nsIMsgIdentity) will be used to send
    * the message. If there is no SMTP server defined in aSenderIdentity, the
    * default SMTP server will be used.
@@ -90,16 +90,25 @@ interface nsISmtpService : nsISupports {
                        in nsIUrlListener aUrlListener, 
                        in nsIMsgStatusFeedback aStatusListener, 
                        in nsIInterfaceRequestor aNotificationCallbacks,
                        in boolean aRequestDSN,
                        out nsIURI aURL,
                        out nsIRequest aRequest);
 
   /**
+   * Verifies that we can logon to the server with given password
+   *
+   * @param  aSmtpServer       Server to try to logon to.
+   * @param  aUrlListener      Listener that will get notified whether logon
+   *                           was successful or not.
+   */
+  void verifyLogon(in nsISmtpServer aServer, in nsIUrlListener aListener);
+
+  /**
    * Return the SMTP server that is associated with an identity.
    */
   void GetSmtpServerByIdentity(in nsIMsgIdentity aSenderIdentity,
                                out nsISmtpServer aServer);
 
   /**
    * A copy of the array of SMTP servers, as stored in the preferences
    */
--- a/mailnews/compose/public/nsISmtpUrl.idl
+++ b/mailnews/compose/public/nsISmtpUrl.idl
@@ -41,17 +41,17 @@
 
 interface nsIMsgIdentity;
 interface nsIPrompt;
 interface nsIAuthPrompt;
 interface nsISmtpServer;
 interface nsIInterfaceRequestor;
 interface nsIFile;
 
-[scriptable, uuid(b167bf57-51c0-41ae-b331-bd7025c01a20)]
+[scriptable, uuid(ffc85194-21cc-42a2-9844-34068888a117)]
 interface nsISmtpUrl : nsISupports {
   /**
    * SMTP Parse specific getters.
    * These retrieve various parts from the url.
    */
 
   /**
    * This list is a list of all recipients to send the email to.
@@ -89,16 +89,18 @@ interface nsISmtpUrl : nsISupports {
    * NOTE:  the SMTP username and SMTP server are in the smtp url
    * smtp://sspitzer@tintin/...
    */
   attribute nsIMsgIdentity senderIdentity;
   attribute nsIPrompt prompt;
   attribute nsIAuthPrompt authPrompt;
   attribute nsIInterfaceRequestor notificationCallbacks;
   attribute nsISmtpServer smtpServer;
+
+  attribute boolean verifyLogon; // we're just verifying the ability to logon
     
   const PRInt32 DEFAULT_SMTP_PORT = 25;
   const PRInt32 DEFAULT_SMTPS_PORT = 465;
 };
 
 [scriptable, uuid(5EE2AFF7-9C6F-11d3-98A3-001083010E9B)]
 interface nsIMailtoUrl : nsISupports {
   /**
--- a/mailnews/compose/src/nsSmtpProtocol.cpp
+++ b/mailnews/compose/src/nsSmtpProtocol.cpp
@@ -567,26 +567,34 @@ PRInt32 nsSmtpProtocol::SendHeloResponse
 {
   PRInt32 status = 0;
   nsCAutoString buffer;
   nsresult rv;
 
   if (m_responseCode != 250)
   {
 #ifdef DEBUG
-    nsresult rv =
+    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);
   }
 
+  // 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)
+    return SendQuit();
+
   // extract the email address from the identity
   nsCString emailAddress;
   nsCOMPtr <nsIMsgIdentity> senderIdentity;
   rv = m_runningURL->GetSenderIdentity(getter_AddRefs(senderIdentity));
   if (NS_FAILED(rv) || !senderIdentity)
   {
     m_urlErrorState = NS_ERROR_COULD_NOT_GET_USERS_MAIL_ADDRESS;
     return(NS_ERROR_COULD_NOT_GET_USERS_MAIL_ADDRESS);
@@ -1154,23 +1162,23 @@ PRInt32 nsSmtpProtocol::AuthLoginStep1()
   nsCAutoString password;
   nsCOMPtr<nsISmtpServer> smtpServer;
   rv = m_runningURL->GetSmtpServer(getter_AddRefs(smtpServer));
   if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
 
   rv = smtpServer->GetUsername(getter_Copies(username));
   if (username.IsEmpty())
   {
-    rv = GetUsernamePassword(getter_Copies(username), getter_Copies(password));
+    rv = GetUsernamePassword(getter_Copies(username), password);
     m_usernamePrompted = PR_TRUE;
     if (username.IsEmpty() || password.IsEmpty())
       return NS_ERROR_SMTP_PASSWORD_UNDEFINED;
   }
 
-  GetPassword(getter_Copies(password));
+  GetPassword(password);
   if (password.IsEmpty())
   {
     m_urlErrorState = NS_ERROR_SMTP_PASSWORD_UNDEFINED;
     return NS_ERROR_SMTP_PASSWORD_UNDEFINED;
   }
 
   if (TestFlag(SMTP_AUTH_CRAM_MD5_ENABLED))
     PR_snprintf(buffer, sizeof(buffer), "AUTH CRAM-MD5" CRLF);
@@ -1225,17 +1233,17 @@ PRInt32 nsSmtpProtocol::AuthLoginStep2()
   * if not then use cached pop password
   * if pop password undefined
   * sync with smtp password
   */
   PRInt32 status = 0;
   nsresult rv;
   nsCAutoString password;
 
-  GetPassword(getter_Copies(password));
+  GetPassword(password);
   if (password.IsEmpty())
   {
     m_urlErrorState = NS_ERROR_SMTP_PASSWORD_UNDEFINED;
     return NS_ERROR_SMTP_PASSWORD_UNDEFINED;
   }
 
   if (!password.IsEmpty())
   {
@@ -1489,31 +1497,29 @@ PRInt32 nsSmtpProtocol::SendDataResponse
 
   if (m_responseCode != 354)
   {
     nsresult rv = nsExplainErrorDetails(m_runningURL, NS_ERROR_SENDING_DATA_COMMAND, m_responseText.get());
     NS_ASSERTION(NS_SUCCEEDED(rv), "failed to explain SMTP error");
 
     m_urlErrorState = NS_ERROR_BUT_DONT_SHOW_ALERT;
     return(NS_ERROR_SENDING_DATA_COMMAND);
-    }
+  }
 
-    PR_FREEIF(command);
+  PR_FREEIF(command);
 
-    m_nextState = SMTP_SEND_POST_DATA;
-    ClearFlag(SMTP_PAUSE_FOR_READ);   /* send data directly */
+  m_nextState = SMTP_SEND_POST_DATA;
+  ClearFlag(SMTP_PAUSE_FOR_READ);   /* send data directly */
 
-    UpdateStatus(SMTP_DELIV_MAIL);
+  UpdateStatus(SMTP_DELIV_MAIL);
 
-    {
+  {
 //      m_runningURL->GetBodySize(&m_totalMessageSize);
-    }
-
-
-    return(status);
+  }
+  return(status);
 }
 
 PRInt32 nsSmtpProtocol::SendMessageInFile()
 {
   nsCOMPtr<nsIFile> file;
   nsCOMPtr<nsIURI> url = do_QueryInterface(m_runningURL);
   m_runningURL->GetPostMessageFile(getter_AddRefs(file));
   if (url && file)
@@ -1571,25 +1577,29 @@ PRInt32 nsSmtpProtocol::SendMessageRespo
     NS_ASSERTION(NS_SUCCEEDED(rv), "failed to explain SMTP error");
 
     m_urlErrorState = NS_ERROR_BUT_DONT_SHOW_ALERT;
     return(NS_ERROR_SENDING_MESSAGE);
   }
 
   UpdateStatus(SMTP_PROGRESS_MAILSENT);
 
-    /* else */
-    m_sendDone = PR_TRUE;
-    nsCOMPtr<nsIURI> url = do_QueryInterface(m_runningURL);
-       SendData(url, "QUIT"CRLF); // send a quit command to close the connection with the server.
-    m_nextState = SMTP_RESPONSE;
-    m_nextStateAfterResponse = SMTP_DONE;
-    return(0);
+  /* else */
+  return SendQuit();
 }
 
+PRInt32 nsSmtpProtocol::SendQuit()
+{
+  m_sendDone = PR_TRUE;
+  nsCOMPtr<nsIURI> url = do_QueryInterface(m_runningURL);
+  SendData(url, "QUIT"CRLF); // send a quit command to close the connection with the server.
+  m_nextState = SMTP_RESPONSE;
+  m_nextStateAfterResponse = SMTP_DONE;
+  return(0);
+}
 
 nsresult nsSmtpProtocol::LoadUrl(nsIURI * aURL, nsISupports * aConsumer )
 {
   nsresult rv = NS_OK;
 
   PRInt32 status = 0;
 	m_continuationResponse = -1;  /* init */
 	if (aURL)
@@ -1850,38 +1860,33 @@ nsresult nsSmtpProtocol::LoadUrl(nsIURI 
     }
     }
   } /* while(!SMTP_PAUSE_FOR_READ) */
 
   return NS_OK;
 }
 
 nsresult
-nsSmtpProtocol::GetPassword(char **aPassword)
+nsSmtpProtocol::GetPassword(nsCString &aPassword)
 {
-    NS_ENSURE_ARG_POINTER(aPassword);
-
     nsresult rv;
     nsCOMPtr<nsISmtpUrl> smtpUrl = do_QueryInterface(m_runningURL, &rv);
     NS_ENSURE_SUCCESS(rv,rv);
 
     nsCOMPtr<nsISmtpServer> smtpServer;
     rv = smtpUrl->GetSmtpServer(getter_AddRefs(smtpServer));
     NS_ENSURE_SUCCESS(rv,rv);
 
     rv = smtpServer->GetPassword(aPassword);
     NS_ENSURE_SUCCESS(rv,rv);
 
-    if (*aPassword && **aPassword)
+    if (!aPassword.IsEmpty())
         return rv;
     // empty password
 
-    NS_Free(*aPassword);
-    *aPassword = nsnull;
-
     nsCOMPtr <nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv,rv);
 
     nsCOMPtr<nsIPrefBranch> prefBranch;
     rv = prefs->GetBranch(nsnull, getter_AddRefs(prefBranch));
     NS_ENSURE_SUCCESS(rv,rv);
 
     nsCString username;
@@ -1904,17 +1909,17 @@ nsSmtpProtocol::GetPassword(char **aPass
     formatStrings[1] = hostnameUTF16.get();
 
     rv = PromptForPassword(smtpServer, smtpUrl, formatStrings, aPassword);
     NS_ENSURE_SUCCESS(rv,rv);
     return rv;
 }
 
 nsresult
-nsSmtpProtocol::PromptForPassword(nsISmtpServer *aSmtpServer, nsISmtpUrl *aSmtpUrl, const PRUnichar **formatStrings, char **aPassword)
+nsSmtpProtocol::PromptForPassword(nsISmtpServer *aSmtpServer, nsISmtpUrl *aSmtpUrl, const PRUnichar **formatStrings, nsACString &aPassword)
 {
   nsresult rv;
   nsCOMPtr<nsIStringBundleService> stringService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv,rv);
 
   nsCOMPtr<nsIStringBundle> composeStringBundle;
   rv = stringService->CreateBundle("chrome://messenger/locale/messengercompose/composeMsgs.properties", getter_AddRefs(composeStringBundle));
   NS_ENSURE_SUCCESS(rv,rv);
@@ -1940,47 +1945,46 @@ nsSmtpProtocol::PromptForPassword(nsISmt
 
   rv = aSmtpServer->GetPasswordWithUI(passwordPromptString.get(), passwordTitle.get(),
     netPrompt, aPassword);
   NS_ENSURE_SUCCESS(rv,rv);
   return rv;
 }
 
 nsresult
-nsSmtpProtocol::GetUsernamePassword(char **aUsername, char **aPassword)
+nsSmtpProtocol::GetUsernamePassword(char **aUsername, nsACString &aPassword)
 {
     NS_ENSURE_ARG_POINTER(aUsername);
-    NS_ENSURE_ARG_POINTER(aPassword);
 
     nsresult rv;
     nsCOMPtr<nsISmtpUrl> smtpUrl = do_QueryInterface(m_runningURL, &rv);
     NS_ENSURE_SUCCESS(rv,rv);
 
     nsCOMPtr<nsISmtpServer> smtpServer;
     rv = smtpUrl->GetSmtpServer(getter_AddRefs(smtpServer));
     NS_ENSURE_SUCCESS(rv,rv);
 
     rv = smtpServer->GetPassword(aPassword);
     NS_ENSURE_SUCCESS(rv,rv);
 
-    if (*aPassword && **aPassword) {
+    if (!aPassword.IsEmpty())
+    {
         rv = smtpServer->GetUsername(aUsername);
         NS_ENSURE_SUCCESS(rv,rv);
 
         if (*aUsername && **aUsername)
             return rv;
 
         // empty username
         NS_Free(*aUsername);
         *aUsername = 0;
     }
     // empty password
 
-    NS_Free(*aPassword);
-    *aPassword = 0;
+    aPassword.Truncate();
 
     nsCString hostname;
     rv = smtpServer->GetHostname(getter_Copies(hostname));
     NS_ENSURE_SUCCESS(rv, rv);
 
     const PRUnichar *formatStrings[] =
     {
       NS_ConvertASCIItoUTF16(hostname).get(),
--- a/mailnews/compose/src/nsSmtpProtocol.h
+++ b/mailnews/compose/src/nsSmtpProtocol.h
@@ -211,16 +211,17 @@ private:
     //						designed to re-act to the current "state". I've attempted to 
     //						group them together based on functionality. 
     ////////////////////////////////////////////////////////////////////////////////////////
 
     PRInt32 SmtpResponse(nsIInputStream * inputStream, PRUint32 length); 
     PRInt32 ExtensionLoginResponse(nsIInputStream * inputStream, PRUint32 length);
     PRInt32 SendHeloResponse(nsIInputStream * inputStream, PRUint32 length);
     PRInt32 SendEhloResponse(nsIInputStream * inputStream, PRUint32 length);	
+    PRInt32 SendQuit();
 
     PRInt32 AuthGSSAPIFirst();
     PRInt32 AuthGSSAPIStep();
     PRInt32 AuthLoginStep0();
     PRInt32 AuthLoginStep0Response();
     PRInt32 AuthLoginStep1();
     PRInt32 AuthLoginStep2();
     PRInt32 AuthLoginResponse(nsIInputStream * stream, PRUint32 length);
@@ -238,18 +239,20 @@ private:
 
     ////////////////////////////////////////////////////////////////////////////////////////
     // End of Protocol Methods
     ////////////////////////////////////////////////////////////////////////////////////////
 
     PRInt32 SendMessageInFile();
 
     void AppendHelloArgument(nsACString& aResult);
-    nsresult GetPassword(char **aPassword);
-    nsresult GetUsernamePassword(char **aUsername, char **aPassword);
-    nsresult PromptForPassword(nsISmtpServer *aSmtpServer, nsISmtpUrl *aSmtpUrl, const PRUnichar **formatStrings, char **aPassword);
+    nsresult GetPassword(nsCString &aPassword);
+    nsresult GetUsernamePassword(char **aUsername, nsACString &aPassword);
+    nsresult PromptForPassword(nsISmtpServer *aSmtpServer, nsISmtpUrl *aSmtpUrl, 
+                               const PRUnichar **formatStrings, 
+                               nsACString &aPassword);
 
     void BackupAuthFlags();
     void RestoreAuthFlags();
     PRInt32 m_origAuthFlags;
 };
 
 #endif  // nsSmtpProtocol_h___
--- a/mailnews/compose/src/nsSmtpServer.cpp
+++ b/mailnews/compose/src/nsSmtpServer.cpp
@@ -31,29 +31,31 @@
  * 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 ***** */
 
-#include "nsIServiceManager.h"
+#include "msgCore.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsEscape.h"
 #include "nsSmtpServer.h"
 #include "nsIObserverService.h"
 #include "nsNetUtil.h"
 #include "nsIAuthPrompt.h"
 #include "nsReadableUtils.h"
 #include "nsISmtpUrl.h"
 #include "nsMsgUtils.h"
 #include "nsIMsgAccountManager.h"
 #include "nsMsgBaseCID.h"
+#include "nsISmtpService.h"
+#include "nsMsgCompCID.h"
 
 NS_IMPL_ADDREF(nsSmtpServer)
 NS_IMPL_RELEASE(nsSmtpServer)
 NS_INTERFACE_MAP_BEGIN(nsSmtpServer)
     NS_INTERFACE_MAP_ENTRY(nsISmtpServer)
     NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISmtpServer)
 NS_INTERFACE_MAP_END
@@ -312,19 +314,18 @@ nsSmtpServer::SetUsername(const char * a
     if (aUsername)
         return mPrefBranch->SetCharPref("username", aUsername);
     else
         mPrefBranch->ClearUserPref("username");
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSmtpServer::GetPassword(char * *aPassword)
+nsSmtpServer::GetPassword(nsACString& aPassword)
 {
-    NS_ENSURE_ARG_POINTER(aPassword);
     if (m_password.IsEmpty() && !m_logonFailed)
     {
       // try to avoid prompting the user for another password. If the user has set
       // the appropriate pref, we'll use the password from an incoming server, if
       // the user has already logged onto that server.
 
       // if this is set, we'll only use this, and not the other prefs
       // user_pref("mail.smtpserver.smtp1.incomingAccount", "server1");
@@ -401,44 +402,46 @@ nsSmtpServer::GetPassword(char * *aPassw
                   }
                 }
               }
             }
           }
         }
       }
       if (incomingServerToUse)
-      {
-        nsCString tmpPassword;
-        nsresult rv = incomingServerToUse->GetPassword(tmpPassword);
-        *aPassword = ToNewCString(tmpPassword);
-        return rv;
-      }
+        return incomingServerToUse->GetPassword(aPassword);
     }
-    *aPassword = ToNewCString(m_password);
+    aPassword = m_password;
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSmtpServer::SetPassword(const char * aPassword)
+nsSmtpServer::VerifyLogon(nsIUrlListener *aUrlListener)
 {
-    m_password = aPassword;
-    return NS_OK;
+  nsresult rv;
+  nsCOMPtr<nsISmtpService> smtpService(do_GetService(NS_SMTPSERVICE_CONTRACTID, &rv));
+  NS_ENSURE_SUCCESS(rv, rv);
+  return smtpService->VerifyLogon(this, aUrlListener);
+}
+
+
+NS_IMETHODIMP
+nsSmtpServer::SetPassword(const nsACString& aPassword)
+{
+  m_password = aPassword;
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSmtpServer::GetPasswordWithUI(const PRUnichar * aPromptMessage, const
                                 PRUnichar *aPromptTitle,
                                 nsIAuthPrompt* aDialog,
-                                char **aPassword)
+                                nsACString &aPassword)
 {
     nsresult rv = NS_OK;
-
-    NS_ENSURE_ARG_POINTER(aPassword);
-
     if (m_password.IsEmpty())
     {
         NS_ENSURE_ARG_POINTER(aDialog);
 
         // prompt the user for the password
         if (NS_SUCCEEDED(rv))
         {
             nsString uniPassword;
@@ -456,44 +459,42 @@ nsSmtpServer::GetPasswordWithUI(const PR
             rv = aDialog->PromptPassword(aPromptTitle, aPromptMessage,
                     NS_ConvertASCIItoUTF16(serverUri).get(), savePasswordType,
                     getter_Copies(uniPassword), &okayValue);
             if (NS_FAILED(rv))
                 return rv;
 
             if (!okayValue) // if the user pressed cancel, just return NULL;
             {
-                *aPassword = nsnull;
+                aPassword.Truncate();
                 return rv;
             }
 
             // we got a password back...so remember it
-            nsCString aCStr; LossyCopyUTF16toASCII(uniPassword, aCStr);
+            nsCString aCStr;
+            LossyCopyUTF16toASCII(uniPassword, aCStr);
 
-            rv = SetPassword(aCStr.get());
+            rv = SetPassword(aCStr);
             if (NS_FAILED(rv))
                 return rv;
         } // if we got a prompt dialog
     } // if the password is empty
 
-    rv = GetPassword(aPassword);
-    return rv;
+    return GetPassword(aPassword);
 }
 
 NS_IMETHODIMP
 nsSmtpServer::GetUsernamePasswordWithUI(const PRUnichar * aPromptMessage, const
                                 PRUnichar *aPromptTitle,
                                 nsIAuthPrompt* aDialog,
                                 char **aUsername,
-                                char **aPassword)
+                                nsACString &aPassword)
 {
     nsresult rv = NS_OK;
-
     NS_ENSURE_ARG_POINTER(aUsername);
-    NS_ENSURE_ARG_POINTER(aPassword);
 
     if (m_password.IsEmpty()) {
         NS_ENSURE_ARG_POINTER(aDialog);
         // prompt the user for the password
         if (NS_SUCCEEDED(rv))
         {
             nsString uniUsername;
             nsString uniPassword;
@@ -506,40 +507,39 @@ nsSmtpServer::GetUsernamePasswordWithUI(
                                          NS_ConvertASCIItoUTF16(serverUri).get(), nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
                                          getter_Copies(uniUsername), getter_Copies(uniPassword), &okayValue);
             if (NS_FAILED(rv))
                 return rv;
 
             if (!okayValue) // if the user pressed cancel, just return NULL;
             {
                 *aUsername = nsnull;
-                *aPassword = nsnull;
+                aPassword.Truncate();
                 return rv;
             }
 
             // we got a userid and password back...so remember it
             nsCString aCStr;
 
             LossyCopyUTF16toASCII(uniUsername, aCStr);
             rv = SetUsername(aCStr.get());
             if (NS_FAILED(rv))
                 return rv;
 
             LossyCopyUTF16toASCII(uniPassword, aCStr);
-            rv = SetPassword(aCStr.get());
+            rv = SetPassword(aCStr);
             if (NS_FAILED(rv))
                 return rv;
         } // if we got a prompt dialog
     } // if the password is empty
 
     rv = GetUsername(aUsername);
     if (NS_FAILED(rv))
         return rv;
-    rv = GetPassword(aPassword);
-    return rv;
+    return GetPassword(aPassword);
 }
 
 NS_IMETHODIMP
 nsSmtpServer::ForgetPassword()
 {
     nsresult rv;
     nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1", &rv);
     NS_ENSURE_SUCCESS(rv,rv);
@@ -554,17 +554,17 @@ nsSmtpServer::ForgetPassword()
 
     //this is need to make sure wallet service has been created
     rv = CreateServicesForPasswordManager();
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = observerService->NotifyObservers(uri, "login-failed", nsnull);
     NS_ENSURE_SUCCESS(rv,rv);
 
-    rv = SetPassword("");
+    rv = SetPassword(EmptyCString());
     m_logonFailed = PR_TRUE;
     return rv;
 }
 
 NS_IMETHODIMP
 nsSmtpServer::GetServerURI(char **aResult)
 {
     NS_ENSURE_ARG_POINTER(aResult);
@@ -574,19 +574,17 @@ nsSmtpServer::GetServerURI(char **aResul
     uri += "smtp";
     uri += "://";
 
     nsCString username;
     rv = GetUsername(getter_Copies(username));
 
     if (NS_SUCCEEDED(rv) && !username.IsEmpty()) {
         nsCString escapedUsername;
-        *((char **)getter_Copies(escapedUsername)) =
-            nsEscape(username.get(), url_XAlphas);
-//            nsEscape(username, url_Path);
+        MsgEscapeString(username, nsINetUtil::ESCAPE_XALPHAS, escapedUsername);
         // not all servers have a username
         uri.Append(escapedUsername);
         uri += '@';
     }
 
     nsCString hostname;
     rv = GetHostname(getter_Copies(hostname));
 
--- a/mailnews/compose/src/nsSmtpService.cpp
+++ b/mailnews/compose/src/nsSmtpService.cpp
@@ -82,19 +82,17 @@ typedef struct _findServerByHostnameEntr
 } findServerByHostnameEntry;
 
 static NS_DEFINE_CID(kCSmtpUrlCID, NS_SMTPURL_CID);
 static NS_DEFINE_CID(kCMailtoUrlCID, NS_MAILTOURL_CID);
 
 // foward declarations...
 nsresult
 NS_MsgBuildSmtpUrl(nsIFile * aFilePath,
-                   const nsCString &aSmtpHostName, 
-                   PRInt32 aSmtpPort,
-                   const nsCString &aSmtpUserName, 
+                   nsISmtpServer *aServer,
                    const char* aRecipients, 
                    nsIMsgIdentity * aSenderIdentity,
                    nsIUrlListener * aUrlListener,
                    nsIMsgStatusFeedback *aStatusFeedback,
                    nsIInterfaceRequestor* aNotificationCallbacks,
                    nsIURI ** aUrl,
                    PRBool aRequestDSN);
 
@@ -109,17 +107,17 @@ nsSmtpService::~nsSmtpService()
 {
     // save the SMTP servers to disk
 
 }
 
 NS_IMPL_ISUPPORTS2(nsSmtpService, nsISmtpService, nsIProtocolHandler)
 
 
-nsresult nsSmtpService::SendMailMessage(nsIFile * aFilePath,
+NS_IMETHODIMP nsSmtpService::SendMailMessage(nsIFile * aFilePath,
                                         const char * aRecipients, 
                                         nsIMsgIdentity * aSenderIdentity,
                                         const char * aPassword,
                                         nsIUrlListener * aUrlListener, 
                                         nsIMsgStatusFeedback *aStatusFeedback,
                                         nsIInterfaceRequestor* aNotificationCallbacks,
                                         PRBool aRequestDSN,
                                         nsIURI ** aURL,
@@ -129,48 +127,25 @@ nsresult nsSmtpService::SendMailMessage(
   nsresult rv = NS_OK;
 
   nsCOMPtr<nsISmtpServer> smtpServer;
   rv = GetSmtpServerByIdentity(aSenderIdentity, getter_AddRefs(smtpServer));
 
   if (NS_SUCCEEDED(rv) && smtpServer)
   {
     if (aPassword && *aPassword)
-      smtpServer->SetPassword(aPassword);
-
-    nsCString smtpHostName;
-    nsCString smtpUserName;
-    PRInt32 smtpPort;
-    PRInt32 trySSL;
-
-    smtpServer->GetHostname(getter_Copies(smtpHostName));
-    smtpServer->GetUsername(getter_Copies(smtpUserName));
-    smtpServer->GetPort(&smtpPort);
-    smtpServer->GetTrySSL(&trySSL);
+      smtpServer->SetPassword(nsDependentCString(aPassword));
 
-    if (smtpPort == 0)
+    if (!CHECK_SIMULATED_ERROR(SIMULATED_SEND_ERROR_10)) 
     {
-        if (trySSL == PREF_SECURE_ALWAYS_SMTPS)
-            smtpPort = nsISmtpUrl::DEFAULT_SMTPS_PORT;
-        else
-            smtpPort = nsISmtpUrl::DEFAULT_SMTP_PORT;
-    }
-
-    if (!smtpHostName.IsEmpty() && !CHECK_SIMULATED_ERROR(SIMULATED_SEND_ERROR_10)) 
-    {
-      rv = NS_MsgBuildSmtpUrl(aFilePath, smtpHostName, smtpPort, smtpUserName,
+      rv = NS_MsgBuildSmtpUrl(aFilePath, smtpServer,
                               aRecipients, aSenderIdentity, aUrlListener, aStatusFeedback, 
                               aNotificationCallbacks, &urlToRun, aRequestDSN); // this ref counts urlToRun
       if (NS_SUCCEEDED(rv) && urlToRun)	
-      {
-        nsCOMPtr<nsISmtpUrl> smtpUrl = do_QueryInterface(urlToRun, &rv);
-        if (NS_SUCCEEDED(rv))
-            smtpUrl->SetSmtpServer(smtpServer);
         rv = NS_MsgLoadSmtpUrl(urlToRun, nsnull, aRequest);
-      }
 
       if (aURL) // does the caller want a handle on the url?
         *aURL = urlToRun; // transfer our ref count to the caller....
       else
         NS_IF_RELEASE(urlToRun);
     }
     else
       rv = NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER;
@@ -179,63 +154,76 @@ nsresult nsSmtpService::SendMailMessage(
   return rv;
 }
 
 
 // The following are two convience functions I'm using to help expedite building and running a mail to url...
 
 // short cut function for creating a mailto url...
 nsresult NS_MsgBuildSmtpUrl(nsIFile * aFilePath,
-                            const nsCString &aSmtpHostName,
-                            PRInt32 aSmtpPort,
-                            const nsCString &aSmtpUserName,
+                            nsISmtpServer *aSmtpServer,
                             const char * aRecipients, 
                             nsIMsgIdentity * aSenderIdentity,
                             nsIUrlListener * aUrlListener, 
                             nsIMsgStatusFeedback *aStatusFeedback,
                             nsIInterfaceRequestor* aNotificationCallbacks,
                             nsIURI ** aUrl,
                             PRBool aRequestDSN)
 {
   // 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;
+
+    aSmtpServer->GetHostname(getter_Copies(smtpHostName));
+    aSmtpServer->GetUsername(getter_Copies(smtpUserName));
+    aSmtpServer->GetPort(&smtpPort);
+    aSmtpServer->GetTrySSL(&trySSL);
+
+    if (!smtpPort)
+      smtpPort = (trySSL == PREF_SECURE_ALWAYS_SMTPS) ? 
+        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://");
 
-  if (!aSmtpUserName.IsEmpty())
+  if (!smtpUserName.IsEmpty())
   {
     nsCString escapedUsername;
-    MsgEscapeString(aSmtpUserName, nsINetUtil::ESCAPE_XALPHAS,
+    MsgEscapeString(smtpUserName, nsINetUtil::ESCAPE_XALPHAS,
                     escapedUsername);
     urlSpec.Append(escapedUsername);
     urlSpec.Append('@');
   }
 
-  urlSpec.Append(aSmtpHostName);
-  if (aSmtpHostName.FindChar(':') == -1)
+  urlSpec.Append(smtpHostName);
+  if (smtpHostName.FindChar(':') == -1)
   {
     urlSpec.Append(':');
-    urlSpec.AppendInt(aSmtpPort);
+    urlSpec.AppendInt(smtpPort);
   }
 
   nsCOMPtr<nsIMsgMailNewsUrl> url(do_QueryInterface(smtpUrl, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   url->SetSpec(urlSpec);
   smtpUrl->SetRecipients(aRecipients);
   smtpUrl->SetRequestDSN(aRequestDSN);
   smtpUrl->SetPostMessageFile(aFilePath);
   smtpUrl->SetSenderIdentity(aSenderIdentity);
   smtpUrl->SetNotificationCallbacks(aNotificationCallbacks);
+  smtpUrl->SetSmtpServer(aSmtpServer);
 
   nsCOMPtr<nsIPrompt> smtpPrompt(do_GetInterface(aNotificationCallbacks));
   nsCOMPtr<nsIAuthPrompt> smtpAuthPrompt(do_GetInterface(aNotificationCallbacks));
   if (!smtpPrompt || !smtpAuthPrompt)
   {
     nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
     NS_ENSURE_SUCCESS(rv, rv);
 
@@ -278,16 +266,32 @@ nsresult NS_MsgLoadSmtpUrl(nsIURI * aUrl
         rv = smtpProtocol->LoadUrl(aUrl, aConsumer); // protocol will get destroyed when url is completed...
         smtpProtocol->QueryInterface(NS_GET_IID(nsIRequest), (void **) aRequest);
         NS_RELEASE(smtpProtocol);
     }
 
     return rv;
 }
 
+NS_IMETHODIMP nsSmtpService::VerifyLogon(nsISmtpServer *aServer,
+                                         nsIUrlListener *aUrlListener)
+{
+  NS_ENSURE_ARG_POINTER(aServer);
+  nsCString popHost;
+  nsCString popUser;
+  nsCOMPtr <nsIURI> urlToRun;
+
+  nsresult rv = NS_MsgBuildSmtpUrl(nsnull, aServer,
+                          nsnull, nsnull, aUrlListener, nsnull, 
+                          nsnull , getter_AddRefs(urlToRun), PR_FALSE);
+  if (NS_SUCCEEDED(rv) && urlToRun)	
+    rv = NS_MsgLoadSmtpUrl(urlToRun, nsnull, nsnull /* aRequest */);
+  return rv;
+}
+
 NS_IMETHODIMP nsSmtpService::GetScheme(nsACString &aScheme)
 {
     aScheme = "mailto";
     return NS_OK; 
 }
 
 NS_IMETHODIMP nsSmtpService::GetDefaultPort(PRInt32 *aDefaultPort)
 {
--- a/mailnews/compose/src/nsSmtpUrl.cpp
+++ b/mailnews/compose/src/nsSmtpUrl.cpp
@@ -308,17 +308,17 @@ nsresult nsMailtoUrl::ParseMailtoUrl(cha
 
   return NS_OK;
 }
 
 
 NS_IMETHODIMP nsMailtoUrl::SetSpec(const nsACString &aSpec)
 {
   m_baseURL->SetSpec(aSpec);
-	return ParseUrl();
+  return ParseUrl();
 }
 
 nsresult nsMailtoUrl::CleanupMailtoState()
 {
     m_ccPart = "";
     m_subjectPart = "";
     m_newsgroupPart = "";
     m_newsHostPart = ""; 
@@ -576,16 +576,17 @@ NS_IMETHODIMP nsMailtoUrl::Resolve(const
 /////////////////////////////////////////////////////////////////////////////////////
 
 nsSmtpUrl::nsSmtpUrl() : nsMsgMailNewsUrl()
 {
   // nsISmtpUrl specific state...
 
   m_isPostMessage = PR_TRUE;
   m_requestDSN = PR_FALSE;
+  m_verifyLogon = PR_FALSE;
 }
  
 nsSmtpUrl::~nsSmtpUrl()
 {
 }
   
 NS_IMPL_ISUPPORTS_INHERITED1(nsSmtpUrl, nsMsgMailNewsUrl, nsISmtpUrl)  
 
@@ -603,23 +604,25 @@ nsSmtpUrl::SetRecipients(const char * aR
     nsUnescape(m_toPart.BeginWriting());
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSmtpUrl::GetRecipients(char ** aRecipientsList)
 {
   NS_ENSURE_ARG_POINTER(aRecipientsList);
-	if (aRecipientsList)
-		*aRecipientsList = ToNewCString(m_toPart);
-	return NS_OK;
+  if (aRecipientsList)
+    *aRecipientsList = ToNewCString(m_toPart);
+  return NS_OK;
 }
 
 NS_IMPL_GETSET(nsSmtpUrl, PostMessage, PRBool, m_isPostMessage)
 
+NS_IMPL_GETSET(nsSmtpUrl, VerifyLogon, PRBool, m_verifyLogon)
+
 // the message can be stored in a file....allow accessors for getting and setting
 // the file name to post...
 NS_IMETHODIMP nsSmtpUrl::SetPostMessageFile(nsIFile * aFile)
 {
   NS_ENSURE_ARG_POINTER(aFile);
   m_fileName = aFile;
   return NS_OK;
 }
--- a/mailnews/compose/src/nsSmtpUrl.h
+++ b/mailnews/compose/src/nsSmtpUrl.h
@@ -64,53 +64,54 @@ protected:
   nsresult ParseUrl();
   nsresult CleanupMailtoState();
   nsresult ParseMailtoUrl(char * searchPart);
 
   nsCOMPtr<nsIURI> m_baseURL;
     
   // data retrieved from parsing the url: (Note the url could be a post from file or it could be in the url)
   nsCString m_toPart;
-	nsCString m_ccPart;
-	nsCString	m_subjectPart;
-	nsCString	m_newsgroupPart;
-	nsCString	m_newsHostPart;
-	nsCString	m_referencePart;
-	nsCString	m_bodyPart;
-	nsCString	m_bccPart;
-	nsCString	m_followUpToPart;
-	nsCString	m_fromPart;
-	nsCString	m_htmlPart;
-	nsCString	m_organizationPart;
-	nsCString	m_replyToPart;
-	nsCString	m_priorityPart;
+  nsCString m_ccPart;
+  nsCString m_subjectPart;
+  nsCString m_newsgroupPart;
+  nsCString m_newsHostPart;
+  nsCString m_referencePart;
+  nsCString m_bodyPart;
+  nsCString m_bccPart;
+  nsCString m_followUpToPart;
+  nsCString m_fromPart;
+  nsCString m_htmlPart;
+  nsCString m_organizationPart;
+  nsCString m_replyToPart;
+  nsCString m_priorityPart;
 
   MSG_ComposeFormat mFormat;
 };
 
 class nsSmtpUrl : public nsISmtpUrl, public nsMsgMailNewsUrl
 {
 public:
-	NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_ISUPPORTS_INHERITED
 
-	// From nsISmtpUrl
-	NS_DECL_NSISMTPURL
+  // From nsISmtpUrl
+  NS_DECL_NSISMTPURL
 
-	// nsSmtpUrl
-    nsSmtpUrl();
+  // nsSmtpUrl
+  nsSmtpUrl();
 
 protected:
   virtual ~nsSmtpUrl();
 
   // data retrieved from parsing the url: (Note the url could be a post from
   // file or it could be in the url)
   nsCString m_toPart;
 
   PRBool m_isPostMessage;
   PRBool m_requestDSN;
+  PRBool m_verifyLogon;
 
   // Smtp specific event sinks
   nsCOMPtr<nsIFile> m_fileName;
   nsCOMPtr<nsIMsgIdentity> m_senderIdentity;
   nsCOMPtr<nsIPrompt> m_netPrompt;
   nsCOMPtr<nsIAuthPrompt> m_netAuthPrompt;
   nsCOMPtr<nsIInterfaceRequestor> m_callbacks;
   nsCOMPtr<nsISmtpServer> m_smtpServer;
--- a/mailnews/imap/public/nsIImapService.idl
+++ b/mailnews/imap/public/nsIImapService.idl
@@ -53,23 +53,21 @@ interface nsIUrlListener;
 interface nsIURI;
 interface nsIEventTarget;
 interface nsIFile;
 interface nsIMsgFolder;
 interface nsIMsgWindow;
 interface nsIImapIncomingServer;
 interface nsICacheSession;
 
-[scriptable, uuid(cb905844-b1e1-4850-96c7-407c166319f2)]
+[scriptable, uuid(55ebf0c5-0492-43f4-a17c-56f87cfab5f9)]
 interface nsIImapService : nsISupports
 {
-	// As always, you can pass in null for the url listener and the url if you don't require either.....
-	// aClientEventTarget is the event queue of the event sinks. We post events into this queue.
-	// mscott -- eventually this function will take in the account (identity/incoming server) associated with 
-	// the request
+  // You can pass in null for the url listener and the url if you don't require either.....
+  // aClientEventTarget is the event queue of the event sinks. We post events into this queue.
   void selectFolder(in nsIEventTarget aClientEventTarget, 
                     in nsIMsgFolder aImapMailFolder,
                     in nsIUrlListener aUrlListener,
                     in nsIMsgWindow   aMsgWindow,
                     out nsIURI aURL);
   
   void liteSelectFolder(in nsIEventTarget aClientEventTarget, 
                         in nsIMsgFolder aImapMailFolder,
@@ -109,16 +107,19 @@ interface nsIImapService : nsISupports
                in nsIMsgFolder aImapMailFolder,
                in nsIUrlListener aUrlListener,
                out nsIURI aURL);
   
   nsIURI updateFolderStatus(in nsIEventTarget aClientEventTarget, 
                in nsIMsgFolder aImapMailFolder,
                in nsIUrlListener aUrlListener);
 
+  void verifyLogon(in nsIMsgFolder aImapMailFolder, 
+                   in nsIUrlListener aUrlListener);
+
   void biff(in nsIEventTarget aClientEventTarget, 
             in nsIMsgFolder aImapMailFolder,
             in nsIUrlListener aUrlListener,
             out nsIURI aURL,
             in unsigned long aUidHighWater);
 
   void deleteMessages(in nsIEventTarget aClientEventTarget, 
                       in nsIMsgFolder aImapMailFolder,
--- a/mailnews/imap/public/nsIImapUrl.idl
+++ b/mailnews/imap/public/nsIImapUrl.idl
@@ -55,17 +55,17 @@ typedef long nsImapContentModifiedType;
 interface nsImapContentModifiedTypes
 {
   const long IMAP_CONTENT_NOT_MODIFIED = 0;
   const long IMAP_CONTENT_MODIFIED_VIEW_INLINE = 1;
   const long IMAP_CONTENT_MODIFIED_VIEW_AS_LINKS = 2;
   const long IMAP_CONTENT_FORCE_CONTENT_NOT_MODIFIED = 3;
 } ;
 
-[scriptable, uuid(2065D454-2459-4204-B76F-0650C6FB8683)]
+[scriptable, uuid(be01aef6-f8c1-49b5-ae98-7f2be1977e50)]
 interface nsIImapUrl : nsISupports
 {
   ///////////////////////////////////////////////////////////////////////////////
   // Getters and Setters for the imap specific event sinks to bind to to the url
   ///////////////////////////////////////////////////////////////////////////////
   attribute nsIImapMailFolderSink imapMailFolderSink;
   attribute nsIImapMessageSink imapMessageSink;
   attribute nsIImapServerSink imapServerSink;
@@ -146,16 +146,17 @@ interface nsIImapUrl : nsISupports
   const long nsImapRefreshAllACLs  = 0x00000013;
   const long nsImapListFolder  = 0x00000014;
   const long nsImapUpgradeToSubscription = 0x00000015;
   const long nsImapFolderStatus  = 0x00000016;
   const long nsImapRefreshFolderUrls = 0x00000017;
   const long nsImapEnsureExistsFolder = 0x00000018;
   const long nsImapOfflineToOnlineCopy = 0x00000019;
   const long nsImapOfflineToOnlineMove = 0x0000001A;
+  const long nsImapVerifylogon = 0x0000001B;
   // it's okay to add more imap actions that require us to
   // be in the authenticated state here without renumbering
   // the imap selected state url actions. just make sure you don't
   // set the high bit...
 
   // nsImapSelectedState urls. Note, the high bit is always set for
   // imap actions which require us to be in the selected state
   const long nsImapSelectFolder  = 0x10000002;
--- a/mailnews/imap/src/nsImapIncomingServer.cpp
+++ b/mailnews/imap/src/nsImapIncomingServer.cpp
@@ -85,17 +85,16 @@
 #include "nsITimer.h"
 #include "nsMsgUtils.h"
 
 #define PREF_TRASH_FOLDER_NAME "trash_folder_name"
 #define DEFAULT_TRASH_FOLDER_NAME "Trash"
 
 static NS_DEFINE_CID(kImapProtocolCID, NS_IMAPPROTOCOL_CID);
 static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
-static NS_DEFINE_CID(kImapServiceCID, NS_IMAPSERVICE_CID);
 static NS_DEFINE_CID(kSubscribableServerCID, NS_SUBSCRIBABLESERVER_CID);
 static NS_DEFINE_CID(kCImapHostSessionListCID, NS_IIMAPHOSTSESSIONLIST_CID);
 
 NS_IMPL_ADDREF_INHERITED(nsImapIncomingServer, nsMsgIncomingServer)
 NS_IMPL_RELEASE_INHERITED(nsImapIncomingServer, nsMsgIncomingServer)
 
 NS_INTERFACE_MAP_BEGIN(nsImapIncomingServer)
   NS_INTERFACE_MAP_ENTRY(nsIImapServerSink)
@@ -929,25 +928,39 @@ nsImapIncomingServer::PerformExpand(nsIM
   rv = ResetFoldersToUnverified(nsnull);
 
   nsCOMPtr<nsIMsgFolder> rootMsgFolder;
   rv = GetRootFolder(getter_AddRefs(rootMsgFolder));
   NS_ENSURE_SUCCESS(rv, rv);
   
   if (!rootMsgFolder) return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIImapService> imapService = do_GetService(kImapServiceCID, &rv);
+  nsCOMPtr<nsIImapService> imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
-  if (!imapService)
-    return NS_ERROR_FAILURE;
   rv = imapService->DiscoverAllFolders(NS_GetCurrentThread(), rootMsgFolder,
                                        this, aMsgWindow, nsnull);
   return rv;
 }
 
+NS_IMETHODIMP
+nsImapIncomingServer::VerifyLogon(nsIUrlListener *aUrlListener)
+{
+  nsresult rv;
+
+  nsCOMPtr<nsIImapService> imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIMsgFolder> rootFolder;
+  // this will create the resource if it doesn't exist, but it shouldn't
+  // do anything on disk.
+  rv = GetRootFolder(getter_AddRefs(rootFolder));
+  NS_ENSURE_SUCCESS(rv, rv);
+  return imapService->VerifyLogon(rootFolder, aUrlListener);
+}
+
+
 NS_IMETHODIMP nsImapIncomingServer::PerformBiff(nsIMsgWindow* aMsgWindow)
 {
   nsCOMPtr<nsIMsgFolder> rootMsgFolder;
   nsresult rv = GetRootMsgFolder(getter_AddRefs(rootMsgFolder));
   if(NS_SUCCEEDED(rv))
   {
     SetPerformingBiff(PR_TRUE);
     rv = rootMsgFolder->GetNewMessages(aMsgWindow, nsnull);
@@ -2080,17 +2093,17 @@ nsImapIncomingServer::StartPopulatingWit
 
   rv = SetShowFullName(PR_FALSE);
   NS_ENSURE_SUCCESS(rv,rv);
 
   nsCString serverUri;
   rv = GetServerURI(serverUri);
   NS_ENSURE_SUCCESS(rv,rv);
 
-  nsCOMPtr<nsIImapService> imapService = do_GetService(kImapServiceCID, &rv);
+  nsCOMPtr<nsIImapService> imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv,rv);
 
 /*
     if uri = imap://user@host/foo/bar, the serverUri is imap://user@host
     to get path from uri, skip over imap://user@host + 1 (for the /)
 */
   const char *path = uri + serverUri.Length() + 1;
   return imapService->GetListOfFoldersWithPath(this, aMsgWindow, nsDependentCString(path));
@@ -2109,17 +2122,17 @@ nsImapIncomingServer::StartPopulating(ns
 
   // imap always uses the canonical delimiter form of paths for subscribe ui.
   rv = SetDelimiter('/');
   NS_ENSURE_SUCCESS(rv,rv);
 
   rv = SetShowFullName(PR_FALSE);
   NS_ENSURE_SUCCESS(rv,rv);
 
-  nsCOMPtr<nsIImapService> imapService = do_GetService(kImapServiceCID, &rv);
+  nsCOMPtr<nsIImapService> imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv,rv);
   return imapService->GetListOfFoldersOnServer(this, aMsgWindow);
 }
 
 NS_IMETHODIMP
 nsImapIncomingServer::OnStartRunningUrl(nsIURI *url)
 {
   return NS_OK;
@@ -2279,17 +2292,17 @@ nsImapIncomingServer::Unsubscribe(const 
 {
   return SubscribeToFolder(nsDependentString(aName), PR_FALSE, nsnull);
 }
 
 NS_IMETHODIMP
 nsImapIncomingServer::SubscribeToFolder(const nsAString& aName, PRBool subscribe, nsIURI **aUri)
 {
   nsresult rv;
-  nsCOMPtr<nsIImapService> imapService = do_GetService(kImapServiceCID, &rv);
+  nsCOMPtr<nsIImapService> imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIMsgFolder> rootMsgFolder;
   rv = GetRootFolder(getter_AddRefs(rootMsgFolder));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Locate the folder so that the correct hierarchical delimiter is used in the
   // folder pathnames, otherwise root's (ie, '^') is used and this is wrong.
@@ -2683,24 +2696,17 @@ nsImapIncomingServer::GetFormattedString
                                 getter_Copies(aResult));
   }
   return rv;
 }
 
 nsresult
 nsImapIncomingServer::GetPrefForServerAttribute(const char *prefSuffix, PRBool *prefValue)
 {
-  NS_ENSURE_ARG_POINTER(prefSuffix);
-  nsresult rv;
-  nsCAutoString prefName;
-  nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
-
-  // Time to check if this server has the pref
-  // (mail.server.<serverkey>.prefSuffix) already set
-  return mPrefBranch->GetBoolPref(prefName.get(), prefValue);
+  return GetBoolValue(prefSuffix, prefValue);
 }
 
 NS_IMETHODIMP
 nsImapIncomingServer::GetCanFileMessagesOnServer(PRBool *aCanFileMessagesOnServer)
 {
   NS_ENSURE_ARG_POINTER(aCanFileMessagesOnServer);
   // Initialize aCanFileMessagesOnServer true, a default value for IMAP
   *aCanFileMessagesOnServer = PR_TRUE;
--- a/mailnews/imap/src/nsImapIncomingServer.h
+++ b/mailnews/imap/src/nsImapIncomingServer.h
@@ -92,16 +92,17 @@ public:
   NS_IMETHOD GetFilterScope(nsMsgSearchScopeValue *filterScope);
   NS_IMETHOD GetSearchScope(nsMsgSearchScopeValue *searchScope);
   NS_IMETHOD GetServerRequiresPasswordForBiff(PRBool *aServerRequiresPasswordForBiff);
   NS_IMETHOD OnUserOrHostNameChanged(const nsACString& oldName, const nsACString& newName);
   NS_IMETHOD GetNumIdleConnections(PRInt32 *aNumIdleConnections);
   NS_IMETHOD ForgetSessionPassword();
   NS_IMETHOD GetMsgFolderFromURI(nsIMsgFolder *aFolderResource, const nsACString& aURI, nsIMsgFolder **aFolder);
   NS_IMETHOD SetSocketType(PRInt32 aSocketType);
+  NS_IMETHOD VerifyLogon(nsIUrlListener *aUrlListener);
 
 protected:
   nsresult GetFolder(const nsACString& name, nsIMsgFolder** pFolder);
   nsresult ResetFoldersToUnverified(nsIMsgFolder *parentFolder);
   void GetUnverifiedSubFolders(nsIMsgFolder *parentFolder,
                                nsCOMArray<nsIMsgImapMailFolder> &aFoldersArray);
   void GetUnverifiedFolders(nsCOMArray<nsIMsgImapMailFolder> &aFolderArray);
   nsresult DeleteNonVerifiedFolders(nsIMsgFolder *parentFolder);
--- a/mailnews/imap/src/nsImapProtocol.cpp
+++ b/mailnews/imap/src/nsImapProtocol.cpp
@@ -1550,17 +1550,17 @@ PRBool nsImapProtocol::ProcessCurrentURL
          HandleCurrentUrlError();
 
   }
   else if (!logonFailed)
       HandleCurrentUrlError();
 
   if (mailnewsurl && m_imapMailFolderSink)
   {
-      rv = GetServerStateParser().LastCommandSuccessful()
+      rv = GetServerStateParser().LastCommandSuccessful() && !logonFailed
             ? NS_OK : NS_ERROR_FAILURE;
       // we are done with this url.
       m_imapMailFolderSink->SetUrlState(this, mailnewsurl, PR_FALSE, rv);
        // doom the cache entry
       if (NS_FAILED(rv) && DeathSignalReceived() && m_mockChannel)
         m_mockChannel->Cancel(rv);
   }
   else
@@ -4727,19 +4727,28 @@ nsImapProtocol::AlertUserEventUsingId(PR
   }
 }
 
 void
 nsImapProtocol::AlertUserEvent(const char * message)
 {
   if (m_imapServerSink)
   {
-    nsCOMPtr<nsIMsgWindow> msgWindow;
-    GetMsgWindow(getter_AddRefs(msgWindow));
-    m_imapServerSink->FEAlert(NS_ConvertASCIItoUTF16(message), msgWindow);
+    PRBool suppressErrorMsg = PR_FALSE;
+
+    nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(m_runningUrl);
+    if (mailnewsUrl)
+      mailnewsUrl->GetSuppressErrorMsgs(&suppressErrorMsg);
+
+    if (!suppressErrorMsg)
+    {
+      nsCOMPtr<nsIMsgWindow> msgWindow;
+      GetMsgWindow(getter_AddRefs(msgWindow));
+      m_imapServerSink->FEAlert(NS_ConvertASCIItoUTF16(message), msgWindow);
+    }
   }
 }
 
 void
 nsImapProtocol::AlertUserEventFromServer(const char * aServerEvent)
 {
     if (m_imapServerSink)
     {
@@ -7434,20 +7443,21 @@ void nsImapProtocol::ProcessAuthenticate
     case nsIImapUrl::nsImapRenameFolder:
       sourceMailbox = OnCreateServerSourceFolderPathString();
       OnRenameFolder(sourceMailbox);
       break;
     case nsIImapUrl::nsImapMoveFolderHierarchy:
       sourceMailbox = OnCreateServerSourceFolderPathString();
       OnMoveFolderHierarchy(sourceMailbox);
       break;
+    case nsIImapUrl::nsImapVerifylogon:
+      break;
     default:
       break;
   }
-
   PR_Free(sourceMailbox);
 }
 
 void nsImapProtocol::ProcessAfterAuthenticated()
 {
   // if we're a netscape server, and we haven't got the admin url, get it
   PRBool hasAdminUrl = PR_TRUE;
 
@@ -7616,18 +7626,17 @@ void nsImapProtocol::Check()
 }
 
 nsresult nsImapProtocol::GetMsgWindow(nsIMsgWindow **aMsgWindow)
 {
     nsresult rv = NS_OK;
     nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl =
         do_QueryInterface(m_runningUrl, &rv);
     if (NS_FAILED(rv)) return rv;
-    rv = mailnewsUrl->GetMsgWindow(aMsgWindow);
-    return rv;
+    return mailnewsUrl->GetMsgWindow(aMsgWindow);
 }
 
 nsresult nsImapProtocol::GetPassword(nsCString &password)
 {
   nsCOMPtr<nsIMsgWindow> msgWindow;
 
   if (password.IsEmpty() && m_imapServerSink &&
       !(m_useSecAuth && GetServerStateParser().GetCapabilityFlag() & kHasAuthGssApiCapability))
@@ -7755,18 +7764,23 @@ PRBool nsImapProtocol::TryToLogon()
       }
 
       if (!clientSucceeded || !GetServerStateParser().LastCommandSuccessful())
       {
           // 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 && !DeathSignalReceived() && clientSucceeded)
-            rv = m_imapServerSink->ForgetPassword();
-
+          {
+            nsCOMPtr<nsIMsgWindow> msgWindow;
+            GetMsgWindow(getter_AddRefs(msgWindow));
+            // if there's no msg window, don't forget the password
+            if (msgWindow)
+              rv = m_imapServerSink->ForgetPassword();
+          }
           if (!DeathSignalReceived() && clientSucceeded)
           {
             AlertUserEventUsingId(IMAP_LOGIN_FAILED);
             m_hostSessionList->SetPasswordForHost(GetImapServerKey(), nsnull);
             m_currentBiffState = nsIMsgFolder::nsMsgBiffState_Unknown;
             SendSetBiffIndicatorEvent(m_currentBiffState);
             password.Truncate();
         } // if we didn't receive the death signal...
--- a/mailnews/imap/src/nsImapService.cpp
+++ b/mailnews/imap/src/nsImapService.cpp
@@ -1411,16 +1411,42 @@ nsresult nsImapService::FolderCommand(ns
       rv = uri->SetSpec(urlSpec);
       if (NS_SUCCEEDED(rv))
         rv = GetImapConnectionAndLoadUrl(clientEventTarget, imapUrl, nsnull, url);
     }
   }
   return rv;
 }
 
+NS_IMETHODIMP
+nsImapService::VerifyLogon(nsIMsgFolder *aFolder, nsIUrlListener *aUrlListener)
+{
+  nsCOMPtr<nsIImapUrl> aImapUrl;
+  nsCAutoString urlSpec;
+  
+  PRUnichar delimiter = '/'; // shouldn't matter what is is.
+  nsresult rv = CreateStartOfImapUrl(EmptyCString(), getter_AddRefs(aImapUrl), aFolder,
+                                     aUrlListener, urlSpec, delimiter);
+  if (NS_SUCCEEDED(rv) && aImapUrl)
+  {
+    nsCOMPtr<nsIURI> uri = do_QueryInterface(aImapUrl);
+    
+    nsCOMPtr<nsIMsgMailNewsUrl> mailNewsUrl = do_QueryInterface(aImapUrl);
+    mailNewsUrl->SetSuppressErrorMsgs(PR_TRUE);
+    rv = SetImapUrlSink(aFolder, aImapUrl);
+    urlSpec.Append("/verifyLogon");
+    rv = uri->SetSpec(urlSpec);
+    if (NS_SUCCEEDED(rv))
+      rv = GetImapConnectionAndLoadUrl(NS_GetCurrentThread(), aImapUrl, nsnull, nsnull);
+  }
+  return rv;
+
+}
+
+
 // Noop, used to update a folder (causes server to send changes).
 NS_IMETHODIMP nsImapService::Noop(nsIEventTarget *aClientEventTarget, 
                                   nsIMsgFolder *aImapMailFolder,
                                   nsIUrlListener *aUrlListener, 
                                   nsIURI **aURL)
 {
   return FolderCommand(aClientEventTarget, aImapMailFolder, aUrlListener,
                        "/selectnoop>", nsIImapUrl::nsImapSelectNoopFolder, nsnull, aURL);
--- a/mailnews/imap/src/nsImapUrl.cpp
+++ b/mailnews/imap/src/nsImapUrl.cpp
@@ -455,17 +455,17 @@ void nsImapUrl::ParseImapPart(char *imap
   {
     m_imapAction  = nsImapMsgFetch;
     ParseUidChoice();
     PR_FREEIF(m_sourceCanonicalFolderPathSubString);
     ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
     ParseListOfMessageIds();
     // if fetched by spam filter, the action will be changed to nsImapMsgFetchPeek
   }
-  else /* if (fInternal) no concept of internal - not sure there will be one */
+  else
   {
     if (!PL_strcasecmp(m_urlidSubString, "header"))
     {
       m_imapAction = nsImapMsgHeader;
       ParseUidChoice();
       ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
       ParseListOfMessageIds();
     }
@@ -709,16 +709,20 @@ void nsImapUrl::ParseImapPart(char *imap
       m_imapAction = nsImapUpgradeToSubscription;
       ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
     }
     else if (!PL_strcasecmp(m_urlidSubString, "folderstatus"))
     {
       m_imapAction = nsImapFolderStatus;
       ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
     }
+    else if (!PL_strcasecmp(m_urlidSubString, "verifyLogon"))
+    {
+      m_imapAction = nsImapVerifylogon;
+    }
     else if (m_imapAction == nsIImapUrl::nsImapUserDefinedMsgCommand)
     {
       m_command = m_urlidSubString; // save this
       ParseUidChoice();
       ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
       ParseListOfMessageIds();
     }
     else if (m_imapAction == nsIImapUrl::nsImapMsgStoreCustomKeywords)
--- a/mailnews/local/public/nsIPop3Service.idl
+++ b/mailnews/local/public/nsIPop3Service.idl
@@ -39,23 +39,22 @@
 #include "nsIUrlListener.idl"
 #include "nsIPop3IncomingServer.idl"
 #include "nsIMsgFolder.idl"
 
 interface nsIURI;
 interface nsIStreamListener;
 interface nsIMsgWindow;
 interface nsIMsgFolder;
+
 /*
  * The Pop3 Service is an interface designed to make building and running
- * pop3 urls easier. I'm not sure if this service will go away when the
- * new networking model comes on line (as part of the N2 project). So
- * I reserve the right to change my mind and take this service away =).
+ * pop3 urls easier. 
  */
-[scriptable, uuid(3BB459E0-D746-11d2-806A-006008128C4E)]
+[scriptable, uuid(d3b0eead-a0aa-47bd-a751-aa01e01c1ff7)]
 interface nsIPop3Service : nsISupports {
   /*
    * All of these functions build pop3 urls and run them. If you want
    * a handle on the running task, pass in a valid nsIURI ptr. You can later
    * interrupt this action by asking the netlib service manager to interrupt
    * the url you are given back. Remember to release aURL when you are
    * done with it. Pass nsnull in for aURL if you
    * don't care about the returned URL.
@@ -64,15 +63,25 @@ interface nsIPop3Service : nsISupports {
   /*
    * right now getting new mail doesn't require any user specific data.
    * We use the default current identity for this information. I suspect that
    * we'll eventually pass in an identity to this call so you can get
    * mail on different pop3 accounts....
    */
 
   nsIURI GetNewMail(in nsIMsgWindow aMsgWindow, in nsIUrlListener aUrlListener,
-          in nsIMsgFolder aInbox,
-                    in nsIPop3IncomingServer popServer);
+                    in nsIMsgFolder aInbox, in nsIPop3IncomingServer popServer);
 
   nsIURI CheckForNewMail(in nsIMsgWindow aMsgWindow, in nsIUrlListener aUrlListener,
-             in nsIMsgFolder inbox,
-                         in nsIPop3IncomingServer popServer);
+                         in nsIMsgFolder inbox, in nsIPop3IncomingServer popServer);
+
+  /**
+   * Verify that we can logon 
+   * 
+   * @param  aServer - pop3 server we're logging on to.
+   * @param  aUrlListener - gets called back with success or failure.
+   *
+   */
+  void verifyLogon(in nsIMsgIncomingServer aServer, 
+                   in nsIUrlListener aUrlListener);
+
+
 };
--- a/mailnews/local/src/nsPop3IncomingServer.cpp
+++ b/mailnews/local/src/nsPop3IncomingServer.cpp
@@ -416,16 +416,25 @@ nsPop3IncomingServer::GetCanCreateFolder
   NS_ENSURE_ARG_POINTER(aCanCreateFoldersOnServer);
 
   nsCString deferredToAccount;
   GetDeferredToAccount(deferredToAccount);
   *aCanCreateFoldersOnServer = deferredToAccount.IsEmpty();
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsPop3IncomingServer::VerifyLogon(nsIUrlListener *aUrlListener)
+{
+  nsresult rv;
+  nsCOMPtr<nsIPop3Service> pop3Service = do_GetService(kCPop3ServiceCID, &rv);
+  NS_ENSURE_SUCCESS(rv,rv);
+  return pop3Service->VerifyLogon(this, aUrlListener);
+}
+
 NS_IMETHODIMP nsPop3IncomingServer::DownloadMailFromServers(nsISupportsArray *aServers,
                               nsIMsgWindow *aMsgWindow,
                               nsIMsgFolder *aFolder,
                               nsIUrlListener *aUrlListener)
 {
   nsPop3GetMailChainer *getMailChainer = new nsPop3GetMailChainer;
   NS_ENSURE_TRUE(getMailChainer, NS_ERROR_OUT_OF_MEMORY);
   getMailChainer->AddRef(); // this object owns itself and releases when done.
--- a/mailnews/local/src/nsPop3IncomingServer.h
+++ b/mailnews/local/src/nsPop3IncomingServer.h
@@ -63,18 +63,19 @@ public:
   NS_IMETHOD PerformBiff(nsIMsgWindow *aMsgWindow);
   NS_IMETHOD GetDownloadMessagesAtStartup(PRBool *getMessages);
   NS_IMETHOD GetCanBeDefaultServer(PRBool *canBeDefaultServer);
   NS_IMETHOD GetCanSearchMessages(PRBool *canSearchMessages);
   NS_IMETHOD GetOfflineSupportLevel(PRInt32 *aSupportLevel);
   NS_IMETHOD GetRootMsgFolder(nsIMsgFolder **aRootMsgFolder);
   NS_IMETHOD GetCanFileMessagesOnServer(PRBool *aCanFileMessagesOnServer);
   NS_IMETHOD GetCanCreateFoldersOnServer(PRBool *aCanCreateFoldersOnServer);
+  NS_IMETHOD VerifyLogon(nsIUrlListener *aUrlListener);
   NS_IMETHOD GetNewMessages(nsIMsgFolder *aFolder, nsIMsgWindow *aMsgWindow,
-                    nsIUrlListener *aUrlListener);
+                            nsIUrlListener *aUrlListener);
 
 protected:
   nsresult GetInbox(nsIMsgWindow *msgWindow, nsIMsgFolder **inbox);
 
 private:
   PRUint32 m_capabilityFlags;
   PRBool m_authenticated;
   nsCOMPtr <nsIPop3Protocol> m_runningProtocol;
--- a/mailnews/local/src/nsPop3Protocol.cpp
+++ b/mailnews/local/src/nsPop3Protocol.cpp
@@ -786,21 +786,22 @@ nsresult nsPop3Protocol::LoadUrl(nsIURI*
   rv = NS_CheckPortSafety(port, "pop");
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCAutoString queryPart;
   rv = url->GetQuery(queryPart);
   NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get the url spect");
 
   m_pop3ConData->only_check_for_new_mail = (PL_strcasestr(queryPart.get(), "check") != nsnull);
+  m_pop3ConData->verify_logon = (PL_strcasestr(queryPart.get(), "verifyLogon") != nsnull);
   m_pop3ConData->get_url = (PL_strcasestr(queryPart.get(), "gurl") != nsnull);
 
   PRBool deleteByAgeFromServer = PR_FALSE;
   PRInt32 numDaysToLeaveOnServer = -1;
-  if (!m_pop3ConData->only_check_for_new_mail)
+  if (!m_pop3ConData->only_check_for_new_mail && !m_pop3ConData->verify_logon)
   {
     // Pick up pref setting regarding leave messages on server, message size limit
 
     m_pop3Server->GetLeaveMessagesOnServer(&m_pop3ConData->leave_on_server);
     m_pop3Server->GetHeadersOnly(&m_pop3ConData->headers_only);
     PRBool limitMessageSize = PR_FALSE;
 
     nsCOMPtr<nsIMsgIncomingServer> server = do_QueryInterface(m_pop3Server);
@@ -837,17 +838,19 @@ nsresult nsPop3Protocol::LoadUrl(nsIURI*
   if (server)
   {
     rv = server->GetLocalPath(getter_AddRefs(mailDirectory));
     server->SetServerBusy(PR_TRUE); // the server is now busy
     server->GetHostName(hostName);
     server->GetUsername(userName);
   }
 
-  m_pop3ConData->uidlinfo = net_pop3_load_state(hostName.get(), userName.get(), mailDirectory);
+  if (!m_pop3ConData->verify_logon)
+    m_pop3ConData->uidlinfo = net_pop3_load_state(hostName.get(), userName.get(), mailDirectory);
+
   m_pop3ConData->biffstate = nsIMsgFolder::nsMsgBiffState_NoMail;
 
   if (m_pop3ConData->uidlinfo && numDaysToLeaveOnServer > 0)
   {
     PRUint32 nowInSeconds = TimeInSecondsFromPRTime(PR_Now());
     PRUint32 cutOffDay = nowInSeconds - (60 * 60 * 24 * numDaysToLeaveOnServer);
 
     PL_HashTableEnumerateEntries(m_pop3ConData->uidlinfo->hash, net_pop3_delete_old_msgs_mapper, (void *) cutOffDay);
@@ -1430,18 +1433,21 @@ void nsPop3Protocol::RestoreAuthFlags()
 
 PRInt32 nsPop3Protocol::AuthFallback()
 {
     if (m_pop3ConData->command_succeeded)
         if(m_password_already_sent)
         {
             m_nsIPop3Sink->SetUserAuthenticated(PR_TRUE);
             ClearFlag(POP3_PASSWORD_FAILED);
-            m_pop3ConData->next_state = (m_pop3ConData->get_url)
-              ? POP3_SEND_GURL : POP3_SEND_STAT;
+            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
     {
         // 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))
--- a/mailnews/local/src/nsPop3Protocol.h
+++ b/mailnews/local/src/nsPop3Protocol.h
@@ -230,16 +230,18 @@ typedef struct _Pop3ConData {
     PRInt32 cur_msg_size;
     PRBool truncating_cur_msg;  /* are we using top and uidl? */
     PRBool msg_del_started;     /* True if MSG_BeginMailDel...
                                  * called
                                  */
     PRBool only_check_for_new_mail;
     nsMsgBiffState biffstate;     /* If just checking for, what the answer is. */
 
+    PRBool verify_logon;        /* true if we're just seeing if we can logon */
+
     void *msg_closure;
 
     PRBool graph_progress_bytes_p; /* whether we should display info about
                                       the bytes transferred (usually we
                                       display info about the number of
                                       messages instead.) */
 
     Pop3UidlHost *uidlinfo;
--- a/mailnews/local/src/nsPop3Service.cpp
+++ b/mailnews/local/src/nsPop3Service.cpp
@@ -45,16 +45,17 @@
 
 #include "nsPop3URL.h"
 #include "nsPop3Sink.h"
 #include "nsPop3Protocol.h"
 #include "nsMsgLocalCID.h"
 #include "nsMsgBaseCID.h"
 #include "nsCOMPtr.h"
 #include "nsIMsgWindow.h"
+#include "nsINetUtil.h"
 
 #include "nsIRDFService.h"
 #include "nsRDFCID.h"
 #include "nsIDirectoryService.h"
 #include "nsMailDirServiceDefs.h"
 #include "prprf.h"
 #include "nsEscape.h"
 #include "nsMsgUtils.h"
@@ -166,16 +167,60 @@ nsresult nsPop3Service::GetMail(PRBool d
     rv = RunPopUrl(server, url);
 
   if (aURL && url) // we already have a ref count on pop3url...
     NS_IF_ADDREF(*aURL = url);
 
   return rv;
 }
 
+NS_IMETHODIMP nsPop3Service::VerifyLogon(nsIMsgIncomingServer *aServer,
+                                         nsIUrlListener *aUrlListener)
+{
+  NS_ENSURE_ARG_POINTER(aServer);
+  nsCString popHost;
+  nsCString popUser;
+  PRInt32 popPort = -1;
+
+  nsresult rv = aServer->GetHostName(popHost);
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (popHost.IsEmpty())
+    return NS_MSG_INVALID_OR_MISSING_SERVER;
+
+  rv = aServer->GetPort(&popPort);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aServer->GetUsername(popUser);
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (popUser.IsEmpty())
+    return NS_MSG_SERVER_USERNAME_MISSING;
+
+  nsCString escapedUsername;
+  MsgEscapeString(popUser, nsINetUtil::ESCAPE_XALPHAS, escapedUsername);
+
+  nsCOMPtr <nsIPop3IncomingServer> popServer = do_QueryInterface(aServer, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+  // now construct a pop3 url...
+  // we need to escape the username because it may contain
+  // characters like / % or @
+  char * urlSpec = PR_smprintf("pop3://%s@%s:%d/?verifyLogon", 
+                              escapedUsername.get(), popHost.get(), popPort);
+  if (!urlSpec)
+    return NS_ERROR_OUT_OF_MEMORY;
+  nsCOMPtr<nsIURI> url;
+  rv = BuildPop3Url(urlSpec, nsnull, popServer, aUrlListener, 
+                    getter_AddRefs(url), nsnull);
+  PR_smprintf_free(urlSpec);
+
+  if (NS_SUCCEEDED(rv) && url)
+    rv = RunPopUrl(aServer, url);
+
+  return rv;
+}
+
 nsresult nsPop3Service::BuildPop3Url(const char * urlSpec,
                                      nsIMsgFolder *inbox,
                                      nsIPop3IncomingServer *server,
                                      nsIUrlListener * aUrlListener,
                                      nsIURI ** aUrl,
                                      nsIMsgWindow *aMsgWindow)
 {
   nsresult rv;