pull/204/head
M66B 3 years ago
parent 9a09474c3a
commit a215bcf6e8

@ -320,7 +320,6 @@ public class EmailProvider implements Parcelable {
}
}
}
} catch (Throwable ex) {
Log.w(ex);
}
@ -338,21 +337,35 @@ public class EmailProvider implements Parcelable {
EntityLog.log(context, "Replacing auto config by profile=" + provider.name);
return Arrays.asList(provider);
}
}
// https://help.dreamhost.com/hc/en-us/articles/214918038-Email-client-configuration-overview
if (autoconfig.imap.host != null &&
autoconfig.imap.host.endsWith(".dreamhost.com"))
autoconfig.imap.host = "imap.dreamhost.com";
if (autoconfig.smtp.host != null &&
autoconfig.smtp.host.endsWith(".dreamhost.com"))
autoconfig.smtp.host = "smtp.dreamhost.com";
// https://docs.aws.amazon.com/workmail/latest/userguide/using_IMAP_client.html
if (autoconfig.imap.host != null &&
autoconfig.imap.host.endsWith(".awsapps.com"))
autoconfig.partial = false;
Collections.sort(providers, new Comparator<EmailProvider>() {
@Override
public int compare(EmailProvider p1, EmailProvider p2) {
return -Integer.compare(p1.getScore(), p2.getScore());
}
});
for (EmailProvider autoconfig : result) {
EntityLog.log(context, "Provider" +
" score=" + autoconfig.getScore() +
" imap=" + autoconfig.imap +
" smtp=" + autoconfig.smtp);
// https://help.dreamhost.com/hc/en-us/articles/214918038-Email-client-configuration-overview
if (autoconfig.imap.host != null &&
autoconfig.imap.host.endsWith(".dreamhost.com"))
autoconfig.imap.host = "imap.dreamhost.com";
if (autoconfig.smtp.host != null &&
autoconfig.smtp.host.endsWith(".dreamhost.com"))
autoconfig.smtp.host = "smtp.dreamhost.com";
// https://docs.aws.amazon.com/workmail/latest/userguide/using_IMAP_client.html
if (autoconfig.imap.host != null &&
autoconfig.imap.host.endsWith(".awsapps.com"))
autoconfig.partial = false;
}
return result;
}
@ -611,6 +624,7 @@ public class EmailProvider implements Parcelable {
provider.imap.host = records[0].name;
provider.imap.port = records[0].port;
provider.imap.starttls = false;
provider.imap.checkCertificate(context);
EntityLog.log(context, "_imaps._tcp." + domain + "=" + provider.imap);
} catch (UnknownHostException ignored) {
// Identifies an IMAP server that MAY ... require the MUA to use the "STARTTLS" command
@ -620,6 +634,7 @@ public class EmailProvider implements Parcelable {
provider.imap.host = records[0].name;
provider.imap.port = records[0].port;
provider.imap.starttls = (provider.imap.port == 143);
provider.imap.checkCertificate(context);
EntityLog.log(context, "_imap._tcp." + domain + "=" + provider.imap);
}
}
@ -633,6 +648,7 @@ public class EmailProvider implements Parcelable {
provider.smtp.host = records[0].name;
provider.smtp.port = records[0].port;
provider.smtp.starttls = (provider.smtp.port == 587);
provider.smtp.checkCertificate(context);
EntityLog.log(context, "_submission._tcp." + domain + "=" + provider.smtp);
} catch (UnknownHostException ignored) {
// https://tools.ietf.org/html/rfc8314
@ -642,6 +658,7 @@ public class EmailProvider implements Parcelable {
provider.smtp.host = records[0].name;
provider.smtp.port = records[0].port;
provider.smtp.starttls = false;
provider.smtp.checkCertificate(context);
EntityLog.log(context, "_submissions._tcp." + domain + "=" + provider.smtp);
}
@ -808,6 +825,12 @@ public class EmailProvider implements Parcelable {
}
};
private int getScore() {
if (imap == null || smtp == null)
return -1;
return imap.score + smtp.score;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof EmailProvider) {
@ -834,6 +857,7 @@ public class EmailProvider implements Parcelable {
public int port;
public boolean starttls;
private int score = 0;
private Future<Boolean> isReachable;
private Server() {
@ -843,9 +867,20 @@ public class EmailProvider implements Parcelable {
this.host = (prefix == null ? "" : prefix + ".") + domain;
this.port = port;
this.starttls = starttls;
this.isReachable = getReachable(context);
}
private void checkCertificate(Context context) {
try {
getReachable(context).get();
} catch (Throwable ex) {
Log.e(ex);
}
}
private Future<Boolean> getReachable(Context context) {
Log.i("Scanning " + this);
this.isReachable = executor.submit(new Callable<Boolean>() {
return executor.submit(new Callable<Boolean>() {
// Returns:
// false: closed
// true: listening
@ -881,10 +916,28 @@ public class EmailProvider implements Parcelable {
List<String> names = EntityCertificate.getDnsNames((X509Certificate) cert);
EntityLog.log(context, "Certificate " + address +
" " + TextUtils.join(",", names));
if (EntityCertificate.matches(host, names)) {
score += 2;
EntityLog.log(context, "Trusted " + address);
return true;
}
for (String name : names)
try {
String similar = name;
if (similar.startsWith("*."))
similar = similar.substring(2);
InetAddress isimilar = InetAddress.getByName(similar);
if (iaddr.equals(isimilar)) {
score += 1;
EntityLog.log(context, "Similar " + similar + " host=" + host);
host = similar;
return true;
}
} catch (Throwable ex) {
Log.w(ex);
}
}
EntityLog.log(context, "Untrusted " + address);

@ -41,7 +41,6 @@ import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayInputStream;
import java.net.InetAddress;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
@ -217,31 +216,6 @@ public class EntityCertificate {
return result;
}
static String getSimilarDnsName(X509Certificate certificate, @NonNull String host) {
if (certificate == null)
return null;
try {
InetAddress haddr = InetAddress.getByName(host);
List<String> names = getDnsNames(certificate);
for (String _name : names)
try {
String name = (_name.startsWith("*.") ? _name.substring(2) : _name);
InetAddress naddr = InetAddress.getByName(name);
Log.i("host=" + host + " name=" + _name + "" +
" haddr=" + haddr + " naddr=" + naddr);
if (haddr.equals(naddr))
return name;
} catch (Throwable ex) {
Log.w(ex);
}
} catch (Throwable ex) {
Log.w(ex);
}
return null;
}
static boolean matches(String server, List<String> names) {
for (String name : names)
if (matches(server, name)) {

@ -289,8 +289,8 @@ public class FragmentQuickSetup extends FragmentBase {
List<EmailProvider> providers = EmailProvider.fromEmail(context, email, EmailProvider.Discover.ALL);
for (EmailProvider provider : providers)
try {
EntityLog.log(context, "imap=" + provider.imap);
EntityLog.log(context, "smtp=" + provider.smtp);
EntityLog.log(context, "Checking" +
" imap=" + provider.imap + " smtp=" + provider.smtp);
String user = (provider.user == EmailProvider.UserType.EMAIL ? email : username);
Log.i("User type=" + provider.user + " name=" + user);
@ -313,16 +313,7 @@ public class FragmentQuickSetup extends FragmentBase {
null, null);
} catch (EmailService.UntrustedException ex) {
imap_certificate = ex.getCertificate();
String similar = EntityCertificate.getSimilarDnsName(imap_certificate, provider.imap.host);
if (similar == null)
imap_fingerprint = EntityCertificate.getKeyFingerprint(imap_certificate);
else
provider.imap.host = similar;
iservice.connect(
provider.imap.host, provider.imap.port,
AUTH_TYPE_PASSWORD, null,
user, password,
null, imap_fingerprint);
imap_fingerprint = EntityCertificate.getKeyFingerprint(imap_certificate);
} catch (Throwable ex) {
Log.w(ex);
// Why not AuthenticationFailedException?
@ -338,6 +329,9 @@ public class FragmentQuickSetup extends FragmentBase {
AUTH_TYPE_PASSWORD, null,
user, password,
null, null);
} catch (EmailService.UntrustedException ex1) {
imap_certificate = ex1.getCertificate();
imap_fingerprint = EntityCertificate.getKeyFingerprint(imap_certificate);
} catch (Throwable ex1) {
Log.w(ex1);
if (!(ex instanceof AuthenticationFailedException) &&
@ -381,16 +375,7 @@ public class FragmentQuickSetup extends FragmentBase {
null, null);
} catch (EmailService.UntrustedException ex) {
smtp_certificate = ex.getCertificate();
String similar = EntityCertificate.getSimilarDnsName(smtp_certificate, provider.smtp.host);
if (similar == null)
smtp_fingerprint = EntityCertificate.getKeyFingerprint(smtp_certificate);
else
provider.smtp.host = similar;
iservice.connect(
provider.smtp.host, provider.smtp.port,
AUTH_TYPE_PASSWORD, null,
user, password,
null, smtp_fingerprint);
smtp_fingerprint = EntityCertificate.getKeyFingerprint(smtp_certificate);
}
max_size = iservice.getMaxSize();

Loading…
Cancel
Save