mirror of https://github.com/M66B/FairEmail.git
Always move sent messages to the sent folder (if any)
This commit is contained in:
parent
bd1c741f2e
commit
fc87b37b20
10
FAQ.md
10
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
|
|||
<br />
|
||||
|
||||
<a name="faq7"></a>
|
||||
**(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.~~
|
||||
|
||||
<br />
|
||||
|
||||
|
@ -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.
|
||||
|
||||
<br />
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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<EntityFolder> 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<EntityFolder>());
|
||||
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<Void>() {
|
||||
@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<IdentityFolders>() {
|
||||
@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<EntityFolder> folders;
|
||||
|
|
|
@ -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();
|
||||
// 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);
|
||||
|
||||
// Message could be moved
|
||||
message = db.message().getMessage(message.id);
|
||||
EntityFolder sent = db.folder().getFolderByType(ident.account, EntityFolder.SENT);
|
||||
if (sent != null) {
|
||||
long id = message.id;
|
||||
long folder = message.folder;
|
||||
|
||||
// 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);
|
||||
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);
|
||||
|
||||
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
|
||||
sid = message.id;
|
||||
message.id = id;
|
||||
message.folder = folder;
|
||||
message.seen = false;
|
||||
message.ui_seen = false;
|
||||
message.ui_browsed = false;
|
||||
message.ui_hide = false;
|
||||
}
|
||||
|
||||
Address[] to = imessage.getAllRecipients();
|
||||
itransport.sendMessage(imessage, to);
|
||||
EntityLog.log(this, "Sent via " + ident.host + "/" + ident.user +
|
||||
" to " + TextUtils.join(", ", to));
|
||||
|
||||
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) {
|
||||
|
|
|
@ -484,34 +484,6 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/cbReadReceipt" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvSent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:text="@string/title_store_copy"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvReceipt" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spSent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvSent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvSentHint"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/title_identity_sent_hint"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textStyle="italic"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/spSent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnSave"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -519,7 +491,7 @@
|
|||
android:layout_marginTop="12dp"
|
||||
android:text="@string/title_save"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvSentHint" />
|
||||
app:layout_constraintTop_toBottomOf="@id/tvReceipt" />
|
||||
|
||||
<eu.faircode.email.ContentLoadingProgressBar
|
||||
android:id="@+id/pbSave"
|
||||
|
|
|
@ -194,7 +194,6 @@
|
|||
<string name="title_authorize">Select account</string>
|
||||
<string name="title_authorizing">Authorizing account …</string>
|
||||
<string name="title_setup_advanced">Advanced</string>
|
||||
<string name="title_store_copy">Store a copy of sent messages in:</string>
|
||||
<string name="title_synchronize_account">Synchronize (receive messages)</string>
|
||||
<string name="title_synchronize_identity">Synchronize (send messages)</string>
|
||||
<string name="title_primary_account">Primary (default account)</string>
|
||||
|
@ -214,7 +213,6 @@
|
|||
<string name="title_account_delete">Delete this account permanently?</string>
|
||||
<string name="title_identity_delete">Delete this identity permanently?</string>
|
||||
<string name="title_pop">POP is not supported</string>
|
||||
<string name="title_identity_sent_hint">Sent messages will automatically be stored in the sent folder already in most cases</string>
|
||||
<string name="title_edit_html">Edit as HTML</string>
|
||||
|
||||
<string name="title_unseen_count" translatable="false">%1$s (%2$d)</string>
|
||||
|
|
Loading…
Reference in New Issue