From bcf65b7f711c6db380cf07698c97811cc463e82d Mon Sep 17 00:00:00 2001 From: M66B Date: Mon, 31 Aug 2020 11:53:48 +0200 Subject: [PATCH] Added rule forward with attachments (untested) --- app/src/main/java/eu/faircode/email/Core.java | 2 +- .../java/eu/faircode/email/EntityRule.java | 59 ++++++++++++++----- .../java/eu/faircode/email/FragmentRule.java | 44 ++++++++++---- app/src/main/res/layout/fragment_rule.xml | 49 ++++++++++++++- app/src/main/res/values/strings.xml | 4 +- 5 files changed, 125 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/Core.java b/app/src/main/java/eu/faircode/email/Core.java index 2ba574e287..4fd579c749 100644 --- a/app/src/main/java/eu/faircode/email/Core.java +++ b/app/src/main/java/eu/faircode/email/Core.java @@ -1802,7 +1802,7 @@ class Core { } } - private static void onRule(Context context, JSONArray jargs, EntityMessage message) throws JSONException, IOException { + private static void onRule(Context context, JSONArray jargs, EntityMessage message) throws JSONException, IOException, AddressException { // Download message body DB db = DB.getInstance(context); diff --git a/app/src/main/java/eu/faircode/email/EntityRule.java b/app/src/main/java/eu/faircode/email/EntityRule.java index f52c941385..b42bf6cbf7 100644 --- a/app/src/main/java/eu/faircode/email/EntityRule.java +++ b/app/src/main/java/eu/faircode/email/EntityRule.java @@ -57,6 +57,7 @@ import javax.mail.Address; import javax.mail.Header; import javax.mail.Message; import javax.mail.MessagingException; +import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import static androidx.room.ForeignKey.CASCADE; @@ -294,7 +295,7 @@ public class EntityRule { return matched; } - boolean execute(Context context, EntityMessage message) throws JSONException, IOException { + boolean execute(Context context, EntityMessage message) throws JSONException, IOException, AddressException { boolean executed = _execute(context, message); if (id != null && executed) { DB db = DB.getInstance(context); @@ -303,7 +304,7 @@ public class EntityRule { return executed; } - private boolean _execute(Context context, EntityMessage message) throws JSONException, IOException { + private boolean _execute(Context context, EntityMessage message) throws JSONException, IOException, AddressException { JSONObject jaction = new JSONObject(action); int type = jaction.getInt("type"); Log.i("Executing rule=" + type + ":" + name + " message=" + message.id); @@ -408,18 +409,30 @@ public class EntityRule { return true; } - private boolean onActionAnswer(Context context, EntityMessage message, JSONObject jargs) throws JSONException, IOException { - if (!message.content) { - EntityOperation.queue(context, message, EntityOperation.BODY); - EntityOperation.queue(context, message, EntityOperation.RULE, this.id); - return true; - } + private boolean onActionAnswer(Context context, EntityMessage message, JSONObject jargs) throws JSONException, IOException, AddressException { + DB db = DB.getInstance(context); long iid = jargs.getLong("identity"); long aid = jargs.getLong("answer"); - boolean cc = (jargs.has("cc") && jargs.getBoolean("cc")); + String to = jargs.optString("to"); + boolean cc = jargs.optBoolean("cc"); + boolean attachments = jargs.optBoolean("attachments"); - DB db = DB.getInstance(context); + if (!message.content) + EntityOperation.queue(context, message, EntityOperation.BODY); + + boolean complete = true; + if (attachments) + for (EntityAttachment attachment : db.attachment().getAttachments(message.id)) + if (!attachment.available) { + complete = false; + EntityOperation.queue(context, message, EntityOperation.ATTACHMENT, attachment.id); + } + + if (!message.content || !complete) { + EntityOperation.queue(context, message, EntityOperation.RULE, this.id); + return true; + } EntityIdentity identity = db.identity().getIdentity(iid); if (identity == null) @@ -448,15 +461,25 @@ public class EntityRule { reply.folder = db.folder().getOutbox().id; reply.identity = identity.id; reply.msgid = EntityMessage.generateMessageId(); - reply.references = (message.references == null ? "" : message.references + " ") + message.msgid; - reply.inreplyto = message.msgid; - reply.thread = message.thread; - reply.to = (message.reply == null || message.reply.length == 0 ? message.from : message.reply); + + if (TextUtils.isEmpty(to)) { + reply.references = (message.references == null ? "" : message.references + " ") + message.msgid; + reply.inreplyto = message.msgid; + reply.thread = message.thread; + reply.to = (message.reply == null || message.reply.length == 0 ? message.from : message.reply); + } else { + reply.wasforwardedfrom = message.msgid; + reply.thread = reply.msgid; // new thread + reply.to = InternetAddress.parseHeader(to, false); + } + reply.from = from; if (cc) reply.cc = message.cc; reply.unsubscribe = "mailto:" + identity.email; - reply.subject = context.getString(R.string.title_subject_reply, message.subject == null ? "" : message.subject); + reply.subject = context.getString( + TextUtils.isEmpty(to) ? R.string.title_subject_reply : R.string.title_subject_forward, + message.subject == null ? "" : message.subject); reply.received = new Date().getTime(); reply.sender = MessageHelper.getSortKey(reply.from); @@ -468,6 +491,7 @@ public class EntityRule { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); boolean extended_reply = prefs.getBoolean("extended_reply", false); boolean quote_reply = prefs.getBoolean("quote_reply", true); + boolean quote = (quote_reply && TextUtils.isEmpty(to)); String body = answer.getText(message.from); Document msg = JsoupEx.parse(body); @@ -478,7 +502,7 @@ public class EntityRule { div.appendChild(p); Document answering = JsoupEx.parse(message.getFile(context)); - div.appendChild(answering.body().tagName(quote_reply ? "blockquote" : "p")); + div.appendChild(answering.body().tagName(quote ? "blockquote" : "p")); msg.body().appendChild(div); @@ -493,6 +517,9 @@ public class EntityRule { HtmlHelper.getPreview(body), null); + if (attachments) + EntityAttachment.copy(context, message.id, reply.id); + EntityOperation.queue(context, reply, EntityOperation.SEND); // Batch send operations, wait until after commit diff --git a/app/src/main/java/eu/faircode/email/FragmentRule.java b/app/src/main/java/eu/faircode/email/FragmentRule.java index 50610f676e..f4b130a3a1 100644 --- a/app/src/main/java/eu/faircode/email/FragmentRule.java +++ b/app/src/main/java/eu/faircode/email/FragmentRule.java @@ -43,7 +43,7 @@ import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.EditText; -import android.widget.ImageView; +import android.widget.ImageButton; import android.widget.NumberPicker; import android.widget.ScrollView; import android.widget.Spinner; @@ -88,12 +88,12 @@ public class FragmentRule extends FragmentBase { private EditText etSender; private CheckBox cbSender; - private ImageView ibSender; + private ImageButton ibSender; private CheckBox cbKnownSender; private EditText etRecipient; private CheckBox cbRecipient; - private ImageView ibRecipient; + private ImageButton ibRecipient; private EditText etSubject; private CheckBox cbSubject; @@ -129,7 +129,10 @@ public class FragmentRule extends FragmentBase { private Spinner spIdent; private Spinner spAnswer; + private EditText etTo; + private ImageButton ibTo; private CheckBox cbCc; + private CheckBox cbWithAttachments; private Button btnTtsSetup; private Button btnTtsData; @@ -170,8 +173,9 @@ public class FragmentRule extends FragmentBase { private final static int REQUEST_DELETE = 4; private final static int REQUEST_SCHEDULE_START = 5; private final static int REQUEST_SCHEDULE_END = 6; - private final static int REQUEST_TTS_CHECK = 7; - private final static int REQUEST_TTS_DATA = 8; + private static final int REQUEST_TO = 7; + private final static int REQUEST_TTS_CHECK = 8; + private final static int REQUEST_TTS_DATA = 9; @Override public void onCreate(Bundle savedInstanceState) { @@ -249,7 +253,10 @@ public class FragmentRule extends FragmentBase { spIdent = view.findViewById(R.id.spIdent); spAnswer = view.findViewById(R.id.spAnswer); + etTo = view.findViewById(R.id.etTo); + ibTo = view.findViewById(R.id.ibTo); cbCc = view.findViewById(R.id.cbCc); + cbWithAttachments = view.findViewById(R.id.cbWithAttachments); btnTtsSetup = view.findViewById(R.id.btnTtsSetup); btnTtsData = view.findViewById(R.id.btnTtsData); @@ -452,6 +459,14 @@ public class FragmentRule extends FragmentBase { spIdent.setOnItemSelectedListener(onItemSelectedListener); spAnswer.setOnItemSelectedListener(onItemSelectedListener); + ibTo.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent pick = new Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Email.CONTENT_URI); + startActivityForResult(Helper.getChooser(getContext(), pick), REQUEST_TO); + } + }); + btnTtsSetup.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -623,11 +638,11 @@ public class FragmentRule extends FragmentBase { switch (requestCode) { case REQUEST_SENDER: if (resultCode == RESULT_OK && data != null) - onPickContact(data, true); + onPickContact(data, etSender); break; case REQUEST_RECIPIENT: if (resultCode == RESULT_OK && data != null) - onPickContact(data, true); + onPickContact(data, etRecipient); break; case REQUEST_COLOR: if (resultCode == RESULT_OK && data != null) { @@ -652,6 +667,10 @@ public class FragmentRule extends FragmentBase { if (resultCode == RESULT_OK) onScheduleEnd(data.getBundleExtra("args")); break; + case REQUEST_TO: + if (resultCode == RESULT_OK && data != null) + onPickContact(data, etTo); + break; case REQUEST_TTS_CHECK: if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) ToastEx.makeText(getContext(), R.string.title_rule_tts_ok, Toast.LENGTH_LONG).show(); @@ -669,7 +688,7 @@ public class FragmentRule extends FragmentBase { } } - private void onPickContact(Intent data, boolean sender) { + private void onPickContact(Intent data, final EditText et) { Uri uri = data.getData(); if (uri == null) return; try (Cursor cursor = getContext().getContentResolver().query(uri, @@ -678,10 +697,7 @@ public class FragmentRule extends FragmentBase { }, null, null, null)) { if (cursor != null && cursor.moveToFirst()) - if (sender) - etSender.setText(cursor.getString(0)); - else - etRecipient.setText(cursor.getString(0)); + et.setText(cursor.getString(0)); } catch (Throwable ex) { Log.e(ex); Log.unexpectedError(getParentFragmentManager(), ex); @@ -871,7 +887,9 @@ public class FragmentRule extends FragmentBase { break; } + etTo.setText(jaction.optString("to")); cbCc.setChecked(jaction.optBoolean("cc")); + cbWithAttachments.setChecked(jaction.optBoolean("attachments")); break; } @@ -1173,7 +1191,9 @@ public class FragmentRule extends FragmentBase { EntityAnswer answer = (EntityAnswer) spAnswer.getSelectedItem(); jaction.put("identity", identity == null ? -1 : identity.id); jaction.put("answer", answer == null ? -1 : answer.id); + jaction.put("to", etTo.getText().toString().trim()); jaction.put("cc", cbCc.isChecked()); + jaction.put("attachments", cbWithAttachments.isChecked()); break; } } diff --git a/app/src/main/res/layout/fragment_rule.xml b/app/src/main/res/layout/fragment_rule.xml index bc8f85101a..de31080f64 100644 --- a/app/src/main/res/layout/fragment_rule.xml +++ b/app/src/main/res/layout/fragment_rule.xml @@ -669,6 +669,40 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tvAnswerTemplate" /> + + + + + + + app:layout_constraintTop_toBottomOf="@id/etTo" /> + + + app:layout_constraintTop_toBottomOf="@id/cbWithAttachments" />