1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-12-25 09:08:49 -05:00

Merge remote-tracking branch 'zjw/issue_2389_cert_error_notice2'

* zjw/issue_2389_cert_error_notice2:
  Fix Issue 2389:  Self signed certificate expiry causes silent send/receive failure.
This commit is contained in:
Jesse Vincent 2013-01-15 14:44:21 -05:00
commit ae6c7e37ca
13 changed files with 108 additions and 12 deletions

View File

@ -221,6 +221,8 @@ Please submit bug reports, contribute new features and ask questions at
<string name="notification_action_reply">Reply</string> <string name="notification_action_reply">Reply</string>
<string name="notification_action_read">Read</string> <string name="notification_action_read">Read</string>
<string name="notification_action_delete">Delete</string> <string name="notification_action_delete">Delete</string>
<string name="notification_certificate_error_title">Certificate error</string>
<string name="notification_certificate_error_text">Check your server settings</string>
<string name="notification_bg_sync_ticker">Checking mail: <xliff:g id="account">%s</xliff:g>:<xliff:g id="folder">%s</xliff:g></string> <string name="notification_bg_sync_ticker">Checking mail: <xliff:g id="account">%s</xliff:g>:<xliff:g id="folder">%s</xliff:g></string>
<string name="notification_bg_sync_title">Checking mail</string> <string name="notification_bg_sync_title">Checking mail</string>

View File

@ -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 // Must not conflict with an account number
public static final int FETCHING_EMAIL_NOTIFICATION = -5000; public static final int FETCHING_EMAIL_NOTIFICATION = -5000;
public static final int SEND_FAILED_NOTIFICATION = -1500; public static final int SEND_FAILED_NOTIFICATION = -1500;
public static final int CONNECTIVITY_ID = -3; 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 { public static class Intents {

View File

@ -3,6 +3,9 @@ package com.fsck.k9.activity.setup;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Application;
import android.app.NotificationManager;
import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
@ -105,6 +108,7 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
finish(); finish();
return; return;
} }
clearCertificateErrorNotifications();
if (mCheckIncoming) { if (mCheckIncoming) {
store = mAccount.getRemoteStore(); 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) { private void showErrorDialog(final int msgResId, final Object... args) {
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
public void run() { public void run() {

View File

@ -33,7 +33,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class AccountSetupIncoming extends K9Activity implements OnClickListener { 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 String EXTRA_MAKE_DEFAULT = "makeDefault";
private static final int[] POP3_PORTS = { private static final int[] POP3_PORTS = {

View File

@ -26,7 +26,7 @@ import java.net.URLEncoder;
public class AccountSetupOutgoing extends K9Activity implements OnClickListener, public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
OnCheckedChangeListener { OnCheckedChangeListener {
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 String EXTRA_MAKE_DEFAULT = "makeDefault";

View File

@ -3295,13 +3295,30 @@ public class MessagingController implements Runnable {
PendingIntent pi = PendingIntent.getActivity(mApplication, 0, i, 0); PendingIntent pi = PendingIntent.getActivity(mApplication, 0, i, 0);
builder.setContentIntent(pi); 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); K9.NOTIFICATION_LED_BLINK_FAST, true);
notifMgr.notify(K9.SEND_FAILED_NOTIFICATION - account.getAccountNumber(), notifMgr.notify(K9.SEND_FAILED_NOTIFICATION - account.getAccountNumber(),
builder.build()); 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. * Display an ongoing notification while checking for new messages on the server.
* *

View File

@ -1,6 +1,18 @@
package com.fsck.k9.mail; 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 class CertificateValidationException extends MessagingException {
public static final long serialVersionUID = -1; public static final long serialVersionUID = -1;
@ -8,7 +20,44 @@ public class CertificateValidationException extends MessagingException {
super(message); super(message);
} }
public CertificateValidationException(String message, Throwable throwable) { public CertificateValidationException(final String message,
Throwable throwable, final Account account, final boolean incoming) {
super(message, throwable); 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);
} }
} }

View File

@ -14,7 +14,7 @@ public abstract class Transport {
public synchronized static Transport getInstance(Account account) throws MessagingException { public synchronized static Transport getInstance(Account account) throws MessagingException {
String uri = account.getTransportUri(); String uri = account.getTransportUri();
if (uri.startsWith("smtp")) { if (uri.startsWith("smtp")) {
return new SmtpTransport(uri); return new SmtpTransport(account);
} else if (uri.startsWith("webdav")) { } else if (uri.startsWith("webdav")) {
return new WebDavTransport(account); return new WebDavTransport(account);
} else { } else {

View File

@ -429,6 +429,10 @@ public class ImapStore extends Store {
mCombinedPrefix = prefix; mCombinedPrefix = prefix;
} }
@Override
public Account getAccount() {
return mAccount;
}
} }
private static final SimpleDateFormat RFC3501_DATE = new SimpleDateFormat("dd-MMM-yyyy", Locale.US); 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) { } catch (SSLException e) {
throw new CertificateValidationException(e.getMessage(), e); throw new CertificateValidationException(e.getMessage(), e, mSettings.getAccount(), true);
} catch (GeneralSecurityException gse) { } catch (GeneralSecurityException gse) {
throw new MessagingException( throw new MessagingException(
"Unable to open connection to IMAP server due to security error.", gse); "Unable to open connection to IMAP server due to security error.", gse);

View File

@ -391,7 +391,7 @@ public class Pop3Store extends Store {
mCapabilities = getCapabilities(); mCapabilities = getCapabilities();
} catch (SSLException e) { } catch (SSLException e) {
throw new CertificateValidationException(e.getMessage(), e); throw new CertificateValidationException(e.getMessage(), e, mAccount, true);
} catch (GeneralSecurityException gse) { } catch (GeneralSecurityException gse) {
throw new MessagingException( throw new MessagingException(
"Unable to open connection to POP server due to security error.", gse); "Unable to open connection to POP server due to security error.", gse);

View File

@ -848,7 +848,7 @@ public class WebDavStore extends Store {
response.getStatusLine().toString()); response.getStatusLine().toString());
} }
} catch (SSLException e) { } catch (SSLException e) {
throw new CertificateValidationException(e.getMessage(), e); throw new CertificateValidationException(e.getMessage(), e, mAccount, true);
} catch (IOException ioe) { } catch (IOException ioe) {
Log.e(K9.LOG_TAG, "IOException: " + ioe + "\nTrace: " + processException(ioe)); Log.e(K9.LOG_TAG, "IOException: " + ioe + "\nTrace: " + processException(ioe));
throw new MessagingException("IOException", ioe); throw new MessagingException("IOException", ioe);

View File

@ -182,6 +182,7 @@ public class SmtpTransport extends Transport {
} }
Account mAccount;
String mHost; String mHost;
int mPort; int mPort;
String mUsername; String mUsername;
@ -194,14 +195,15 @@ public class SmtpTransport extends Transport {
private boolean m8bitEncodingAllowed; private boolean m8bitEncodingAllowed;
private int mLargestAcceptableMessage; private int mLargestAcceptableMessage;
public SmtpTransport(String uri) throws MessagingException { public SmtpTransport(Account account) throws MessagingException {
ServerSettings settings; ServerSettings settings;
try { try {
settings = decodeUri(uri); settings = decodeUri(account.getTransportUri());
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new MessagingException("Error while decoding transport URI", e); throw new MessagingException("Error while decoding transport URI", e);
} }
mAccount = account;
mHost = settings.host; mHost = settings.host;
mPort = settings.port; mPort = settings.port;
@ -387,7 +389,7 @@ public class SmtpTransport extends Transport {
} }
} }
} catch (SSLException e) { } catch (SSLException e) {
throw new CertificateValidationException(e.getMessage(), e); throw new CertificateValidationException(e.getMessage(), e, mAccount, false);
} catch (GeneralSecurityException gse) { } catch (GeneralSecurityException gse) {
throw new MessagingException( throw new MessagingException(
"Unable to open connection to SMTP server due to security error.", gse); "Unable to open connection to SMTP server due to security error.", gse);

View File

@ -1,5 +1,6 @@
package com.fsck.k9.mail.transport.imap; 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;
import com.fsck.k9.mail.store.ImapStore.AuthType; import com.fsck.k9.mail.store.ImapStore.AuthType;
import com.fsck.k9.mail.store.ImapStore.ImapConnection; import com.fsck.k9.mail.store.ImapStore.ImapConnection;
@ -34,4 +35,6 @@ public interface ImapSettings {
void setCombinedPrefix(String prefix); void setCombinedPrefix(String prefix);
Account getAccount();
} }