mirror of
https://github.com/M66B/FairEmail.git
synced 2026-01-03 11:28:41 +01:00
Scan+score
This commit is contained in:
@@ -320,7 +320,6 @@ public class EmailProvider implements Parcelable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Throwable ex) {
|
||||
Log.w(ex);
|
||||
}
|
||||
@@ -338,22 +337,36 @@ 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();
|
||||
|
||||
Reference in New Issue
Block a user