diff --git a/FAQ.md b/FAQ.md index f90b5d07d1..8fa186015b 100644 --- a/FAQ.md +++ b/FAQ.md @@ -146,6 +146,7 @@ FairEmail follows all the best practices for an email client as decribed in [thi * [(83) What does 'User is authenticated but not connected' mean?](#user-content-faq83) * [(84) What are local contacts for?](#user-content-faq84) * [(85) Why is an identity not available?](#user-content-faq85) +* [(86) What are 'extra privacy features'?](#user-content-faq86) [I have another question.](#support) @@ -1398,6 +1399,16 @@ FairEmail will try to select the best identity based on the *to* address of the
+ +**(86) What are 'extra privacy features'?** + +The advanced option *extra privacy features* enables: + +* Detection and removal of [tracking images](#user-content-faq82) +* Splitting linked images into an image and a link + +
+ ## Support diff --git a/app/src/main/java/eu/faircode/email/FragmentOptions.java b/app/src/main/java/eu/faircode/email/FragmentOptions.java index 48f1f4ec88..c408bd9364 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptions.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptions.java @@ -84,7 +84,6 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O private SwitchCompat swAddresses; private SwitchCompat swMonospaced; private SwitchCompat swHtml; - private SwitchCompat swTracking; private SwitchCompat swImages; private SwitchCompat swActionbar; @@ -106,6 +105,7 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O private SwitchCompat swLight; private Button btnSound; + private SwitchCompat swParanoid; private SwitchCompat swEnglish; private SwitchCompat swUpdates; private SwitchCompat swDebug; @@ -124,11 +124,11 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O "enabled", "schedule_start", "schedule_end", "metered", "download", "startup", "date", "threading", "avatars", "identicons", "name_email", "subject_italic", "flags", "preview", - "addresses", "monospaced", "autohtml", "remove_tracking", "autoimages", "actionbar", + "addresses", "monospaced", "autohtml", "autoimages", "actionbar", "pull", "swipenav", "autoexpand", "autoclose", "autonext", "collapse", "autoread", "automove", "autoresize", "sender", "autosend", "notify_preview", "search_local", "light", "sound", - "updates", "debug", + "paranoid", "updates", "debug", "first", "why", "last_update_check", "app_support", "message_swipe", "message_select", "folder_actions", "folder_sync", "edit_ref_confirmed", "show_html_confirmed", "show_images_confirmed", "print_html_confirmed", "show_organization", "style_toolbar" }; @@ -163,7 +163,6 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O swAddresses = view.findViewById(R.id.swAddresses); swMonospaced = view.findViewById(R.id.swMonospaced); swHtml = view.findViewById(R.id.swHtml); - swTracking = view.findViewById(R.id.swTracking); swImages = view.findViewById(R.id.swImages); swActionbar = view.findViewById(R.id.swActionbar); @@ -185,6 +184,7 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O swLight = view.findViewById(R.id.swLight); btnSound = view.findViewById(R.id.btnSound); + swParanoid = view.findViewById(R.id.swParanoid); swEnglish = view.findViewById(R.id.swEnglish); swUpdates = view.findViewById(R.id.swUpdates); swDebug = view.findViewById(R.id.swDebug); @@ -251,6 +251,13 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O } }); + swParanoid.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { + prefs.edit().putBoolean("paranoid", checked).apply(); + } + }); + swEnglish.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { @@ -388,13 +395,6 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O } }); - swTracking.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { - prefs.edit().putBoolean("remove_tracking", checked).apply(); - } - }); - swImages.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { @@ -635,7 +635,6 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O swAddresses.setChecked(prefs.getBoolean("addresses", true)); swMonospaced.setChecked(prefs.getBoolean("monospaced", false)); swHtml.setChecked(prefs.getBoolean("autohtml", false)); - swTracking.setChecked(prefs.getBoolean("remove_tracking", true)); swImages.setChecked(prefs.getBoolean("autoimages", false)); swActionbar.setChecked(prefs.getBoolean("actionbar", true)); @@ -657,6 +656,7 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O swNotifyPreview.setEnabled(Helper.isPro(getContext())); swSearchLocal.setChecked(prefs.getBoolean("search_local", false)); swLight.setChecked(prefs.getBoolean("light", false)); + swParanoid.setChecked(prefs.getBoolean("paranoid", true)); swEnglish.setChecked(prefs.getBoolean("english", false)); swUpdates.setChecked(prefs.getBoolean("updates", true)); swUpdates.setVisibility(Helper.isPlayStoreInstall(getContext()) ? View.GONE : View.VISIBLE); diff --git a/app/src/main/java/eu/faircode/email/HtmlHelper.java b/app/src/main/java/eu/faircode/email/HtmlHelper.java index 83fe1c4ea1..e3248d95cf 100644 --- a/app/src/main/java/eu/faircode/email/HtmlHelper.java +++ b/app/src/main/java/eu/faircode/email/HtmlHelper.java @@ -75,8 +75,8 @@ public class HtmlHelper { static String removeTracking(Context context, String html) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - boolean remove_tracking = prefs.getBoolean("remove_tracking", true); - if (!remove_tracking) + boolean paranoid = prefs.getBoolean("paranoid", true); + if (!paranoid) return html; Document document = Jsoup.parse(html); @@ -101,6 +101,9 @@ public class HtmlHelper { } static String sanitize(Context context, String html, boolean showQuotes) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + boolean paranoid = prefs.getBoolean("paranoid", true); + Document parsed = Jsoup.parse(html); Whitelist whitelist = Whitelist.relaxed() .addTags("hr", "abbr") @@ -190,7 +193,7 @@ public class HtmlHelper { String src = img.attr("src"); String alt = img.attr("alt"); String title = img.attr("title"); - boolean tracking = isTrackingPixel(img); + boolean tracking = (paranoid && isTrackingPixel(img)); // Create image container Element div = document.createElement("div"); @@ -225,26 +228,27 @@ public class HtmlHelper { // Split parent link and linked image boolean linked = false; - for (Element parent : img.parents()) - if ("a".equals(parent.tagName()) && - !TextUtils.isEmpty(parent.attr("href"))) { - String text = parent.attr("title").trim(); - if (TextUtils.isEmpty(text)) - text = parent.attr("alt").trim(); - if (TextUtils.isEmpty(text)) - text = context.getString(R.string.title_hint_image_link); - - img.remove(); - parent.appendText(text); - String outer = parent.outerHtml(); - - parent.tagName("span"); - parent.html(outer); - parent.appendChild(div); - - linked = true; - break; - } + if (paranoid) + for (Element parent : img.parents()) + if ("a".equals(parent.tagName()) && + !TextUtils.isEmpty(parent.attr("href"))) { + String text = parent.attr("title").trim(); + if (TextUtils.isEmpty(text)) + text = parent.attr("alt").trim(); + if (TextUtils.isEmpty(text)) + text = context.getString(R.string.title_hint_image_link); + + img.remove(); + parent.appendText(text); + String outer = parent.outerHtml(); + + parent.tagName("span"); + parent.html(outer); + parent.appendChild(div); + + linked = true; + break; + } if (!linked) { img.tagName("div"); diff --git a/app/src/main/res/layout/fragment_options.xml b/app/src/main/res/layout/fragment_options.xml index e7186c2a87..c20cdc9de3 100644 --- a/app/src/main/res/layout/fragment_options.xml +++ b/app/src/main/res/layout/fragment_options.xml @@ -439,18 +439,6 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/swHtml" /> - - + + Show address details by default Use monospaced font for message text Automatically show original message for known contacts - Attempt to remove tracking from original messages Automatically show images for known contacts Conversation action bar @@ -190,6 +189,7 @@ Use notification light Select notification sound Force English language + Extra privacy features Check for updates Debug mode