diff --git a/app/src/main/java/eu/faircode/email/EmailService.java b/app/src/main/java/eu/faircode/email/EmailService.java
index 1be0ae172d..578103c3ce 100644
--- a/app/src/main/java/eu/faircode/email/EmailService.java
+++ b/app/src/main/java/eu/faircode/email/EmailService.java
@@ -97,11 +97,9 @@ public class EmailService implements AutoCloseable {
static final int PURPOSE_USE = 2;
static final int PURPOSE_SEARCH = 3;
+ final static int DEFAULT_CONNECT_TIMEOUT = 20; // seconds
+
private final static int SEARCH_TIMEOUT = 2 * 60 * 1000; // milliseconds
- private final static int CONNECT_TIMEOUT = 20 * 1000; // milliseconds
- private final static int CONNECT_TIMEOUT_CHECK = 20 * 1000; // milliseconds
- private final static int WRITE_TIMEOUT = 60 * 1000; // milliseconds
- private final static int READ_TIMEOUT = 60 * 1000; // milliseconds
private final static int FETCH_SIZE = 1024 * 1024; // bytes, default 16K
private final static int POOL_TIMEOUT = 45 * 1000; // milliseconds, default 45 sec
@@ -155,20 +153,17 @@ public class EmailService implements AutoCloseable {
properties.put("mail." + protocol + ".sasl.realm", realm == null ? "" : realm);
properties.put("mail." + protocol + ".auth.ntlm.domain", realm == null ? "" : realm);
- // TODO: make timeouts configurable?
// writetimeout: one thread overhead
+ int timeout = prefs.getInt("timeout", DEFAULT_CONNECT_TIMEOUT) * 1000;
+ Log.i("Timeout=" + timeout);
if (purpose == PURPOSE_SEARCH) {
- properties.put("mail." + protocol + ".connectiontimeout", Integer.toString(CONNECT_TIMEOUT));
+ properties.put("mail." + protocol + ".connectiontimeout", Integer.toString(timeout));
properties.put("mail." + protocol + ".writetimeout", Integer.toString(SEARCH_TIMEOUT));
properties.put("mail." + protocol + ".timeout", Integer.toString(SEARCH_TIMEOUT));
- } else if (purpose == PURPOSE_CHECK) {
- properties.put("mail." + protocol + ".connectiontimeout", Integer.toString(CONNECT_TIMEOUT_CHECK));
- properties.put("mail." + protocol + ".writetimeout", Integer.toString(WRITE_TIMEOUT));
- properties.put("mail." + protocol + ".timeout", Integer.toString(READ_TIMEOUT));
} else {
- properties.put("mail." + protocol + ".connectiontimeout", Integer.toString(CONNECT_TIMEOUT));
- properties.put("mail." + protocol + ".writetimeout", Integer.toString(WRITE_TIMEOUT));
- properties.put("mail." + protocol + ".timeout", Integer.toString(READ_TIMEOUT));
+ properties.put("mail." + protocol + ".connectiontimeout", Integer.toString(timeout));
+ properties.put("mail." + protocol + ".writetimeout", Integer.toString(timeout * 2));
+ properties.put("mail." + protocol + ".timeout", Integer.toString(timeout * 2));
}
if (debug && BuildConfig.DEBUG)
diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsConnection.java b/app/src/main/java/eu/faircode/email/FragmentOptionsConnection.java
index 19e566b0d0..17bb26dd23 100644
--- a/app/src/main/java/eu/faircode/email/FragmentOptionsConnection.java
+++ b/app/src/main/java/eu/faircode/email/FragmentOptionsConnection.java
@@ -29,7 +29,9 @@ import android.net.NetworkRequest;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
+import android.text.Editable;
import android.text.TextUtils;
+import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -56,6 +58,7 @@ public class FragmentOptionsConnection extends FragmentBase implements SharedPre
private Spinner spDownload;
private SwitchCompat swRoaming;
private SwitchCompat swRlah;
+ private EditText etTimeout;
private SwitchCompat swSslHarden;
private SwitchCompat swSocks;
private EditText etSocks;
@@ -65,7 +68,7 @@ public class FragmentOptionsConnection extends FragmentBase implements SharedPre
private TextView tvConnectionRoaming;
private final static String[] RESET_OPTIONS = new String[]{
- "metered", "download", "roaming", "rlah", "ssl_harden", "socks_enabled", "socks_proxy"
+ "metered", "download", "roaming", "rlah", "timeout", "ssl_harden", "socks_enabled", "socks_proxy"
};
@Override
@@ -82,6 +85,7 @@ public class FragmentOptionsConnection extends FragmentBase implements SharedPre
spDownload = view.findViewById(R.id.spDownload);
swRoaming = view.findViewById(R.id.swRoaming);
swRlah = view.findViewById(R.id.swRlah);
+ etTimeout = view.findViewById(R.id.etTimeout);
swSslHarden = view.findViewById(R.id.swSslHarden);
swSocks = view.findViewById(R.id.swSocks);
etSocks = view.findViewById(R.id.etSocks);
@@ -131,6 +135,31 @@ public class FragmentOptionsConnection extends FragmentBase implements SharedPre
}
});
+ etTimeout.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ // Do nothing
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ try {
+ int timeout = (s.length() > 0 ? Integer.parseInt(s.toString()) : 0);
+ if (timeout == 0)
+ prefs.edit().remove("timeout").apply();
+ else
+ prefs.edit().putInt("timeout", timeout).apply();
+ } catch (NumberFormatException ex) {
+ Log.e(ex);
+ }
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ // Do nothing
+ }
+ });
+
swSslHarden.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
@@ -186,6 +215,9 @@ public class FragmentOptionsConnection extends FragmentBase implements SharedPre
@Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
+ if ("timeout".equals(key))
+ return;
+
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
setOptions();
}
@@ -255,6 +287,11 @@ public class FragmentOptionsConnection extends FragmentBase implements SharedPre
swRoaming.setChecked(prefs.getBoolean("roaming", true));
swRlah.setChecked(prefs.getBoolean("rlah", true));
+
+ int timeout = prefs.getInt("timeout", 0);
+ etTimeout.setText(timeout == 0 ? null : Integer.toString(timeout));
+ etTimeout.setHint(Integer.toString(EmailService.DEFAULT_CONNECT_TIMEOUT));
+
swSslHarden.setChecked(prefs.getBoolean("ssl_harden", false));
swSocks.setChecked(prefs.getBoolean("socks_enabled", false));
etSocks.setText(prefs.getString("socks_proxy", null));
diff --git a/app/src/main/res/layout/fragment_options_connection.xml b/app/src/main/res/layout/fragment_options_connection.xml
index 39e9058663..8242690595 100644
--- a/app/src/main/res/layout/fragment_options_connection.xml
+++ b/app/src/main/res/layout/fragment_options_connection.xml
@@ -123,6 +123,41 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swRlah" />
+
+
+
+
+
+
Automatically download messages and attachments on a metered connection up to
Download messages and attachments while roaming
Roam like at home
+ Connection timeout (seconds)
Harden SSL connections
Use SOCKS proxy
Manage connectivity
@@ -456,6 +457,7 @@
Metered connections are generally mobile connections or paid Wi-Fi hotspots
Disabling this option will disable receiving and sending messages on mobile internet connections
Assuming no roaming within the EU
+ The read/write timeout will be set to the double of the connection timeout. Higher values will result in more battery use.
Enabling this will disable weak SSL protocols and ciphers
Using a remote proxy server is insecure because proxy connections are not encrypted
Messages headers will always be fetched when roaming. You can use the device\'s roaming setting to disable internet while roaming.