Simplified alert handling

pull/169/head
M66B 5 years ago
parent 46d5289756
commit 4b30caee1f

@ -138,7 +138,7 @@ FairEmail follows all the best practices for an email client as described in [th
* [(20) Can I get a refund?](#user-content-faq20) * [(20) Can I get a refund?](#user-content-faq20)
* [(21) How do I enable the notification light?](#user-content-faq21) * [(21) How do I enable the notification light?](#user-content-faq21)
* [(22) What does account/folder error ... mean?](#user-content-faq22) * [(22) What does account/folder error ... mean?](#user-content-faq22)
* [(23) Why do I get 'Too many simultaneous connections' or 'Maximum number of connections ... exceeded' ?](#user-content-faq23) * [(23) Why do I get alert .. ?](#user-content-faq23)
* [(24) What is browse messages on the server?](#user-content-faq24) * [(24) What is browse messages on the server?](#user-content-faq24)
* [(25) Why can't I select/open/save an image, attachment or a file?](#user-content-faq25) * [(25) Why can't I select/open/save an image, attachment or a file?](#user-content-faq25)
* [(26) Can I help to translate FairEmail in my own language?](#user-content-faq26) * [(26) Can I help to translate FairEmail in my own language?](#user-content-faq26)
@ -842,27 +842,34 @@ When in doubt, you can ask for [support](#user-content-support).
<br /> <br />
<a name="faq23"></a> <a name="faq23"></a>
**(23) Why do I get 'Too many simultaneous connections' or 'Maximum number of connections ... exceeded' ?** **(23) Why do I get alert ... ?**
The message *Too many simultaneous connections* is sent by the email server *General*
when there are too many folder connections for the same email account at the same time.
Alerts are warning messages sent by email servers.
*Too many simultaneous connections* or *Maximum number of connections exceeded*
This alert will be sent when there are too many folder connections for the same email account at the same time.
Possible causes are: Possible causes are:
* There are multiple email clients connected to the same account * There are multiple email clients connected to the same account
* The same email client is connected multiple times to the same account * The same email client is connected multiple times to the same account
* The previous connection was terminated abruptly for example by abruptly losing internet connectivity, for example when turning on flight mode * Previous connections were terminated abruptly for example by abruptly losing internet connectivity
If only FairEmail is connecting to the email server, first try to wait half an hour to see if the problem resolves itself, First try to wait some time to see if the problem resolves itself,
else enable the folder setting *Poll instead of synchronize* for some folders (long press folder in the folder list > Edit properties). else try to enable the folder setting *Poll instead of synchronize* for some folders (long press folder in the folder list, edit properties).
The poll interval can be configured in the account settings. The poll interval can be configured in the account settings.
You also might want to disable *Browse messages on the server* in the advanced account settings (Setup > Step 1 > Manage > Tap account > Advanced).
The maximum number of simultaneous folder connections for Gmail is 15, The maximum number of simultaneous folder connections for Gmail is 15,
so you can synchronize at most 15 folders simultaneously on *all* your devices at the same time. so you can synchronize at most 15 folders simultaneously on *all* your devices at the same time.
For this reason Gmail user folders are set to poll by default.
See [here](https://support.google.com/mail/answer/7126229) for details. See [here](https://support.google.com/mail/answer/7126229) for details.
When using a Dovecot server,
you might want to change the setting [mail_max_userip_connections](https://doc.dovecot.org/settings/dovecot_core_settings/#mail-max-userip-connections).
<br /> <br />
<a name="faq24"></a> <a name="faq24"></a>

@ -106,11 +106,12 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB
static final int REQUEST_UNIFIED = 1; static final int REQUEST_UNIFIED = 1;
static final int REQUEST_FOLDER = 2; static final int REQUEST_FOLDER = 2;
static final int REQUEST_WHY = 3; static final int REQUEST_WHY = 3;
static final int REQUEST_THREAD = 4; static final int REQUEST_ALERT = 4;
static final int REQUEST_OUTBOX = 5; static final int REQUEST_THREAD = 5;
static final int REQUEST_ERROR = 6; static final int REQUEST_OUTBOX = 6;
static final int REQUEST_UPDATE = 7; static final int REQUEST_ERROR = 7;
static final int REQUEST_WIDGET = 8; static final int REQUEST_UPDATE = 8;
static final int REQUEST_WIDGET = 9;
static final String ACTION_VIEW_FOLDERS = BuildConfig.APPLICATION_ID + ".VIEW_FOLDERS"; static final String ACTION_VIEW_FOLDERS = BuildConfig.APPLICATION_ID + ".VIEW_FOLDERS";
static final String ACTION_VIEW_MESSAGES = BuildConfig.APPLICATION_ID + ".VIEW_MESSAGES"; static final String ACTION_VIEW_MESSAGES = BuildConfig.APPLICATION_ID + ".VIEW_MESSAGES";
@ -826,6 +827,12 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB
Helper.viewFAQ(this, 2); Helper.viewFAQ(this, 2);
} }
} else if ("alert".equals(action)) {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
getSupportFragmentManager().popBackStack("unified", 0);
Helper.viewFAQ(this, 23);
} else if ("outbox".equals(action)) } else if ("outbox".equals(action))
onMenuOutbox(); onMenuOutbox();

@ -244,14 +244,14 @@ public class ApplicationEx extends Application {
nm.createNotificationChannel(update); nm.createNotificationChannel(update);
} }
// Warn // Warnings
NotificationChannel warning = new NotificationChannel( NotificationChannel warning = new NotificationChannel(
"warning", getString(R.string.channel_warning), "warning", getString(R.string.channel_warning),
NotificationManager.IMPORTANCE_HIGH); NotificationManager.IMPORTANCE_HIGH);
warning.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); warning.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
nm.createNotificationChannel(warning); nm.createNotificationChannel(warning);
// Error // Errors
NotificationChannel error = new NotificationChannel( NotificationChannel error = new NotificationChannel(
"error", "error",
getString(R.string.channel_error), getString(R.string.channel_error),
@ -259,6 +259,14 @@ public class ApplicationEx extends Application {
error.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); error.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
nm.createNotificationChannel(error); nm.createNotificationChannel(error);
// Server alerts
NotificationChannel alerts = new NotificationChannel(
"alerts",
getString(R.string.channel_alert),
NotificationManager.IMPORTANCE_HIGH);
alerts.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
nm.createNotificationChannel(alerts);
// Contacts grouping // Contacts grouping
NotificationChannelGroup group = new NotificationChannelGroup( NotificationChannelGroup group = new NotificationChannelGroup(
"contacts", "contacts",

@ -3191,27 +3191,13 @@ class Core {
.setPriority(NotificationCompat.PRIORITY_MAX) .setPriority(NotificationCompat.PRIORITY_MAX)
.setOnlyAlertOnce(true) .setOnlyAlertOnce(true)
.setCategory(NotificationCompat.CATEGORY_ERROR) .setCategory(NotificationCompat.CATEGORY_ERROR)
.setVisibility(NotificationCompat.VISIBILITY_SECRET); .setVisibility(NotificationCompat.VISIBILITY_SECRET)
.setStyle(new NotificationCompat.BigTextStyle()
builder.setStyle(new NotificationCompat.BigTextStyle() .bigText(Log.formatThrowable(ex, "\n", false)));
.bigText(Log.formatThrowable(ex, "\n", false)));
return builder; return builder;
} }
static class AlertException extends Throwable {
private String alert;
AlertException(String alert) {
this.alert = alert;
}
@Override
public String getMessage() {
return alert;
}
}
static class State { static class State {
private ConnectionHelper.NetworkState networkState; private ConnectionHelper.NetworkState networkState;
private Thread thread; private Thread thread;

@ -273,7 +273,7 @@ public class Helper {
if (question == 0) if (question == 0)
view(context, Uri.parse(FAQ_URI), false); view(context, Uri.parse(FAQ_URI), false);
else else
view(context, Uri.parse(Helper.FAQ_URI + "#user-content-faq" + question), false); view(context, Uri.parse(FAQ_URI + "#user-content-faq" + question), false);
} }
static Intent getIntentOpenKeychain() { static Intent getIntentOpenKeychain() {

@ -552,9 +552,6 @@ public class Log {
("Not connected".equals(ex.getMessage()) || ("Not connected".equals(ex.getMessage()) ||
"This operation is not allowed on a closed folder".equals(ex.getMessage()))) "This operation is not allowed on a closed folder".equals(ex.getMessage())))
return null; return null;
if (ex instanceof Core.AlertException)
return ex.getMessage();
} }
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();

@ -707,6 +707,31 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
return builder; return builder;
} }
private NotificationCompat.Builder getNotificationAlert(String account, String message) {
// Build pending intent
Intent alert = new Intent(this, ActivityView.class);
alert.setAction("alert");
PendingIntent piAlert = PendingIntent.getActivity(this, ActivityView.REQUEST_ALERT, alert, PendingIntent.FLAG_UPDATE_CURRENT);
// Build notification
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this, "alerts")
.setSmallIcon(R.drawable.baseline_warning_white_24)
.setContentTitle(getString(R.string.title_notification_alert, account))
.setContentText(message)
.setContentIntent(piAlert)
.setAutoCancel(false)
.setShowWhen(true)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setOnlyAlertOnce(true)
.setCategory(NotificationCompat.CATEGORY_ERROR)
.setVisibility(NotificationCompat.VISIBILITY_SECRET)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(message));
return builder;
}
private void setUnseen(Integer unseen) { private void setUnseen(Integer unseen) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean badge = prefs.getBoolean("badge", true); boolean badge = prefs.getBoolean("badge", true);
@ -779,21 +804,11 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
try { try {
wlFolder.acquire(); wlFolder.acquire();
String message = e.getMessage(); EntityLog.log(ServiceSynchronize.this, account.name + " " + e.getMessage());
Log.w(account.name + " alert: " + message);
EntityLog.log(
ServiceSynchronize.this, account.name + " " +
Log.formatThrowable(new Core.AlertException(message), false));
db.account().setAccountError(account.id, message);
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify("alert:" + account.id, 1, nm.notify("alert:" + account.id, 1,
Core.getNotificationError( getNotificationAlert(account.name, e.getMessage()).build());
ServiceSynchronize.this, "warning", account.name,
new Core.AlertException(message))
.build());
state.error(null);
} finally { } finally {
wlFolder.release(); wlFolder.release();
} }

@ -15,6 +15,7 @@
<string name="channel_update">Updates</string> <string name="channel_update">Updates</string>
<string name="channel_warning">Warnings</string> <string name="channel_warning">Warnings</string>
<string name="channel_error">Errors</string> <string name="channel_error">Errors</string>
<string name="channel_alert">Server alerts</string>
<string name="channel_group_contacts">Contacts</string> <string name="channel_group_contacts">Contacts</string>
<plurals name="page_conversation"> <plurals name="page_conversation">
@ -87,6 +88,7 @@
<string name="title_notification_waiting">Waiting for suitable connection</string> <string name="title_notification_waiting">Waiting for suitable connection</string>
<string name="title_notification_sending">Sending messages</string> <string name="title_notification_sending">Sending messages</string>
<string name="title_notification_failed">\'%1$s\' failed</string> <string name="title_notification_failed">\'%1$s\' failed</string>
<string name="title_notification_alert">\'%1$s\' server alert</string>
<string name="title_name_count">%1$s (%2$s)</string> <string name="title_name_count">%1$s (%2$s)</string>

Loading…
Cancel
Save