diff --git a/res/values/strings.xml b/res/values/strings.xml index 44e80e7ad..d1b691547 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -221,6 +221,8 @@ Please submit bug reports, contribute new features and ask questions at Reply Read Delete + Certificate error + Check your server settings Checking mail: %s:%s Checking mail diff --git a/src/com/fsck/k9/K9.java b/src/com/fsck/k9/K9.java index f9ade23e5..124290ce8 100644 --- a/src/com/fsck/k9/K9.java +++ b/src/com/fsck/k9/K9.java @@ -345,12 +345,14 @@ public class K9 extends Application { - public static final int NOTIFICATION_LED_SENDING_FAILURE_COLOR = 0xffff0000; + public static final int NOTIFICATION_LED_FAILURE_COLOR = 0xffff0000; // Must not conflict with an account number public static final int FETCHING_EMAIL_NOTIFICATION = -5000; public static final int SEND_FAILED_NOTIFICATION = -1500; public static final int CONNECTIVITY_ID = -3; + public static final int CERTIFICATE_EXCEPTION_NOTIFICATION_INCOMING = -4; + public static final int CERTIFICATE_EXCEPTION_NOTIFICATION_OUTGOING = -5; public static class Intents { diff --git a/src/com/fsck/k9/activity/setup/AccountSetupCheckSettings.java b/src/com/fsck/k9/activity/setup/AccountSetupCheckSettings.java index 6ce001788..bf4773c9b 100644 --- a/src/com/fsck/k9/activity/setup/AccountSetupCheckSettings.java +++ b/src/com/fsck/k9/activity/setup/AccountSetupCheckSettings.java @@ -3,6 +3,9 @@ package com.fsck.k9.activity.setup; import android.app.Activity; import android.app.AlertDialog; +import android.app.Application; +import android.app.NotificationManager; +import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; @@ -105,6 +108,7 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList finish(); return; } + clearCertificateErrorNotifications(); if (mCheckIncoming) { store = mAccount.getRemoteStore(); @@ -195,6 +199,19 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList }); } + private void clearCertificateErrorNotifications() { + final Application app = getApplication(); + final NotificationManager notifMgr = (NotificationManager) app + .getSystemService(Context.NOTIFICATION_SERVICE); + final String uuid = mAccount.getUuid(); + if (mCheckOutgoing){ + notifMgr.cancel(uuid, K9.CERTIFICATE_EXCEPTION_NOTIFICATION_OUTGOING); + } + if (mCheckIncoming){ + notifMgr.cancel(uuid, K9.CERTIFICATE_EXCEPTION_NOTIFICATION_INCOMING); + } + } + private void showErrorDialog(final int msgResId, final Object... args) { mHandler.post(new Runnable() { public void run() { diff --git a/src/com/fsck/k9/activity/setup/AccountSetupIncoming.java b/src/com/fsck/k9/activity/setup/AccountSetupIncoming.java index 23fa80406..4e341aa28 100644 --- a/src/com/fsck/k9/activity/setup/AccountSetupIncoming.java +++ b/src/com/fsck/k9/activity/setup/AccountSetupIncoming.java @@ -33,7 +33,7 @@ import java.util.HashMap; import java.util.Map; public class AccountSetupIncoming extends K9Activity implements OnClickListener { - private static final String EXTRA_ACCOUNT = "account"; + public static final String EXTRA_ACCOUNT = "account"; private static final String EXTRA_MAKE_DEFAULT = "makeDefault"; private static final int[] POP3_PORTS = { diff --git a/src/com/fsck/k9/activity/setup/AccountSetupOutgoing.java b/src/com/fsck/k9/activity/setup/AccountSetupOutgoing.java index 15f1c9bb4..d49059a43 100644 --- a/src/com/fsck/k9/activity/setup/AccountSetupOutgoing.java +++ b/src/com/fsck/k9/activity/setup/AccountSetupOutgoing.java @@ -26,7 +26,7 @@ import java.net.URLEncoder; public class AccountSetupOutgoing extends K9Activity implements OnClickListener, OnCheckedChangeListener { - private static final String EXTRA_ACCOUNT = "account"; + public static final String EXTRA_ACCOUNT = "account"; private static final String EXTRA_MAKE_DEFAULT = "makeDefault"; diff --git a/src/com/fsck/k9/controller/MessagingController.java b/src/com/fsck/k9/controller/MessagingController.java index 07b22e6d2..f2284c9e7 100644 --- a/src/com/fsck/k9/controller/MessagingController.java +++ b/src/com/fsck/k9/controller/MessagingController.java @@ -3295,13 +3295,30 @@ public class MessagingController implements Runnable { PendingIntent pi = PendingIntent.getActivity(mApplication, 0, i, 0); builder.setContentIntent(pi); - configureNotification(builder, null, null, K9.NOTIFICATION_LED_SENDING_FAILURE_COLOR, + configureNotification(builder, null, null, K9.NOTIFICATION_LED_FAILURE_COLOR, K9.NOTIFICATION_LED_BLINK_FAST, true); notifMgr.notify(K9.SEND_FAILED_NOTIFICATION - account.getAccountNumber(), builder.build()); } + public void notify(String tag, int id, String title, String text, PendingIntent pi) { + final NotificationManager notifMgr = (NotificationManager) mApplication + .getSystemService(Context.NOTIFICATION_SERVICE); + NotificationCompat.Builder builder = new NotificationCompat.Builder(mApplication); + builder.setSmallIcon(R.drawable.stat_notify_email_generic); + builder.setWhen(System.currentTimeMillis()); + builder.setAutoCancel(true); + builder.setTicker(title); + builder.setContentTitle(title); + builder.setContentText(text); + builder.setContentIntent(pi); + configureNotification(builder, null, null, + K9.NOTIFICATION_LED_FAILURE_COLOR, + K9.NOTIFICATION_LED_BLINK_FAST, true); + notifMgr.notify(tag, id, builder.build()); + } + /** * Display an ongoing notification while checking for new messages on the server. * diff --git a/src/com/fsck/k9/mail/CertificateValidationException.java b/src/com/fsck/k9/mail/CertificateValidationException.java index ed35cf8ac..b34b66f44 100644 --- a/src/com/fsck/k9/mail/CertificateValidationException.java +++ b/src/com/fsck/k9/mail/CertificateValidationException.java @@ -1,6 +1,18 @@ package com.fsck.k9.mail; +import android.app.Application; +import android.app.PendingIntent; +import android.content.Intent; +import com.fsck.k9.Account; +import com.fsck.k9.K9; +import com.fsck.k9.R; +import com.fsck.k9.activity.setup.AccountSetupIncoming; +import com.fsck.k9.activity.setup.AccountSetupOutgoing; +import com.fsck.k9.controller.MessagingController; +import java.security.cert.CertPathValidatorException; +import java.security.cert.CertificateException; + public class CertificateValidationException extends MessagingException { public static final long serialVersionUID = -1; @@ -8,7 +20,44 @@ public class CertificateValidationException extends MessagingException { super(message); } - public CertificateValidationException(String message, Throwable throwable) { + public CertificateValidationException(final String message, + Throwable throwable, final Account account, final boolean incoming) { super(message, throwable); + /* + * We get here because of an SSLException. We are only interested in + * creating a notification if the underlying cause is certificate + * related. + */ + while (throwable != null + && !(throwable instanceof CertPathValidatorException) + && !(throwable instanceof CertificateException)) { + throwable = throwable.getCause(); + } + if (throwable == null) + return; + final Application app = K9.app; + final String title = app + .getString(R.string.notification_certificate_error_title); + final String text = app + .getString(R.string.notification_certificate_error_text); + final Class className; + final String extraName; + final int id; + if (incoming) { + className = AccountSetupIncoming.class; + extraName = AccountSetupIncoming.EXTRA_ACCOUNT; + id = K9.CERTIFICATE_EXCEPTION_NOTIFICATION_INCOMING; + } else { + className = AccountSetupOutgoing.class; + extraName = AccountSetupOutgoing.EXTRA_ACCOUNT; + id = K9.CERTIFICATE_EXCEPTION_NOTIFICATION_OUTGOING; + } + final Intent i = new Intent(app, className); + final String uuid = account.getUuid(); + i.setAction(Intent.ACTION_EDIT); + i.putExtra(extraName, uuid); + final PendingIntent pi = PendingIntent.getActivity(app, 0, i, 0); + MessagingController controller = MessagingController.getInstance(app); + controller.notify(uuid, id, title, text, pi); } } \ No newline at end of file diff --git a/src/com/fsck/k9/mail/Transport.java b/src/com/fsck/k9/mail/Transport.java index a0450ffeb..28011dacd 100644 --- a/src/com/fsck/k9/mail/Transport.java +++ b/src/com/fsck/k9/mail/Transport.java @@ -14,7 +14,7 @@ public abstract class Transport { public synchronized static Transport getInstance(Account account) throws MessagingException { String uri = account.getTransportUri(); if (uri.startsWith("smtp")) { - return new SmtpTransport(uri); + return new SmtpTransport(account); } else if (uri.startsWith("webdav")) { return new WebDavTransport(account); } else { diff --git a/src/com/fsck/k9/mail/store/ImapStore.java b/src/com/fsck/k9/mail/store/ImapStore.java index 9bca9990e..9b0efca3f 100644 --- a/src/com/fsck/k9/mail/store/ImapStore.java +++ b/src/com/fsck/k9/mail/store/ImapStore.java @@ -429,6 +429,10 @@ public class ImapStore extends Store { mCombinedPrefix = prefix; } + @Override + public Account getAccount() { + return mAccount; + } } private static final SimpleDateFormat RFC3501_DATE = new SimpleDateFormat("dd-MMM-yyyy", Locale.US); @@ -2623,7 +2627,7 @@ public class ImapStore extends Store { } catch (SSLException e) { - throw new CertificateValidationException(e.getMessage(), e); + throw new CertificateValidationException(e.getMessage(), e, mSettings.getAccount(), true); } catch (GeneralSecurityException gse) { throw new MessagingException( "Unable to open connection to IMAP server due to security error.", gse); diff --git a/src/com/fsck/k9/mail/store/Pop3Store.java b/src/com/fsck/k9/mail/store/Pop3Store.java index ec7c56961..85b85110b 100644 --- a/src/com/fsck/k9/mail/store/Pop3Store.java +++ b/src/com/fsck/k9/mail/store/Pop3Store.java @@ -391,7 +391,7 @@ public class Pop3Store extends Store { mCapabilities = getCapabilities(); } catch (SSLException e) { - throw new CertificateValidationException(e.getMessage(), e); + throw new CertificateValidationException(e.getMessage(), e, mAccount, true); } catch (GeneralSecurityException gse) { throw new MessagingException( "Unable to open connection to POP server due to security error.", gse); diff --git a/src/com/fsck/k9/mail/store/WebDavStore.java b/src/com/fsck/k9/mail/store/WebDavStore.java index 770e61e38..26199a285 100644 --- a/src/com/fsck/k9/mail/store/WebDavStore.java +++ b/src/com/fsck/k9/mail/store/WebDavStore.java @@ -848,7 +848,7 @@ public class WebDavStore extends Store { response.getStatusLine().toString()); } } catch (SSLException e) { - throw new CertificateValidationException(e.getMessage(), e); + throw new CertificateValidationException(e.getMessage(), e, mAccount, true); } catch (IOException ioe) { Log.e(K9.LOG_TAG, "IOException: " + ioe + "\nTrace: " + processException(ioe)); throw new MessagingException("IOException", ioe); diff --git a/src/com/fsck/k9/mail/transport/SmtpTransport.java b/src/com/fsck/k9/mail/transport/SmtpTransport.java index 050a582b3..99cd76d61 100644 --- a/src/com/fsck/k9/mail/transport/SmtpTransport.java +++ b/src/com/fsck/k9/mail/transport/SmtpTransport.java @@ -182,6 +182,7 @@ public class SmtpTransport extends Transport { } + Account mAccount; String mHost; int mPort; String mUsername; @@ -194,14 +195,15 @@ public class SmtpTransport extends Transport { private boolean m8bitEncodingAllowed; private int mLargestAcceptableMessage; - public SmtpTransport(String uri) throws MessagingException { + public SmtpTransport(Account account) throws MessagingException { ServerSettings settings; try { - settings = decodeUri(uri); + settings = decodeUri(account.getTransportUri()); } catch (IllegalArgumentException e) { throw new MessagingException("Error while decoding transport URI", e); } + mAccount = account; mHost = settings.host; mPort = settings.port; @@ -387,7 +389,7 @@ public class SmtpTransport extends Transport { } } } catch (SSLException e) { - throw new CertificateValidationException(e.getMessage(), e); + throw new CertificateValidationException(e.getMessage(), e, mAccount, false); } catch (GeneralSecurityException gse) { throw new MessagingException( "Unable to open connection to SMTP server due to security error.", gse); diff --git a/src/com/fsck/k9/mail/transport/imap/ImapSettings.java b/src/com/fsck/k9/mail/transport/imap/ImapSettings.java index 769763015..7e367cac6 100644 --- a/src/com/fsck/k9/mail/transport/imap/ImapSettings.java +++ b/src/com/fsck/k9/mail/transport/imap/ImapSettings.java @@ -1,5 +1,6 @@ package com.fsck.k9.mail.transport.imap; +import com.fsck.k9.Account; import com.fsck.k9.mail.store.ImapStore; import com.fsck.k9.mail.store.ImapStore.AuthType; import com.fsck.k9.mail.store.ImapStore.ImapConnection; @@ -34,4 +35,6 @@ public interface ImapSettings { void setCombinedPrefix(String prefix); + Account getAccount(); + }