From 716262adf81e3b6d0b5534224d5b434504d3da14 Mon Sep 17 00:00:00 2001 From: M66B Date: Thu, 20 Aug 2026 13:36:37 +0200 Subject: [PATCH] Added support for PGPony --- FAQ.md | 6 +++-- .../eu/faircode/email/AdapterMessage.java | 4 ++-- .../java/eu/faircode/email/ApplicationEx.java | 3 +++ .../eu/faircode/email/FragmentCompose.java | 19 ++++++++------- .../eu/faircode/email/FragmentMessages.java | 23 +++++++++++-------- .../email/FragmentOptionsEncryption.java | 4 ++-- .../main/java/eu/faircode/email/Helper.java | 4 ---- .../java/eu/faircode/email/PgpHelper.java | 20 ++++++++++++---- app/src/main/res/values/strings.xml | 4 ++-- 9 files changed, 53 insertions(+), 34 deletions(-) diff --git a/FAQ.md b/FAQ.md index c81c088eb7..11b15a3ff0 100644 --- a/FAQ.md +++ b/FAQ.md @@ -1029,8 +1029,10 @@ If you want to undo decryption, you can tap on the "close" padlock icon. *PGP* -You'll need to install and configure [OpenKeychain](https://f-droid.org/en/packages/org.sufficientlysecure.keychain/) first. -FairEmail was tested with OpenKeychain version 5.4. Later versions will most likely be compatible, but earlier versions might not be. +You'll need to install and configure [OpenKeychain](https://f-droid.org/en/packages/org.sufficientlysecure.keychain/) or [PGPony](https://github.com/norsehorse-dev/PGPonyAndroid) first. +FairEmail was tested with OpenKeychain version 5.4 and PGPony 4.1.1. Later versions will most likely be compatible, but earlier versions might not be. + +**Note** that you need to select the correct OpenPGP provider on the encryption settings tab page. [PGPony for Android](https://github.com/norsehorse-dev/PGPonyAndroid) is reported to work too. You can select the PGP provider on the encryption settings tab page. diff --git a/app/src/main/java/eu/faircode/email/AdapterMessage.java b/app/src/main/java/eu/faircode/email/AdapterMessage.java index 92bf366685..7041a980a8 100644 --- a/app/src/main/java/eu/faircode/email/AdapterMessage.java +++ b/app/src/main/java/eu/faircode/email/AdapterMessage.java @@ -3285,8 +3285,8 @@ public class AdapterMessage extends RecyclerView.Adapter= 0 && begin < end) { String[] lines = body - .substring(begin, end + Helper.PGP_END_MESSAGE.length()) + .substring(begin, end + PgpHelper.PGP_END_MESSAGE.length()) .split("\\r?\\n"); List disarmored = new ArrayList<>(); @@ -10269,13 +10269,10 @@ public class FragmentMessages extends FragmentBase if (auto) return; - if (ex instanceof IllegalArgumentException) { - Log.i(ex); - Helper.setSnackbarOptions( - Snackbar.make(view, ex.getMessage(), Snackbar.LENGTH_LONG)) - .show(); - } else if (ex instanceof OperationCanceledException) { - Snackbar snackbar = Helper.setSnackbarOptions(Snackbar.make(view, R.string.title_no_openpgp, Snackbar.LENGTH_INDEFINITE)); + if (!PgpHelper.isOpenKeychainInstalled(getContext())) { + String text = getString(R.string.title_no_openpgp); + text += "\n" + Log.formatThrowable(ex, false); + Snackbar snackbar = Helper.setSnackbarOptions(Snackbar.make(view, text, Snackbar.LENGTH_INDEFINITE)); snackbar.setAction(R.string.title_fix, new View.OnClickListener() { @Override public void onClick(View v) { @@ -10283,7 +10280,13 @@ public class FragmentMessages extends FragmentBase Helper.viewFAQ(v.getContext(), 12); } }); + Helper.setSnackbarLines(snackbar, 7); snackbar.show(); + } else if (ex instanceof IllegalArgumentException) { + Log.i(ex); + Helper.setSnackbarOptions( + Snackbar.make(view, ex.getMessage(), Snackbar.LENGTH_LONG)) + .show(); } else Log.unexpectedError(getParentFragmentManager(), ex); } diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java b/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java index d03ae8c7bb..5287b2a2e5 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java @@ -351,7 +351,7 @@ public class FragmentOptionsEncryption extends FragmentBase btnImportPgp.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - String provider = prefs.getString("openpgp_provider", Helper.PGP_OPENKEYCHAIN_PACKAGE); + String provider = PgpHelper.getPackageName(v.getContext()); PackageManager pm = v.getContext().getPackageManager(); Intent intent = pm.getLaunchIntentForPackage(provider); @@ -689,7 +689,7 @@ public class FragmentOptionsEncryption extends FragmentBase swAutoDecrypt.setChecked(prefs.getBoolean("auto_decrypt", false)); swAutoUndoDecrypt.setChecked(prefs.getBoolean("auto_undecrypt", false)); - String provider = prefs.getString("openpgp_provider", Helper.PGP_OPENKEYCHAIN_PACKAGE); + String provider = PgpHelper.getPackageName(getContext()); spOpenPgp.setTag(provider); for (int pos = 0; pos < openPgpProvider.size(); pos++) if (provider.equals(openPgpProvider.get(pos))) { diff --git a/app/src/main/java/eu/faircode/email/Helper.java b/app/src/main/java/eu/faircode/email/Helper.java index f31b42e396..e38dff3804 100644 --- a/app/src/main/java/eu/faircode/email/Helper.java +++ b/app/src/main/java/eu/faircode/email/Helper.java @@ -220,10 +220,6 @@ public class Helper { static final String PLAY_PACKAGE_NAME = "com.android.vending"; - static final String PGP_OPENKEYCHAIN_PACKAGE = "org.sufficientlysecure.keychain"; - static final String PGP_BEGIN_MESSAGE = "-----BEGIN PGP MESSAGE-----"; - static final String PGP_END_MESSAGE = "-----END PGP MESSAGE-----"; - static final String PACKAGE_WEBVIEW = "https://play.google.com/store/apps/details?id=com.google.android.webview"; static final String PRIVACY_URI = "https://email.faircode.eu/privacy/"; static final String TUTORIALS_URI = "https://github.com/M66B/FairEmail/tree/master/tutorials#main"; diff --git a/app/src/main/java/eu/faircode/email/PgpHelper.java b/app/src/main/java/eu/faircode/email/PgpHelper.java index 0b32acef7f..f970d4dde6 100644 --- a/app/src/main/java/eu/faircode/email/PgpHelper.java +++ b/app/src/main/java/eu/faircode/email/PgpHelper.java @@ -50,6 +50,11 @@ public class PgpHelper { private static final long CONNECT_TIMEOUT = 5000L; private static final long KEY_TIMEOUT = 250L; + static final String PGP_BEGIN_MESSAGE = "-----BEGIN PGP MESSAGE-----"; + static final String PGP_END_MESSAGE = "-----END PGP MESSAGE-----"; + private static final String PGP_OPENKEYCHAIN_PACKAGE = "org.sufficientlysecure.keychain"; + private static final String PGP_PGPONY = "com.pgpony.android"; + static Intent execute(Context context, Intent data, InputStream is, OutputStream os) { return execute(context, data, is, os, CONNECT_TIMEOUT); } @@ -160,19 +165,26 @@ public class PgpHelper { } static String getPackageName(Context context) { + PackageManager pm = context.getPackageManager(); + Intent intent = new Intent(OpenPgpApi.SERVICE_INTENT_2); + List ris = pm.queryIntentServices(intent, 0); // package whitelisted + if (ris != null && ris.size() == 1 && ris.get(0).serviceInfo != null) { + String pkg = ris.get(0).serviceInfo.packageName; + if (pkg != null) + return pkg; + } + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - return prefs.getString("openpgp_provider", Helper.PGP_OPENKEYCHAIN_PACKAGE); + return prefs.getString("openpgp_provider", PGP_OPENKEYCHAIN_PACKAGE); } static boolean isOpenKeychainInstalled(Context context) { - String provider = getPackageName(context); - try { + String provider = getPackageName(context); PackageManager pm = context.getPackageManager(); Intent intent = new Intent(OpenPgpApi.SERVICE_INTENT_2); intent.setPackage(provider); List ris = pm.queryIntentServices(intent, 0); - return (ris != null && ris.size() > 0); } catch (Throwable ex) { Log.e(ex); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 08b8918df6..5ccef4682d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1951,9 +1951,9 @@ Automatic Load plain text Load HTML - OpenKeychain not found + OpenPGP provider not found PGP end-to-end encryption needs to be configured first - Transferring to OpenKeychain + Transferring to OpenPGP provider Use the padlock to decrypt the message Verify the signature to show the message text Message is not signed or encrypted