diff --git a/FAQ.md b/FAQ.md index 2206f79cd2..ea6b986d01 100644 --- a/FAQ.md +++ b/FAQ.md @@ -68,7 +68,7 @@ FairEmail follows all the best practices for an email client as decribed in [thi * [(4) How can I use an invalid security certificate / IMAP STARTTLS / an empty password?](#user-content-faq4) * [(5) How can I customize the message view?](#user-content-faq5) * [(6) How can I login to Gmail / G suite?](#user-content-faq6) -* [(7) Why are messages in the outbox not moved to the sent folder?](#user-content-faq7) +* [~~(7) Why are messages in the outbox not moved to the sent folder?~~](#user-content-faq7) * [(8) Can I use a Microsoft Exchange account?](#user-content-faq8) * [(9) What are identities?](#user-content-faq9) * [(11) Why is POP not supported?](#user-content-faq11) @@ -246,13 +246,13 @@ If this doesn't work, see here for more solutions: [https://support.google.com/m
-**(7) Why are messages in the outbox not moved to the sent folder?** +**~~(7) Why are messages in the outbox not moved to the sent folder?~~** -Messages in the outbox are moved to the sent folder as soon as your provider adds the message to the sent folder. +~~Messages in the outbox are moved to the sent folder as soon as your provider adds the message to the sent folder. Note that this requires a sent folder to be selected and to be set to synchronizing. If this doesn't happen, your provider might not keep track of sent messages or you might be using an SMTP server not related to the provider. In these cases you can use the advanced identity setting *Store a copy of sent messages in* and select the sent folder. -There is a menu to move sent messages in the outbox to the sent folder. +There is a menu to move sent messages in the outbox to the sent folder.~~
@@ -983,6 +983,8 @@ Messages shown dimmed are locally moved messages for which the move is not confi This can happen when there is no connection with the server or when the messages are too old to be synchronized. Eventually, these messages will be synchronized when the connection to the server is restored or will be deleted if they are too old to be synchronized. +Some providers don't store sent messages, in this case messages in the sent folder might never be synchronized. + You can view these messages, but you cannot move these messages again until the previous move has been confirmed by the server.
diff --git a/app/src/main/java/eu/faircode/email/DaoMessage.java b/app/src/main/java/eu/faircode/email/DaoMessage.java index 5803edfcd7..18922463be 100644 --- a/app/src/main/java/eu/faircode/email/DaoMessage.java +++ b/app/src/main/java/eu/faircode/email/DaoMessage.java @@ -296,6 +296,9 @@ public interface DaoMessage { @Query("UPDATE message SET ui_ignored = :ui_ignored WHERE id = :id") int setMessageUiIgnored(long id, boolean ui_ignored); + @Query("UPDATE message SET sent = :sent WHERE id = :id") + int setMessageSent(long id, Long sent); + @Query("UPDATE message SET warning = :warning WHERE id = :id") int setMessageWarning(long id, String warning); diff --git a/app/src/main/java/eu/faircode/email/EntityIdentity.java b/app/src/main/java/eu/faircode/email/EntityIdentity.java index 3b906d91c7..a75479c40b 100644 --- a/app/src/main/java/eu/faircode/email/EntityIdentity.java +++ b/app/src/main/java/eu/faircode/email/EntityIdentity.java @@ -81,7 +81,7 @@ public class EntityIdentity { public Boolean read_receipt; @NonNull public Boolean store_sent = false; // obsolete - public Long sent_folder; + public Long sent_folder; // obsolete public Boolean tbd; public String state; public String error; @@ -109,9 +109,6 @@ public class EntityIdentity { json.put("bcc", bcc); json.put("delivery_receipt", delivery_receipt); json.put("read_receipt", read_receipt); - json.put("store_sent", store_sent); - if (sent_folder != null) - json.put("sent_folder", sent_folder); // not state // not error return json; @@ -157,12 +154,6 @@ public class EntityIdentity { else identity.read_receipt = false; - if (json.has("store_sent")) - identity.store_sent = json.getBoolean("store_sent"); - - if (json.has("sent_folder")) - identity.sent_folder = json.getLong("sent_folder"); - return identity; } @@ -187,7 +178,6 @@ public class EntityIdentity { (this.replyto == null ? other.replyto == null : this.replyto.equals(other.replyto)) && this.delivery_receipt.equals(other.delivery_receipt) && this.read_receipt.equals(other.read_receipt) && - (this.sent_folder == null ? other.sent_folder == null : this.sent_folder.equals(other.sent_folder)) && (this.tbd == null ? other.tbd == null : this.tbd.equals(other.tbd)) && (this.state == null ? other.state == null : this.state.equals(other.state)) && (this.error == null ? other.error == null : this.error.equals(other.error))); diff --git a/app/src/main/java/eu/faircode/email/FragmentIdentity.java b/app/src/main/java/eu/faircode/email/FragmentIdentity.java index 5a92200816..44a8bce3f8 100644 --- a/app/src/main/java/eu/faircode/email/FragmentIdentity.java +++ b/app/src/main/java/eu/faircode/email/FragmentIdentity.java @@ -110,7 +110,6 @@ public class FragmentIdentity extends FragmentBase { private EditText etBcc; private CheckBox cbDeliveryReceipt; private CheckBox cbReadReceipt; - private Spinner spSent; private Button btnSave; private ContentLoadingProgressBar pbSave; @@ -123,7 +122,6 @@ public class FragmentIdentity extends FragmentBase { private long id = -1; private int color = Color.TRANSPARENT; - private ArrayAdapter adapter; @Override public void onCreate(Bundle savedInstanceState) { @@ -175,7 +173,6 @@ public class FragmentIdentity extends FragmentBase { etBcc = view.findViewById(R.id.etBcc); cbDeliveryReceipt = view.findViewById(R.id.cbDeliveryReceipt); cbReadReceipt = view.findViewById(R.id.cbReadReceipt); - spSent = view.findViewById(R.id.spSent); btnSave = view.findViewById(R.id.btnSave); pbSave = view.findViewById(R.id.pbSave); @@ -233,13 +230,10 @@ public class FragmentIdentity extends FragmentBase { etUser.setText(account.user); tilPassword.getEditText().setText(account.password); etRealm.setText(account.realm); - - setFolders(account.id); } @Override public void onNothingSelected(AdapterView adapterView) { - adapter.clear(); } }); @@ -407,10 +401,6 @@ public class FragmentIdentity extends FragmentBase { } }); - adapter = new ArrayAdapter<>(getContext(), R.layout.spinner_item1, android.R.id.text1, new ArrayList()); - adapter.setDropDownViewResource(R.layout.spinner_item1_dropdown); - spSent.setAdapter(adapter); - // Initialize Helper.setViewsEnabled(view, false); btnAutoConfig.setEnabled(false); @@ -502,7 +492,6 @@ public class FragmentIdentity extends FragmentBase { args.putString("signature", Html.toHtml(etSignature.getText())); args.putBoolean("synchronize", cbSynchronize.isChecked()); args.putBoolean("primary", cbPrimary.isChecked()); - args.putSerializable("sent", (EntityFolder) spSent.getSelectedItem()); new SimpleTask() { @Override @@ -546,7 +535,6 @@ public class FragmentIdentity extends FragmentBase { String bcc = args.getString("bcc"); boolean delivery_receipt = args.getBoolean("delivery_receipt"); boolean read_receipt = args.getBoolean("read_receipt"); - EntityFolder sent = (EntityFolder) args.getSerializable("sent"); if (TextUtils.isEmpty(name)) throw new IllegalArgumentException(context.getString(R.string.title_no_name)); @@ -646,7 +634,7 @@ public class FragmentIdentity extends FragmentBase { identity.delivery_receipt = delivery_receipt; identity.read_receipt = read_receipt; identity.store_sent = false; - identity.sent_folder = (sent == null ? null : sent.id); + identity.sent_folder = null; identity.error = null; if (identity.primary) @@ -838,7 +826,6 @@ public class FragmentIdentity extends FragmentBase { // OAuth token could be updated if (pos > 0 && accounts.get(pos).auth_type != Helper.AUTH_TYPE_PASSWORD) tilPassword.getEditText().setText(accounts.get(pos).password); - setFolders(account.id); break; } } @@ -941,64 +928,6 @@ public class FragmentIdentity extends FragmentBase { vwColor.setBackground(border); } - private void setFolders(long account) { - Bundle args = new Bundle(); - args.putLong("account", account); - args.putLong("identity", id); - - new SimpleTask() { - @Override - protected IdentityFolders onExecute(Context context, Bundle args) { - long aid = args.getLong("account"); - long iid = args.getLong("identity"); - - DB db = DB.getInstance(context); - IdentityFolders result = new IdentityFolders(); - result.identity = db.identity().getIdentity(iid); - result.folders = db.folder().getFolders(aid); - - if (result.folders != null) { - for (EntityFolder folder : result.folders) - folder.display = folder.getDisplayName(context); - EntityFolder.sort(context, result.folders); - } - - return result; - } - - @Override - protected void onExecuted(Bundle args, IdentityFolders result) { - EntityFolder none = new EntityFolder(); - none.name = "-"; - result.folders.add(0, none); - - adapter.clear(); - adapter.addAll(result.folders); - - if (result.identity != null) - for (int pos = 0; pos < result.folders.size(); pos++) { - EntityFolder folder = result.folders.get(pos); - if (result.identity.store_sent) { - if (EntityFolder.SENT.equals(folder.type)) { - spSent.setSelection(pos); - break; - } - } else if (result.identity.sent_folder != null) { - if (result.identity.sent_folder.equals(folder.id)) { - spSent.setSelection(pos); - break; - } - } - } - } - - @Override - protected void onException(Bundle args, Throwable ex) { - Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex); - } - }.execute(this, args, "identity:folders:get"); - } - class IdentityFolders { EntityIdentity identity; List folders; diff --git a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java index 6386da59a6..29c2adff6b 100644 --- a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java +++ b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java @@ -1790,51 +1790,62 @@ public class ServiceSynchronize extends LifecycleService { db.identity().setIdentityState(ident.id, "connected"); // Send message - Address[] to = imessage.getAllRecipients(); - itransport.sendMessage(imessage, to); - EntityLog.log(this, "Sent via " + ident.host + "/" + ident.user + - " to " + TextUtils.join(", ", to)); - - db.identity().setIdentityError(ident.id, null); - - NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - nm.cancel("send", message.identity.intValue()); - - // Append replied/forwarded text - if (message.replying != null || message.forwarding != null) { - String html = message.read(this); - html += HtmlHelper.getQuote(this, - message.replying == null ? message.forwarding : message.replying, false); - message.write(this, html); - } - + Long sid = null; try { - db.beginTransaction(); - - // Message could be moved - message = db.message().getMessage(message.id); + // Append replied/forwarded text + String body = message.read(this); + if (message.replying != null || message.forwarding != null) + body += HtmlHelper.getQuote(this, + message.replying == null ? message.forwarding : message.replying, false); + + EntityFolder sent = db.folder().getFolderByType(ident.account, EntityFolder.SENT); + if (sent != null) { + long id = message.id; + long folder = message.folder; + + message.id = null; + message.folder = sent.id; + message.seen = true; + message.ui_seen = true; + message.ui_hide = true; + message.ui_browsed = true; // prevent deleting on sync + message.error = null; + message.id = db.message().insertMessage(message); + message.write(this, body); + + sid = message.id; + message.id = id; + message.folder = folder; + message.seen = false; + message.ui_seen = false; + message.ui_browsed = false; + message.ui_hide = false; + } - // Mark message as sent - // - will be moved to sent folder by synchronize message later - message.sent = imessage.getSentDate().getTime(); - message.seen = true; - message.ui_seen = true; - message.error = null; - db.message().updateMessage(message); + Address[] to = imessage.getAllRecipients(); + itransport.sendMessage(imessage, to); + EntityLog.log(this, "Sent via " + ident.host + "/" + ident.user + + " to " + TextUtils.join(", ", to)); - if (ident.store_sent || ident.sent_folder != null) { - EntityFolder sent; - if (ident.store_sent) - sent = db.folder().getFolderByType(ident.account, EntityFolder.SENT); - else - sent = db.folder().getFolder(ident.sent_folder); - if (sent != null) { - message.folder = sent.id; - message.uid = null; - db.message().updateMessage(message); - Log.i("Appending sent msgid=" + message.msgid); - EntityOperation.queue(this, db, message, EntityOperation.ADD); // Could already exist + try { + db.beginTransaction(); + + if (sid == null) { + db.message().setMessageSent(message.id, imessage.getSentDate().getTime()); + db.message().setMessageSeen(message.id, true); + db.message().setMessageUiSeen(message.id, true); + db.message().setMessageError(message.id, null); + message.write(this, body); + } else { + db.message().setMessageSent(sid, imessage.getSentDate().getTime()); + db.message().setMessageUiHide(sid, false); + db.message().deleteMessage(message.id); + //EntityOperation.queue(this, db, message, EntityOperation.ADD); } + + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); } if (message.replying != null) { @@ -1842,9 +1853,14 @@ public class ServiceSynchronize extends LifecycleService { EntityOperation.queue(this, db, replying, EntityOperation.ANSWERED, true); } - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); + db.identity().setIdentityError(ident.id, null); + + NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + nm.cancel("send", message.identity.intValue()); + } catch (Throwable ex) { + if (sid != null) + db.message().deleteMessage(sid); + throw ex; } } catch (MessagingException ex) { if (ex instanceof SendFailedException) { diff --git a/app/src/main/res/layout/fragment_identity.xml b/app/src/main/res/layout/fragment_identity.xml index c43dfe62de..844be84fed 100644 --- a/app/src/main/res/layout/fragment_identity.xml +++ b/app/src/main/res/layout/fragment_identity.xml @@ -484,34 +484,6 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/cbReadReceipt" /> - - - - - -