diff --git a/app/src/main/java/eu/faircode/email/AdapterMessage.java b/app/src/main/java/eu/faircode/email/AdapterMessage.java index 54edfab841..288d7c8d37 100644 --- a/app/src/main/java/eu/faircode/email/AdapterMessage.java +++ b/app/src/main/java/eu/faircode/email/AdapterMessage.java @@ -2917,10 +2917,12 @@ public class AdapterMessage extends RecyclerView.Adapter 0) { @@ -1159,12 +1150,12 @@ class Core { } catch (IOException ex) { if (ex.getCause() instanceof MessagingException) { Log.w(folder.name, ex); - db.folder().setFolderError(folder.id, Helper.formatThrowable(ex, true)); + db.folder().setFolderError(folder.id, Helper.formatThrowable(ex)); } else throw ex; } catch (Throwable ex) { Log.e(folder.name, ex); - db.folder().setFolderError(folder.id, Helper.formatThrowable(ex, true)); + db.folder().setFolderError(folder.id, Helper.formatThrowable(ex)); } finally { // Free memory ((IMAPMessage) isub[j]).invalidateHeaders(); @@ -2117,58 +2108,17 @@ class Core { builder.setSound(uri); } - static void reportError(Context context, EntityAccount account, EntityFolder folder, Throwable ex) { - // FolderClosedException: can happen when no connectivity + // FolderClosedException: can happen when no connectivity - // IllegalStateException: - // - "This operation is not allowed on a closed folder" - // - can happen when syncing message + // IllegalStateException: + // - "This operation is not allowed on a closed folder" + // - can happen when syncing message - // ConnectionException - // - failed to create new store connection (connectivity) + // ConnectionException + // - failed to create new store connection (connectivity) - // MailConnectException - // - on connectivity problems when connecting to store - - String title; - if (account == null) - title = Helper.localizeFolderName(context, folder.name); - else if (folder == null) - title = account.name; - else - title = account.name + "/" + Helper.localizeFolderName(context, folder.name); - - String tag = "error:" + (account == null ? 0 : account.id) + ":" + (folder == null ? 0 : folder.id); - - EntityLog.log(context, title + " " + Helper.formatThrowable(ex)); - - NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - if (nm == null) - return; - - if (ex instanceof AuthenticationFailedException || // Also: Too many simultaneous connections - ex instanceof AlertException || - ex instanceof SendFailedException) - nm.notify(tag, 1, getNotificationError(context, "error", title, ex).build()); - - // connection failure: Too many simultaneous connections - - if (BuildConfig.DEBUG && - !(ex instanceof SendFailedException) && - !(ex instanceof MailConnectException) && - !(ex instanceof FolderClosedException) && - !(ex instanceof IllegalStateException) && - !(ex instanceof StoreClosedException) && - !(ex instanceof UnknownHostException) && - !(ex instanceof MessageRemovedException) && - !(ex instanceof MessagingException && ex.getCause() instanceof UnknownHostException) && - !(ex instanceof MessagingException && ex.getCause() instanceof ConnectionException) && - !(ex instanceof MessagingException && ex.getCause() instanceof SocketException) && - !(ex instanceof MessagingException && ex.getCause() instanceof SocketTimeoutException) && - !(ex instanceof MessagingException && ex.getCause() instanceof SSLException) && - !(ex instanceof MessagingException && "connection failure".equals(ex.getMessage()))) - nm.notify(tag, 1, getNotificationError(context, "error", title, ex).build()); - } + // MailConnectException + // - on connectivity problems when connecting to store static NotificationCompat.Builder getNotificationError(Context context, String channel, String title, Throwable ex) { // Build pending intent @@ -2192,7 +2142,7 @@ class Core { .setVisibility(NotificationCompat.VISIBILITY_SECRET); builder.setStyle(new NotificationCompat.BigTextStyle() - .bigText(Helper.formatThrowable(ex, false, "\n"))); + .bigText(Helper.formatThrowable(ex, "\n"))); return builder; } diff --git a/app/src/main/java/eu/faircode/email/FragmentAccount.java b/app/src/main/java/eu/faircode/email/FragmentAccount.java index 897154aa7d..44f0072a5f 100644 --- a/app/src/main/java/eu/faircode/email/FragmentAccount.java +++ b/app/src/main/java/eu/faircode/email/FragmentAccount.java @@ -1027,7 +1027,7 @@ public class FragmentAccount extends FragmentBase { if (!synchronize) { NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - nm.cancel("receive", account.id.intValue()); + nm.cancel("receive:" + account.id, 1); } return false; diff --git a/app/src/main/java/eu/faircode/email/FragmentIdentity.java b/app/src/main/java/eu/faircode/email/FragmentIdentity.java index 46eb44d14d..c53706607b 100644 --- a/app/src/main/java/eu/faircode/email/FragmentIdentity.java +++ b/app/src/main/java/eu/faircode/email/FragmentIdentity.java @@ -19,6 +19,7 @@ package eu.faircode.email; Copyright 2018-2019 by Marcel Bokhorst (M66B) */ +import android.app.NotificationManager; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -755,6 +756,11 @@ public class FragmentIdentity extends FragmentBase { db.endTransaction(); } + if (!synchronize) { + NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + nm.cancel("send:" + identity.id, 1); + } + return false; } diff --git a/app/src/main/java/eu/faircode/email/Helper.java b/app/src/main/java/eu/faircode/email/Helper.java index 1ada206374..8940f1ea04 100644 --- a/app/src/main/java/eu/faircode/email/Helper.java +++ b/app/src/main/java/eu/faircode/email/Helper.java @@ -382,33 +382,24 @@ public class Helper { } static String formatThrowable(Throwable ex) { - return formatThrowable(ex, false, " "); + return formatThrowable(ex, " "); } - static String formatThrowable(Throwable ex, boolean sanitize) { - return formatThrowable(ex, sanitize, " "); - } - - static String formatThrowable(Throwable ex, boolean sanitize, String separator) { - if (sanitize) { - if (ex instanceof MessageRemovedException) - return null; - - if (ex instanceof IOException && - ex.getCause() instanceof MessageRemovedException) - return null; + static String formatThrowable(Throwable ex, String separator) { + if (ex instanceof MessageRemovedException) + return null; - if (ex instanceof FolderClosedException) - return null; + if (ex instanceof IOException && + ex.getCause() instanceof MessageRemovedException) + return null; - if (ex instanceof IllegalStateException && - ("Not connected".equals(ex.getMessage()) || - "This operation is not allowed on a closed folder".equals(ex.getMessage()))) - return null; + if (ex instanceof FolderClosedException) + return null; - //if (ex instanceof MailConnectException && ex.getCause() instanceof UnknownHostException) - // return null; - } + if (ex instanceof IllegalStateException && + ("Not connected".equals(ex.getMessage()) || + "This operation is not allowed on a closed folder".equals(ex.getMessage()))) + return null; StringBuilder sb = new StringBuilder(); if (BuildConfig.DEBUG) diff --git a/app/src/main/java/eu/faircode/email/ServiceSend.java b/app/src/main/java/eu/faircode/email/ServiceSend.java index 51261510e3..b3367fc4b4 100644 --- a/app/src/main/java/eu/faircode/email/ServiceSend.java +++ b/app/src/main/java/eu/faircode/email/ServiceSend.java @@ -51,6 +51,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.mail.Address; +import javax.mail.AuthenticationFailedException; import javax.mail.Message; import javax.mail.MessageRemovedException; import javax.mail.MessagingException; @@ -150,7 +151,6 @@ public class ServiceSend extends LifecycleService { db.operation().deleteOperation(op.id); } catch (Throwable ex) { Log.e(outbox.name, ex); - Core.reportError(ServiceSend.this, null, outbox, ex); db.operation().setOperationError(op.id, Helper.formatThrowable(ex)); if (message != null) @@ -174,7 +174,7 @@ public class ServiceSend extends LifecycleService { } } catch (Throwable ex) { Log.e(outbox.name, ex); - db.folder().setFolderError(outbox.id, Helper.formatThrowable(ex, true)); + db.folder().setFolderError(outbox.id, Helper.formatThrowable(ex)); } finally { db.folder().setFolderState(outbox.id, null); db.folder().setFolderSyncState(outbox.id, null); @@ -294,6 +294,9 @@ public class ServiceSend extends LifecycleService { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); boolean debug = prefs.getBoolean("debug", false); + if (message.identity == null) + throw new IllegalArgumentException("Identity removed"); + EntityIdentity ident = db.identity().getIdentity(message.identity); String protocol = ident.getProtocol(); @@ -410,45 +413,28 @@ public class ServiceSend extends LifecycleService { db.identity().setIdentityError(ident.id, null); NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - nm.cancel("send", message.identity.intValue()); + nm.cancel("send:" + message.identity, 1); } catch (MessagingException ex) { - // Caused by: com.sun.mail.smtp.SMTPAddressFailedException: 554 Refused. Sending to remote addresses (relaying) is not allowed. -/* - if (ex instanceof SendFailedException) { - SendFailedException sfe = (SendFailedException) ex; - - StringBuilder sb = new StringBuilder(); - - sb.append(sfe.getMessage()); - - sb.append(' ').append(getString(R.string.title_address_sent)); - sb.append(' ').append(MessageHelper.formatAddresses(sfe.getValidSentAddresses())); - - sb.append(' ').append(getString(R.string.title_address_unsent)); - sb.append(' ').append(MessageHelper.formatAddresses(sfe.getValidUnsentAddresses())); + Log.e(ex); - sb.append(' ').append(getString(R.string.title_address_invalid)); - sb.append(' ').append(MessageHelper.formatAddresses(sfe.getInvalidAddresses())); - - ex = new SendFailedException( - sb.toString(), - sfe.getNextException(), - sfe.getValidSentAddresses(), - sfe.getValidUnsentAddresses(), - sfe.getInvalidAddresses()); - } -*/ db.identity().setIdentityError(ident.id, Helper.formatThrowable(ex)); - EntityLog.log(this, ident.name + " last attempt: " + new Date(message.last_attempt)); + if (ex instanceof AuthenticationFailedException || + ex instanceof SendFailedException) { + NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + nm.notify("send:" + message.identity, 1, + Core.getNotificationError(this, "error", ident.name, ex) + .build()); + throw ex; + } long now = new Date().getTime(); long delayed = now - message.last_attempt; if (delayed > IDENTITY_ERROR_AFTER * 60 * 1000L || ex instanceof SendFailedException) { Log.i("Reporting send error after=" + delayed); NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - nm.notify("send", message.identity.intValue(), - Core.getNotificationError(this, "error", ident.name, ex).build()); + nm.notify("send:" + message.identity, 1, + Core.getNotificationError(this, "warning", ident.name, ex).build()); } throw ex; diff --git a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java index 70537d57b1..01f3a16c29 100644 --- a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java +++ b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java @@ -65,6 +65,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.RejectedExecutionException; +import javax.mail.AuthenticationFailedException; import javax.mail.FetchProfile; import javax.mail.Folder; import javax.mail.FolderClosedException; @@ -597,10 +598,16 @@ public class ServiceSynchronize extends LifecycleService { String message = e.getMessage(); Log.w(account.name + " alert: " + message); db.account().setAccountError(account.id, message); - if (BuildConfig.DEBUG || - (message != null && !message.startsWith("Too many simultaneous connections"))) - Core.reportError(ServiceSynchronize.this, account, null, - new Core.AlertException(message)); + + if (message != null && !message.startsWith("Too many simultaneous connections")) { + NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + nm.notify("receive:" + account.id, 1, + Core.getNotificationError( + ServiceSynchronize.this, "warning", account.name, + new Core.AlertException(message)) + .build()); + } + state.error(null); } finally { wlFolder.release(); @@ -698,6 +705,14 @@ public class ServiceSynchronize extends LifecycleService { try { ConnectionHelper.connect(this, istore, account); } catch (Throwable ex) { + if (ex instanceof AuthenticationFailedException) { + NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + nm.notify("receive:" + account.id, 1, + Core.getNotificationError(this, "error", account.name, ex) + .build()); + throw ex; + } + // Report account connection error if (account.last_connected != null && !ConnectionHelper.airplaneMode(this)) { EntityLog.log(this, account.name + " last connected: " + new Date(account.last_connected)); @@ -710,7 +725,7 @@ public class ServiceSynchronize extends LifecycleService { SimpleDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT) .format(account.last_connected)), ex); NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - nm.notify("receive", account.id.intValue(), + nm.notify("receive:" + account.id, 1, Core.getNotificationError(this, "warning", account.name, warning) .build()); } @@ -746,14 +761,14 @@ public class ServiceSynchronize extends LifecycleService { db.folder().setFolderReadOnly(folder.id, false); } catch (ReadOnlyFolderException ex) { Log.w(folder.name + " read only"); - db.folder().setFolderError(folder.id, Helper.formatThrowable(ex, true)); + db.folder().setFolderError(folder.id, Helper.formatThrowable(ex)); try { ifolder.open(Folder.READ_ONLY); db.folder().setFolderReadOnly(folder.id, true); } catch (MessagingException ex1) { Log.w(ex1); db.folder().setFolderState(folder.id, null); - db.folder().setFolderError(folder.id, Helper.formatThrowable(ex1, true)); + db.folder().setFolderError(folder.id, Helper.formatThrowable(ex1)); continue; } } catch (FolderNotFoundException ex) { @@ -763,10 +778,10 @@ public class ServiceSynchronize extends LifecycleService { } catch (MessagingException ex) { Log.w(ex); db.folder().setFolderState(folder.id, null); - db.folder().setFolderError(folder.id, Helper.formatThrowable(ex, true)); + db.folder().setFolderError(folder.id, Helper.formatThrowable(ex)); continue; } catch (Throwable ex) { - db.folder().setFolderError(folder.id, Helper.formatThrowable(ex, true)); + db.folder().setFolderError(folder.id, Helper.formatThrowable(ex)); throw ex; } mapFolders.put(folder, ifolder); @@ -818,19 +833,18 @@ public class ServiceSynchronize extends LifecycleService { } catch (IOException ex) { if (ex.getCause() instanceof MessagingException) { Log.w(folder.name, ex); - db.folder().setFolderError(folder.id, Helper.formatThrowable(ex, true)); + db.folder().setFolderError(folder.id, Helper.formatThrowable(ex)); } else throw ex; } catch (Throwable ex) { Log.e(folder.name, ex); - db.folder().setFolderError(folder.id, Helper.formatThrowable(ex, true)); + db.folder().setFolderError(folder.id, Helper.formatThrowable(ex)); } int count = ifolder.getMessageCount(); db.folder().setFolderTotal(folder.id, count < 0 ? null : count); } catch (Throwable ex) { Log.e(folder.name, ex); - Core.reportError(ServiceSynchronize.this, account, folder, ex); state.error(ex); } finally { wlMessage.release(); @@ -859,8 +873,7 @@ public class ServiceSynchronize extends LifecycleService { db.folder().setFolderTotal(folder.id, count < 0 ? null : count); } catch (Throwable ex) { Log.e(folder.name, ex); - Core.reportError(ServiceSynchronize.this, account, folder, ex); - db.folder().setFolderError(folder.id, Helper.formatThrowable(ex, true)); + db.folder().setFolderError(folder.id, Helper.formatThrowable(ex)); state.error(ex); } finally { wlMessage.release(); @@ -902,16 +915,15 @@ public class ServiceSynchronize extends LifecycleService { } catch (IOException ex) { if (ex.getCause() instanceof MessagingException) { Log.w(folder.name, ex); - db.folder().setFolderError(folder.id, Helper.formatThrowable(ex, true)); + db.folder().setFolderError(folder.id, Helper.formatThrowable(ex)); } else throw ex; } catch (Throwable ex) { Log.e(folder.name, ex); - db.folder().setFolderError(folder.id, Helper.formatThrowable(ex, true)); + db.folder().setFolderError(folder.id, Helper.formatThrowable(ex)); } } catch (Throwable ex) { Log.e(folder.name, ex); - Core.reportError(ServiceSynchronize.this, account, folder, ex); state.error(ex); } finally { wlMessage.release(); @@ -1008,8 +1020,7 @@ public class ServiceSynchronize extends LifecycleService { } catch (Throwable ex) { Log.e(folder.name, ex); - Core.reportError(ServiceSynchronize.this, account, folder, ex); - db.folder().setFolderError(folder.id, Helper.formatThrowable(ex, true)); + db.folder().setFolderError(folder.id, Helper.formatThrowable(ex)); state.error(ex); } finally { if (shouldClose) { @@ -1081,7 +1092,7 @@ public class ServiceSynchronize extends LifecycleService { db.account().setAccountWarning(account.id, capIdle ? null : getString(R.string.title_no_idle)); NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - nm.cancel("receive", account.id.intValue()); + nm.cancel("receive:" + account.id, 1); // Schedule keep alive alarm EntityLog.log(this, account.name + " wait=" + account.poll_interval); @@ -1121,7 +1132,6 @@ public class ServiceSynchronize extends LifecycleService { Log.w(ex); } catch (Throwable ex) { Log.e(account.name, ex); - Core.reportError(this, account, null, ex); db.account().setAccountError(account.id, Helper.formatThrowable(ex)); } finally { // Stop watching for operations diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2fa4d1e3b5..1e5b9c2dfa 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -539,10 +539,6 @@ Text size Select all - Sent: - Unsent: - Invalid: - Previous Next