Select receipt request in send dialog

pull/162/head
M66B 5 years ago
parent 43612ecd2b
commit 88fc8efe81

File diff suppressed because it is too large Load Diff

@ -58,7 +58,7 @@ import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory;
// https://developer.android.com/topic/libraries/architecture/room.html
@Database(
version = 106,
version = 107,
entities = {
EntityIdentity.class,
EntityAccount.class,
@ -1049,6 +1049,13 @@ public abstract class DB extends RoomDatabase {
db.execSQL("UPDATE `message` SET total = size");
}
})
.addMigrations(new Migration(106, 107) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase db) {
Log.i("DB migration from version " + startVersion + " to " + endVersion);
db.execSQL("ALTER TABLE `message` ADD COLUMN `receipt` INTEGER");
}
})
.build();
}

@ -367,6 +367,9 @@ public interface DaoMessage {
@Query("UPDATE message SET priority = :priority WHERE id = :id")
int setMessagePriority(long id, Integer priority);
@Query("UPDATE message SET receipt_request = :receipt_request WHERE id = :id")
int setMessageReceiptRequest(long id, Boolean receipt_request);
@Query("UPDATE message SET notifying = :notifying WHERE id = :id")
int setMessageNotifying(long id, int notifying);

@ -99,6 +99,7 @@ public class EntityMessage implements Serializable {
public String inreplyto;
public String thread; // compose = null
public Integer priority;
public Boolean receipt; // is receipt
public Boolean receipt_request;
public Address[] receipt_to;
public Boolean dkim;
@ -262,6 +263,8 @@ public class EntityMessage implements Serializable {
Objects.equals(this.deliveredto, other.deliveredto) &&
Objects.equals(this.inreplyto, other.inreplyto) &&
Objects.equals(this.thread, other.thread) &&
Objects.equals(this.priority, other.priority) &&
Objects.equals(this.receipt, other.receipt) &&
Objects.equals(this.receipt_request, other.receipt_request) &&
MessageHelper.equal(this.receipt_to, other.receipt_to) &&
Objects.equals(this.dkim, other.dkim) &&

@ -2091,7 +2091,7 @@ public class FragmentCompose extends FragmentBase {
if ("reply_all".equals(action))
data.draft.cc = ref.getAllRecipients(data.identities);
else if ("receipt".equals(action))
data.draft.receipt_request = true;
data.draft.receipt = true;
} else if ("forward".equals(action) || "editasnew".equals(action))
data.draft.thread = data.draft.msgid; // new thread
@ -2807,11 +2807,11 @@ public class FragmentCompose extends FragmentBase {
if (draft.to == null && draft.cc == null && draft.bcc == null)
throw new IllegalArgumentException(context.getString(R.string.title_to_missing));
if (identity.plain_only)
db.message().setMessagePlainOnly(draft.id, true);
db.message().setMessagePlainOnly(draft.id, identity.plain_only);
if (identity.encrypt)
db.message().setMessageEncrypt(draft.id, true);
db.message().setMessageEncrypt(draft.id, identity.encrypt);
db.message().setMessageReceiptRequest(draft.id, identity.delivery_receipt || identity.read_receipt);
if (TextUtils.isEmpty(draft.subject))
args.putBoolean("remind_subject", true);
@ -3435,6 +3435,8 @@ public class FragmentCompose extends FragmentBase {
final TextView tvVia = dview.findViewById(R.id.tvVia);
final CheckBox cbPlainOnly = dview.findViewById(R.id.cbPlainOnly);
final CheckBox cbEncrypt = dview.findViewById(R.id.cbEncrypt);
final CheckBox cbReceipt = dview.findViewById(R.id.cbReceipt);
final TextView tvReceipt = dview.findViewById(R.id.tvReceipt);
final Spinner spPriority = dview.findViewById(R.id.spPriority);
final TextView tvSendAt = dview.findViewById(R.id.tvSendAt);
final ImageButton ibSendAt = dview.findViewById(R.id.ibSendAt);
@ -3445,6 +3447,7 @@ public class FragmentCompose extends FragmentBase {
tvRemindAttachment.setVisibility(remind_attachment ? View.VISIBLE : View.GONE);
tvTo.setText(null);
tvVia.setText(null);
tvReceipt.setVisibility(View.GONE);
spPriority.setTag(1);
spPriority.setSelection(1);
tvSendAt.setText(null);
@ -3515,6 +3518,35 @@ public class FragmentCompose extends FragmentBase {
}
});
cbReceipt.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
tvReceipt.setVisibility(checked ? View.VISIBLE : View.GONE);
Bundle args = new Bundle();
args.putLong("id", id);
args.putBoolean("receipt", checked);
new SimpleTask<Void>() {
@Override
protected Void onExecute(Context context, Bundle args) {
long id = args.getLong("id");
boolean receipt = args.getBoolean("receipt");
DB db = DB.getInstance(context);
db.message().setMessageReceiptRequest(id, receipt);
return null;
}
@Override
protected void onException(Bundle args, Throwable ex) {
Helper.unexpectedError(getFragmentManager(), ex);
}
}.execute(FragmentDialogSend.this, args, "compose:receipt");
}
});
spPriority.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
@ -3586,6 +3618,7 @@ public class FragmentCompose extends FragmentBase {
cbPlainOnly.setChecked(draft.plain_only != null && draft.plain_only);
cbEncrypt.setChecked(draft.encrypt != null && draft.encrypt);
cbReceipt.setChecked(draft.receipt_request != null && draft.receipt_request);
int priority = (draft.priority == null ? 1 : draft.priority);
spPriority.setTag(priority);

@ -110,8 +110,7 @@ public class FragmentIdentity extends FragmentBase {
private EditText etBcc;
private TextView tvEncryptPro;
private CheckBox cbEncrypt;
private CheckBox cbDeliveryReceipt;
private CheckBox cbReadReceipt;
private CheckBox cbReceipt;
private Button btnSave;
private ContentLoadingProgressBar pbSave;
@ -191,8 +190,7 @@ public class FragmentIdentity extends FragmentBase {
etBcc = view.findViewById(R.id.etBcc);
tvEncryptPro = view.findViewById(R.id.tvEncryptPro);
cbEncrypt = view.findViewById(R.id.cbEncrypt);
cbDeliveryReceipt = view.findViewById(R.id.cbDeliveryReceipt);
cbReadReceipt = view.findViewById(R.id.cbReadReceipt);
cbReceipt = view.findViewById(R.id.cbReceipt);
btnSave = view.findViewById(R.id.btnSave);
pbSave = view.findViewById(R.id.pbSave);
@ -512,8 +510,7 @@ public class FragmentIdentity extends FragmentBase {
args.putString("replyto", etReplyTo.getText().toString().trim());
args.putString("bcc", etBcc.getText().toString().trim());
args.putBoolean("encrypt", cbEncrypt.isChecked());
args.putBoolean("delivery_receipt", cbDeliveryReceipt.isChecked());
args.putBoolean("read_receipt", cbReadReceipt.isChecked());
args.putBoolean("receipt", cbReceipt.isChecked());
args.putLong("account", account == null ? -1 : account.id);
args.putString("host", etHost.getText().toString());
args.putBoolean("starttls", rgEncryption.getCheckedRadioButtonId() == R.id.radio_starttls);
@ -579,8 +576,7 @@ public class FragmentIdentity extends FragmentBase {
String replyto = args.getString("replyto");
String bcc = args.getString("bcc");
boolean encrypt = args.getBoolean("encrypt");
boolean delivery_receipt = args.getBoolean("delivery_receipt");
boolean read_receipt = args.getBoolean("read_receipt");
boolean receipt = args.getBoolean("receipt");
boolean should = args.getBoolean("should");
@ -691,9 +687,9 @@ public class FragmentIdentity extends FragmentBase {
return true;
if (!Objects.equals(identity.encrypt, encrypt))
return true;
if (!Objects.equals(identity.delivery_receipt, delivery_receipt))
if (!Objects.equals(identity.delivery_receipt, receipt))
return true;
if (!Objects.equals(identity.read_receipt, read_receipt))
if (!Objects.equals(identity.read_receipt, receipt))
return true;
if (identity.error != null)
return true;
@ -758,8 +754,8 @@ public class FragmentIdentity extends FragmentBase {
identity.replyto = replyto;
identity.bcc = bcc;
identity.encrypt = encrypt;
identity.delivery_receipt = delivery_receipt;
identity.read_receipt = read_receipt;
identity.delivery_receipt = receipt;
identity.read_receipt = receipt;
identity.sent_folder = null;
identity.sign_key = null;
identity.error = null;
@ -895,8 +891,7 @@ public class FragmentIdentity extends FragmentBase {
etReplyTo.setText(identity == null ? null : identity.replyto);
etBcc.setText(identity == null ? null : identity.bcc);
cbEncrypt.setChecked(identity == null ? false : identity.encrypt);
cbDeliveryReceipt.setChecked(identity == null ? false : identity.delivery_receipt);
cbReadReceipt.setChecked(identity == null ? false : identity.read_receipt);
cbReceipt.setChecked(identity == null ? false : identity.delivery_receipt || identity.read_receipt);
auth = (identity == null ? MailService.AUTH_TYPE_PASSWORD : identity.auth_type);

@ -46,6 +46,7 @@ import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
@ -167,6 +168,34 @@ public class MessageHelper {
if (message.subject != null)
imessage.setSubject(message.subject);
// Send message
if (identity != null) {
// Add reply to
if (identity.replyto != null)
imessage.setReplyTo(InternetAddress.parse(identity.replyto));
// Add extra bcc
if (identity.bcc != null) {
List<Address> bcc = new ArrayList<>();
Address[] existing = imessage.getRecipients(Message.RecipientType.BCC);
if (existing != null)
bcc.addAll(Arrays.asList(existing));
bcc.addAll(Arrays.asList(InternetAddress.parse(identity.bcc)));
imessage.setRecipients(Message.RecipientType.BCC, bcc.toArray(new Address[0]));
}
// Delivery/read request
if (message.receipt_request != null && message.receipt_request) {
String to = (identity.replyto == null ? identity.email : identity.replyto);
// defacto standard
imessage.addHeader("Return-Receipt-To", to);
// https://tools.ietf.org/html/rfc3798
imessage.addHeader("Disposition-Notification-To", to);
}
}
MailDateFormat mdf = new MailDateFormat();
mdf.setTimeZone(TimeZone.getTimeZone("UTC"));
imessage.setHeader("Date", mdf.format(new Date()));
@ -236,7 +265,7 @@ public class MessageHelper {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean usenet = prefs.getBoolean("usenet_signature", false);
if (message.receipt_request != null && message.receipt_request) {
if (message.receipt != null && message.receipt) {
// https://www.ietf.org/rfc/rfc3798.txt
Multipart report = new MimeMultipart("report; report-type=disposition-notification");

@ -39,7 +39,6 @@ import androidx.preference.PreferenceManager;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@ -50,12 +49,10 @@ import java.util.concurrent.Executors;
import javax.mail.Address;
import javax.mail.AuthenticationFailedException;
import javax.mail.Message;
import javax.mail.MessageRemovedException;
import javax.mail.MessagingException;
import javax.mail.SendFailedException;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
@ -325,30 +322,6 @@ public class ServiceSend extends ServiceBase {
Session isession = Session.getInstance(props, null);
MimeMessage imessage = MessageHelper.from(this, message, ident, isession);
// Add reply to
if (ident.replyto != null)
imessage.setReplyTo(InternetAddress.parse(ident.replyto));
// Add bcc
if (ident.bcc != null) {
List<Address> bcc = new ArrayList<>();
Address[] existing = imessage.getRecipients(Message.RecipientType.BCC);
if (existing != null)
bcc.addAll(Arrays.asList(existing));
bcc.addAll(Arrays.asList(InternetAddress.parse(ident.bcc)));
imessage.setRecipients(Message.RecipientType.BCC, bcc.toArray(new Address[0]));
}
if (message.receipt_request == null || !message.receipt_request) {
// defacto standard
if (ident.delivery_receipt)
imessage.addHeader("Return-Receipt-To", ident.replyto == null ? ident.email : ident.replyto);
// https://tools.ietf.org/html/rfc3798
if (ident.read_receipt)
imessage.addHeader("Disposition-Notification-To", ident.replyto == null ? ident.email : ident.replyto);
}
// Prepare sent message
Long sid = null;
EntityFolder sent = db.folder().getFolderByType(message.account, EntityFolder.SENT);
@ -367,7 +340,6 @@ public class ServiceSend extends ServiceBase {
message.id = null;
message.folder = sent.id;
message.identity = null;
message.receipt_request = helper.getReceiptRequested();
message.from = helper.getFrom();
message.bcc = helper.getBcc();
message.reply = helper.getReply();

@ -34,7 +34,7 @@
android:id="@+id/tvRemindAttachment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginTop="24dp"
android:text="@string/title_attachment_reminder"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="?attr/colorWarning"
@ -45,7 +45,7 @@
android:id="@+id/tvToTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginTop="24dp"
android:text="@string/title_to"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintStart_toStartOf="parent"
@ -110,6 +110,26 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbPlainOnly" />
<CheckBox
android:id="@+id/cbReceipt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_send_receipt"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbEncrypt" />
<TextView
android:id="@+id/tvReceipt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_send_receipt_remark"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textStyle="italic"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbReceipt" />
<TextView
android:id="@+id/tvPriority"
android:layout_width="wrap_content"
@ -118,7 +138,7 @@
android:text="@string/title_send_priority"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbEncrypt" />
app:layout_constraintTop_toBottomOf="@id/tvReceipt" />
<Spinner
android:id="@+id/spPriority"

@ -583,33 +583,14 @@
app:layout_constraintTop_toBottomOf="@id/cbEncrypt" />
<CheckBox
android:id="@+id/cbDeliveryReceipt"
android:id="@+id/cbReceipt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_identity_delivery_receipt"
android:text="@string/title_identity_receipt"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvEncryptPro" />
<CheckBox
android:id="@+id/cbReadReceipt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_identity_read_receipt"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbDeliveryReceipt" />
<TextView
android:id="@+id/tvReceipt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_identity_receipt_remark"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textStyle="italic"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbReadReceipt" />
<Button
android:id="@+id/btnSave"
android:layout_width="wrap_content"
@ -618,7 +599,7 @@
android:tag="disable"
android:text="@string/title_save"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvReceipt" />
app:layout_constraintTop_toBottomOf="@id/cbReceipt" />
<eu.faircode.email.ContentLoadingProgressBar
android:id="@+id/pbSave"

@ -368,10 +368,8 @@
<string name="title_advanced_sender_regex">Regex to match edited addresses</string>
<string name="title_identity_reply_to">Reply to address</string>
<string name="title_identity_encrypt">Encrypt by default</string>
<string name="title_identity_receipt">Request delivery/read receipt by default</string>
<string name="title_identity_use_ip_hint">In case of \'invalid greeting\', \'requires valid address\' or a similar error, try to change this setting</string>
<string name="title_identity_read_receipt">Request read receipt</string>
<string name="title_identity_delivery_receipt">Request delivery receipt</string>
<string name="title_identity_receipt_remark">Most providers ignore receipt requests</string>
<string name="title_optional">Optional</string>
<string name="title_recommended">Recommended</string>
<string name="title_account_linked">Linked account</string>
@ -606,6 +604,8 @@
<string name="title_insert_contact_group">Insert contact group</string>
<string name="title_insert_template">Insert template</string>
<string name="title_send_plain_text">Plain text only</string>
<string name="title_send_receipt">Request delivery/read receipt</string>
<string name="title_send_receipt_remark">Most providers and email clients ignore receipt requests</string>
<string name="title_from_missing">Sender missing</string>
<string name="title_to_missing">Recipient missing</string>

Loading…
Cancel
Save