Loading k9mail-library/src/main/java/com/fsck/k9/mail/AuthenticationFailedException.java +2 −0 Original line number Diff line number Diff line Loading @@ -3,6 +3,8 @@ package com.fsck.k9.mail; public class AuthenticationFailedException extends MessagingException { public static final long serialVersionUID = -1; public static final String OAUTH2_ERROR_INVALID_REFRESH_TOKEN = "oauth2-invalid refresh token"; public static final String OAUTH2_ERROR_UNKNOWN = "oauth2-unknown"; public AuthenticationFailedException(String message) { super(message); Loading k9mail/src/main/java/com/fsck/k9/account/AndroidSpecificOAuth2TokenProvider.java +29 −5 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ package com.fsck.k9.account; import com.fsck.k9.mail.AuthenticationFailedException; import com.fsck.k9.mail.oauth.OAuth2AuthorizationCodeFlowTokenProvider; import com.fsck.k9.mail.oauth.SpecificOAuth2TokenProvider; import com.google.gson.Gson; import com.google.gson.annotations.SerializedName; import java.io.IOException; Loading Loading @@ -42,16 +43,39 @@ abstract class AndroidSpecificOAuth2TokenProvider extends SpecificOAuth2TokenPro public String refreshToken(String username, String refreshToken) throws AuthenticationFailedException { Call<RefreshResponse> call = getRefreshTokenCall(refreshToken); RefreshResponse response; Response<RefreshResponse> response; RefreshResponse refreshResponse; try { response = call.execute().body(); response = call.execute(); refreshResponse = response.body(); } catch (IOException e) { throw new AuthenticationFailedException(e.getMessage()); } if (response == null) { throw new AuthenticationFailedException("Error when getting refresh token"); if (refreshResponse == null) { if (response.errorBody() != null) { try { String errorBody = response.errorBody().string(); OAuth2Error oAuth2Error = new Gson().fromJson(errorBody, OAuth2Error.class); switch (oAuth2Error.error) { case "invalid_grant": throw new AuthenticationFailedException(AuthenticationFailedException.OAUTH2_ERROR_INVALID_REFRESH_TOKEN); default: throw new AuthenticationFailedException(AuthenticationFailedException.OAUTH2_ERROR_UNKNOWN); } } catch (IOException e) { throw new AuthenticationFailedException(AuthenticationFailedException.OAUTH2_ERROR_UNKNOWN); } } else { throw new AuthenticationFailedException(AuthenticationFailedException.OAUTH2_ERROR_UNKNOWN); } } return response.accessToken; return refreshResponse.accessToken; } protected static class OAuth2Error { String error; @SerializedName("error_description") String errorDescription; } protected static class ExchangeResponse { Loading k9mail/src/main/java/com/fsck/k9/activity/setup/AccountSetupActivity.java +46 −2 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ import android.widget.Spinner; import android.widget.TextView; import com.fsck.k9.mail.ServerSettings.Type; import com.fsck.k9.service.StorageGoneReceiver; import com.fsck.k9.view.ClientCertificateSpinner; import me.zhanghai.android.materialprogressbar.MaterialProgressBar; Loading Loading @@ -92,10 +93,12 @@ public class AccountSetupActivity extends AppCompatActivity implements AccountSe private ClientCertificateSpinner clientCertificateSpinner; private TextView clientCertificateLabelView; private TextInputLayout usernameViewLayout; private TextInputLayout passwordViewLayout; private TextInputLayout serverViewLayout; private TextInputEditText serverView; private TextInputEditText portView; private TextView securityTypeLabelView; private Spinner securityTypeView; private Spinner authTypeView; private CheckBox imapAutoDetectNamespaceView; Loading Loading @@ -758,6 +761,7 @@ public class AccountSetupActivity extends AppCompatActivity implements AccountSe View incomingView = findViewById(R.id.account_setup_incoming); coordinatorLayout = (CoordinatorLayout) findViewById(R.id.incoming_coordinator_layout); usernameView = (EditText) incomingView.findViewById(R.id.incoming_account_username); usernameViewLayout = (TextInputLayout) incomingView.findViewById(R.id.incoming_account_username_layout); passwordView = (EditText) incomingView.findViewById(R.id.incoming_account_password); clientCertificateSpinner = (ClientCertificateSpinner) incomingView.findViewById(R.id.incoming_account_client_certificate_spinner); clientCertificateLabelView = (TextView) incomingView.findViewById(R.id.account_client_certificate_label); Loading @@ -765,6 +769,7 @@ public class AccountSetupActivity extends AppCompatActivity implements AccountSe serverViewLayout = (TextInputLayout) incomingView.findViewById(R.id.incoming_account_server_layout); serverView = (TextInputEditText) incomingView.findViewById(R.id.incoming_account_server); portView = (TextInputEditText) incomingView.findViewById(R.id.incoming_account_port); securityTypeLabelView = (TextView) incomingView.findViewById(R.id.account_setup_incoming_security_label); securityTypeView = (Spinner) incomingView.findViewById(R.id.incoming_account_security_type); authTypeView = (Spinner) incomingView.findViewById(R.id.incoming_account_auth_type); imapAutoDetectNamespaceView = (CheckBox) incomingView.findViewById(R.id.imap_autodetect_namespace); Loading Loading @@ -849,24 +854,38 @@ public class AccountSetupActivity extends AppCompatActivity implements AccountSe @Override public void setViewNotExternalInIncoming() { passwordView.setVisibility(View.VISIBLE); passwordViewLayout.setVisibility(View.VISIBLE); clientCertificateLabelView.setVisibility(View.GONE); clientCertificateSpinner.setVisibility(View.GONE); imapAutoDetectNamespaceView.setEnabled(true); passwordViewLayout.setEnabled(true); securityTypeView.setEnabled(true); portView.setEnabled(true); passwordView.requestFocus(); } @Override public void setViewExternalInIncoming() { passwordView.setVisibility(View.GONE); passwordViewLayout.setVisibility(View.GONE); clientCertificateLabelView.setVisibility(View.VISIBLE); clientCertificateSpinner.setVisibility(View.VISIBLE); imapAutoDetectNamespaceView.setEnabled(true); passwordViewLayout.setEnabled(true); securityTypeView.setEnabled(true); portView.setEnabled(true); clientCertificateSpinner.chooseCertificate(); } @Override public void setViewOAuth2InIncoming() { imapAutoDetectNamespaceView.setEnabled(false); passwordViewLayout.setEnabled(false); securityTypeView.setEnabled(false); portView.setEnabled(false); } @Override public void showFailureToast(Exception use) { failure(use); Loading Loading @@ -902,6 +921,17 @@ public class AccountSetupActivity extends AppCompatActivity implements AccountSe Toast.makeText(this, toastText, Toast.LENGTH_LONG).show(); } @Override public void showInvalidOAuthError() { usernameViewLayout.setErrorEnabled(true); usernameViewLayout.setError(getString(R.string.OAuth2_not_supported)); } @Override public void clearInvalidOAuthError() { usernameViewLayout.setError(""); } // names public void namesStart() { Loading Loading @@ -1068,6 +1098,7 @@ public class AccountSetupActivity extends AppCompatActivity implements AccountSe final View outgoingView = findViewById(R.id.account_setup_outgoing); coordinatorLayout = (CoordinatorLayout) outgoingView.findViewById(R.id.outgoing_coordinator_layout); usernameView = (EditText) outgoingView.findViewById(R.id.outgoing_account_username); usernameViewLayout = (TextInputLayout) outgoingView.findViewById(R.id.outgoing_account_username_layout); passwordView = (EditText) outgoingView.findViewById(R.id.outgoing_account_password); passwordViewLayout = (TextInputLayout) outgoingView.findViewById(R.id.outgoing_account_password_layout); clientCertificateSpinner = (ClientCertificateSpinner) outgoingView.findViewById(R.id.outgoing_account_client_certificate_spinner); Loading Loading @@ -1182,6 +1213,9 @@ public class AccountSetupActivity extends AppCompatActivity implements AccountSe passwordViewLayout.setVisibility(View.VISIBLE); clientCertificateLabelView.setVisibility(View.GONE); clientCertificateSpinner.setVisibility(View.GONE); passwordViewLayout.setEnabled(true); securityTypeView.setEnabled(true); portView.setEnabled(true); passwordView.requestFocus(); } Loading @@ -1192,11 +1226,21 @@ public class AccountSetupActivity extends AppCompatActivity implements AccountSe passwordViewLayout.setVisibility(View.GONE); clientCertificateLabelView.setVisibility(View.VISIBLE); clientCertificateSpinner.setVisibility(View.VISIBLE); passwordViewLayout.setEnabled(true); securityTypeView.setEnabled(true); portView.setEnabled(true); // This may again invoke onInputChangedInOutgoing() clientCertificateSpinner.chooseCertificate(); } @Override public void setViewOAuth2InOutgoing() { passwordViewLayout.setEnabled(false); securityTypeView.setEnabled(false); portView.setEnabled(false); } public static void actionEditIncomingSettings(Activity context, Account account) { context.startActivity(intentActionEditIncomingSettings(context, account)); } Loading k9mail/src/main/java/com/fsck/k9/activity/setup/AccountSetupContract.java +6 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,7 @@ interface AccountSetupContract { void setViewNotExternalInIncoming(); void setViewExternalInIncoming(); void setViewOAuth2InIncoming(); void showFailureToast(Exception use); Loading @@ -88,6 +89,8 @@ interface AccountSetupContract { void setSubscribedFoldersOnly(boolean subscribedFoldersOnly); void showInvalidSettingsToast(); void showInvalidOAuthError(); void clearInvalidOAuthError(); /* --Names-- */ void setDoneButtonInNamesEnabled(boolean enabled); Loading @@ -112,10 +115,13 @@ interface AccountSetupContract { void setViewNotExternalInOutgoing(); void setViewExternalInOutgoing(); void setViewOAuth2InOutgoing(); void goToOutgoingChecking(); void goToAccountNames(); // --- void goBack(); void end(); Loading k9mail/src/main/java/com/fsck/k9/activity/setup/AccountSetupPresenter.java +47 −42 Original line number Diff line number Diff line Loading @@ -67,7 +67,7 @@ import java.util.Locale; import java.util.Map; import com.fsck.k9.setup.ServerNameSuggester; import org.xbill.DNS.TextParseException; import timber.log.Timber; import static com.fsck.k9.mail.ServerSettings.Type.IMAP; Loading Loading @@ -496,14 +496,6 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, private class CheckOutgoingTask extends CheckAccountTask { private CheckOutgoingTask(Account account) { super(account); } private CheckOutgoingTask(Account account, CheckSettingsSuccessCallback callback) { super(account, callback); } private CheckOutgoingTask(AccountConfig accountConfig) { super(accountConfig); } Loading Loading @@ -537,14 +529,6 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, } private class CheckIncomingTask extends CheckAccountTask { private CheckIncomingTask(Account account) { super(account); } private CheckIncomingTask(Account account, CheckSettingsSuccessCallback callback) { super(account, callback); } private CheckIncomingTask(AccountConfig accountConfig) { super(accountConfig); } Loading Loading @@ -593,25 +577,13 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, */ private abstract class CheckAccountTask extends AsyncTask<CheckDirection, Integer, Boolean> { private final AccountConfig accountConfig; private final Account account; private CheckSettingsSuccessCallback callback; private CheckAccountTask(Account account) { this(account, null); } private CheckAccountTask(Account account, CheckSettingsSuccessCallback callback) { this.account = account; this.accountConfig = null; this.callback = callback; } private CheckAccountTask(AccountConfig accountConfig) { this(accountConfig, null); } private CheckAccountTask(AccountConfig accountConfig, CheckSettingsSuccessCallback callback) { this.account = null; this.accountConfig = accountConfig; this.callback = callback; } Loading @@ -628,6 +600,10 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, } catch (OAuth2NeedUserPromptException ignored) { } catch (final AuthenticationFailedException afe) { Timber.e(afe, "Error while testing settings"); if (afe.getMessage().equals(AuthenticationFailedException.OAUTH2_ERROR_INVALID_REFRESH_TOKEN)) { Globals.getOAuth2TokenProvider().disconnectEmailWithK9(accountConfig.getEmail()); replayChecking(); } else { handler.post(new Runnable() { @Override public void run() { Loading @@ -635,6 +611,7 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, view.showErrorDialog(R.string.account_setup_failed_auth_message); } }); } } catch (CertificateValidationException cve) { handleCertificateValidationException(cve); } catch (final Exception e) { Loading Loading @@ -670,7 +647,8 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, void clearCertificateErrorNotifications(CheckDirection direction) { final MessagingController ctrl = MessagingController.getInstance(context); ctrl.clearCertificateErrorNotifications(account, direction); ctrl.clearCertificateErrorNotifications((Account) accountConfig, direction); } @Override Loading Loading @@ -1191,7 +1169,6 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, public void onInputChangedInIncoming(String certificateAlias, String server, String port, String username, String password, AuthType authType, ConnectionSecurity connectionSecurity) { revokeInvalidSettingsAndUpdateViewInIncoming(authType, connectionSecurity, port); validateFieldInIncoming(certificateAlias, server, currentIncomingPort, username, password, currentIncomingAuthType, Loading Loading @@ -1246,7 +1223,6 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, ConnectionSecurity connectionSecurity, String port) { boolean isAuthTypeExternal = (AuthType.EXTERNAL == authType); boolean hasConnectionSecurity = (connectionSecurity != ConnectionSecurity.NONE); if (isAuthTypeExternal && !hasConnectionSecurity) { Loading Loading @@ -1293,6 +1269,8 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, private void validateFieldInIncoming(String certificateAlias, String server, String port, String username, String password, AuthType authType, ConnectionSecurity connectionSecurity) { boolean isAuthTypeOAuth = (AuthType.XOAUTH2 == authType); boolean isOAuthValid = canOAuth2(username); boolean isAuthTypeExternal = (AuthType.EXTERNAL == authType); boolean hasConnectionSecurity = (connectionSecurity != ConnectionSecurity.NONE); Loading @@ -1300,7 +1278,7 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, boolean hasValidUserName = Utility.requiredFieldValid(username); boolean hasValidPasswordSettings = hasValidUserName && !isAuthTypeExternal && !isAuthTypeExternal && !isAuthTypeOAuth && Utility.requiredFieldValid(password); boolean hasValidExternalAuthSettings = hasValidUserName Loading @@ -1308,13 +1286,27 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, && hasConnectionSecurity && hasValidCertificateAlias; boolean hasValidOAuth2Settings = hasValidUserName && isAuthTypeOAuth && isOAuthValid; final boolean enabled = Utility.domainFieldValid(server) && Utility.requiredFieldValid(port) && (hasValidPasswordSettings || hasValidExternalAuthSettings); && (hasValidPasswordSettings || hasValidExternalAuthSettings || hasValidOAuth2Settings); checkInvalidOAuthError(isAuthTypeOAuth, isOAuthValid); view.setNextButtonInIncomingEnabled(enabled); } private void checkInvalidOAuthError(boolean isAuthTypeOAuth, boolean isOAuthValid) { if (isAuthTypeOAuth && !isOAuthValid) { view.showInvalidOAuthError(); } else { view.clearInvalidOAuthError(); } } private void updateAccount() { Account account = (Account) accountConfig; Loading @@ -1334,6 +1326,8 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, private void updateViewFromAuthTypeInIncoming(AuthType authType) { if (authType == AuthType.EXTERNAL) { view.setViewExternalInIncoming(); } else if (authType == AuthType.XOAUTH2) { view.setViewOAuth2InIncoming(); } else { view.setViewNotExternalInIncoming(); } Loading Loading @@ -1521,6 +1515,8 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, ConnectionSecurity connectionSecurity, boolean requireLogin) { boolean isAuthTypeOAuth = (AuthType.XOAUTH2 == authType); boolean isOAuthValid = canOAuth2(username); boolean isAuthTypeExternal = (AuthType.EXTERNAL == authType); boolean hasConnectionSecurity = (connectionSecurity != ConnectionSecurity.NONE); Loading @@ -1536,10 +1532,17 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, && hasConnectionSecurity && hasValidCertificateAlias; boolean hasValidOAuth2Settings = hasValidUserName && isAuthTypeOAuth && isOAuthValid; boolean enabled = Utility.domainFieldValid(server) && Utility.requiredFieldValid(port) && (!requireLogin || hasValidPasswordSettings || hasValidExternalAuthSettings); || hasValidPasswordSettings || hasValidExternalAuthSettings || hasValidOAuth2Settings); checkInvalidOAuthError(isAuthTypeOAuth, isOAuthValid); view.setNextButtonInOutgoingEnabled(enabled); } Loading Loading @@ -1579,6 +1582,8 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, private void updateViewFromAuthTypeInOutgoing(AuthType authType) { if (authType == AuthType.EXTERNAL) { view.setViewExternalInOutgoing(); } else if (authType == AuthType.XOAUTH2) { view.setViewOAuth2InOutgoing(); } else { view.setViewNotExternalInOutgoing(); } Loading Loading
k9mail-library/src/main/java/com/fsck/k9/mail/AuthenticationFailedException.java +2 −0 Original line number Diff line number Diff line Loading @@ -3,6 +3,8 @@ package com.fsck.k9.mail; public class AuthenticationFailedException extends MessagingException { public static final long serialVersionUID = -1; public static final String OAUTH2_ERROR_INVALID_REFRESH_TOKEN = "oauth2-invalid refresh token"; public static final String OAUTH2_ERROR_UNKNOWN = "oauth2-unknown"; public AuthenticationFailedException(String message) { super(message); Loading
k9mail/src/main/java/com/fsck/k9/account/AndroidSpecificOAuth2TokenProvider.java +29 −5 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ package com.fsck.k9.account; import com.fsck.k9.mail.AuthenticationFailedException; import com.fsck.k9.mail.oauth.OAuth2AuthorizationCodeFlowTokenProvider; import com.fsck.k9.mail.oauth.SpecificOAuth2TokenProvider; import com.google.gson.Gson; import com.google.gson.annotations.SerializedName; import java.io.IOException; Loading Loading @@ -42,16 +43,39 @@ abstract class AndroidSpecificOAuth2TokenProvider extends SpecificOAuth2TokenPro public String refreshToken(String username, String refreshToken) throws AuthenticationFailedException { Call<RefreshResponse> call = getRefreshTokenCall(refreshToken); RefreshResponse response; Response<RefreshResponse> response; RefreshResponse refreshResponse; try { response = call.execute().body(); response = call.execute(); refreshResponse = response.body(); } catch (IOException e) { throw new AuthenticationFailedException(e.getMessage()); } if (response == null) { throw new AuthenticationFailedException("Error when getting refresh token"); if (refreshResponse == null) { if (response.errorBody() != null) { try { String errorBody = response.errorBody().string(); OAuth2Error oAuth2Error = new Gson().fromJson(errorBody, OAuth2Error.class); switch (oAuth2Error.error) { case "invalid_grant": throw new AuthenticationFailedException(AuthenticationFailedException.OAUTH2_ERROR_INVALID_REFRESH_TOKEN); default: throw new AuthenticationFailedException(AuthenticationFailedException.OAUTH2_ERROR_UNKNOWN); } } catch (IOException e) { throw new AuthenticationFailedException(AuthenticationFailedException.OAUTH2_ERROR_UNKNOWN); } } else { throw new AuthenticationFailedException(AuthenticationFailedException.OAUTH2_ERROR_UNKNOWN); } } return response.accessToken; return refreshResponse.accessToken; } protected static class OAuth2Error { String error; @SerializedName("error_description") String errorDescription; } protected static class ExchangeResponse { Loading
k9mail/src/main/java/com/fsck/k9/activity/setup/AccountSetupActivity.java +46 −2 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ import android.widget.Spinner; import android.widget.TextView; import com.fsck.k9.mail.ServerSettings.Type; import com.fsck.k9.service.StorageGoneReceiver; import com.fsck.k9.view.ClientCertificateSpinner; import me.zhanghai.android.materialprogressbar.MaterialProgressBar; Loading Loading @@ -92,10 +93,12 @@ public class AccountSetupActivity extends AppCompatActivity implements AccountSe private ClientCertificateSpinner clientCertificateSpinner; private TextView clientCertificateLabelView; private TextInputLayout usernameViewLayout; private TextInputLayout passwordViewLayout; private TextInputLayout serverViewLayout; private TextInputEditText serverView; private TextInputEditText portView; private TextView securityTypeLabelView; private Spinner securityTypeView; private Spinner authTypeView; private CheckBox imapAutoDetectNamespaceView; Loading Loading @@ -758,6 +761,7 @@ public class AccountSetupActivity extends AppCompatActivity implements AccountSe View incomingView = findViewById(R.id.account_setup_incoming); coordinatorLayout = (CoordinatorLayout) findViewById(R.id.incoming_coordinator_layout); usernameView = (EditText) incomingView.findViewById(R.id.incoming_account_username); usernameViewLayout = (TextInputLayout) incomingView.findViewById(R.id.incoming_account_username_layout); passwordView = (EditText) incomingView.findViewById(R.id.incoming_account_password); clientCertificateSpinner = (ClientCertificateSpinner) incomingView.findViewById(R.id.incoming_account_client_certificate_spinner); clientCertificateLabelView = (TextView) incomingView.findViewById(R.id.account_client_certificate_label); Loading @@ -765,6 +769,7 @@ public class AccountSetupActivity extends AppCompatActivity implements AccountSe serverViewLayout = (TextInputLayout) incomingView.findViewById(R.id.incoming_account_server_layout); serverView = (TextInputEditText) incomingView.findViewById(R.id.incoming_account_server); portView = (TextInputEditText) incomingView.findViewById(R.id.incoming_account_port); securityTypeLabelView = (TextView) incomingView.findViewById(R.id.account_setup_incoming_security_label); securityTypeView = (Spinner) incomingView.findViewById(R.id.incoming_account_security_type); authTypeView = (Spinner) incomingView.findViewById(R.id.incoming_account_auth_type); imapAutoDetectNamespaceView = (CheckBox) incomingView.findViewById(R.id.imap_autodetect_namespace); Loading Loading @@ -849,24 +854,38 @@ public class AccountSetupActivity extends AppCompatActivity implements AccountSe @Override public void setViewNotExternalInIncoming() { passwordView.setVisibility(View.VISIBLE); passwordViewLayout.setVisibility(View.VISIBLE); clientCertificateLabelView.setVisibility(View.GONE); clientCertificateSpinner.setVisibility(View.GONE); imapAutoDetectNamespaceView.setEnabled(true); passwordViewLayout.setEnabled(true); securityTypeView.setEnabled(true); portView.setEnabled(true); passwordView.requestFocus(); } @Override public void setViewExternalInIncoming() { passwordView.setVisibility(View.GONE); passwordViewLayout.setVisibility(View.GONE); clientCertificateLabelView.setVisibility(View.VISIBLE); clientCertificateSpinner.setVisibility(View.VISIBLE); imapAutoDetectNamespaceView.setEnabled(true); passwordViewLayout.setEnabled(true); securityTypeView.setEnabled(true); portView.setEnabled(true); clientCertificateSpinner.chooseCertificate(); } @Override public void setViewOAuth2InIncoming() { imapAutoDetectNamespaceView.setEnabled(false); passwordViewLayout.setEnabled(false); securityTypeView.setEnabled(false); portView.setEnabled(false); } @Override public void showFailureToast(Exception use) { failure(use); Loading Loading @@ -902,6 +921,17 @@ public class AccountSetupActivity extends AppCompatActivity implements AccountSe Toast.makeText(this, toastText, Toast.LENGTH_LONG).show(); } @Override public void showInvalidOAuthError() { usernameViewLayout.setErrorEnabled(true); usernameViewLayout.setError(getString(R.string.OAuth2_not_supported)); } @Override public void clearInvalidOAuthError() { usernameViewLayout.setError(""); } // names public void namesStart() { Loading Loading @@ -1068,6 +1098,7 @@ public class AccountSetupActivity extends AppCompatActivity implements AccountSe final View outgoingView = findViewById(R.id.account_setup_outgoing); coordinatorLayout = (CoordinatorLayout) outgoingView.findViewById(R.id.outgoing_coordinator_layout); usernameView = (EditText) outgoingView.findViewById(R.id.outgoing_account_username); usernameViewLayout = (TextInputLayout) outgoingView.findViewById(R.id.outgoing_account_username_layout); passwordView = (EditText) outgoingView.findViewById(R.id.outgoing_account_password); passwordViewLayout = (TextInputLayout) outgoingView.findViewById(R.id.outgoing_account_password_layout); clientCertificateSpinner = (ClientCertificateSpinner) outgoingView.findViewById(R.id.outgoing_account_client_certificate_spinner); Loading Loading @@ -1182,6 +1213,9 @@ public class AccountSetupActivity extends AppCompatActivity implements AccountSe passwordViewLayout.setVisibility(View.VISIBLE); clientCertificateLabelView.setVisibility(View.GONE); clientCertificateSpinner.setVisibility(View.GONE); passwordViewLayout.setEnabled(true); securityTypeView.setEnabled(true); portView.setEnabled(true); passwordView.requestFocus(); } Loading @@ -1192,11 +1226,21 @@ public class AccountSetupActivity extends AppCompatActivity implements AccountSe passwordViewLayout.setVisibility(View.GONE); clientCertificateLabelView.setVisibility(View.VISIBLE); clientCertificateSpinner.setVisibility(View.VISIBLE); passwordViewLayout.setEnabled(true); securityTypeView.setEnabled(true); portView.setEnabled(true); // This may again invoke onInputChangedInOutgoing() clientCertificateSpinner.chooseCertificate(); } @Override public void setViewOAuth2InOutgoing() { passwordViewLayout.setEnabled(false); securityTypeView.setEnabled(false); portView.setEnabled(false); } public static void actionEditIncomingSettings(Activity context, Account account) { context.startActivity(intentActionEditIncomingSettings(context, account)); } Loading
k9mail/src/main/java/com/fsck/k9/activity/setup/AccountSetupContract.java +6 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,7 @@ interface AccountSetupContract { void setViewNotExternalInIncoming(); void setViewExternalInIncoming(); void setViewOAuth2InIncoming(); void showFailureToast(Exception use); Loading @@ -88,6 +89,8 @@ interface AccountSetupContract { void setSubscribedFoldersOnly(boolean subscribedFoldersOnly); void showInvalidSettingsToast(); void showInvalidOAuthError(); void clearInvalidOAuthError(); /* --Names-- */ void setDoneButtonInNamesEnabled(boolean enabled); Loading @@ -112,10 +115,13 @@ interface AccountSetupContract { void setViewNotExternalInOutgoing(); void setViewExternalInOutgoing(); void setViewOAuth2InOutgoing(); void goToOutgoingChecking(); void goToAccountNames(); // --- void goBack(); void end(); Loading
k9mail/src/main/java/com/fsck/k9/activity/setup/AccountSetupPresenter.java +47 −42 Original line number Diff line number Diff line Loading @@ -67,7 +67,7 @@ import java.util.Locale; import java.util.Map; import com.fsck.k9.setup.ServerNameSuggester; import org.xbill.DNS.TextParseException; import timber.log.Timber; import static com.fsck.k9.mail.ServerSettings.Type.IMAP; Loading Loading @@ -496,14 +496,6 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, private class CheckOutgoingTask extends CheckAccountTask { private CheckOutgoingTask(Account account) { super(account); } private CheckOutgoingTask(Account account, CheckSettingsSuccessCallback callback) { super(account, callback); } private CheckOutgoingTask(AccountConfig accountConfig) { super(accountConfig); } Loading Loading @@ -537,14 +529,6 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, } private class CheckIncomingTask extends CheckAccountTask { private CheckIncomingTask(Account account) { super(account); } private CheckIncomingTask(Account account, CheckSettingsSuccessCallback callback) { super(account, callback); } private CheckIncomingTask(AccountConfig accountConfig) { super(accountConfig); } Loading Loading @@ -593,25 +577,13 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, */ private abstract class CheckAccountTask extends AsyncTask<CheckDirection, Integer, Boolean> { private final AccountConfig accountConfig; private final Account account; private CheckSettingsSuccessCallback callback; private CheckAccountTask(Account account) { this(account, null); } private CheckAccountTask(Account account, CheckSettingsSuccessCallback callback) { this.account = account; this.accountConfig = null; this.callback = callback; } private CheckAccountTask(AccountConfig accountConfig) { this(accountConfig, null); } private CheckAccountTask(AccountConfig accountConfig, CheckSettingsSuccessCallback callback) { this.account = null; this.accountConfig = accountConfig; this.callback = callback; } Loading @@ -628,6 +600,10 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, } catch (OAuth2NeedUserPromptException ignored) { } catch (final AuthenticationFailedException afe) { Timber.e(afe, "Error while testing settings"); if (afe.getMessage().equals(AuthenticationFailedException.OAUTH2_ERROR_INVALID_REFRESH_TOKEN)) { Globals.getOAuth2TokenProvider().disconnectEmailWithK9(accountConfig.getEmail()); replayChecking(); } else { handler.post(new Runnable() { @Override public void run() { Loading @@ -635,6 +611,7 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, view.showErrorDialog(R.string.account_setup_failed_auth_message); } }); } } catch (CertificateValidationException cve) { handleCertificateValidationException(cve); } catch (final Exception e) { Loading Loading @@ -670,7 +647,8 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, void clearCertificateErrorNotifications(CheckDirection direction) { final MessagingController ctrl = MessagingController.getInstance(context); ctrl.clearCertificateErrorNotifications(account, direction); ctrl.clearCertificateErrorNotifications((Account) accountConfig, direction); } @Override Loading Loading @@ -1191,7 +1169,6 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, public void onInputChangedInIncoming(String certificateAlias, String server, String port, String username, String password, AuthType authType, ConnectionSecurity connectionSecurity) { revokeInvalidSettingsAndUpdateViewInIncoming(authType, connectionSecurity, port); validateFieldInIncoming(certificateAlias, server, currentIncomingPort, username, password, currentIncomingAuthType, Loading Loading @@ -1246,7 +1223,6 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, ConnectionSecurity connectionSecurity, String port) { boolean isAuthTypeExternal = (AuthType.EXTERNAL == authType); boolean hasConnectionSecurity = (connectionSecurity != ConnectionSecurity.NONE); if (isAuthTypeExternal && !hasConnectionSecurity) { Loading Loading @@ -1293,6 +1269,8 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, private void validateFieldInIncoming(String certificateAlias, String server, String port, String username, String password, AuthType authType, ConnectionSecurity connectionSecurity) { boolean isAuthTypeOAuth = (AuthType.XOAUTH2 == authType); boolean isOAuthValid = canOAuth2(username); boolean isAuthTypeExternal = (AuthType.EXTERNAL == authType); boolean hasConnectionSecurity = (connectionSecurity != ConnectionSecurity.NONE); Loading @@ -1300,7 +1278,7 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, boolean hasValidUserName = Utility.requiredFieldValid(username); boolean hasValidPasswordSettings = hasValidUserName && !isAuthTypeExternal && !isAuthTypeExternal && !isAuthTypeOAuth && Utility.requiredFieldValid(password); boolean hasValidExternalAuthSettings = hasValidUserName Loading @@ -1308,13 +1286,27 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, && hasConnectionSecurity && hasValidCertificateAlias; boolean hasValidOAuth2Settings = hasValidUserName && isAuthTypeOAuth && isOAuthValid; final boolean enabled = Utility.domainFieldValid(server) && Utility.requiredFieldValid(port) && (hasValidPasswordSettings || hasValidExternalAuthSettings); && (hasValidPasswordSettings || hasValidExternalAuthSettings || hasValidOAuth2Settings); checkInvalidOAuthError(isAuthTypeOAuth, isOAuthValid); view.setNextButtonInIncomingEnabled(enabled); } private void checkInvalidOAuthError(boolean isAuthTypeOAuth, boolean isOAuthValid) { if (isAuthTypeOAuth && !isOAuthValid) { view.showInvalidOAuthError(); } else { view.clearInvalidOAuthError(); } } private void updateAccount() { Account account = (Account) accountConfig; Loading @@ -1334,6 +1326,8 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, private void updateViewFromAuthTypeInIncoming(AuthType authType) { if (authType == AuthType.EXTERNAL) { view.setViewExternalInIncoming(); } else if (authType == AuthType.XOAUTH2) { view.setViewOAuth2InIncoming(); } else { view.setViewNotExternalInIncoming(); } Loading Loading @@ -1521,6 +1515,8 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, ConnectionSecurity connectionSecurity, boolean requireLogin) { boolean isAuthTypeOAuth = (AuthType.XOAUTH2 == authType); boolean isOAuthValid = canOAuth2(username); boolean isAuthTypeExternal = (AuthType.EXTERNAL == authType); boolean hasConnectionSecurity = (connectionSecurity != ConnectionSecurity.NONE); Loading @@ -1536,10 +1532,17 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, && hasConnectionSecurity && hasValidCertificateAlias; boolean hasValidOAuth2Settings = hasValidUserName && isAuthTypeOAuth && isOAuthValid; boolean enabled = Utility.domainFieldValid(server) && Utility.requiredFieldValid(port) && (!requireLogin || hasValidPasswordSettings || hasValidExternalAuthSettings); || hasValidPasswordSettings || hasValidExternalAuthSettings || hasValidOAuth2Settings); checkInvalidOAuthError(isAuthTypeOAuth, isOAuthValid); view.setNextButtonInOutgoingEnabled(enabled); } Loading Loading @@ -1579,6 +1582,8 @@ public class AccountSetupPresenter implements AccountSetupContract.Presenter, private void updateViewFromAuthTypeInOutgoing(AuthType authType) { if (authType == AuthType.EXTERNAL) { view.setViewExternalInOutgoing(); } else if (authType == AuthType.XOAUTH2) { view.setViewOAuth2InOutgoing(); } else { view.setViewNotExternalInOutgoing(); } Loading