Added option for custom EHLO identification

pull/178/head
M66B 4 years ago
parent 4493d77d33
commit 6110ff0aa6

File diff suppressed because it is too large Load Diff

@ -61,7 +61,7 @@ import io.requery.android.database.sqlite.SQLiteDatabase;
// https://developer.android.com/topic/libraries/architecture/room.html
@Database(
version = 153,
version = 154,
entities = {
EntityIdentity.class,
EntityAccount.class,
@ -1538,6 +1538,13 @@ public abstract class DB extends RoomDatabase {
Log.i("DB migration from version " + startVersion + " to " + endVersion);
db.execSQL("ALTER TABLE `identity` ADD COLUMN `unicode` INTEGER NOT NULL DEFAULT 0");
}
})
.addMigrations(new Migration(153, 154) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase db) {
Log.i("DB migration from version " + startVersion + " to " + endVersion);
db.execSQL("ALTER TABLE `identity` ADD COLUMN `ehlo` TEXT");
}
});
}

@ -84,6 +84,7 @@ public class EmailService implements AutoCloseable {
private boolean insecure;
private boolean harden;
private boolean useip;
private String ehlo;
private boolean debug;
private Properties properties;
private Session isession;
@ -231,8 +232,9 @@ public class EmailService implements AutoCloseable {
properties.put("mail." + protocol + ".ignorebodystructuresize", Boolean.toString(enabled));
}
void setUseIp(boolean enabled) {
useip = enabled;
void setUseIp(boolean enabled, String host) {
this.useip = enabled;
this.ehlo = host;
}
void setLeaveOnServer(boolean keep) {
@ -503,14 +505,15 @@ public class EmailService implements AutoCloseable {
// https://tools.ietf.org/html/rfc5321#section-4.1.3
String haddr = (address instanceof Inet4Address ? "[127.0.0.1]" : "[IPv6:::1]");
properties.put("mail." + protocol + ".localhost", useip ? haddr : hdomain);
properties.put("mail." + protocol + ".localhost",
ehlo == null ? (useip ? haddr : hdomain) : ehlo);
Log.i("Using localhost=" + properties.getProperty("mail." + protocol + ".localhost"));
iservice = isession.getTransport(protocol);
try {
iservice.connect(address.getHostAddress(), port, user, password);
} catch (MessagingException ex) {
if (ConnectionHelper.isSyntacticallyInvalid(ex)) {
if (ehlo == null && ConnectionHelper.isSyntacticallyInvalid(ex)) {
properties.put("mail." + protocol + ".localhost", useip ? hdomain : haddr);
Log.i("Fallback localhost=" + properties.getProperty("mail." + protocol + ".localhost"));
try {

@ -84,6 +84,7 @@ public class EntityIdentity {
public String fingerprint;
@NonNull
public Boolean use_ip = true; // instead of domain name
public String ehlo;
@NonNull
public Boolean synchronize;
@NonNull
@ -183,6 +184,7 @@ public class EntityIdentity {
json.put("realm", realm);
json.put("fingerprint", fingerprint);
json.put("use_ip", use_ip);
json.put("ehlo", ehlo);
json.put("synchronize", synchronize);
json.put("primary", primary);
@ -234,6 +236,8 @@ public class EntityIdentity {
identity.fingerprint = json.getString("fingerprint");
if (json.has("use_ip"))
identity.use_ip = json.getBoolean("use_ip");
if (json.has("ehlo"))
identity.ehlo = json.getString("ehlo");
identity.synchronize = json.getBoolean("synchronize");
identity.primary = json.getBoolean("primary");
@ -271,6 +275,7 @@ public class EntityIdentity {
this.password.equals(other.password) &&
Objects.equals(this.realm, other.realm) &&
this.use_ip == other.use_ip &&
Objects.equals(this.ehlo, other.ehlo) &&
this.synchronize.equals(other.synchronize) &&
this.primary.equals(other.primary) &&
this.sender_extra.equals(sender_extra) &&

@ -102,6 +102,7 @@ public class FragmentIdentity extends FragmentBase {
private Button btnOAuth;
private EditText etRealm;
private CheckBox cbUseIp;
private EditText etEhlo;
private CheckBox cbSynchronize;
private CheckBox cbPrimary;
@ -192,6 +193,7 @@ public class FragmentIdentity extends FragmentBase {
btnOAuth = view.findViewById(R.id.btnOAuth);
etRealm = view.findViewById(R.id.etRealm);
cbUseIp = view.findViewById(R.id.cbUseIp);
etEhlo = view.findViewById(R.id.etEhlo);
cbSynchronize = view.findViewById(R.id.cbSynchronize);
cbPrimary = view.findViewById(R.id.cbPrimary);
@ -258,6 +260,7 @@ public class FragmentIdentity extends FragmentBase {
etPort.setText(Integer.toString(provider.smtp.port));
rgEncryption.check(provider.smtp.starttls ? R.id.radio_starttls : R.id.radio_ssl);
cbUseIp.setChecked(provider.useip);
etEhlo.setText(null);
break;
}
@ -379,6 +382,7 @@ public class FragmentIdentity extends FragmentBase {
etPort.setText(position == 0 ? null : Integer.toString(provider.smtp.port));
rgEncryption.check(provider.smtp.starttls ? R.id.radio_starttls : R.id.radio_ssl);
cbUseIp.setChecked(provider.useip);
etEhlo.setText(null);
EntityAccount account = (EntityAccount) spAccount.getSelectedItem();
if (account == null ||
@ -537,6 +541,7 @@ public class FragmentIdentity extends FragmentBase {
etPort.setText(Integer.toString(provider.smtp.port));
rgEncryption.check(provider.smtp.starttls ? R.id.radio_starttls : R.id.radio_ssl);
cbUseIp.setChecked(provider.useip);
etEhlo.setText(null);
}
@Override
@ -593,6 +598,7 @@ public class FragmentIdentity extends FragmentBase {
args.putString("realm", etRealm.getText().toString());
args.putString("fingerprint", cbTrust.isChecked() ? (String) cbTrust.getTag() : null);
args.putBoolean("use_ip", cbUseIp.isChecked());
args.putString("ehlo", etEhlo.getText().toString());
args.putString("signature", signature);
args.putBoolean("synchronize", cbSynchronize.isChecked());
args.putBoolean("primary", cbPrimary.isChecked());
@ -643,6 +649,7 @@ public class FragmentIdentity extends FragmentBase {
String realm = args.getString("realm");
String fingerprint = args.getString("fingerprint");
boolean use_ip = args.getBoolean("use_ip");
String ehlo = args.getString("ehlo");
boolean synchronize = args.getBoolean("synchronize");
boolean primary = args.getBoolean("primary");
@ -705,6 +712,9 @@ public class FragmentIdentity extends FragmentBase {
if (TextUtils.isEmpty(realm))
realm = null;
if (TextUtils.isEmpty(ehlo))
ehlo = null;
if (TextUtils.isEmpty(sender_extra_regex))
sender_extra_regex = null;
@ -763,6 +773,8 @@ public class FragmentIdentity extends FragmentBase {
return true;
if (!Objects.equals(identity.use_ip, use_ip))
return true;
if (!Objects.equals(identity.ehlo, ehlo))
return true;
if (!Objects.equals(identity.synchronize, synchronize))
return true;
if (!Objects.equals(identity.primary, (identity.synchronize && primary)))
@ -793,7 +805,8 @@ public class FragmentIdentity extends FragmentBase {
!Objects.equals(identity.certificate_alias, certificate) ||
!Objects.equals(realm, identityRealm) ||
!Objects.equals(identity.fingerprint, fingerprint) ||
use_ip != identity.use_ip));
use_ip != identity.use_ip) ||
!Objects.equals(identity.ehlo, ehlo));
Log.i("Identity check=" + check);
Long last_connected = null;
@ -806,7 +819,7 @@ public class FragmentIdentity extends FragmentBase {
String protocol = (starttls ? "smtp" : "smtps");
try (EmailService iservice = new EmailService(
context, protocol, realm, insecure, EmailService.PURPOSE_CHECK, true)) {
iservice.setUseIp(use_ip);
iservice.setUseIp(use_ip, ehlo);
iservice.connect(
host, Integer.parseInt(port),
auth, provider,
@ -848,6 +861,7 @@ public class FragmentIdentity extends FragmentBase {
identity.realm = realm;
identity.fingerprint = fingerprint;
identity.use_ip = use_ip;
identity.ehlo = ehlo;
identity.synchronize = synchronize;
identity.primary = (identity.synchronize && primary);
@ -1056,6 +1070,7 @@ public class FragmentIdentity extends FragmentBase {
}
cbUseIp.setChecked(identity == null ? true : identity.use_ip);
etEhlo.setText(identity == null ? null : identity.ehlo);
cbSynchronize.setChecked(identity == null ? true : identity.synchronize);
cbPrimary.setChecked(identity == null ? true : identity.primary);

@ -308,7 +308,7 @@ public class FragmentQuickSetup extends FragmentBase {
String iprotocol = provider.smtp.starttls ? "smtp" : "smtps";
try (EmailService iservice = new EmailService(
context, iprotocol, null, false, EmailService.PURPOSE_CHECK, true)) {
iservice.setUseIp(provider.useip);
iservice.setUseIp(provider.useip, null);
iservice.connect(
provider.smtp.host, provider.smtp.port,
EmailService.AUTH_TYPE_PASSWORD, null,

@ -466,7 +466,7 @@ public class ServiceSend extends ServiceBase {
// Create transport
try (EmailService iservice = new EmailService(
this, ident.getProtocol(), ident.realm, ident.insecure, debug)) {
iservice.setUseIp(ident.use_ip);
iservice.setUseIp(ident.use_ip, ident.ehlo);
iservice.setUnicode(ident.unicode);
// Connect transport

@ -488,6 +488,28 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbUseIp" />
<eu.faircode.email.FixedTextView
android:id="@+id/tvEhlo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_ehlo"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvUseIpHint" />
<eu.faircode.email.EditTextPlain
android:id="@+id/etEhlo"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:autofillHints="name"
android:hint="@string/title_optional"
android:inputType="text"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvEhlo" />
<CheckBox
android:id="@+id/cbSynchronize"
android:layout_width="wrap_content"
@ -495,7 +517,7 @@
android:layout_marginTop="12dp"
android:text="@string/title_enabled"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvUseIpHint" />
app:layout_constraintTop_toBottomOf="@id/etEhlo" />
<CheckBox
android:id="@+id/cbPrimary"
@ -760,7 +782,7 @@
tvSmtp,tvHost,etHost,rgEncryption,cbInsecure,tvInsecureRemark,tvPort,etPort,
tvUser,etUser,tvPassword,tilPassword,btnCertificate,tvCertificate,btnOAuth,
tvRealm,etRealm,
cbUseIp,tvUseIpHint,
cbUseIp,tvUseIpHint,tvEhlo,etEhlo,
cbSynchronize,cbPrimary,
cbSenderExtra,tvSenderExtra,etSenderExtra,tvSenderExtraHint,
tvReplyTo,etReplyTo,tvCc,etCc,tvCcHint,tvBcc,etBcc,tvBccHint,cbUnicode" />

@ -573,6 +573,7 @@
<string name="title_client_certificate">Client certificate</string>
<string name="title_realm">Realm</string>
<string name="title_use_ip">Use local IP address instead of host name</string>
<string name="title_ehlo">Custom HELO/EHLO identification</string>
<string name="title_primary">Primary</string>
<string name="title_primary_account">Primary (default account)</string>
<string name="title_primary_identity">Primary (default identity)</string>

Loading…
Cancel
Save