diff --git a/FAQ.md b/FAQ.md
index 859a1c269b..c113007749 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -49,13 +49,13 @@ See also [this FAQ](#FAQ16).
Valid security certificates are officially signed (not self signed) and have matching a host name.
-**(5) What does 'no IDLE support' mean?**
+~~**(5) What does 'no IDLE support' mean?**~~
-Without [IMAP IDLE](https://en.wikipedia.org/wiki/IMAP_IDLE) emails need to be periodically fetched,
-which is a waste of battery power and internet bandwidth and will delay notification of new emails.
-Since the goal of FairEmail is to offer safe and fast email, providers without IMAP IDLE are not supported.
-You should consider this a problem of the provider, not of the app.
-Almost all email providers offer IMAP IDLE, with as notable exception Yahoo!
+~~Without [IMAP IDLE](https://en.wikipedia.org/wiki/IMAP_IDLE) emails need to be periodically fetched,~~
+~~which is a waste of battery power and internet bandwidth and will delay notification of new emails.~~
+~~Since the goal of FairEmail is to offer safe and fast email, providers without IMAP IDLE are not supported.~~
+~~You should consider this a problem of the provider, not of the app.~~
+~~Almost all email providers offer IMAP IDLE, with as notable exception Yahoo!~~
**(6) How can I login to Gmail / G suite?**
diff --git a/SETUP.md b/SETUP.md
index 83ea84fdd5..121ba6ff73 100644
--- a/SETUP.md
+++ b/SETUP.md
@@ -7,11 +7,6 @@ You'll need to add at least one account to receive email and at least one identi
An internet connection is required to add accounts and identities.
-Your email provider should support IMAP with the IDLE and UIDPLUS extensions.
-All up-to-date email providers do, with as notable exception Yahoo!
-IMAP IDLE is required to limit battery usage,
-see [this FAQ](https://github.com/M66B/open-source-email/blob/master/FAQ.md#FAQ5) for more details.
-
Your email provider should support secure connections.
If your provider doesn't support secure connections and you care at least a little about your privacy,
you are strongly advised to switch to another provider.
diff --git a/app/src/main/java/eu/faircode/email/FragmentAccount.java b/app/src/main/java/eu/faircode/email/FragmentAccount.java
index fe38cd9ae4..e551ca933c 100644
--- a/app/src/main/java/eu/faircode/email/FragmentAccount.java
+++ b/app/src/main/java/eu/faircode/email/FragmentAccount.java
@@ -110,6 +110,7 @@ public class FragmentAccount extends FragmentEx {
private ImageButton ibPro;
private CheckBox cbSynchronize;
private CheckBox cbPrimary;
+ private EditText etInterval;
private Button btnCheck;
private ProgressBar pbCheck;
@@ -173,6 +174,7 @@ public class FragmentAccount extends FragmentEx {
cbSynchronize = view.findViewById(R.id.cbSynchronize);
cbPrimary = view.findViewById(R.id.cbPrimary);
+ etInterval = view.findViewById(R.id.etInterval);
btnCheck = view.findViewById(R.id.btnCheck);
pbCheck = view.findViewById(R.id.pbCheck);
@@ -429,9 +431,6 @@ public class FragmentAccount extends FragmentEx {
throw ex;
}
- if (!istore.hasCapability("IDLE"))
- throw new MessagingException(getContext().getString(R.string.title_no_idle));
-
if (!istore.hasCapability("UIDPLUS"))
throw new MessagingException(getContext().getString(R.string.title_no_uidplus));
@@ -567,6 +566,7 @@ public class FragmentAccount extends FragmentEx {
args.putInt("color", color);
args.putString("signature", Html.toHtml(etSignature.getText()));
args.putBoolean("primary", cbPrimary.isChecked());
+ args.putString("interval", etInterval.getText().toString());
args.putParcelable("drafts", drafts);
args.putParcelable("sent", sent);
@@ -588,6 +588,7 @@ public class FragmentAccount extends FragmentEx {
String signature = args.getString("signature");
boolean synchronize = args.getBoolean("synchronize");
boolean primary = args.getBoolean("primary");
+ String interval = args.getString("interval");
EntityFolder drafts = args.getParcelable("drafts");
EntityFolder sent = args.getParcelable("sent");
@@ -603,6 +604,8 @@ public class FragmentAccount extends FragmentEx {
throw new Throwable(getContext().getString(R.string.title_no_user));
if (TextUtils.isEmpty(password))
throw new Throwable(getContext().getString(R.string.title_no_password));
+ if (TextUtils.isEmpty(interval))
+ interval = "9";
if (synchronize && drafts == null)
throw new Throwable(getContext().getString(R.string.title_no_drafts));
@@ -653,7 +656,7 @@ public class FragmentAccount extends FragmentEx {
account.synchronize = synchronize;
account.primary = (account.synchronize && primary);
account.store_sent = false;
- account.poll_interval = 9;
+ account.poll_interval = Integer.parseInt(interval);
if (!synchronize)
account.error = null;
@@ -874,6 +877,7 @@ public class FragmentAccount extends FragmentEx {
cbSynchronize.setChecked(account == null ? true : account.synchronize);
cbPrimary.setChecked(account == null ? true : account.primary);
+ etInterval.setText(Long.toString(account == null ? 9 : account.poll_interval));
color = (account == null || account.color == null ? Color.TRANSPARENT : account.color);
diff --git a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java
index ed5c06ad29..bf07d880a9 100644
--- a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java
+++ b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java
@@ -642,6 +642,8 @@ public class ServiceSynchronize extends LifecycleService {
db.folder().setFolderState(folder.id, null);
db.account().setAccountState(account.id, "connecting");
Helper.connect(this, istore, account);
+ final boolean capIdle = istore.hasCapability("IDLE");
+ Log.i(Helper.TAG, account.name + " idle=" + capIdle);
db.account().setAccountState(account.id, "connected");
db.account().setAccountError(account.id, null);
@@ -813,15 +815,18 @@ public class ServiceSynchronize extends LifecycleService {
try {
Thread.sleep(account.poll_interval * 60 * 1000L);
- Log.i(Helper.TAG, folder.name + " request NOOP");
- ifolder.doCommand(new IMAPFolder.ProtocolCommand() {
- public Object doCommand(IMAPProtocol p) throws ProtocolException {
- Log.i(Helper.TAG, ifolder.getName() + " start NOOP");
- p.simpleCommand("NOOP", null);
- Log.i(Helper.TAG, ifolder.getName() + " end NOOP");
- return null;
- }
- });
+ if (capIdle) {
+ Log.i(Helper.TAG, folder.name + " request NOOP");
+ ifolder.doCommand(new IMAPFolder.ProtocolCommand() {
+ public Object doCommand(IMAPProtocol p) throws ProtocolException {
+ Log.i(Helper.TAG, ifolder.getName() + " start NOOP");
+ p.simpleCommand("NOOP", null);
+ Log.i(Helper.TAG, ifolder.getName() + " end NOOP");
+ return null;
+ }
+ });
+ } else
+ synchronizeMessages(account, folder, ifolder, state);
} catch (InterruptedException ex) {
Log.w(Helper.TAG, folder.name + " noop " + ex.toString());
@@ -845,32 +850,34 @@ public class ServiceSynchronize extends LifecycleService {
noops.add(noop);
// Receive folder events
- Thread idle = new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- Log.i(Helper.TAG, folder.name + " start idle");
- while (state.running && ifolder.isOpen()) {
- //Log.i(Helper.TAG, folder.name + " do idle");
- ifolder.idle(false);
- //Log.i(Helper.TAG, folder.name + " done idle");
- }
- } catch (Throwable ex) {
- Log.e(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex));
- reportError(account.name, folder.name, ex);
+ if (capIdle) {
+ Thread idle = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Log.i(Helper.TAG, folder.name + " start idle");
+ while (state.running && ifolder.isOpen()) {
+ Log.i(Helper.TAG, folder.name + " do idle");
+ ifolder.idle(false);
+ //Log.i(Helper.TAG, folder.name + " done idle");
+ }
+ } catch (Throwable ex) {
+ Log.e(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex));
+ reportError(account.name, folder.name, ex);
- db.folder().setFolderError(folder.id, Helper.formatThrowable(ex));
+ db.folder().setFolderError(folder.id, Helper.formatThrowable(ex));
- synchronized (state) {
- state.notifyAll();
+ synchronized (state) {
+ state.notifyAll();
+ }
+ } finally {
+ Log.i(Helper.TAG, folder.name + " end idle");
}
- } finally {
- Log.i(Helper.TAG, folder.name + " end idle");
}
- }
- }, "sync.idle." + folder.id);
- idle.start();
- idlers.add(idle);
+ }, "sync.idle." + folder.id);
+ idle.start();
+ idlers.add(idle);
+ }
}
backoff = CONNECT_BACKOFF_START;
diff --git a/app/src/main/res/layout/fragment_account.xml b/app/src/main/res/layout/fragment_account.xml
index 1c2d162231..0af1037da6 100644
--- a/app/src/main/res/layout/fragment_account.xml
+++ b/app/src/main/res/layout/fragment_account.xml
@@ -173,7 +173,6 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvUser" />
-
+
+
+
+
+
+
+
+ app:layout_constraintTop_toBottomOf="@id/etInterval" />
+ app:layout_constraintTop_toBottomOf="@id/etInterval" />
+ app:constraint_referenced_ids="tvName,etName,btnColor,vwColor,ibColorDefault,tvSignature,etSignature,ibPro,cbSynchronize,cbPrimary,tvInterval,etInterval" />
Synchronize (send messages)
Primary (default account)
Primary (default identity)
+ Poll interval (minutes)
Check
Name missing
Email address missing
@@ -119,7 +120,6 @@
User name missing
Password missing
Drafts folder missing
- IMAP IDLE not supported, see the FAQ
IMAP UIDPLUS not supported, see the FAQ
Delete this account permanently?
Delete this identity permanently?
diff --git a/app/src/main/res/xml/providers.xml b/app/src/main/res/xml/providers.xml
index 961096ceca..b8d8775bce 100644
--- a/app/src/main/res/xml/providers.xml
+++ b/app/src/main/res/xml/providers.xml
@@ -36,7 +36,7 @@
starttls="false" />
-
+
@@ -81,7 +81,7 @@
starttls="false" />
-
+