mirror of https://github.com/M66B/FairEmail.git
Bring back polling
This commit is contained in:
parent
5cca576e28
commit
9cafc1223d
12
FAQ.md
12
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.
|
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,
|
~~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.
|
~~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.
|
~~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.
|
~~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!
|
~~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?**
|
||||||
|
|
5
SETUP.md
5
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.
|
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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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");
|
if (capIdle) {
|
||||||
ifolder.doCommand(new IMAPFolder.ProtocolCommand() {
|
Log.i(Helper.TAG, folder.name + " request NOOP");
|
||||||
public Object doCommand(IMAPProtocol p) throws ProtocolException {
|
ifolder.doCommand(new IMAPFolder.ProtocolCommand() {
|
||||||
Log.i(Helper.TAG, ifolder.getName() + " start NOOP");
|
public Object doCommand(IMAPProtocol p) throws ProtocolException {
|
||||||
p.simpleCommand("NOOP", null);
|
Log.i(Helper.TAG, ifolder.getName() + " start NOOP");
|
||||||
Log.i(Helper.TAG, ifolder.getName() + " end NOOP");
|
p.simpleCommand("NOOP", null);
|
||||||
return 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() {
|
if (capIdle) {
|
||||||
@Override
|
Thread idle = new Thread(new Runnable() {
|
||||||
public void run() {
|
@Override
|
||||||
try {
|
public void run() {
|
||||||
Log.i(Helper.TAG, folder.name + " start idle");
|
try {
|
||||||
while (state.running && ifolder.isOpen()) {
|
Log.i(Helper.TAG, folder.name + " start idle");
|
||||||
//Log.i(Helper.TAG, folder.name + " do idle");
|
while (state.running && ifolder.isOpen()) {
|
||||||
ifolder.idle(false);
|
Log.i(Helper.TAG, folder.name + " do idle");
|
||||||
//Log.i(Helper.TAG, folder.name + " done 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));
|
} catch (Throwable ex) {
|
||||||
reportError(account.name, folder.name, 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) {
|
synchronized (state) {
|
||||||
state.notifyAll();
|
state.notifyAll();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
Log.i(Helper.TAG, folder.name + " end idle");
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
Log.i(Helper.TAG, folder.name + " end idle");
|
|
||||||
}
|
}
|
||||||
}
|
}, "sync.idle." + folder.id);
|
||||||
}, "sync.idle." + folder.id);
|
idle.start();
|
||||||
idle.start();
|
idlers.add(idle);
|
||||||
idlers.add(idle);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
backoff = CONNECT_BACKOFF_START;
|
backoff = CONNECT_BACKOFF_START;
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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…
Reference in New Issue