Skip encryption, etc for DSNs

pull/194/merge
M66B 3 years ago
parent 679c15017f
commit ea8223e047

@ -274,6 +274,7 @@ public class FragmentCompose extends FragmentBase {
private boolean monospaced = false; private boolean monospaced = false;
private String compose_font; private String compose_font;
private boolean dsn = true;
private Integer encrypt = null; private Integer encrypt = null;
private boolean media = true; private boolean media = true;
private boolean compact = false; private boolean compact = false;
@ -1586,8 +1587,8 @@ public class FragmentCompose extends FragmentBase {
ImageButton ib = v.findViewById(R.id.button); ImageButton ib = v.findViewById(R.id.button);
TextView tv = v.findViewById(R.id.text); TextView tv = v.findViewById(R.id.text);
v.setAlpha(state == State.LOADED ? 1f : Helper.LOW_LIGHT); v.setAlpha(state == State.LOADED && !dsn ? 1f : Helper.LOW_LIGHT);
ib.setEnabled(state == State.LOADED); ib.setEnabled(state == State.LOADED && !dsn);
if (EntityMessage.PGP_SIGNONLY.equals(encrypt) || EntityMessage.SMIME_SIGNONLY.equals(encrypt)) { if (EntityMessage.PGP_SIGNONLY.equals(encrypt) || EntityMessage.SMIME_SIGNONLY.equals(encrypt)) {
ib.setImageResource(R.drawable.twotone_gesture_24); ib.setImageResource(R.drawable.twotone_gesture_24);
@ -4267,21 +4268,23 @@ public class FragmentCompose extends FragmentBase {
EntityLog.log(context, "Selected=" + selected.email); EntityLog.log(context, "Selected=" + selected.email);
if (plain_only && if (!"dsn".equals(action)) {
!"resend".equals(action) && if (plain_only &&
!"editasnew".equals(action)) !"resend".equals(action) &&
data.draft.plain_only = true; !"editasnew".equals(action))
data.draft.plain_only = true;
if (encrypt_default || selected.encrypt_default) if (encrypt_default || selected.encrypt_default)
if (selected.encrypt == 0) if (selected.encrypt == 0)
data.draft.ui_encrypt = EntityMessage.PGP_SIGNENCRYPT; data.draft.ui_encrypt = EntityMessage.PGP_SIGNENCRYPT;
else else
data.draft.ui_encrypt = EntityMessage.SMIME_SIGNENCRYPT; data.draft.ui_encrypt = EntityMessage.SMIME_SIGNENCRYPT;
else if (sign_default || selected.sign_default) else if (sign_default || selected.sign_default)
if (selected.encrypt == 0) if (selected.encrypt == 0)
data.draft.ui_encrypt = EntityMessage.PGP_SIGNONLY; data.draft.ui_encrypt = EntityMessage.PGP_SIGNONLY;
else else
data.draft.ui_encrypt = EntityMessage.SMIME_SIGNONLY; data.draft.ui_encrypt = EntityMessage.SMIME_SIGNONLY;
}
if (receipt_default) if (receipt_default)
data.draft.receipt_request = true; data.draft.receipt_request = true;
@ -4519,34 +4522,36 @@ public class FragmentCompose extends FragmentBase {
} else if ("participation".equals(action)) } else if ("participation".equals(action))
data.draft.subject = status + ": " + ref.subject; data.draft.subject = status + ": " + ref.subject;
// Sensitivity if (!"dsn".equals(action)) {
data.draft.sensitivity = ref.sensitivity; // Sensitivity
data.draft.sensitivity = ref.sensitivity;
// Plain-only // Plain-only
if (ref.plain_only != null && ref.plain_only) if (ref.plain_only != null && ref.plain_only)
data.draft.plain_only = true; data.draft.plain_only = true;
// Encryption // Encryption
List<Address> recipients = new ArrayList<>(); List<Address> recipients = new ArrayList<>();
if (data.draft.to != null) if (data.draft.to != null)
recipients.addAll(Arrays.asList(data.draft.to)); recipients.addAll(Arrays.asList(data.draft.to));
if (data.draft.cc != null) if (data.draft.cc != null)
recipients.addAll(Arrays.asList(data.draft.cc)); recipients.addAll(Arrays.asList(data.draft.cc));
if (data.draft.bcc != null) if (data.draft.bcc != null)
recipients.addAll(Arrays.asList(data.draft.bcc)); recipients.addAll(Arrays.asList(data.draft.bcc));
if (EntityMessage.PGP_SIGNONLY.equals(ref.ui_encrypt) || if (EntityMessage.PGP_SIGNONLY.equals(ref.ui_encrypt) ||
EntityMessage.PGP_SIGNENCRYPT.equals(ref.ui_encrypt)) { EntityMessage.PGP_SIGNENCRYPT.equals(ref.ui_encrypt)) {
if (Helper.isOpenKeychainInstalled(context) && if (Helper.isOpenKeychainInstalled(context) &&
selected.sign_key != null && selected.sign_key != null &&
hasPgpKey(context, recipients)) hasPgpKey(context, recipients))
data.draft.ui_encrypt = ref.ui_encrypt; data.draft.ui_encrypt = ref.ui_encrypt;
} else if (EntityMessage.SMIME_SIGNONLY.equals(ref.ui_encrypt) || } else if (EntityMessage.SMIME_SIGNONLY.equals(ref.ui_encrypt) ||
EntityMessage.SMIME_SIGNENCRYPT.equals(ref.ui_encrypt)) { EntityMessage.SMIME_SIGNENCRYPT.equals(ref.ui_encrypt)) {
if (ActivityBilling.isPro(context) && if (ActivityBilling.isPro(context) &&
selected.sign_key_alias != null && selected.sign_key_alias != null &&
hasSmimeKey(context, recipients)) hasSmimeKey(context, recipients))
data.draft.ui_encrypt = ref.ui_encrypt; data.draft.ui_encrypt = ref.ui_encrypt;
}
} }
// Reply template // Reply template
@ -4970,6 +4975,7 @@ public class FragmentCompose extends FragmentBase {
} }
working = data.draft.id; working = data.draft.id;
dsn = (data.draft.dsn != null && !EntityMessage.DSN_NONE.equals(data.draft.dsn));
encrypt = data.draft.ui_encrypt; encrypt = data.draft.ui_encrypt;
invalidateOptionsMenu(); invalidateOptionsMenu();
@ -5767,8 +5773,10 @@ public class FragmentCompose extends FragmentBase {
args.putBoolean("remind_external", external); args.putBoolean("remind_external", external);
} }
if (draft.ui_encrypt == null || if ((draft.dsn == null ||
EntityMessage.ENCRYPT_NONE.equals(draft.ui_encrypt)) { EntityMessage.DSN_NONE.equals(draft.dsn)) &&
(draft.ui_encrypt == null ||
EntityMessage.ENCRYPT_NONE.equals(draft.ui_encrypt))) {
args.putBoolean("remind_pgp", hasPgpKey(context, recipients)); args.putBoolean("remind_pgp", hasPgpKey(context, recipients));
args.putBoolean("remind_smime", hasSmimeKey(context, recipients)); args.putBoolean("remind_smime", hasSmimeKey(context, recipients));
} }
@ -6866,7 +6874,6 @@ public class FragmentCompose extends FragmentBase {
final Spinner spEncrypt = dview.findViewById(R.id.spEncrypt); final Spinner spEncrypt = dview.findViewById(R.id.spEncrypt);
final ImageButton ibEncryption = dview.findViewById(R.id.ibEncryption); final ImageButton ibEncryption = dview.findViewById(R.id.ibEncryption);
final Spinner spPriority = dview.findViewById(R.id.spPriority); final Spinner spPriority = dview.findViewById(R.id.spPriority);
final ImageButton ibPriority = dview.findViewById(R.id.ibPriority);
final Spinner spSensitivity = dview.findViewById(R.id.spSensitivity); final Spinner spSensitivity = dview.findViewById(R.id.spSensitivity);
final ImageButton ibSensitivity = dview.findViewById(R.id.ibSensitivity); final ImageButton ibSensitivity = dview.findViewById(R.id.ibSensitivity);
final TextView tvSendAt = dview.findViewById(R.id.tvSendAt); final TextView tvSendAt = dview.findViewById(R.id.tvSendAt);
@ -7131,13 +7138,6 @@ public class FragmentCompose extends FragmentBase {
} }
}); });
ibPriority.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Invisible
}
});
spSensitivity.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { spSensitivity.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

@ -489,226 +489,228 @@ public class MessageHelper {
List<EntityAttachment> attachments = db.attachment().getAttachments(message.id); List<EntityAttachment> attachments = db.attachment().getAttachments(message.id);
if (message.from != null && message.from.length > 0) if (message.dsn == null || EntityMessage.DSN_NONE.equals(message.dsn)) {
for (EntityAttachment attachment : attachments) if (message.from != null && message.from.length > 0)
if (EntityAttachment.PGP_KEY.equals(attachment.encryption)) { for (EntityAttachment attachment : attachments)
InternetAddress from = (InternetAddress) message.from[0]; if (EntityAttachment.PGP_KEY.equals(attachment.encryption)) {
InternetAddress from = (InternetAddress) message.from[0];
if (autocrypt) {
String mode = (mutual ? "mutual" : "nopreference");
StringBuilder sb = new StringBuilder();
File file = attachment.getFile(context);
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line = br.readLine();
while (line != null) {
String data = null;
if (line.length() > 0 &&
!line.startsWith("-----BEGIN ") &&
!line.startsWith("-----END "))
data = line;
line = br.readLine();
// https://www.w3.org/Protocols/rfc822/3_Lexical.html#z0
if (data != null &&
line != null && !line.startsWith("-----END "))
sb.append("\r\n ").append(data);
}
}
if (autocrypt) { // https://autocrypt.org/level1.html#the-autocrypt-header
String mode = (mutual ? "mutual" : "nopreference"); imessage.addHeader("Autocrypt",
"addr=" + from.getAddress() + ";" +
" prefer-encrypt=" + mode + ";" +
" keydata=" + sb.toString());
}
}
StringBuilder sb = new StringBuilder(); // PGP: https://tools.ietf.org/html/rfc3156
File file = attachment.getFile(context); // S/MIME: https://tools.ietf.org/html/rfc8551
try (BufferedReader br = new BufferedReader(new FileReader(file))) { for (final EntityAttachment attachment : attachments)
String line = br.readLine(); if (EntityAttachment.PGP_SIGNATURE.equals(attachment.encryption)) {
while (line != null) { Log.i("Sending PGP signed message");
String data = null;
if (line.length() > 0 && for (final EntityAttachment content : attachments)
!line.startsWith("-----BEGIN ") && if (EntityAttachment.PGP_CONTENT.equals(content.encryption)) {
!line.startsWith("-----END ")) BodyPart bpContent = new MimeBodyPart(new FileInputStream(content.getFile(context)));
data = line;
final ContentType cts = new ContentType(attachment.type);
line = br.readLine(); String micalg = cts.getParameter("micalg");
if (TextUtils.isEmpty(micalg)) {
// https://www.w3.org/Protocols/rfc822/3_Lexical.html#z0 // Some providers strip parameters
if (data != null && // https://tools.ietf.org/html/rfc3156#section-5
line != null && !line.startsWith("-----END ")) Log.w("PGP micalg missing type=" + attachment.type);
sb.append("\r\n ").append(data);
} }
} ParameterList params = cts.getParameterList();
if (params != null)
params.remove("micalg");
cts.setParameterList(params);
// Build signature
BodyPart bpSignature = new MimeBodyPart();
bpSignature.setFileName(attachment.name);
FileDataSource dsSignature = new FileDataSource(attachment.getFile(context));
dsSignature.setFileTypeMap(new FileTypeMap() {
@Override
public String getContentType(File file) {
return cts.toString();
}
// https://autocrypt.org/level1.html#the-autocrypt-header @Override
imessage.addHeader("Autocrypt", public String getContentType(String filename) {
"addr=" + from.getAddress() + ";" + return cts.toString();
" prefer-encrypt=" + mode + ";" + }
" keydata=" + sb.toString()); });
} bpSignature.setDataHandler(new DataHandler(dsSignature));
} bpSignature.setDisposition(Part.INLINE);
// Build message
ContentType ct = new ContentType("multipart/signed");
if (micalg != null)
ct.setParameter("micalg", micalg);
ct.setParameter("protocol", "application/pgp-signature");
String ctx = ct.toString();
int slash = ctx.indexOf("/");
Multipart multipart = new MimeMultipart(ctx.substring(slash + 1));
multipart.addBodyPart(bpContent);
multipart.addBodyPart(bpSignature);
imessage.setContent(multipart);
return imessage;
}
throw new IllegalStateException("PGP content not found");
} else if (EntityAttachment.PGP_MESSAGE.equals(attachment.encryption)) {
Log.i("Sending PGP encrypted message");
// Build header
// https://tools.ietf.org/html/rfc3156
BodyPart bpHeader = new MimeBodyPart();
bpHeader.setContent("Version: 1\n", "application/pgp-encrypted");
// Build content
BodyPart bpContent = new MimeBodyPart();
bpContent.setFileName(attachment.name);
FileDataSource dsContent = new FileDataSource(attachment.getFile(context));
dsContent.setFileTypeMap(new FileTypeMap() {
@Override
public String getContentType(File file) {
return attachment.type;
}
// PGP: https://tools.ietf.org/html/rfc3156 @Override
// S/MIME: https://tools.ietf.org/html/rfc8551 public String getContentType(String filename) {
for (final EntityAttachment attachment : attachments) return attachment.type;
if (EntityAttachment.PGP_SIGNATURE.equals(attachment.encryption)) {
Log.i("Sending PGP signed message");
for (final EntityAttachment content : attachments)
if (EntityAttachment.PGP_CONTENT.equals(content.encryption)) {
BodyPart bpContent = new MimeBodyPart(new FileInputStream(content.getFile(context)));
final ContentType cts = new ContentType(attachment.type);
String micalg = cts.getParameter("micalg");
if (TextUtils.isEmpty(micalg)) {
// Some providers strip parameters
// https://tools.ietf.org/html/rfc3156#section-5
Log.w("PGP micalg missing type=" + attachment.type);
} }
ParameterList params = cts.getParameterList(); });
if (params != null) bpContent.setDataHandler(new DataHandler(dsContent));
params.remove("micalg"); bpContent.setDisposition(Part.INLINE);
cts.setParameterList(params);
// Build message
// Build signature ContentType ct = new ContentType("multipart/encrypted");
BodyPart bpSignature = new MimeBodyPart(); ct.setParameter("protocol", "application/pgp-encrypted");
bpSignature.setFileName(attachment.name); String ctx = ct.toString();
FileDataSource dsSignature = new FileDataSource(attachment.getFile(context)); int slash = ctx.indexOf("/");
dsSignature.setFileTypeMap(new FileTypeMap() { Multipart multipart = new MimeMultipart(ctx.substring(slash + 1));
@Override multipart.addBodyPart(bpHeader);
public String getContentType(File file) { multipart.addBodyPart(bpContent);
return cts.toString(); 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");
for (final EntityAttachment content : attachments)
if (EntityAttachment.SMIME_CONTENT.equals(content.encryption)) {
BodyPart bpContent = new MimeBodyPart(new FileInputStream(content.getFile(context)));
final ContentType cts = new ContentType(attachment.type);
String micalg = cts.getParameter("micalg");
if (TextUtils.isEmpty(micalg)) {
// Some providers strip parameters
Log.w("S/MIME micalg missing type=" + attachment.type);
micalg = "sha-256";
} }
ParameterList params = cts.getParameterList();
if (params != null)
params.remove("micalg");
cts.setParameterList(params);
// Build signature
BodyPart bpSignature = new MimeBodyPart();
bpSignature.setFileName(attachment.name);
FileDataSource dsSignature = new FileDataSource(attachment.getFile(context));
dsSignature.setFileTypeMap(new FileTypeMap() {
@Override
public String getContentType(File file) {
return cts.toString();
}
@Override @Override
public String getContentType(String filename) { public String getContentType(String filename) {
return cts.toString(); return cts.toString();
} }
}); });
bpSignature.setDataHandler(new DataHandler(dsSignature)); bpSignature.setDataHandler(new DataHandler(dsSignature));
bpSignature.setDisposition(Part.INLINE); bpSignature.setDisposition(Part.INLINE);
// Build message // Build message
ContentType ct = new ContentType("multipart/signed"); ContentType ct = new ContentType("multipart/signed");
if (micalg != null)
ct.setParameter("micalg", micalg); ct.setParameter("micalg", micalg);
ct.setParameter("protocol", "application/pgp-signature"); ct.setParameter("protocol", "application/pkcs7-signature");
String ctx = ct.toString(); ct.setParameter("smime-type", "signed-data");
int slash = ctx.indexOf("/"); String ctx = ct.toString();
Multipart multipart = new MimeMultipart(ctx.substring(slash + 1)); int slash = ctx.indexOf("/");
multipart.addBodyPart(bpContent); Multipart multipart = new MimeMultipart(ctx.substring(slash + 1));
multipart.addBodyPart(bpSignature); multipart.addBodyPart(bpContent);
imessage.setContent(multipart); multipart.addBodyPart(bpSignature);
imessage.setContent(multipart);
return imessage;
} return imessage;
throw new IllegalStateException("PGP content not found"); }
} else if (EntityAttachment.PGP_MESSAGE.equals(attachment.encryption)) { throw new IllegalStateException("S/MIME content not found");
Log.i("Sending PGP encrypted message"); } else if (EntityAttachment.SMIME_MESSAGE.equals(attachment.encryption)) {
Log.i("Sending S/MIME encrypted message");
// Build header
// https://tools.ietf.org/html/rfc3156
BodyPart bpHeader = new MimeBodyPart();
bpHeader.setContent("Version: 1\n", "application/pgp-encrypted");
// Build content
BodyPart bpContent = new MimeBodyPart();
bpContent.setFileName(attachment.name);
FileDataSource dsContent = new FileDataSource(attachment.getFile(context));
dsContent.setFileTypeMap(new FileTypeMap() {
@Override
public String getContentType(File file) {
return attachment.type;
}
@Override // Build message
public String getContentType(String filename) { imessage.setDisposition(Part.ATTACHMENT);
return attachment.type; imessage.setFileName(attachment.name);
} imessage.setDescription("S/MIME Encrypted Message");
});
bpContent.setDataHandler(new DataHandler(dsContent)); ContentType ct = new ContentType("application/pkcs7-mime");
bpContent.setDisposition(Part.INLINE); ct.setParameter("name", attachment.name);
ct.setParameter("smime-type", "enveloped-data");
// Build message
ContentType ct = new ContentType("multipart/encrypted"); File file = attachment.getFile(context);
ct.setParameter("protocol", "application/pgp-encrypted"); FileDataSource dataSource = new FileDataSource(file);
String ctx = ct.toString(); dataSource.setFileTypeMap(new FileTypeMap() {
int slash = ctx.indexOf("/"); @Override
Multipart multipart = new MimeMultipart(ctx.substring(slash + 1)); public String getContentType(File file) {
multipart.addBodyPart(bpHeader); return ct.toString();
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");
for (final EntityAttachment content : attachments)
if (EntityAttachment.SMIME_CONTENT.equals(content.encryption)) {
BodyPart bpContent = new MimeBodyPart(new FileInputStream(content.getFile(context)));
final ContentType cts = new ContentType(attachment.type);
String micalg = cts.getParameter("micalg");
if (TextUtils.isEmpty(micalg)) {
// Some providers strip parameters
Log.w("S/MIME micalg missing type=" + attachment.type);
micalg = "sha-256";
} }
ParameterList params = cts.getParameterList();
if (params != null)
params.remove("micalg");
cts.setParameterList(params);
// Build signature
BodyPart bpSignature = new MimeBodyPart();
bpSignature.setFileName(attachment.name);
FileDataSource dsSignature = new FileDataSource(attachment.getFile(context));
dsSignature.setFileTypeMap(new FileTypeMap() {
@Override
public String getContentType(File file) {
return cts.toString();
}
@Override @Override
public String getContentType(String filename) { public String getContentType(String filename) {
return cts.toString(); return ct.toString();
} }
}); });
bpSignature.setDataHandler(new DataHandler(dsSignature));
bpSignature.setDisposition(Part.INLINE);
// Build message
ContentType ct = new ContentType("multipart/signed");
ct.setParameter("micalg", micalg);
ct.setParameter("protocol", "application/pkcs7-signature");
ct.setParameter("smime-type", "signed-data");
String ctx = ct.toString();
int slash = ctx.indexOf("/");
Multipart multipart = new MimeMultipart(ctx.substring(slash + 1));
multipart.addBodyPart(bpContent);
multipart.addBodyPart(bpSignature);
imessage.setContent(multipart);
return imessage;
}
throw new IllegalStateException("S/MIME content not found");
} else if (EntityAttachment.SMIME_MESSAGE.equals(attachment.encryption)) {
Log.i("Sending S/MIME encrypted message");
// Build message
imessage.setDisposition(Part.ATTACHMENT);
imessage.setFileName(attachment.name);
imessage.setDescription("S/MIME Encrypted Message");
ContentType ct = new ContentType("application/pkcs7-mime");
ct.setParameter("name", attachment.name);
ct.setParameter("smime-type", "enveloped-data");
File file = attachment.getFile(context);
FileDataSource dataSource = new FileDataSource(file);
dataSource.setFileTypeMap(new FileTypeMap() {
@Override
public String getContentType(File file) {
return ct.toString();
}
@Override imessage.setDataHandler(new DataHandler(dataSource));
public String getContentType(String filename) {
return ct.toString();
}
});
imessage.setDataHandler(new DataHandler(dataSource)); return imessage;
}
return imessage; if (EntityMessage.PGP_SIGNENCRYPT.equals(message.ui_encrypt) ||
EntityMessage.SMIME_SIGNENCRYPT.equals(message.ui_encrypt)) {
String msg = "Storing unencrypted message" +
" encrypt=" + message.encrypt + "/" + message.ui_encrypt;
Log.w(msg);
throw new IllegalArgumentException(msg);
} }
if (EntityMessage.PGP_SIGNENCRYPT.equals(message.ui_encrypt) ||
EntityMessage.SMIME_SIGNENCRYPT.equals(message.ui_encrypt)) {
String msg = "Storing unencrypted message" +
" encrypt=" + message.encrypt + "/" + message.ui_encrypt;
Log.w(msg);
throw new IllegalArgumentException(msg);
} }
build(context, message, attachments, identity, send, imessage); build(context, message, attachments, identity, send, imessage);

@ -387,25 +387,10 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="12dp" android:layout_marginEnd="12dp"
android:entries="@array/priorityNames" android:entries="@array/priorityNames"
app:layout_constraintEnd_toStartOf="@id/ibPriority" app:layout_constraintEnd_toStartOf="@id/ibSensitivity"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvPriority" /> app:layout_constraintTop_toBottomOf="@id/tvPriority" />
<eu.faircode.email.FixedImageButton
android:id="@+id/ibPriority"
android:layout_width="36dp"
android:layout_height="36dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/title_info"
android:padding="6dp"
android:scaleType="fitCenter"
android:tooltipText="@string/title_info"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@+id/spPriority"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="@drawable/twotone_info_24"
app:tint="?attr/colorAccent" />
<eu.faircode.email.FixedTextView <eu.faircode.email.FixedTextView
android:id="@+id/tvSensitivity" android:id="@+id/tvSensitivity"
android:layout_width="0dp" android:layout_width="0dp"
@ -524,6 +509,8 @@
android:layout_height="0dp" android:layout_height="0dp"
app:constraint_referenced_ids=" app:constraint_referenced_ids="
cbPlainOnly,cbReceipt, cbPlainOnly,cbReceipt,
tvEncrypt,spEncrypt,ibEncryption" /> tvEncrypt,spEncrypt,ibEncryption,
tvPriority,spPriority,
tvSensitivity,spSensitivity,ibSensitivity" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</eu.faircode.email.ScrollViewEx> </eu.faircode.email.ScrollViewEx>
Loading…
Cancel
Save