diff --git a/emailcommon/src/com/android/emailcommon/service/AccountServiceProxy.java b/emailcommon/src/com/android/emailcommon/service/AccountServiceProxy.java
index f4eb93009..d65473894 100644
--- a/emailcommon/src/com/android/emailcommon/service/AccountServiceProxy.java
+++ b/emailcommon/src/com/android/emailcommon/service/AccountServiceProxy.java
@@ -45,11 +45,11 @@ public class AccountServiceProxy extends ServiceProxy implements IAccountService
}
@Override
- public void notifyLoginFailed(final long accountId) {
+ public void notifyLoginFailed(final long accountId, final String reason) {
setTask(new ProxyTask() {
@Override
public void run() throws RemoteException {
- mService.notifyLoginFailed(accountId);
+ mService.notifyLoginFailed(accountId, reason);
}
}, "notifyLoginFailed");
}
diff --git a/emailcommon/src/com/android/emailcommon/service/IAccountService.aidl b/emailcommon/src/com/android/emailcommon/service/IAccountService.aidl
index a29baf58c..d456862b0 100644
--- a/emailcommon/src/com/android/emailcommon/service/IAccountService.aidl
+++ b/emailcommon/src/com/android/emailcommon/service/IAccountService.aidl
@@ -19,7 +19,7 @@ package com.android.emailcommon.service;
import android.os.Bundle;
interface IAccountService {
- oneway void notifyLoginFailed(long accountId);
+ oneway void notifyLoginFailed(long accountId, String reason);
oneway void notifyLoginSucceeded(long accountId);
void reconcileAccounts(String protocol, String accountManagerType);
diff --git a/emailsync/src/com/android/emailsync/AbstractSyncService.java b/emailsync/src/com/android/emailsync/AbstractSyncService.java
index 7cbf13ac5..c9b151a4f 100644
--- a/emailsync/src/com/android/emailsync/AbstractSyncService.java
+++ b/emailsync/src/com/android/emailsync/AbstractSyncService.java
@@ -59,6 +59,7 @@ public abstract class AbstractSyncService implements Runnable {
public Mailbox mMailbox;
protected long mMailboxId;
protected int mExitStatus = EXIT_EXCEPTION;
+ protected String mExitReason;
protected String mMailboxName;
public Account mAccount;
public Context mContext;
diff --git a/emailsync/src/com/android/emailsync/SyncManager.java b/emailsync/src/com/android/emailsync/SyncManager.java
index 9360b070c..d81abee60 100644
--- a/emailsync/src/com/android/emailsync/SyncManager.java
+++ b/emailsync/src/com/android/emailsync/SyncManager.java
@@ -2209,7 +2209,7 @@ public abstract class SyncManager extends Service implements Runnable {
break;
// These errors are not retried automatically
case AbstractSyncService.EXIT_LOGIN_FAILURE:
- new AccountServiceProxy(ssm).notifyLoginFailed(m.mAccountKey);
+ new AccountServiceProxy(ssm).notifyLoginFailed(m.mAccountKey, svc.mExitReason);
lastResult = EmailContent.LAST_SYNC_RESULT_AUTH_ERROR;
break;
case AbstractSyncService.EXIT_SECURITY_FAILURE:
diff --git a/imap2/src/com/android/imap2/Imap2SyncService.java b/imap2/src/com/android/imap2/Imap2SyncService.java
index 5e84ebe76..28135916a 100644
--- a/imap2/src/com/android/imap2/Imap2SyncService.java
+++ b/imap2/src/com/android/imap2/Imap2SyncService.java
@@ -101,6 +101,7 @@ public class Imap2SyncService extends AbstractSyncService {
private static final SimpleDateFormat GMAIL_INTERNALDATE_FORMAT =
new SimpleDateFormat("EEE, dd MMM yy HH:mm:ss z");
private static final String IMAP_ERR = "ERR";
+ private static final String IMAP_NO = "NO";
private static final SimpleDateFormat IMAP_DATE_FORMAT =
new SimpleDateFormat("dd-MMM-yyyy");
@@ -1573,6 +1574,7 @@ public class Imap2SyncService extends AbstractSyncService {
public static class Connection {
Socket socket;
int status;
+ String reason;
ImapInputStream reader;
BufferedWriter writer;
@@ -1649,7 +1651,13 @@ public class Imap2SyncService extends AbstractSyncService {
tag = writeCommand(writer,
"login " + hostAuth.mLogin + ' ' + hostAuth.mPassword);
- if (!readResponse(reader, tag).equals(IMAP_OK)) {
+ if (!IMAP_OK.equals(readResponse(reader, tag))) {
+ if (IMAP_NO.equals(mImapResult)) {
+ int alertPos = mImapErrorLine.indexOf("[ALERT]");
+ if (alertPos > 0) {
+ conn.reason = mImapErrorLine.substring(alertPos + 7);
+ }
+ }
conn.status = EXIT_LOGIN_FAILURE;
} else {
conn.socket = socket;
@@ -1960,6 +1968,7 @@ public class Imap2SyncService extends AbstractSyncService {
Connection conn = connectAndLogin(hostAuth, "main");
if (conn.status != EXIT_DONE) {
mExitStatus = conn.status;
+ mExitReason = conn.reason;
return;
}
setConnection(conn);
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 90317fdf7..a6f3b543e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -911,11 +911,16 @@ as %s.
Couldn\'t sign in
-
The username or password for %s is incorrect.
Do you want to update them now?
+
+
+ Your login to %s failed; the server said: %s
+ Do you want to update your username and/or password?
Default account
diff --git a/src/com/android/email/NotificationController.java b/src/com/android/email/NotificationController.java
index ca87c65fd..bde5db9e1 100644
--- a/src/com/android/email/NotificationController.java
+++ b/src/com/android/email/NotificationController.java
@@ -747,6 +747,10 @@ public class NotificationController {
* NOTE: DO NOT CALL THIS METHOD FROM THE UI THREAD (DATABASE ACCESS)
*/
public void showLoginFailedNotification(long accountId) {
+ showLoginFailedNotification(accountId, null);
+ }
+
+ public void showLoginFailedNotification(long accountId, String reason) {
final Account account = Account.restoreAccountWithId(mContext, accountId);
if (account == null) return;
final Mailbox mailbox = Mailbox.restoreMailboxOfType(mContext, account.mId,
@@ -757,7 +761,7 @@ public class NotificationController {
mContext.getString(R.string.login_failed_title),
account.getDisplayName(),
AccountSettings.createAccountSettingsIntent(mContext, accountId,
- account.mDisplayName),
+ account.mDisplayName, reason),
getLoginFailedNotificationId(accountId));
}
@@ -841,7 +845,8 @@ public class NotificationController {
* account settings screen where he can view the list of enforced policies
*/
public void showSecurityChangedNotification(Account account) {
- Intent intent = AccountSettings.createAccountSettingsIntent(mContext, account.mId, null);
+ Intent intent =
+ AccountSettings.createAccountSettingsIntent(mContext, account.mId, null, null);
String accountName = account.getDisplayName();
String ticker =
mContext.getString(R.string.security_changed_ticker_fmt, accountName);
@@ -855,7 +860,8 @@ public class NotificationController {
* account settings screen where he can view the list of unsupported policies
*/
public void showSecurityUnsupportedNotification(Account account) {
- Intent intent = AccountSettings.createAccountSettingsIntent(mContext, account.mId, null);
+ Intent intent =
+ AccountSettings.createAccountSettingsIntent(mContext, account.mId, null, null);
String accountName = account.getDisplayName();
String ticker =
mContext.getString(R.string.security_unsupported_ticker_fmt, accountName);
diff --git a/src/com/android/email/activity/setup/AccountSettings.java b/src/com/android/email/activity/setup/AccountSettings.java
index 23eb17fa9..b64b95ded 100644
--- a/src/com/android/email/activity/setup/AccountSettings.java
+++ b/src/com/android/email/activity/setup/AccountSettings.java
@@ -76,6 +76,8 @@ public class AccountSettings extends PreferenceActivity {
// Intent extras for our internal activity launch
private static final String EXTRA_ENABLE_DEBUG = "AccountSettings.enable_debug";
private static final String EXTRA_LOGIN_WARNING_FOR_ACCOUNT = "AccountSettings.for_account";
+ private static final String EXTRA_LOGIN_WARNING_REASON_FOR_ACCOUNT =
+ "AccountSettings.for_account_reason";
private static final String EXTRA_TITLE = "AccountSettings.title";
public static final String EXTRA_NO_ACCOUNTS = "AccountSettings.no_account";
@@ -127,7 +129,8 @@ public class AccountSettings extends PreferenceActivity {
* Display (and edit) settings for a specific account, or -1 for any/all accounts
*/
public static void actionSettings(Activity fromActivity, long accountId) {
- fromActivity.startActivity(createAccountSettingsIntent(fromActivity, accountId, null));
+ fromActivity.startActivity(
+ createAccountSettingsIntent(fromActivity, accountId, null, null));
}
/**
@@ -136,13 +139,16 @@ public class AccountSettings extends PreferenceActivity {
* displayed as well.
*/
public static Intent createAccountSettingsIntent(Context context, long accountId,
- String loginWarningAccountName) {
+ String loginWarningAccountName, String loginWarningReason) {
final Uri.Builder b = IntentUtilities.createActivityIntentUrlBuilder("settings");
IntentUtilities.setAccountId(b, accountId);
Intent i = new Intent(Intent.ACTION_EDIT, b.build());
if (loginWarningAccountName != null) {
i.putExtra(EXTRA_LOGIN_WARNING_FOR_ACCOUNT, loginWarningAccountName);
}
+ if (loginWarningReason != null) {
+ i.putExtra(EXTRA_LOGIN_WARNING_REASON_FOR_ACCOUNT, loginWarningReason);
+ }
return i;
}
@@ -182,9 +188,12 @@ public class AccountSettings extends PreferenceActivity {
// Otherwise, we're called from within the Email app and look for our extras
mRequestedAccountId = IntentUtilities.getAccountIdFromIntent(i);
String loginWarningAccount = i.getStringExtra(EXTRA_LOGIN_WARNING_FOR_ACCOUNT);
+ String loginWarningReason =
+ i.getStringExtra(EXTRA_LOGIN_WARNING_REASON_FOR_ACCOUNT);
if (loginWarningAccount != null) {
// Show dialog (first time only - don't re-show on a rotation)
- LoginWarningDialog dialog = LoginWarningDialog.newInstance(loginWarningAccount);
+ LoginWarningDialog dialog =
+ LoginWarningDialog.newInstance(loginWarningAccount, loginWarningReason);
dialog.show(getFragmentManager(), "loginwarning");
}
}
@@ -809,15 +818,17 @@ public class AccountSettings extends PreferenceActivity {
public static class LoginWarningDialog extends DialogFragment
implements DialogInterface.OnClickListener {
private static final String BUNDLE_KEY_ACCOUNT_NAME = "account_name";
+ private String mReason;
/**
* Create a new dialog.
*/
- public static LoginWarningDialog newInstance(String accountName) {
+ public static LoginWarningDialog newInstance(String accountName, String reason) {
final LoginWarningDialog dialog = new LoginWarningDialog();
Bundle b = new Bundle();
b.putString(BUNDLE_KEY_ACCOUNT_NAME, accountName);
dialog.setArguments(b);
+ dialog.mReason = reason;
return dialog;
}
@@ -830,8 +841,13 @@ public class AccountSettings extends PreferenceActivity {
final AlertDialog.Builder b = new AlertDialog.Builder(context);
b.setTitle(R.string.account_settings_login_dialog_title);
b.setIconAttribute(android.R.attr.alertDialogIcon);
- b.setMessage(res.getString(R.string.account_settings_login_dialog_content_fmt,
- accountName));
+ if (mReason != null) {
+ b.setMessage(res.getString(R.string.account_settings_login_dialog_reason_fmt,
+ accountName, mReason));
+ } else {
+ b.setMessage(res.getString(R.string.account_settings_login_dialog_content_fmt,
+ accountName));
+ }
b.setPositiveButton(R.string.okay_action, this);
b.setNegativeButton(R.string.cancel_action, this);
return b.create();
diff --git a/src/com/android/email/service/AccountService.java b/src/com/android/email/service/AccountService.java
index 56f432a7d..b79842fa1 100644
--- a/src/com/android/email/service/AccountService.java
+++ b/src/com/android/email/service/AccountService.java
@@ -47,8 +47,9 @@ public class AccountService extends Service {
private final IAccountService.Stub mBinder = new IAccountService.Stub() {
@Override
- public void notifyLoginFailed(long accountId) {
- NotificationController.getInstance(mContext).showLoginFailedNotification(accountId);
+ public void notifyLoginFailed(long accountId, String reason) {
+ NotificationController nc = NotificationController.getInstance(mContext);
+ nc.showLoginFailedNotification(accountId, reason);
}
@Override