Browse Source

Bring back polling

main
M66B 6 years ago
parent
commit
9cafc1223d
7 changed files with 83 additions and 55 deletions
  1. +6
    -6
      FAQ.md
  2. +0
    -5
      SETUP.md
  3. +8
    -4
      app/src/main/java/eu/faircode/email/FragmentAccount.java
  4. +38
    -31
      app/src/main/java/eu/faircode/email/ServiceSynchronize.java
  5. +26
    -4
      app/src/main/res/layout/fragment_account.xml
  6. +1
    -1
      app/src/main/res/values/strings.xml
  7. +4
    -4
      app/src/main/res/xml/providers.xml

+ 6
- 6
FAQ.md View File

@ -49,13 +49,13 @@ See also [this FAQ](#FAQ16).
Valid security certificates are officially signed (not self signed) and have matching a host name. Valid security certificates are officially signed (not self signed) and have matching a host name.
<a name="FAQ5"></a> <a name="FAQ5"></a>
**(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!~~
<a name="FAQ6"></a> <a name="FAQ6"></a>
**(6) How can I login to Gmail / G suite?** **(6) How can I login to Gmail / G suite?**


+ 0
- 5
SETUP.md View File

@ -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. 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. 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, 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. you are strongly advised to switch to another provider.


+ 8
- 4
app/src/main/java/eu/faircode/email/FragmentAccount.java View File

@ -110,6 +110,7 @@ public class FragmentAccount extends FragmentEx {
private ImageButton ibPro; private ImageButton ibPro;
private CheckBox cbSynchronize; private CheckBox cbSynchronize;
private CheckBox cbPrimary; private CheckBox cbPrimary;
private EditText etInterval;
private Button btnCheck; private Button btnCheck;
private ProgressBar pbCheck; private ProgressBar pbCheck;
@ -173,6 +174,7 @@ public class FragmentAccount extends FragmentEx {
cbSynchronize = view.findViewById(R.id.cbSynchronize); cbSynchronize = view.findViewById(R.id.cbSynchronize);
cbPrimary = view.findViewById(R.id.cbPrimary); cbPrimary = view.findViewById(R.id.cbPrimary);
etInterval = view.findViewById(R.id.etInterval);
btnCheck = view.findViewById(R.id.btnCheck); btnCheck = view.findViewById(R.id.btnCheck);
pbCheck = view.findViewById(R.id.pbCheck); pbCheck = view.findViewById(R.id.pbCheck);
@ -429,9 +431,6 @@ public class FragmentAccount extends FragmentEx {
throw ex; throw ex;
} }
if (!istore.hasCapability("IDLE"))
throw new MessagingException(getContext().getString(R.string.title_no_idle));
if (!istore.hasCapability("UIDPLUS")) if (!istore.hasCapability("UIDPLUS"))
throw new MessagingException(getContext().getString(R.string.title_no_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.putInt("color", color);
args.putString("signature", Html.toHtml(etSignature.getText())); args.putString("signature", Html.toHtml(etSignature.getText()));
args.putBoolean("primary", cbPrimary.isChecked()); args.putBoolean("primary", cbPrimary.isChecked());
args.putString("interval", etInterval.getText().toString());
args.putParcelable("drafts", drafts); args.putParcelable("drafts", drafts);
args.putParcelable("sent", sent); args.putParcelable("sent", sent);
@ -588,6 +588,7 @@ public class FragmentAccount extends FragmentEx {
String signature = args.getString("signature"); String signature = args.getString("signature");
boolean synchronize = args.getBoolean("synchronize"); boolean synchronize = args.getBoolean("synchronize");
boolean primary = args.getBoolean("primary"); boolean primary = args.getBoolean("primary");
String interval = args.getString("interval");
EntityFolder drafts = args.getParcelable("drafts"); EntityFolder drafts = args.getParcelable("drafts");
EntityFolder sent = args.getParcelable("sent"); EntityFolder sent = args.getParcelable("sent");
@ -603,6 +604,8 @@ public class FragmentAccount extends FragmentEx {
throw new Throwable(getContext().getString(R.string.title_no_user)); throw new Throwable(getContext().getString(R.string.title_no_user));
if (TextUtils.isEmpty(password)) if (TextUtils.isEmpty(password))
throw new Throwable(getContext().getString(R.string.title_no_password)); throw new Throwable(getContext().getString(R.string.title_no_password));
if (TextUtils.isEmpty(interval))
interval = "9";
if (synchronize && drafts == null) if (synchronize && drafts == null)
throw new Throwable(getContext().getString(R.string.title_no_drafts)); throw new Throwable(getContext().getString(R.string.title_no_drafts));
@ -653,7 +656,7 @@ public class FragmentAccount extends FragmentEx {
account.synchronize = synchronize; account.synchronize = synchronize;
account.primary = (account.synchronize && primary); account.primary = (account.synchronize && primary);
account.store_sent = false; account.store_sent = false;
account.poll_interval = 9;
account.poll_interval = Integer.parseInt(interval);
if (!synchronize) if (!synchronize)
account.error = null; account.error = null;
@ -874,6 +877,7 @@ public class FragmentAccount extends FragmentEx {
cbSynchronize.setChecked(account == null ? true : account.synchronize); cbSynchronize.setChecked(account == null ? true : account.synchronize);
cbPrimary.setChecked(account == null ? true : account.primary); 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); color = (account == null || account.color == null ? Color.TRANSPARENT : account.color);


+ 38
- 31
app/src/main/java/eu/faircode/email/ServiceSynchronize.java View File

@ -642,6 +642,8 @@ public class ServiceSynchronize extends LifecycleService {
db.folder().setFolderState(folder.id, null); db.folder().setFolderState(folder.id, null);
db.account().setAccountState(account.id, "connecting"); db.account().setAccountState(account.id, "connecting");
Helper.connect(this, istore, account); 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().setAccountState(account.id, "connected");
db.account().setAccountError(account.id, null); db.account().setAccountError(account.id, null);
@ -813,15 +815,18 @@ public class ServiceSynchronize extends LifecycleService {
try { try {
Thread.sleep(account.poll_interval * 60 * 1000L); 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) { } catch (InterruptedException ex) {
Log.w(Helper.TAG, folder.name + " noop " + ex.toString()); Log.w(Helper.TAG, folder.name + " noop " + ex.toString());
@ -845,32 +850,34 @@ public class ServiceSynchronize extends LifecycleService {
noops.add(noop); noops.add(noop);
// Receive folder events // 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; backoff = CONNECT_BACKOFF_START;


+ 26
- 4
app/src/main/res/layout/fragment_account.xml View File

@ -173,7 +173,6 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvUser" /> app:layout_constraintTop_toBottomOf="@id/tvUser" />
<!-- password --> <!-- password -->
<TextView <TextView
@ -318,6 +317,29 @@
android:text="@string/title_primary_account" android:text="@string/title_primary_account"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbSynchronize" /> app:layout_constraintTop_toBottomOf="@id/cbSynchronize" />
<!-- port -->
<TextView
android:id="@+id/tvInterval"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_poll_interval"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbPrimary" />
<EditText
android:id="@+id/etInterval"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="9"
android:inputType="number"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvInterval" />
<!-- check --> <!-- check -->
<Button <Button
@ -327,7 +349,7 @@
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
android:text="@string/title_check" android:text="@string/title_check"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbPrimary" />
app:layout_constraintTop_toBottomOf="@id/etInterval" />
<ProgressBar <ProgressBar
android:id="@+id/pbCheck" android:id="@+id/pbCheck"
@ -347,7 +369,7 @@
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
android:src="@drawable/baseline_delete_24" android:src="@drawable/baseline_delete_24"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbPrimary" />
app:layout_constraintTop_toBottomOf="@id/etInterval" />
<TextView <TextView
android:id="@+id/tvDrafts" android:id="@+id/tvDrafts"
@ -498,7 +520,7 @@
android:id="@+id/grpAdvanced" android:id="@+id/grpAdvanced"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
app:constraint_referenced_ids="tvName,etName,btnColor,vwColor,ibColorDefault,tvSignature,etSignature,ibPro,cbSynchronize,cbPrimary" />
app:constraint_referenced_ids="tvName,etName,btnColor,vwColor,ibColorDefault,tvSignature,etSignature,ibPro,cbSynchronize,cbPrimary,tvInterval,etInterval" />
<androidx.constraintlayout.widget.Group <androidx.constraintlayout.widget.Group
android:id="@+id/grpFolders" android:id="@+id/grpFolders"


+ 1
- 1
app/src/main/res/values/strings.xml View File

@ -110,6 +110,7 @@
<string name="title_synchronize_identity">Synchronize (send messages)</string> <string name="title_synchronize_identity">Synchronize (send messages)</string>
<string name="title_primary_account">Primary (default account)</string> <string name="title_primary_account">Primary (default account)</string>
<string name="title_primary_identity">Primary (default identity)</string> <string name="title_primary_identity">Primary (default identity)</string>
<string name="title_poll_interval">Poll interval (minutes)</string>
<string name="title_check">Check</string> <string name="title_check">Check</string>
<string name="title_no_name">Name missing</string> <string name="title_no_name">Name missing</string>
<string name="title_no_email">Email address missing</string> <string name="title_no_email">Email address missing</string>
@ -119,7 +120,6 @@
<string name="title_no_user">User name missing</string> <string name="title_no_user">User name missing</string>
<string name="title_no_password">Password missing</string> <string name="title_no_password">Password missing</string>
<string name="title_no_drafts">Drafts folder missing</string> <string name="title_no_drafts">Drafts folder missing</string>
<string name="title_no_idle">IMAP IDLE not supported, see the FAQ</string>
<string name="title_no_uidplus">IMAP UIDPLUS not supported, see the FAQ</string> <string name="title_no_uidplus">IMAP UIDPLUS not supported, see the FAQ</string>
<string name="title_account_delete">Delete this account permanently?</string> <string name="title_account_delete">Delete this account permanently?</string>
<string name="title_identity_delete">Delete this identity permanently?</string> <string name="title_identity_delete">Delete this identity permanently?</string>


+ 4
- 4
app/src/main/res/xml/providers.xml View File

@ -36,7 +36,7 @@
starttls="false" /> starttls="false" />
</provider> </provider>
<!-- no IMAP IDLE --> <!-- no IMAP IDLE -->
<!--provider
<provider
name="Yahoo!" name="Yahoo!"
link="https://help.yahoo.com/kb/SLN4075.html"> link="https://help.yahoo.com/kb/SLN4075.html">
<imap <imap
@ -46,7 +46,7 @@
host="smtp.mail.yahoo.com" host="smtp.mail.yahoo.com"
port="465" port="465"
starttls="false" /> starttls="false" />
</provider-->
</provider>
<provider <provider
name="Posteo.de" name="Posteo.de"
link="https://posteo.de/en/help/how-do-i-set-up-posteo-in-an-email-client-pop3-imap-and-smtp"> link="https://posteo.de/en/help/how-do-i-set-up-posteo-in-an-email-client-pop3-imap-and-smtp">
@ -81,7 +81,7 @@
starttls="false" /> starttls="false" />
</provider> </provider>
<!-- no IMAP IDLE --> <!-- no IMAP IDLE -->
<!--provider
<provider
name="SFR.fr" name="SFR.fr"
link="https://assistance.sfr.fr/service-et-accessoire/sfr-mail/serveurs-messagerie-sfr.html"> link="https://assistance.sfr.fr/service-et-accessoire/sfr-mail/serveurs-messagerie-sfr.html">
<imap <imap
@ -91,7 +91,7 @@
host="smtp.sfr.fr" host="smtp.sfr.fr"
port="465" port="465"
starttls="false" /> starttls="false" />
</provider-->
</provider>
<provider <provider
name="infomaniak" name="infomaniak"
link="https://www.infomaniak.com/fr/support/faq/1075/configurer-une-adresse-email-configuration-logiciel-de-messagerie-parametres-courrier"> link="https://www.infomaniak.com/fr/support/faq/1075/configurer-une-adresse-email-configuration-logiciel-de-messagerie-parametres-courrier">


Loading…
Cancel
Save