diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsSend.java b/app/src/main/java/eu/faircode/email/FragmentOptionsSend.java index f7ce36b861..789205542c 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptionsSend.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptionsSend.java @@ -51,6 +51,7 @@ public class FragmentOptionsSend extends FragmentBase implements SharedPreferenc private SwitchCompat swExtendedReply; private SwitchCompat swQuoteReply; private SwitchCompat swPlainOnly; + private SwitchCompat swFormatFlowed; private Spinner spSignatureLocation; private SwitchCompat swUsenetSignature; private SwitchCompat swRemoveSignatures; @@ -67,7 +68,7 @@ public class FragmentOptionsSend extends FragmentBase implements SharedPreferenc private final static String[] RESET_OPTIONS = new String[]{ "keyboard", "suggest_sent", "suggested_received", "prefix_once", "extended_reply", "quote_reply", - "plain_only", "signature_location", "usenet_signature", "remove_signatures", + "plain_only", "format_flowed", "signature_location", "usenet_signature", "remove_signatures", "resize_images", "resize_attachments", "resize", "send_reminders", "receipt_default", "receipt_type", "lookup_mx", "send_delayed" }; @@ -90,6 +91,7 @@ public class FragmentOptionsSend extends FragmentBase implements SharedPreferenc swExtendedReply = view.findViewById(R.id.swExtendedReply); swQuoteReply = view.findViewById(R.id.swQuoteReply); swPlainOnly = view.findViewById(R.id.swPlainOnly); + swFormatFlowed = view.findViewById(R.id.swFormatFlowed); spSignatureLocation = view.findViewById(R.id.spSignatureLocation); swUsenetSignature = view.findViewById(R.id.swUsenetSignature); swRemoveSignatures = view.findViewById(R.id.swRemoveSignatures); @@ -166,6 +168,13 @@ public class FragmentOptionsSend extends FragmentBase implements SharedPreferenc } }); + swFormatFlowed.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { + prefs.edit().putBoolean("format_flowed", checked).apply(); + } + }); + spSignatureLocation.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView adapterView, View view, int position, long id) { @@ -321,6 +330,7 @@ public class FragmentOptionsSend extends FragmentBase implements SharedPreferenc swExtendedReply.setChecked(prefs.getBoolean("extended_reply", false)); swQuoteReply.setChecked(prefs.getBoolean("quote_reply", true)); swPlainOnly.setChecked(prefs.getBoolean("plain_only", false)); + swFormatFlowed.setChecked(prefs.getBoolean("format_flowed", false)); int signature_location = prefs.getInt("signature_location", 1); spSignatureLocation.setSelection(signature_location); diff --git a/app/src/main/java/eu/faircode/email/MessageHelper.java b/app/src/main/java/eu/faircode/email/MessageHelper.java index 18f09d5587..644d36d01a 100644 --- a/app/src/main/java/eu/faircode/email/MessageHelper.java +++ b/app/src/main/java/eu/faircode/email/MessageHelper.java @@ -103,6 +103,7 @@ public class MessageHelper { static final int MAX_MESSAGE_SIZE = 10 * 1024 * 1024; // bytes static final int DEFAULT_ATTACHMENT_DOWNLOAD_SIZE = 256 * 1024; // bytes static final long ATTACHMENT_PROGRESS_UPDATE = 1500L; // milliseconds + static final int FORMAT_FLOWED_LINE_LENGTH = 72; // https://tools.ietf.org/html/rfc4021 @@ -569,6 +570,9 @@ public class MessageHelper { } } + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + boolean format_flowed = prefs.getBoolean("format_flowed", false); + // multipart/mixed // multipart/related // multipart/alternative @@ -578,13 +582,40 @@ public class MessageHelper { // attachments String htmlContent = document.html(); + String htmlContentType = "text/html; charset=" + Charset.defaultCharset().name(); + String plainContent = HtmlHelper.getText(htmlContent); + String plainContentType = "text/plain; charset=" + Charset.defaultCharset().name(); + + if (format_flowed) { + List flowed = new ArrayList<>(); + for (String line : plainContent.split("\\r?\\n")) { + if (line.contains(" ")) { + StringBuffer sb = new StringBuffer(); + for (String word : line.split(" ")) { + if (sb.length() + word.length() > FORMAT_FLOWED_LINE_LENGTH) { + sb.append(' '); + flowed.add(sb.toString()); + sb = new StringBuffer(); + } + if (sb.length() > 0) + sb.append(' '); + sb.append(word); + } + if (sb.length() > 0) + flowed.add(sb.toString()); + } else + flowed.add(line); + } + plainContent = TextUtils.join("\r\n", flowed); + plainContentType += "; format=flowed"; + } BodyPart plainPart = new MimeBodyPart(); - plainPart.setContent(plainContent, "text/plain; charset=" + Charset.defaultCharset().name()); + plainPart.setContent(plainContent, plainContentType); BodyPart htmlPart = new MimeBodyPart(); - htmlPart.setContent(htmlContent, "text/html; charset=" + Charset.defaultCharset().name()); + htmlPart.setContent(htmlContent, htmlContentType); Multipart altMultiPart = new MimeMultipart("alternative"); altMultiPart.addBodyPart(plainPart); @@ -601,7 +632,7 @@ public class MessageHelper { if (availableAttachments == 0) if (message.plain_only != null && message.plain_only) - imessage.setContent(plainContent, "text/plain; charset=" + Charset.defaultCharset().name()); + imessage.setContent(plainContent, plainContentType); else imessage.setContent(altMultiPart); else { diff --git a/app/src/main/res/layout/fragment_options_send.xml b/app/src/main/res/layout/fragment_options_send.xml index cd5445b9ed..aec951a95c 100644 --- a/app/src/main/res/layout/fragment_options_send.xml +++ b/app/src/main/res/layout/fragment_options_send.xml @@ -134,6 +134,17 @@ app:layout_constraintTop_toBottomOf="@id/swQuoteReply" app:switchPadding="12dp" /> + + + app:layout_constraintTop_toBottomOf="@id/swFormatFlowed" /> Signature position Add signature after quoted/forwarded message Send plain text only by default + \'format flowed\' for plain text When requesting a receipt Usenet signature convention Remove recognized signatures