From a6d70ce6f1255ba3faeb9bd8efdee09869b8f492 Mon Sep 17 00:00:00 2001 From: M66B Date: Thu, 17 Sep 2026 16:05:46 +0200 Subject: [PATCH] Improved demo account handling --- .../email/BoundaryCallbackMessages.java | 2 +- app/src/main/java/eu/faircode/email/Core.java | 5 - .../java/eu/faircode/email/EmailService.java | 98 +++++++++---------- .../java/eu/faircode/email/EntityAccount.java | 4 + .../eu/faircode/email/EntityIdentity.java | 4 + .../eu/faircode/email/EntityOperation.java | 15 ++- .../java/eu/faircode/email/ServiceSend.java | 5 - .../eu/faircode/email/ServiceSynchronize.java | 3 + 8 files changed, 66 insertions(+), 70 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java b/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java index e46b14600b..7882b79ccc 100644 --- a/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java +++ b/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java @@ -425,7 +425,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback sid = istore.id(client_id ? getId(context) : null); - if (sid != null) { - Map crumb = new HashMap<>(); - for (String key : sid.keySet()) { - crumb.put(key, sid.get(key)); - EntityLog.log(context, EntityLog.Type.Protocol, "Server " + key + "=" + sid.get(key)); - } - Log.breadcrumb("server", crumb); + // https://www.ietf.org/rfc/rfc2971.txt + IMAPStore istore = (IMAPStore) getStore(); + if (istore.hasCapability("ID")) + try { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + boolean client_id = prefs.getBoolean("client_id", true); + Map sid = istore.id(client_id ? getId(context) : null); + if (sid != null) { + Map crumb = new HashMap<>(); + for (String key : sid.keySet()) { + crumb.put(key, sid.get(key)); + EntityLog.log(context, EntityLog.Type.Protocol, "Server " + key + "=" + sid.get(key)); } - } catch (MessagingException ex) { - Log.w(ex); - // Check for 'User is authenticated but not connected' - if (require_id) - throw ex; + Log.breadcrumb("server", crumb); } + } catch (MessagingException ex) { + Log.w(ex); + // Check for 'User is authenticated but not connected' + if (require_id) + throw ex; + } - // Verizon - // https://senders.yahooinc.com/developer/documentation/#imap-modes-limited - // https://www.ietf.org/archive/id/draft-melnikov-imap-uidonly-00.html - // https://answers.microsoft.com/en-us/outlook_com/forum/all/why-is-an-imap-inbox-only-displaying-10000-items/6d15de5f-9047-4b41-9b58-1d8345bbd002 - if (false && istore.hasCapability("X-UIDONLY") && istore.hasCapability("ENABLE")) - try { - istore.enable("X-UIDONLY"); - } catch (ProtocolException ex) { - Log.e(ex); - } - } + // Verizon + // https://senders.yahooinc.com/developer/documentation/#imap-modes-limited + // https://www.ietf.org/archive/id/draft-melnikov-imap-uidonly-00.html + // https://answers.microsoft.com/en-us/outlook_com/forum/all/why-is-an-imap-inbox-only-displaying-10000-items/6d15de5f-9047-4b41-9b58-1d8345bbd002 + if (false && istore.hasCapability("X-UIDONLY") && istore.hasCapability("ENABLE")) + try { + istore.enable("X-UIDONLY"); + } catch (ProtocolException ex) { + Log.e(ex); + } } else if ("smtp".equals(protocol) || "smtps".equals(protocol)) { // https://tools.ietf.org/html/rfc5321#section-4.1.3 @@ -962,23 +959,22 @@ public class EmailService implements AutoCloseable { Log.i("Using localhost=" + properties.getProperty("mail." + protocol + ".localhost")); iservice = isession.getTransport(protocol); - if (!EntityAccount.isTestUser(user)) - try { - iservice.connect(address.getHostAddress(), port, user, null); - } catch (MessagingException ex) { - if (ehlo == null && ConnectionHelper.isSyntacticallyInvalid(ex)) { - properties.put("mail." + protocol + ".localhost", useip ? hdomain : haddr); - Log.i("Fallback localhost=" + properties.getProperty("mail." + protocol + ".localhost")); - try { - iservice.connect(address.getHostAddress(), port, user, null); - } catch (MessagingException ex1) { - if (ConnectionHelper.isSyntacticallyInvalid(ex1)) - Log.e("Used localhost=" + haddr + "/" + hdomain); - throw ex1; - } - } else - throw ex; - } + try { + iservice.connect(address.getHostAddress(), port, user, null); + } catch (MessagingException ex) { + if (ehlo == null && ConnectionHelper.isSyntacticallyInvalid(ex)) { + properties.put("mail." + protocol + ".localhost", useip ? hdomain : haddr); + Log.i("Fallback localhost=" + properties.getProperty("mail." + protocol + ".localhost")); + try { + iservice.connect(address.getHostAddress(), port, user, null); + } catch (MessagingException ex1) { + if (ConnectionHelper.isSyntacticallyInvalid(ex1)) + Log.e("Used localhost=" + haddr + "/" + hdomain); + throw ex1; + } + } else + throw ex; + } } else throw new NoSuchProviderException(protocol); } diff --git a/app/src/main/java/eu/faircode/email/EntityAccount.java b/app/src/main/java/eu/faircode/email/EntityAccount.java index b0574960c0..4db10c4384 100644 --- a/app/src/main/java/eu/faircode/email/EntityAccount.java +++ b/app/src/main/java/eu/faircode/email/EntityAccount.java @@ -565,6 +565,10 @@ public class EntityAccount extends EntityOrder implements Serializable { }; } + boolean isTestAccount() { + return isTestUser(this.user); + } + static boolean isTestUser(String user) { return (user != null && user.endsWith("@demo.faircode.eu")); } diff --git a/app/src/main/java/eu/faircode/email/EntityIdentity.java b/app/src/main/java/eu/faircode/email/EntityIdentity.java index 3a08b2cf6f..b3158a8000 100644 --- a/app/src/main/java/eu/faircode/email/EntityIdentity.java +++ b/app/src/main/java/eu/faircode/email/EntityIdentity.java @@ -458,6 +458,10 @@ public class EntityIdentity { return (display == null ? name : display); } + boolean isTestIdentity() { + return EntityAccount.isTestUser(this.user); + } + static EntityIdentity getTestIdentity(Long account, String user) { EntityIdentity identity = new EntityIdentity(); identity.account = account; diff --git a/app/src/main/java/eu/faircode/email/EntityOperation.java b/app/src/main/java/eu/faircode/email/EntityOperation.java index 3d6f6ebc2f..06c3a13e7c 100644 --- a/app/src/main/java/eu/faircode/email/EntityOperation.java +++ b/app/src/main/java/eu/faircode/email/EntityOperation.java @@ -116,6 +116,13 @@ public class EntityOperation { static void queue(Context context, EntityMessage message, String name, Object... values) { DB db = DB.getInstance(context); + EntityAccount account = db.account().getAccount(message.account); + if (account != null && account.isTestAccount()) { + if (DELETE.equals(name) || SEND.equals(name)) + db.message().deleteMessage(message.id); + return; + } + try { JSONArray jargs = new JSONArray(); for (Object value : values) @@ -124,7 +131,6 @@ public class EntityOperation { if (SEEN.equals(name)) { boolean seen = jargs.getBoolean(0); boolean ignore = jargs.optBoolean(1, true); - EntityAccount account = db.account().getAccount(message.account); for (EntityMessage similar : db.message().getMessagesBySimilarity(message.account, message.id, message.msgid, message.hash)) { if ((account != null && !account.isGmail() && !account.isWebDe()) && !Objects.equals(message.id, similar.id) && @@ -141,7 +147,6 @@ public class EntityOperation { } else if (FLAG.equals(name)) { boolean flagged = jargs.getBoolean(0); Integer color = (jargs.length() > 1 && !jargs.isNull(1) ? jargs.getInt(1) : null); - EntityAccount account = db.account().getAccount(message.id); for (EntityMessage similar : db.message().getMessagesBySimilarity(message.account, message.id, message.msgid, message.hash)) { if ((account != null && !account.isGmail()) && !Objects.equals(message.id, similar.id) && @@ -164,7 +169,6 @@ public class EntityOperation { return; } else if (ANSWERED.equals(name)) { - EntityAccount account = db.account().getAccount(message.id); for (EntityMessage similar : db.message().getMessagesBySimilarity(message.account, message.id, message.msgid, message.hash)) { if ((account != null && !account.isGmail()) && !Objects.equals(message.id, similar.id) && @@ -206,7 +210,6 @@ public class EntityOperation { DB.Converters.fromStringArray(fkeywords.toArray(new String[0]))); } } else { - EntityAccount account = db.account().getAccount(message.account); if (account != null && account.protocol == EntityAccount.TYPE_POP) { EntityFolder folder = db.folder().getFolder(message.folder); if (folder != null) { @@ -320,7 +323,6 @@ public class EntityOperation { " auto read=" + autoread + " flag=" + autounflag + " importance=" + reset_importance); if (autoread || autounflag || reset_importance) { - EntityAccount account = db.account().getAccount(message.account); for (EntityMessage similar : db.message().getMessagesBySimilarity(message.account, message.id, message.msgid, message.hash)) { if ((account != null && !account.isGmail()) && !Objects.equals(message.id, similar.id) && @@ -343,7 +345,6 @@ public class EntityOperation { boolean premove = true; if (source.account.equals(target.account)) { - EntityAccount account = db.account().getAccount(message.account); if (account != null && account.isGmail()) { if (EntityFolder.ARCHIVE.equals(source.type) && !(EntityFolder.SENT.equals(target.type) || @@ -540,8 +541,6 @@ public class EntityOperation { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); boolean perform_expunge = prefs.getBoolean("perform_expunge", true); - EntityAccount account = db.account().getAccount(message.account); - if (perform_expunge || account == null || account.protocol != EntityAccount.TYPE_IMAP) { diff --git a/app/src/main/java/eu/faircode/email/ServiceSend.java b/app/src/main/java/eu/faircode/email/ServiceSend.java index 17d2b3a6a9..4dd71d721a 100644 --- a/app/src/main/java/eu/faircode/email/ServiceSend.java +++ b/app/src/main/java/eu/faircode/email/ServiceSend.java @@ -672,11 +672,6 @@ public class ServiceSend extends ServiceBase implements SharedPreferences.OnShar throw new IllegalArgumentException("Message body missing"); EntityAccount account = db.account().getAccount(message.account); - if (EntityAccount.isTestUser(account.user)){ - db.operation().deleteOperation(operation.id); - db.message().deleteMessage(message.id); - return; - } EntityIdentity ident = db.identity().getIdentity(message.identity); if (ident == null) diff --git a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java index 82614138bc..5d2a484bc5 100644 --- a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java +++ b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java @@ -1631,6 +1631,9 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences final PowerManager.WakeLock wlMessage = pm.newWakeLock( PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID + ":account." + account.id + ".message"); + if (account != null && account.isTestAccount()) + return; + long start = new Date().getTime(); try { wlAccount.acquire(Helper.WAKELOCK_MAX);