diff --git a/app/src/main/java/eu/faircode/email/FragmentCompose.java b/app/src/main/java/eu/faircode/email/FragmentCompose.java index 07e9f9702a..5e63678661 100644 --- a/app/src/main/java/eu/faircode/email/FragmentCompose.java +++ b/app/src/main/java/eu/faircode/email/FragmentCompose.java @@ -2336,9 +2336,33 @@ public class FragmentCompose extends FragmentBase { } } else { // Serialize message - try (OutputStream out = new FileOutputStream(input)) { - imessage.writeTo(out); - } + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + boolean encrypt_subject = prefs.getBoolean("encrypt_subject", false); + if (encrypt_subject) { + imessage.saveChanges(); + BodyPart bpContent = new MimeBodyPart() { + @Override + public void setContent(Object content, String type) throws MessagingException { + super.setContent(content, type); + + updateHeaders(); + + ContentType ct = new ContentType(type); + ct.setParameter("protected-headers", "v1"); + setHeader("Content-Type", ct.toString()); + setHeader("Subject", draft.subject == null ? "" : draft.subject); + } + }; + + bpContent.setContent(imessage.getContent(), imessage.getContentType()); + + try (OutputStream out = new FileOutputStream(input)) { + bpContent.writeTo(out); + } + } else + try (OutputStream out = new FileOutputStream(input)) { + imessage.writeTo(out); + } } } diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java index 71b224ab8b..4769f634e8 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessages.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java @@ -201,14 +201,11 @@ import java.util.Objects; import java.util.Properties; import javax.mail.Address; -import javax.mail.BodyPart; import javax.mail.MessageRemovedException; import javax.mail.MessagingException; import javax.mail.Session; -import javax.mail.internet.ContentType; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; -import javax.mail.internet.MimeMultipart; import me.everything.android.ui.overscroll.IOverScrollDecor; import me.everything.android.ui.overscroll.IOverScrollUpdateListener; @@ -5972,37 +5969,17 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. MessageHelper.MessageParts parts; Properties props = MessageHelper.getSessionProperties(); Session isession = Session.getInstance(props, null); + MimeMessage imessage; try (InputStream fis = new FileInputStream(plain)) { - MimeMessage imessage = new MimeMessage(isession, fis); - MessageHelper helper = new MessageHelper(imessage, context); - parts = helper.getMessageParts(); - - // https://github.com/autocrypt/protected-headers - try { - Object content = imessage.getContent(); - - BodyPart bp = null; - if (content instanceof MimeMultipart) { - MimeMultipart mmp = (MimeMultipart) content; - if (mmp.getCount() > 0) - bp = mmp.getBodyPart(0); - } else if (content instanceof BodyPart) - bp = (BodyPart) content; - - if (bp != null) { - ContentType ct = new ContentType(bp.getContentType()); - if ("v1".equals(ct.getParameter("protected-headers"))) { - String[] subject = bp.getHeader("subject"); - if (subject != null && subject.length != 0) - db.message().setMessageSubject(message.id, subject[0]); - } - } - - } catch (Throwable ex) { - Log.e(ex); - } + imessage = new MimeMessage(isession, fis); } + MessageHelper helper = new MessageHelper(imessage, context); + parts = helper.getMessageParts(); + String subject = parts.getProtectedSubject(); + if (subject != null) + db.message().setMessageSubject(message.id, subject); + try { db.beginTransaction(); diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java b/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java index c629b7f542..e0542e8fe6 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java @@ -77,6 +77,7 @@ public class FragmentOptionsEncryption extends FragmentBase implements SharedPre private TextView tvOpenPgpStatus; private SwitchCompat swAutocrypt; private SwitchCompat swAutocryptMutual; + private SwitchCompat swEncryptSubject; private SwitchCompat swCheckCertificate; private Button btnManageCertificates; @@ -90,7 +91,7 @@ public class FragmentOptionsEncryption extends FragmentBase implements SharedPre private final static String[] RESET_OPTIONS = new String[]{ "sign_default", "encrypt_default", "auto_decrypt", - "openpgp_provider", "autocrypt", "autocrypt_mutual", + "openpgp_provider", "autocrypt", "autocrypt_mutual", "encrypt_subject", "check_certificate" }; @@ -113,6 +114,7 @@ public class FragmentOptionsEncryption extends FragmentBase implements SharedPre tvOpenPgpStatus = view.findViewById(R.id.tvOpenPgpStatus); swAutocrypt = view.findViewById(R.id.swAutocrypt); swAutocryptMutual = view.findViewById(R.id.swAutocryptMutual); + swEncryptSubject = view.findViewById(R.id.swEncryptSubject); swCheckCertificate = view.findViewById(R.id.swCheckCertificate); btnManageCertificates = view.findViewById(R.id.btnManageCertificates); @@ -204,6 +206,13 @@ public class FragmentOptionsEncryption extends FragmentBase implements SharedPre } }); + swEncryptSubject.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { + prefs.edit().putBoolean("encrypt_subject", checked).apply(); + } + }); + // S/MIME swCheckCertificate.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @@ -367,6 +376,7 @@ public class FragmentOptionsEncryption extends FragmentBase implements SharedPre swAutocrypt.setChecked(prefs.getBoolean("autocrypt", true)); swAutocryptMutual.setChecked(prefs.getBoolean("autocrypt_mutual", true)); swAutocryptMutual.setEnabled(swAutocrypt.isChecked()); + swEncryptSubject.setChecked(prefs.getBoolean("encrypt_subject", false)); swCheckCertificate.setChecked(prefs.getBoolean("check_certificate", true)); } diff --git a/app/src/main/java/eu/faircode/email/MessageHelper.java b/app/src/main/java/eu/faircode/email/MessageHelper.java index 3e5d819482..374ef21eb3 100644 --- a/app/src/main/java/eu/faircode/email/MessageHelper.java +++ b/app/src/main/java/eu/faircode/email/MessageHelper.java @@ -169,6 +169,7 @@ public class MessageHelper { boolean hide_timezone = prefs.getBoolean("hide_timezone", true); boolean autocrypt = prefs.getBoolean("autocrypt", true); boolean mutual = prefs.getBoolean("autocrypt_mutual", true); + boolean encrypt_subject = prefs.getBoolean("encrypt_subject", false); MimeMessageEx imessage = new MimeMessageEx(isession, message.msgid); @@ -401,6 +402,9 @@ public class MessageHelper { multipart.addBodyPart(bpContent); imessage.setContent(multipart); + if (encrypt_subject) + imessage.setSubject("..."); + return imessage; } else if (EntityAttachment.SMIME_SIGNATURE.equals(attachment.encryption)) { Log.i("Sending S/MIME signed message"); @@ -1636,11 +1640,16 @@ public class MessageHelper { } class MessageParts { + private String protected_subject; private List text = new ArrayList<>(); private List extra = new ArrayList<>(); private List attachments = new ArrayList<>(); private ArrayList warnings = new ArrayList<>(); + String getProtectedSubject() { + return protected_subject; + } + Boolean isPlainOnly() { if (text.size() + extra.size() == 0) return null; @@ -2299,6 +2308,19 @@ public class MessageHelper { private void getMessageParts(Part part, MessageParts parts, Integer encrypt) throws IOException, MessagingException { try { Log.d("Part class=" + part.getClass() + " type=" + part.getContentType()); + + // https://github.com/autocrypt/protected-headers + try { + ContentType ct = new ContentType(part.getContentType()); + if ("v1".equals(ct.getParameter("protected-headers"))) { + String[] subject = part.getHeader("subject"); + if (subject != null && subject.length != 0) + parts.protected_subject = subject[0]; + } + } catch (Throwable ex) { + Log.e(ex); + } + if (part.isMimeType("multipart/*")) { Multipart multipart; Object content = part.getContent(); diff --git a/app/src/main/res/layout/fragment_options_encryption.xml b/app/src/main/res/layout/fragment_options_encryption.xml index 6dca4c502d..a15317a684 100644 --- a/app/src/main/res/layout/fragment_options_encryption.xml +++ b/app/src/main/res/layout/fragment_options_encryption.xml @@ -144,6 +144,18 @@ app:layout_constraintTop_toBottomOf="@id/swAutocrypt" app:switchPadding="12dp" /> + + + app:layout_constraintTop_toBottomOf="@id/swEncryptSubject" />