mirror of https://github.com/M66B/FairEmail.git
Allow insecure connections
This commit is contained in:
parent
0453b79b49
commit
7d642f468d
12
FAQ.md
12
FAQ.md
|
@ -99,15 +99,15 @@ This IMAP extension is required to implement two way synchronization, which is n
|
||||||
So, unless your provider can enable this extension, you cannot use FairEmail for this provider.
|
So, unless your provider can enable this extension, you cannot use FairEmail for this provider.
|
||||||
|
|
||||||
<a name="FAQ11"></a>
|
<a name="FAQ11"></a>
|
||||||
**(11) Why is STARTTLS for IMAP not supported?**
|
~~**(11) Why is STARTTLS for IMAP not supported?**~~
|
||||||
|
|
||||||
STARTTLS starts with a not encrypted connection and is therefore not secure.
|
~~STARTTLS starts with a not encrypted connection and is therefore not secure.~~
|
||||||
All well known IMAP servers support IMAP with a plain SSL connection, so there is no need to support STARTTLS for IMAP.
|
~~All well known IMAP servers support IMAP with a plain SSL connection, so there is no need to support STARTTLS for IMAP.~~
|
||||||
If you encounter an IMAP server that requires STARTTLS, please let me know.
|
~~If you encounter an IMAP server that requires STARTTLS, please let me know.~~
|
||||||
|
|
||||||
For more background information, please see [this article](https://www.eff.org/nl/deeplinks/2018/06/announcing-starttls-everywhere-securing-hop-hop-email-delivery).
|
~~For more background information, please see [this article](https://www.eff.org/nl/deeplinks/2018/06/announcing-starttls-everywhere-securing-hop-hop-email-delivery).~~
|
||||||
|
|
||||||
tl;dr; "*Additionally, even if you configure STARTTLS perfectly and use a valid certificate, there’s still no guarantee your communication will be encrypted.*"
|
~~tl;dr; "*Additionally, even if you configure STARTTLS perfectly and use a valid certificate, there’s still no guarantee your communication will be encrypted.*"~~
|
||||||
|
|
||||||
<a name="FAQ13"></a>
|
<a name="FAQ13"></a>
|
||||||
**(13) How does search on server work?**
|
**(13) How does search on server work?**
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -45,7 +45,7 @@ import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||||
// https://developer.android.com/topic/libraries/architecture/room.html
|
// https://developer.android.com/topic/libraries/architecture/room.html
|
||||||
|
|
||||||
@Database(
|
@Database(
|
||||||
version = 22,
|
version = 23,
|
||||||
entities = {
|
entities = {
|
||||||
EntityIdentity.class,
|
EntityIdentity.class,
|
||||||
EntityAccount.class,
|
EntityAccount.class,
|
||||||
|
@ -275,6 +275,15 @@ public abstract class DB extends RoomDatabase {
|
||||||
db.execSQL("CREATE UNIQUE INDEX `index_message_msgid_folder_ui_found` ON `message` (`msgid`, `folder`, `ui_found`)");
|
db.execSQL("CREATE UNIQUE INDEX `index_message_msgid_folder_ui_found` ON `message` (`msgid`, `folder`, `ui_found`)");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.addMigrations(new Migration(22, 23) {
|
||||||
|
@Override
|
||||||
|
public void migrate(SupportSQLiteDatabase db) {
|
||||||
|
Log.i(Helper.TAG, "DB migration from version " + startVersion + " to " + endVersion);
|
||||||
|
db.execSQL("ALTER TABLE `account` ADD COLUMN `starttls` INTEGER NOT NULL DEFAULT 0");
|
||||||
|
db.execSQL("ALTER TABLE `account` ADD COLUMN `insecure` INTEGER NOT NULL DEFAULT 0");
|
||||||
|
db.execSQL("ALTER TABLE `identity` ADD COLUMN `insecure` INTEGER NOT NULL DEFAULT 0");
|
||||||
|
}
|
||||||
|
})
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,10 @@ public class EntityAccount {
|
||||||
@NonNull
|
@NonNull
|
||||||
public String host; // IMAP
|
public String host; // IMAP
|
||||||
@NonNull
|
@NonNull
|
||||||
|
public Boolean starttls;
|
||||||
|
@NonNull
|
||||||
|
public Boolean insecure;
|
||||||
|
@NonNull
|
||||||
public Integer port;
|
public Integer port;
|
||||||
@NonNull
|
@NonNull
|
||||||
public String user;
|
public String user;
|
||||||
|
|
|
@ -54,10 +54,12 @@ public class EntityIdentity {
|
||||||
@NonNull
|
@NonNull
|
||||||
public String host; // SMTP
|
public String host; // SMTP
|
||||||
@NonNull
|
@NonNull
|
||||||
public Integer port;
|
|
||||||
@NonNull
|
|
||||||
public Boolean starttls;
|
public Boolean starttls;
|
||||||
@NonNull
|
@NonNull
|
||||||
|
public Boolean insecure;
|
||||||
|
@NonNull
|
||||||
|
public Integer port;
|
||||||
|
@NonNull
|
||||||
public String user;
|
public String user;
|
||||||
@NonNull
|
@NonNull
|
||||||
public String password;
|
public String password;
|
||||||
|
|
|
@ -28,12 +28,14 @@ import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.drawable.GradientDrawable;
|
import android.graphics.drawable.GradientDrawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
@ -93,14 +95,19 @@ public class FragmentAccount extends FragmentEx {
|
||||||
private ViewGroup view;
|
private ViewGroup view;
|
||||||
|
|
||||||
private Spinner spProvider;
|
private Spinner spProvider;
|
||||||
private EditText etHost;
|
|
||||||
private EditText etDomain;
|
private EditText etDomain;
|
||||||
private Button btnAutoConfig;
|
private Button btnAutoConfig;
|
||||||
|
|
||||||
|
private EditText etHost;
|
||||||
|
private CheckBox cbStartTls;
|
||||||
|
private CheckBox cbInsecure;
|
||||||
private EditText etPort;
|
private EditText etPort;
|
||||||
private Button btnAuthorize;
|
|
||||||
private EditText etUser;
|
private EditText etUser;
|
||||||
private TextInputLayout tilPassword;
|
private TextInputLayout tilPassword;
|
||||||
|
|
||||||
|
private Button btnAuthorize;
|
||||||
|
|
||||||
private Button btnAdvanced;
|
private Button btnAdvanced;
|
||||||
|
|
||||||
private TextView tvName;
|
private TextView tvName;
|
||||||
|
@ -155,6 +162,9 @@ public class FragmentAccount extends FragmentEx {
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
setSubtitle(R.string.title_edit_account);
|
setSubtitle(R.string.title_edit_account);
|
||||||
|
|
||||||
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
|
final boolean insecure = prefs.getBoolean("insecure", false);
|
||||||
|
|
||||||
view = (ViewGroup) inflater.inflate(R.layout.fragment_account, container, false);
|
view = (ViewGroup) inflater.inflate(R.layout.fragment_account, container, false);
|
||||||
|
|
||||||
// Get controls
|
// Get controls
|
||||||
|
@ -165,11 +175,13 @@ public class FragmentAccount extends FragmentEx {
|
||||||
|
|
||||||
etHost = view.findViewById(R.id.etHost);
|
etHost = view.findViewById(R.id.etHost);
|
||||||
etPort = view.findViewById(R.id.etPort);
|
etPort = view.findViewById(R.id.etPort);
|
||||||
|
cbStartTls = view.findViewById(R.id.cbStartTls);
|
||||||
btnAuthorize = view.findViewById(R.id.btnAuthorize);
|
cbInsecure = view.findViewById(R.id.cbInsecure);
|
||||||
etUser = view.findViewById(R.id.etUser);
|
etUser = view.findViewById(R.id.etUser);
|
||||||
tilPassword = view.findViewById(R.id.tilPassword);
|
tilPassword = view.findViewById(R.id.tilPassword);
|
||||||
|
|
||||||
|
btnAuthorize = view.findViewById(R.id.btnAuthorize);
|
||||||
|
|
||||||
btnAdvanced = view.findViewById(R.id.btnAdvanced);
|
btnAdvanced = view.findViewById(R.id.btnAdvanced);
|
||||||
|
|
||||||
etName = view.findViewById(R.id.etName);
|
etName = view.findViewById(R.id.etName);
|
||||||
|
@ -214,6 +226,8 @@ public class FragmentAccount extends FragmentEx {
|
||||||
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
|
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
|
||||||
Provider provider = (Provider) adapterView.getSelectedItem();
|
Provider provider = (Provider) adapterView.getSelectedItem();
|
||||||
grpServer.setVisibility(position == 1 ? View.VISIBLE : View.GONE);
|
grpServer.setVisibility(position == 1 ? View.VISIBLE : View.GONE);
|
||||||
|
cbStartTls.setVisibility(position == 1 && insecure ? View.VISIBLE : View.GONE);
|
||||||
|
cbInsecure.setVisibility(position == 1 && insecure ? View.VISIBLE : View.GONE);
|
||||||
grpAuthorize.setVisibility(position > 0 ? View.VISIBLE : View.GONE);
|
grpAuthorize.setVisibility(position > 0 ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
btnAuthorize.setVisibility(provider.type == null ? View.GONE : View.VISIBLE);
|
btnAuthorize.setVisibility(provider.type == null ? View.GONE : View.VISIBLE);
|
||||||
|
@ -293,6 +307,13 @@ public class FragmentAccount extends FragmentEx {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cbStartTls.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
|
||||||
|
etPort.setHint(checked ? "143" : "993");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
tilPassword.getEditText().addTextChangedListener(new TextWatcher() {
|
tilPassword.getEditText().addTextChangedListener(new TextWatcher() {
|
||||||
@Override
|
@Override
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
@ -401,6 +422,8 @@ public class FragmentAccount extends FragmentEx {
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putLong("id", id);
|
args.putLong("id", id);
|
||||||
args.putString("host", etHost.getText().toString());
|
args.putString("host", etHost.getText().toString());
|
||||||
|
args.putBoolean("starttls", cbStartTls.isChecked());
|
||||||
|
args.putBoolean("insecure", cbInsecure.isChecked());
|
||||||
args.putString("port", etPort.getText().toString());
|
args.putString("port", etPort.getText().toString());
|
||||||
args.putString("user", etUser.getText().toString());
|
args.putString("user", etUser.getText().toString());
|
||||||
args.putString("password", tilPassword.getEditText().getText().toString());
|
args.putString("password", tilPassword.getEditText().getText().toString());
|
||||||
|
@ -411,6 +434,8 @@ public class FragmentAccount extends FragmentEx {
|
||||||
protected CheckResult onLoad(Context context, Bundle args) throws Throwable {
|
protected CheckResult onLoad(Context context, Bundle args) throws Throwable {
|
||||||
long id = args.getLong("id");
|
long id = args.getLong("id");
|
||||||
String host = args.getString("host");
|
String host = args.getString("host");
|
||||||
|
boolean starttls = args.getBoolean("starttls");
|
||||||
|
boolean insecure = args.getBoolean("insecure");
|
||||||
String port = args.getString("port");
|
String port = args.getString("port");
|
||||||
String user = args.getString("user");
|
String user = args.getString("user");
|
||||||
String password = args.getString("password");
|
String password = args.getString("password");
|
||||||
|
@ -419,22 +444,22 @@ public class FragmentAccount extends FragmentEx {
|
||||||
if (TextUtils.isEmpty(host))
|
if (TextUtils.isEmpty(host))
|
||||||
throw new Throwable(getContext().getString(R.string.title_no_host));
|
throw new Throwable(getContext().getString(R.string.title_no_host));
|
||||||
if (TextUtils.isEmpty(port))
|
if (TextUtils.isEmpty(port))
|
||||||
port = "993";
|
port = (starttls ? "143" : "993");
|
||||||
if (TextUtils.isEmpty(user))
|
if (TextUtils.isEmpty(user))
|
||||||
throw new Throwable(getContext().getString(R.string.title_no_user));
|
throw new Throwable(getContext().getString(R.string.title_no_user));
|
||||||
if (TextUtils.isEmpty(password))
|
if (TextUtils.isEmpty(password) && !insecure)
|
||||||
throw new Throwable(getContext().getString(R.string.title_no_password));
|
throw new Throwable(getContext().getString(R.string.title_no_password));
|
||||||
|
|
||||||
CheckResult result = new CheckResult();
|
CheckResult result = new CheckResult();
|
||||||
result.folders = new ArrayList<>();
|
result.folders = new ArrayList<>();
|
||||||
|
|
||||||
// Check IMAP server / get folders
|
// Check IMAP server / get folders
|
||||||
Properties props = MessageHelper.getSessionProperties(auth_type);
|
Properties props = MessageHelper.getSessionProperties(auth_type, insecure);
|
||||||
Session isession = Session.getInstance(props, null);
|
Session isession = Session.getInstance(props, null);
|
||||||
isession.setDebug(true);
|
isession.setDebug(true);
|
||||||
IMAPStore istore = null;
|
IMAPStore istore = null;
|
||||||
try {
|
try {
|
||||||
istore = (IMAPStore) isession.getStore("imaps");
|
istore = (IMAPStore) isession.getStore(starttls ? "imap" : "imaps");
|
||||||
try {
|
try {
|
||||||
istore.connect(host, Integer.parseInt(port), user, password);
|
istore.connect(host, Integer.parseInt(port), user, password);
|
||||||
} catch (AuthenticationFailedException ex) {
|
} catch (AuthenticationFailedException ex) {
|
||||||
|
@ -574,6 +599,8 @@ public class FragmentAccount extends FragmentEx {
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putLong("id", id);
|
args.putLong("id", id);
|
||||||
args.putString("host", etHost.getText().toString());
|
args.putString("host", etHost.getText().toString());
|
||||||
|
args.putBoolean("starttls", cbStartTls.isChecked());
|
||||||
|
args.putBoolean("insecure", cbInsecure.isChecked());
|
||||||
args.putString("port", etPort.getText().toString());
|
args.putString("port", etPort.getText().toString());
|
||||||
args.putString("user", etUser.getText().toString());
|
args.putString("user", etUser.getText().toString());
|
||||||
args.putString("password", tilPassword.getEditText().getText().toString());
|
args.putString("password", tilPassword.getEditText().getText().toString());
|
||||||
|
@ -597,6 +624,8 @@ public class FragmentAccount extends FragmentEx {
|
||||||
@Override
|
@Override
|
||||||
protected Void onLoad(Context context, Bundle args) throws Throwable {
|
protected Void onLoad(Context context, Bundle args) throws Throwable {
|
||||||
String host = args.getString("host");
|
String host = args.getString("host");
|
||||||
|
boolean starttls = args.getBoolean("starttls");
|
||||||
|
boolean insecure = args.getBoolean("insecure");
|
||||||
String port = args.getString("port");
|
String port = args.getString("port");
|
||||||
String user = args.getString("user");
|
String user = args.getString("user");
|
||||||
String password = args.getString("password");
|
String password = args.getString("password");
|
||||||
|
@ -619,10 +648,10 @@ public class FragmentAccount extends FragmentEx {
|
||||||
if (TextUtils.isEmpty(host))
|
if (TextUtils.isEmpty(host))
|
||||||
throw new Throwable(getContext().getString(R.string.title_no_host));
|
throw new Throwable(getContext().getString(R.string.title_no_host));
|
||||||
if (TextUtils.isEmpty(port))
|
if (TextUtils.isEmpty(port))
|
||||||
port = "993";
|
port = (starttls ? "143" : "993");
|
||||||
if (TextUtils.isEmpty(user))
|
if (TextUtils.isEmpty(user))
|
||||||
throw new Throwable(getContext().getString(R.string.title_no_user));
|
throw new Throwable(getContext().getString(R.string.title_no_user));
|
||||||
if (TextUtils.isEmpty(password))
|
if (TextUtils.isEmpty(password) && !insecure)
|
||||||
throw new Throwable(getContext().getString(R.string.title_no_password));
|
throw new Throwable(getContext().getString(R.string.title_no_password));
|
||||||
if (TextUtils.isEmpty(interval))
|
if (TextUtils.isEmpty(interval))
|
||||||
interval = "9";
|
interval = "9";
|
||||||
|
@ -633,11 +662,11 @@ public class FragmentAccount extends FragmentEx {
|
||||||
|
|
||||||
// Check IMAP server
|
// Check IMAP server
|
||||||
if (synchronize) {
|
if (synchronize) {
|
||||||
Session isession = Session.getInstance(MessageHelper.getSessionProperties(auth_type), null);
|
Session isession = Session.getInstance(MessageHelper.getSessionProperties(auth_type, insecure), null);
|
||||||
isession.setDebug(true);
|
isession.setDebug(true);
|
||||||
IMAPStore istore = null;
|
IMAPStore istore = null;
|
||||||
try {
|
try {
|
||||||
istore = (IMAPStore) isession.getStore("imaps");
|
istore = (IMAPStore) isession.getStore(starttls ? "imap" : "imaps");
|
||||||
try {
|
try {
|
||||||
istore.connect(host, Integer.parseInt(port), user, password);
|
istore.connect(host, Integer.parseInt(port), user, password);
|
||||||
} catch (AuthenticationFailedException ex) {
|
} catch (AuthenticationFailedException ex) {
|
||||||
|
@ -669,6 +698,8 @@ public class FragmentAccount extends FragmentEx {
|
||||||
account = new EntityAccount();
|
account = new EntityAccount();
|
||||||
|
|
||||||
account.host = host;
|
account.host = host;
|
||||||
|
account.starttls = starttls;
|
||||||
|
account.insecure = insecure;
|
||||||
account.port = Integer.parseInt(port);
|
account.port = Integer.parseInt(port);
|
||||||
account.user = user;
|
account.user = user;
|
||||||
account.password = password;
|
account.password = password;
|
||||||
|
@ -828,6 +859,8 @@ public class FragmentAccount extends FragmentEx {
|
||||||
// Initialize
|
// Initialize
|
||||||
Helper.setViewsEnabled(view, false);
|
Helper.setViewsEnabled(view, false);
|
||||||
btnAuthorize.setVisibility(View.GONE);
|
btnAuthorize.setVisibility(View.GONE);
|
||||||
|
cbStartTls.setVisibility(View.GONE);
|
||||||
|
cbInsecure.setVisibility(View.GONE);
|
||||||
tilPassword.setPasswordVisibilityToggleEnabled(id < 0);
|
tilPassword.setPasswordVisibilityToggleEnabled(id < 0);
|
||||||
|
|
||||||
btnAdvanced.setVisibility(View.GONE);
|
btnAdvanced.setVisibility(View.GONE);
|
||||||
|
|
|
@ -135,9 +135,9 @@ public class FragmentFolder extends FragmentEx {
|
||||||
if (folder == null || !folder.name.equals(name)) {
|
if (folder == null || !folder.name.equals(name)) {
|
||||||
EntityAccount account = db.account().getAccount(folder == null ? aid : folder.account);
|
EntityAccount account = db.account().getAccount(folder == null ? aid : folder.account);
|
||||||
|
|
||||||
Properties props = MessageHelper.getSessionProperties(account.auth_type);
|
Properties props = MessageHelper.getSessionProperties(account.auth_type, account.insecure);
|
||||||
Session isession = Session.getInstance(props, null);
|
Session isession = Session.getInstance(props, null);
|
||||||
istore = (IMAPStore) isession.getStore("imaps");
|
istore = (IMAPStore) isession.getStore(account.starttls ? "imap" : "imaps");
|
||||||
Helper.connect(context, istore, account);
|
Helper.connect(context, istore, account);
|
||||||
|
|
||||||
if (folder == null) {
|
if (folder == null) {
|
||||||
|
@ -239,9 +239,9 @@ public class FragmentFolder extends FragmentEx {
|
||||||
EntityFolder folder = db.folder().getFolder(id);
|
EntityFolder folder = db.folder().getFolder(id);
|
||||||
EntityAccount account = db.account().getAccount(folder.account);
|
EntityAccount account = db.account().getAccount(folder.account);
|
||||||
|
|
||||||
Properties props = MessageHelper.getSessionProperties(account.auth_type);
|
Properties props = MessageHelper.getSessionProperties(account.auth_type, account.insecure);
|
||||||
Session isession = Session.getInstance(props, null);
|
Session isession = Session.getInstance(props, null);
|
||||||
istore = (IMAPStore) isession.getStore("imaps");
|
istore = (IMAPStore) isession.getStore(account.starttls ? "imap" : "imaps");
|
||||||
Helper.connect(context, istore, account);
|
Helper.connect(context, istore, account);
|
||||||
|
|
||||||
IMAPFolder ifolder = (IMAPFolder) istore.getFolder(folder.name);
|
IMAPFolder ifolder = (IMAPFolder) istore.getFolder(folder.name);
|
||||||
|
|
|
@ -21,8 +21,10 @@ package eu.faircode.email;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -74,6 +76,7 @@ public class FragmentIdentity extends FragmentEx {
|
||||||
private Button btnAutoConfig;
|
private Button btnAutoConfig;
|
||||||
private EditText etHost;
|
private EditText etHost;
|
||||||
private CheckBox cbStartTls;
|
private CheckBox cbStartTls;
|
||||||
|
private CheckBox cbInsecure;
|
||||||
private EditText etPort;
|
private EditText etPort;
|
||||||
private EditText etUser;
|
private EditText etUser;
|
||||||
private TextInputLayout tilPassword;
|
private TextInputLayout tilPassword;
|
||||||
|
@ -102,6 +105,9 @@ public class FragmentIdentity extends FragmentEx {
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
setSubtitle(R.string.title_edit_identity);
|
setSubtitle(R.string.title_edit_identity);
|
||||||
|
|
||||||
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
|
final boolean insecure = prefs.getBoolean("insecure", false);
|
||||||
|
|
||||||
view = (ViewGroup) inflater.inflate(R.layout.fragment_identity, container, false);
|
view = (ViewGroup) inflater.inflate(R.layout.fragment_identity, container, false);
|
||||||
|
|
||||||
// Get controls
|
// Get controls
|
||||||
|
@ -120,8 +126,8 @@ public class FragmentIdentity extends FragmentEx {
|
||||||
|
|
||||||
etHost = view.findViewById(R.id.etHost);
|
etHost = view.findViewById(R.id.etHost);
|
||||||
cbStartTls = view.findViewById(R.id.cbStartTls);
|
cbStartTls = view.findViewById(R.id.cbStartTls);
|
||||||
|
cbInsecure = view.findViewById(R.id.cbInsecure);
|
||||||
etPort = view.findViewById(R.id.etPort);
|
etPort = view.findViewById(R.id.etPort);
|
||||||
|
|
||||||
etUser = view.findViewById(R.id.etUser);
|
etUser = view.findViewById(R.id.etUser);
|
||||||
tilPassword = view.findViewById(R.id.tilPassword);
|
tilPassword = view.findViewById(R.id.tilPassword);
|
||||||
|
|
||||||
|
@ -191,21 +197,6 @@ public class FragmentIdentity extends FragmentEx {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
btnAdvanced.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
int visibility = (grpAdvanced.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE);
|
|
||||||
grpAdvanced.setVisibility(visibility);
|
|
||||||
if (visibility == View.VISIBLE)
|
|
||||||
new Handler().post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
((ScrollView) view).smoothScrollTo(0, tvEmail.getTop());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
spProvider.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
spProvider.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
|
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
|
||||||
|
@ -275,6 +266,22 @@ public class FragmentIdentity extends FragmentEx {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
btnAdvanced.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
int visibility = (grpAdvanced.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE);
|
||||||
|
grpAdvanced.setVisibility(visibility);
|
||||||
|
cbInsecure.setVisibility(insecure ? visibility : View.GONE);
|
||||||
|
if (visibility == View.VISIBLE)
|
||||||
|
new Handler().post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
((ScrollView) view).smoothScrollTo(0, tvEmail.getTop());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
cbStartTls.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
cbStartTls.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
|
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
|
||||||
|
@ -307,6 +314,7 @@ public class FragmentIdentity extends FragmentEx {
|
||||||
args.putInt("auth_type", account == null || account.auth_type == null ? Helper.AUTH_TYPE_PASSWORD : account.auth_type);
|
args.putInt("auth_type", account == null || account.auth_type == null ? Helper.AUTH_TYPE_PASSWORD : account.auth_type);
|
||||||
args.putString("host", etHost.getText().toString());
|
args.putString("host", etHost.getText().toString());
|
||||||
args.putBoolean("starttls", cbStartTls.isChecked());
|
args.putBoolean("starttls", cbStartTls.isChecked());
|
||||||
|
args.putBoolean("insecure", cbInsecure.isChecked());
|
||||||
args.putString("port", etPort.getText().toString());
|
args.putString("port", etPort.getText().toString());
|
||||||
args.putString("user", etUser.getText().toString());
|
args.putString("user", etUser.getText().toString());
|
||||||
args.putString("password", tilPassword.getEditText().getText().toString());
|
args.putString("password", tilPassword.getEditText().getText().toString());
|
||||||
|
@ -324,6 +332,7 @@ public class FragmentIdentity extends FragmentEx {
|
||||||
String replyto = args.getString("replyto");
|
String replyto = args.getString("replyto");
|
||||||
String host = args.getString("host");
|
String host = args.getString("host");
|
||||||
boolean starttls = args.getBoolean("starttls");
|
boolean starttls = args.getBoolean("starttls");
|
||||||
|
boolean insecure = args.getBoolean("insecure");
|
||||||
String port = args.getString("port");
|
String port = args.getString("port");
|
||||||
String user = args.getString("user");
|
String user = args.getString("user");
|
||||||
String password = args.getString("password");
|
String password = args.getString("password");
|
||||||
|
@ -339,10 +348,10 @@ public class FragmentIdentity extends FragmentEx {
|
||||||
if (TextUtils.isEmpty(host))
|
if (TextUtils.isEmpty(host))
|
||||||
throw new IllegalArgumentException(getContext().getString(R.string.title_no_host));
|
throw new IllegalArgumentException(getContext().getString(R.string.title_no_host));
|
||||||
if (TextUtils.isEmpty(port))
|
if (TextUtils.isEmpty(port))
|
||||||
port = "465";
|
port = (starttls ? "587" : "465");
|
||||||
if (TextUtils.isEmpty(user))
|
if (TextUtils.isEmpty(user))
|
||||||
throw new IllegalArgumentException(getContext().getString(R.string.title_no_user));
|
throw new IllegalArgumentException(getContext().getString(R.string.title_no_user));
|
||||||
if (TextUtils.isEmpty(password))
|
if (TextUtils.isEmpty(password) && !insecure)
|
||||||
throw new IllegalArgumentException(getContext().getString(R.string.title_no_password));
|
throw new IllegalArgumentException(getContext().getString(R.string.title_no_password));
|
||||||
|
|
||||||
if (TextUtils.isEmpty(replyto))
|
if (TextUtils.isEmpty(replyto))
|
||||||
|
@ -350,7 +359,7 @@ public class FragmentIdentity extends FragmentEx {
|
||||||
|
|
||||||
// Check SMTP server
|
// Check SMTP server
|
||||||
if (synchronize) {
|
if (synchronize) {
|
||||||
Properties props = MessageHelper.getSessionProperties(auth_type);
|
Properties props = MessageHelper.getSessionProperties(auth_type, insecure);
|
||||||
Session isession = Session.getInstance(props, null);
|
Session isession = Session.getInstance(props, null);
|
||||||
isession.setDebug(true);
|
isession.setDebug(true);
|
||||||
Transport itransport = isession.getTransport(starttls ? "smtp" : "smtps");
|
Transport itransport = isession.getTransport(starttls ? "smtp" : "smtps");
|
||||||
|
@ -382,8 +391,9 @@ public class FragmentIdentity extends FragmentEx {
|
||||||
identity.email = email;
|
identity.email = email;
|
||||||
identity.replyto = replyto;
|
identity.replyto = replyto;
|
||||||
identity.host = host;
|
identity.host = host;
|
||||||
identity.port = Integer.parseInt(port);
|
|
||||||
identity.starttls = starttls;
|
identity.starttls = starttls;
|
||||||
|
identity.insecure = insecure;
|
||||||
|
identity.port = Integer.parseInt(port);
|
||||||
identity.user = user;
|
identity.user = user;
|
||||||
identity.password = password;
|
identity.password = password;
|
||||||
identity.auth_type = auth_type;
|
identity.auth_type = auth_type;
|
||||||
|
@ -476,6 +486,7 @@ public class FragmentIdentity extends FragmentEx {
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
Helper.setViewsEnabled(view, false);
|
Helper.setViewsEnabled(view, false);
|
||||||
|
cbInsecure.setVisibility(View.GONE);
|
||||||
tilPassword.setPasswordVisibilityToggleEnabled(id < 0);
|
tilPassword.setPasswordVisibilityToggleEnabled(id < 0);
|
||||||
btnSave.setVisibility(View.GONE);
|
btnSave.setVisibility(View.GONE);
|
||||||
btnAdvanced.setVisibility(View.GONE);
|
btnAdvanced.setVisibility(View.GONE);
|
||||||
|
|
|
@ -38,6 +38,7 @@ public class FragmentOptions extends FragmentEx {
|
||||||
private CheckBox cbBrowse;
|
private CheckBox cbBrowse;
|
||||||
private CheckBox cbSwipe;
|
private CheckBox cbSwipe;
|
||||||
private CheckBox cbCompact;
|
private CheckBox cbCompact;
|
||||||
|
private CheckBox cbInsecure;
|
||||||
private CheckBox cbDebug;
|
private CheckBox cbDebug;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -54,6 +55,7 @@ public class FragmentOptions extends FragmentEx {
|
||||||
cbBrowse = view.findViewById(R.id.cbBrowse);
|
cbBrowse = view.findViewById(R.id.cbBrowse);
|
||||||
cbSwipe = view.findViewById(R.id.cbSwipe);
|
cbSwipe = view.findViewById(R.id.cbSwipe);
|
||||||
cbCompact = view.findViewById(R.id.cbCompact);
|
cbCompact = view.findViewById(R.id.cbCompact);
|
||||||
|
cbInsecure = view.findViewById(R.id.cbInsecure);
|
||||||
cbDebug = view.findViewById(R.id.cbDebug);
|
cbDebug = view.findViewById(R.id.cbDebug);
|
||||||
|
|
||||||
// Wire controls
|
// Wire controls
|
||||||
|
@ -112,6 +114,14 @@ public class FragmentOptions extends FragmentEx {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cbInsecure.setChecked(prefs.getBoolean("insecure", false));
|
||||||
|
cbInsecure.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
|
||||||
|
prefs.edit().putBoolean("insecure", checked).apply();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
cbDebug.setChecked(prefs.getBoolean("debug", false));
|
cbDebug.setChecked(prefs.getBoolean("debug", false));
|
||||||
cbDebug.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
cbDebug.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -63,11 +63,13 @@ public class MessageHelper {
|
||||||
|
|
||||||
final static int NETWORK_TIMEOUT = 60 * 1000; // milliseconds
|
final static int NETWORK_TIMEOUT = 60 * 1000; // milliseconds
|
||||||
|
|
||||||
static Properties getSessionProperties(int auth_type) {
|
static Properties getSessionProperties(int auth_type, boolean insecure) {
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
|
|
||||||
|
String checkserveridentity = Boolean.toString(!insecure).toLowerCase();
|
||||||
|
|
||||||
// https://javaee.github.io/javamail/docs/api/com/sun/mail/imap/package-summary.html#properties
|
// https://javaee.github.io/javamail/docs/api/com/sun/mail/imap/package-summary.html#properties
|
||||||
props.put("mail.imaps.ssl.checkserveridentity", "true");
|
props.put("mail.imaps.ssl.checkserveridentity", checkserveridentity);
|
||||||
props.put("mail.imaps.ssl.trust", "*");
|
props.put("mail.imaps.ssl.trust", "*");
|
||||||
props.put("mail.imaps.starttls.enable", "false");
|
props.put("mail.imaps.starttls.enable", "false");
|
||||||
|
|
||||||
|
@ -79,22 +81,35 @@ public class MessageHelper {
|
||||||
props.put("mail.imaps.connectionpool.debug", "true");
|
props.put("mail.imaps.connectionpool.debug", "true");
|
||||||
props.put("mail.imaps.connectionpooltimeout", Integer.toString(3 * 60 * 1000)); // default: 45 sec
|
props.put("mail.imaps.connectionpooltimeout", Integer.toString(3 * 60 * 1000)); // default: 45 sec
|
||||||
|
|
||||||
// "mail.imaps.finalizecleanclose"
|
|
||||||
|
|
||||||
// https://tools.ietf.org/html/rfc4978
|
// https://tools.ietf.org/html/rfc4978
|
||||||
// https://docs.oracle.com/javase/8/docs/api/java/util/zip/Deflater.html
|
// https://docs.oracle.com/javase/8/docs/api/java/util/zip/Deflater.html
|
||||||
if (true) {
|
|
||||||
Log.i(Helper.TAG, "IMAP compress enabled");
|
|
||||||
props.put("mail.imaps.compress.enable", "true");
|
props.put("mail.imaps.compress.enable", "true");
|
||||||
//props.put("mail.imaps.compress.level", "-1");
|
//props.put("mail.imaps.compress.level", "-1");
|
||||||
//props.put("mail.imaps.compress.strategy", "0");
|
//props.put("mail.imaps.compress.strategy", "0");
|
||||||
}
|
|
||||||
|
|
||||||
props.put("mail.imaps.fetchsize", Integer.toString(48 * 1024)); // default 16K
|
props.put("mail.imaps.fetchsize", Integer.toString(48 * 1024)); // default 16K
|
||||||
props.put("mail.imaps.peek", "true");
|
props.put("mail.imaps.peek", "true");
|
||||||
|
|
||||||
|
props.put("mail.imap.ssl.checkserveridentity", checkserveridentity);
|
||||||
|
props.put("mail.imap.ssl.trust", "*");
|
||||||
|
props.put("mail.imap.starttls.enable", "true");
|
||||||
|
props.put("mail.imap.starttls.required", "true");
|
||||||
|
props.put("mail.imap.auth", "true");
|
||||||
|
|
||||||
|
props.put("mail.imap.connectiontimeout", Integer.toString(NETWORK_TIMEOUT));
|
||||||
|
props.put("mail.imap.timeout", Integer.toString(NETWORK_TIMEOUT));
|
||||||
|
props.put("mail.imap.writetimeout", Integer.toString(NETWORK_TIMEOUT)); // one thread overhead
|
||||||
|
|
||||||
|
props.put("mail.imap.connectionpool.debug", "true");
|
||||||
|
props.put("mail.imap.connectionpooltimeout", Integer.toString(3 * 60 * 1000)); // default: 45 sec
|
||||||
|
|
||||||
|
props.put("mail.imap.compress.enable", "true");
|
||||||
|
|
||||||
|
props.put("mail.imap.fetchsize", Integer.toString(48 * 1024)); // default 16K
|
||||||
|
props.put("mail.imap.peek", "true");
|
||||||
|
|
||||||
// https://javaee.github.io/javamail/docs/api/com/sun/mail/smtp/package-summary.html#properties
|
// https://javaee.github.io/javamail/docs/api/com/sun/mail/smtp/package-summary.html#properties
|
||||||
props.put("mail.smtps.ssl.checkserveridentity", "true");
|
props.put("mail.smtps.ssl.checkserveridentity", checkserveridentity);
|
||||||
props.put("mail.smtps.ssl.trust", "*");
|
props.put("mail.smtps.ssl.trust", "*");
|
||||||
props.put("mail.smtps.starttls.enable", "false");
|
props.put("mail.smtps.starttls.enable", "false");
|
||||||
props.put("mail.smtps.starttls.required", "false");
|
props.put("mail.smtps.starttls.required", "false");
|
||||||
|
@ -104,7 +119,7 @@ public class MessageHelper {
|
||||||
props.put("mail.smtps.writetimeout", Integer.toString(NETWORK_TIMEOUT)); // one thread overhead
|
props.put("mail.smtps.writetimeout", Integer.toString(NETWORK_TIMEOUT)); // one thread overhead
|
||||||
props.put("mail.smtps.timeout", Integer.toString(NETWORK_TIMEOUT));
|
props.put("mail.smtps.timeout", Integer.toString(NETWORK_TIMEOUT));
|
||||||
|
|
||||||
props.put("mail.smtp.ssl.checkserveridentity", "true");
|
props.put("mail.smtp.ssl.checkserveridentity", checkserveridentity);
|
||||||
props.put("mail.smtp.ssl.trust", "*");
|
props.put("mail.smtp.ssl.trust", "*");
|
||||||
props.put("mail.smtp.starttls.enable", "true");
|
props.put("mail.smtp.starttls.enable", "true");
|
||||||
props.put("mail.smtp.starttls.required", "true");
|
props.put("mail.smtp.starttls.required", "true");
|
||||||
|
@ -145,6 +160,7 @@ public class MessageHelper {
|
||||||
Log.i(Helper.TAG, "Auth type=" + auth_type);
|
Log.i(Helper.TAG, "Auth type=" + auth_type);
|
||||||
if (auth_type == Helper.AUTH_TYPE_GMAIL) {
|
if (auth_type == Helper.AUTH_TYPE_GMAIL) {
|
||||||
props.put("mail.imaps.auth.mechanisms", "XOAUTH2");
|
props.put("mail.imaps.auth.mechanisms", "XOAUTH2");
|
||||||
|
props.put("mail.imap.auth.mechanisms", "XOAUTH2");
|
||||||
props.put("mail.smtps.auth.mechanisms", "XOAUTH2");
|
props.put("mail.smtps.auth.mechanisms", "XOAUTH2");
|
||||||
props.put("mail.smtp.auth.mechanisms", "XOAUTH2");
|
props.put("mail.smtp.auth.mechanisms", "XOAUTH2");
|
||||||
}
|
}
|
||||||
|
|
|
@ -574,12 +574,12 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
System.setProperty("mail.socket.debug", Boolean.toString(debug));
|
System.setProperty("mail.socket.debug", Boolean.toString(debug));
|
||||||
|
|
||||||
// Create session
|
// Create session
|
||||||
Properties props = MessageHelper.getSessionProperties(account.auth_type);
|
Properties props = MessageHelper.getSessionProperties(account.auth_type, account.insecure);
|
||||||
final Session isession = Session.getInstance(props, null);
|
final Session isession = Session.getInstance(props, null);
|
||||||
isession.setDebug(debug);
|
isession.setDebug(debug);
|
||||||
// adb -t 1 logcat | grep "fairemail\|System.out"
|
// adb -t 1 logcat | grep "fairemail\|System.out"
|
||||||
|
|
||||||
final IMAPStore istore = (IMAPStore) isession.getStore("imaps");
|
final IMAPStore istore = (IMAPStore) isession.getStore(account.starttls ? "imap" : "imaps");
|
||||||
final Map<EntityFolder, IMAPFolder> folders = new HashMap<>();
|
final Map<EntityFolder, IMAPFolder> folders = new HashMap<>();
|
||||||
List<Thread> syncs = new ArrayList<>();
|
List<Thread> syncs = new ArrayList<>();
|
||||||
List<Thread> idlers = new ArrayList<>();
|
List<Thread> idlers = new ArrayList<>();
|
||||||
|
@ -1331,7 +1331,7 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create session
|
// Create session
|
||||||
Properties props = MessageHelper.getSessionProperties(ident.auth_type);
|
Properties props = MessageHelper.getSessionProperties(ident.auth_type, ident.insecure);
|
||||||
final Session isession = Session.getInstance(props, null);
|
final Session isession = Session.getInstance(props, null);
|
||||||
|
|
||||||
// Create message
|
// Create message
|
||||||
|
|
|
@ -68,12 +68,12 @@ public class ViewModelBrowse extends ViewModel {
|
||||||
EntityAccount account = db.account().getAccount(folder.account);
|
EntityAccount account = db.account().getAccount(folder.account);
|
||||||
|
|
||||||
if (imessages == null) {
|
if (imessages == null) {
|
||||||
Properties props = MessageHelper.getSessionProperties(account.auth_type);
|
Properties props = MessageHelper.getSessionProperties(account.auth_type, account.insecure);
|
||||||
props.setProperty("mail.imap.throwsearchexception", "true");
|
props.setProperty("mail.imap.throwsearchexception", "true");
|
||||||
Session isession = Session.getInstance(props, null);
|
Session isession = Session.getInstance(props, null);
|
||||||
|
|
||||||
Log.i(Helper.TAG, "Boundary connecting account=" + account.name);
|
Log.i(Helper.TAG, "Boundary connecting account=" + account.name);
|
||||||
istore = (IMAPStore) isession.getStore("imaps");
|
istore = (IMAPStore) isession.getStore(account.starttls ? "imap" : "imaps");
|
||||||
Helper.connect(context, istore, account);
|
Helper.connect(context, istore, account);
|
||||||
|
|
||||||
Log.i(Helper.TAG, "Boundary opening folder=" + folder.name);
|
Log.i(Helper.TAG, "Boundary opening folder=" + folder.name);
|
||||||
|
|
|
@ -58,8 +58,8 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="12dp"
|
||||||
android:minHeight="0dp"
|
|
||||||
android:minWidth="0dp"
|
android:minWidth="0dp"
|
||||||
|
android:minHeight="0dp"
|
||||||
android:text="@string/title_autoconfig"
|
android:text="@string/title_autoconfig"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/etDomain" />
|
app:layout_constraintTop_toBottomOf="@id/etDomain" />
|
||||||
|
@ -118,6 +118,24 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/tvHost" />
|
app:layout_constraintTop_toBottomOf="@id/tvHost" />
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/cbStartTls"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:text="@string/title_starttls"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/etHost" />
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/cbInsecure"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:text="@string/title_allow_insecure"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/cbStartTls" />
|
||||||
|
|
||||||
<!-- port -->
|
<!-- port -->
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -128,7 +146,7 @@
|
||||||
android:text="@string/title_port"
|
android:text="@string/title_port"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/etHost" />
|
app:layout_constraintTop_toBottomOf="@id/cbInsecure" />
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/etPort"
|
android:id="@+id/etPort"
|
||||||
|
@ -146,8 +164,8 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="12dp"
|
||||||
android:minHeight="0dp"
|
|
||||||
android:minWidth="0dp"
|
android:minWidth="0dp"
|
||||||
|
android:minHeight="0dp"
|
||||||
android:text="@string/title_authorize"
|
android:text="@string/title_authorize"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/etPort" />
|
app:layout_constraintTop_toBottomOf="@id/etPort" />
|
||||||
|
@ -207,8 +225,8 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="12dp"
|
||||||
android:minHeight="0dp"
|
|
||||||
android:minWidth="0dp"
|
android:minWidth="0dp"
|
||||||
|
android:minHeight="0dp"
|
||||||
android:text="@string/title_setup_advanced"
|
android:text="@string/title_setup_advanced"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/tilPassword" />
|
app:layout_constraintTop_toBottomOf="@id/tilPassword" />
|
||||||
|
@ -241,8 +259,8 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="12dp"
|
||||||
android:minHeight="0dp"
|
|
||||||
android:minWidth="0dp"
|
android:minWidth="0dp"
|
||||||
|
android:minHeight="0dp"
|
||||||
android:text="@string/title_account_color"
|
android:text="@string/title_account_color"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/etName" />
|
app:layout_constraintTop_toBottomOf="@id/etName" />
|
||||||
|
|
|
@ -214,6 +214,15 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/etHost" />
|
app:layout_constraintTop_toBottomOf="@id/etHost" />
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/cbInsecure"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:text="@string/title_allow_insecure"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/cbStartTls" />
|
||||||
|
|
||||||
<!-- port -->
|
<!-- port -->
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -224,7 +233,7 @@
|
||||||
android:text="@string/title_port"
|
android:text="@string/title_port"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/cbStartTls" />
|
app:layout_constraintTop_toBottomOf="@id/cbInsecure" />
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/etPort"
|
android:id="@+id/etPort"
|
||||||
|
|
|
@ -71,6 +71,16 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/cbSwipe" />
|
app:layout_constraintTop_toBottomOf="@id/cbSwipe" />
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/cbInsecure"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="12dp"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:text="@string/title_allow_insecure"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/cbCompact" />
|
||||||
|
|
||||||
<CheckBox
|
<CheckBox
|
||||||
android:id="@+id/cbDebug"
|
android:id="@+id/cbDebug"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -79,6 +89,6 @@
|
||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="12dp"
|
||||||
android:text="@string/title_advanced_debug"
|
android:text="@string/title_advanced_debug"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/cbCompact" />
|
app:layout_constraintTop_toBottomOf="@id/cbInsecure" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
|
@ -106,6 +106,7 @@
|
||||||
<string name="title_custom">Custom</string>
|
<string name="title_custom">Custom</string>
|
||||||
<string name="title_host">Host name</string>
|
<string name="title_host">Host name</string>
|
||||||
<string name="title_starttls">STARTTLS</string>
|
<string name="title_starttls">STARTTLS</string>
|
||||||
|
<string name="title_allow_insecure">Allow insecure connections</string>
|
||||||
<string name="title_port">Port number</string>
|
<string name="title_port">Port number</string>
|
||||||
<string name="title_user">User name</string>
|
<string name="title_user">User name</string>
|
||||||
<string name="title_password">Password</string>
|
<string name="title_password">Password</string>
|
||||||
|
|
Loading…
Reference in New Issue