mirror of https://github.com/M66B/FairEmail.git
Separated IMAP/SMTP server discovery
This commit is contained in:
parent
24bf725ea0
commit
f8a9f3326d
|
@ -68,6 +68,8 @@ public class EmailProvider {
|
||||||
public UserType user = UserType.EMAIL;
|
public UserType user = UserType.EMAIL;
|
||||||
public StringBuilder documentation; // html
|
public StringBuilder documentation; // html
|
||||||
|
|
||||||
|
enum Discover {ALL, IMAP, SMTP}
|
||||||
|
|
||||||
enum UserType {LOCAL, EMAIL}
|
enum UserType {LOCAL, EMAIL}
|
||||||
|
|
||||||
private static final int DNS_TIMEOUT = 5 * 1000; // milliseconds
|
private static final int DNS_TIMEOUT = 5 * 1000; // milliseconds
|
||||||
|
@ -143,8 +145,8 @@ public class EmailProvider {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static EmailProvider fromDomain(Context context, String domain) throws IOException {
|
static EmailProvider fromDomain(Context context, String domain, Discover discover) throws IOException {
|
||||||
EmailProvider autoconfig = _fromDomain(context, domain);
|
EmailProvider autoconfig = _fromDomain(context, domain, discover);
|
||||||
|
|
||||||
// Always prefer built-in profiles
|
// Always prefer built-in profiles
|
||||||
// - ISPDB is not always correct
|
// - ISPDB is not always correct
|
||||||
|
@ -160,11 +162,11 @@ public class EmailProvider {
|
||||||
return autoconfig;
|
return autoconfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static EmailProvider _fromDomain(Context context, String domain) throws IOException {
|
private static EmailProvider _fromDomain(Context context, String domain, Discover discover) throws IOException {
|
||||||
try {
|
try {
|
||||||
// Assume the provider knows best
|
// Assume the provider knows best
|
||||||
Log.i("Provider from DNS domain=" + domain);
|
Log.i("Provider from DNS domain=" + domain);
|
||||||
return fromDNS(context, domain);
|
return fromDNS(context, domain, discover);
|
||||||
} catch (Throwable ex) {
|
} catch (Throwable ex) {
|
||||||
Log.w(ex);
|
Log.w(ex);
|
||||||
try {
|
try {
|
||||||
|
@ -176,7 +178,7 @@ public class EmailProvider {
|
||||||
try {
|
try {
|
||||||
// Scan ports
|
// Scan ports
|
||||||
Log.i("Provider from template domain=" + domain);
|
Log.i("Provider from template domain=" + domain);
|
||||||
return fromTemplate(context, domain);
|
return fromTemplate(context, domain, discover);
|
||||||
} catch (Throwable ex2) {
|
} catch (Throwable ex2) {
|
||||||
Log.w(ex2);
|
Log.w(ex2);
|
||||||
throw new UnknownHostException(context.getString(R.string.title_setup_no_settings, domain));
|
throw new UnknownHostException(context.getString(R.string.title_setup_no_settings, domain));
|
||||||
|
@ -365,38 +367,43 @@ public class EmailProvider {
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static EmailProvider fromDNS(Context context, String domain) throws TextParseException, UnknownHostException {
|
private static EmailProvider fromDNS(Context context, String domain, Discover discover) throws TextParseException, UnknownHostException {
|
||||||
// https://tools.ietf.org/html/rfc6186
|
// https://tools.ietf.org/html/rfc6186
|
||||||
SRVRecord imap;
|
EmailProvider provider = new EmailProvider(domain);
|
||||||
boolean starttls;
|
|
||||||
try {
|
if (discover == Discover.ALL || discover == Discover.IMAP) {
|
||||||
// Identifies an IMAP server where TLS is initiated directly upon connection to the IMAP server.
|
SRVRecord imap;
|
||||||
imap = lookup(context, "_imaps._tcp." + domain);
|
boolean starttls;
|
||||||
// ... service is not supported at all at a particular domain by setting the target of an SRV RR to "."
|
try {
|
||||||
if (TextUtils.isEmpty(imap.getTarget().toString(true)))
|
// Identifies an IMAP server where TLS is initiated directly upon connection to the IMAP server.
|
||||||
throw new UnknownHostException(imap.toString());
|
imap = lookup(context, "_imaps._tcp." + domain);
|
||||||
starttls = false;
|
// ... service is not supported at all at a particular domain by setting the target of an SRV RR to "."
|
||||||
} catch (UnknownHostException ex) {
|
if (TextUtils.isEmpty(imap.getTarget().toString(true)))
|
||||||
// Identifies an IMAP server that MAY ... require the MUA to use the "STARTTLS" command
|
throw new UnknownHostException(imap.toString());
|
||||||
imap = lookup(context, "_imap._tcp." + domain);
|
starttls = false;
|
||||||
if (TextUtils.isEmpty(imap.getTarget().toString(true)))
|
} catch (UnknownHostException ex) {
|
||||||
throw new UnknownHostException(imap.toString());
|
// Identifies an IMAP server that MAY ... require the MUA to use the "STARTTLS" command
|
||||||
starttls = (imap.getPort() == 143);
|
imap = lookup(context, "_imap._tcp." + domain);
|
||||||
|
if (TextUtils.isEmpty(imap.getTarget().toString(true)))
|
||||||
|
throw new UnknownHostException(imap.toString());
|
||||||
|
starttls = (imap.getPort() == 143);
|
||||||
|
}
|
||||||
|
|
||||||
|
provider.imap_host = imap.getTarget().toString(true);
|
||||||
|
provider.imap_port = imap.getPort();
|
||||||
|
provider.imap_starttls = starttls;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that this covers connections both with and without Transport Layer Security (TLS)
|
if (discover == Discover.ALL || discover == Discover.SMTP) {
|
||||||
SRVRecord smtp = lookup(context, "_submission._tcp." + domain);
|
// Note that this covers connections both with and without Transport Layer Security (TLS)
|
||||||
if (TextUtils.isEmpty(smtp.getTarget().toString(true)))
|
SRVRecord smtp = lookup(context, "_submission._tcp." + domain);
|
||||||
throw new UnknownHostException(smtp.toString());
|
if (TextUtils.isEmpty(smtp.getTarget().toString(true)))
|
||||||
|
throw new UnknownHostException(smtp.toString());
|
||||||
|
|
||||||
EmailProvider provider = new EmailProvider(domain);
|
provider.smtp_host = smtp.getTarget().toString(true);
|
||||||
provider.imap_host = imap.getTarget().toString(true);
|
provider.smtp_port = smtp.getPort();
|
||||||
provider.imap_port = imap.getPort();
|
provider.smtp_starttls = (provider.smtp_port == 587);
|
||||||
provider.imap_starttls = starttls;
|
}
|
||||||
|
|
||||||
provider.smtp_host = smtp.getTarget().toString(true);
|
|
||||||
provider.smtp_port = smtp.getPort();
|
|
||||||
provider.smtp_starttls = (provider.smtp_port == 587);
|
|
||||||
|
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
@ -444,52 +451,74 @@ public class EmailProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static EmailProvider fromTemplate(Context context, String domain)
|
private static EmailProvider fromTemplate(Context context, String domain, Discover discover)
|
||||||
throws ExecutionException, InterruptedException, UnknownHostException {
|
throws ExecutionException, InterruptedException, UnknownHostException {
|
||||||
List<Server> imaps = new ArrayList<>();
|
Server imap = null;
|
||||||
List<Server> smtps = new ArrayList<>();
|
Server smtp = null;
|
||||||
|
|
||||||
// SSL
|
if (discover == Discover.ALL || discover == Discover.IMAP) {
|
||||||
imaps.add(new Server(domain, null, 993));
|
List<Server> imaps = new ArrayList<>();
|
||||||
imaps.add(new Server(domain, "imap", 993));
|
// SSL
|
||||||
imaps.add(new Server(domain, "mail", 993));
|
imaps.add(new Server(domain, null, 993));
|
||||||
imaps.add(new Server(domain, "mx", 993));
|
imaps.add(new Server(domain, "imap", 993));
|
||||||
// STARTTLS
|
imaps.add(new Server(domain, "mail", 993));
|
||||||
imaps.add(new Server(domain, null, 143));
|
imaps.add(new Server(domain, "mx", 993));
|
||||||
imaps.add(new Server(domain, "imap", 143));
|
// STARTTLS
|
||||||
imaps.add(new Server(domain, "mail", 143));
|
imaps.add(new Server(domain, null, 143));
|
||||||
imaps.add(new Server(domain, "mx", 143));
|
imaps.add(new Server(domain, "imap", 143));
|
||||||
|
imaps.add(new Server(domain, "mail", 143));
|
||||||
|
imaps.add(new Server(domain, "mx", 143));
|
||||||
|
|
||||||
// SSL
|
for (Server server : imaps)
|
||||||
smtps.add(new Server(domain, null, 465));
|
if (server.reachable.get()) {
|
||||||
smtps.add(new Server(domain, "smtp", 465));
|
imap = server;
|
||||||
smtps.add(new Server(domain, "mail", 465));
|
break;
|
||||||
smtps.add(new Server(domain, "mx", 465));
|
}
|
||||||
// STARTTLS
|
|
||||||
smtps.add(new Server(domain, null, 587));
|
|
||||||
smtps.add(new Server(domain, "smtp", 587));
|
|
||||||
smtps.add(new Server(domain, "mail", 587));
|
|
||||||
smtps.add(new Server(domain, "mx", 587));
|
|
||||||
|
|
||||||
for (Server imap : imaps)
|
if (imap == null)
|
||||||
if (imap.reachable.get())
|
throw new UnknownHostException(domain + " template");
|
||||||
for (Server smtp : smtps)
|
}
|
||||||
if (smtp.reachable.get()) {
|
|
||||||
EmailProvider provider = new EmailProvider();
|
|
||||||
provider.name = domain;
|
|
||||||
|
|
||||||
provider.imap_host = imap.host;
|
if (discover == Discover.ALL || discover == Discover.SMTP) {
|
||||||
provider.imap_port = imap.port;
|
List<Server> smtps = new ArrayList<>();
|
||||||
provider.imap_starttls = (imap.port == 143);
|
// SSL
|
||||||
|
smtps.add(new Server(domain, null, 465));
|
||||||
|
smtps.add(new Server(domain, "smtp", 465));
|
||||||
|
smtps.add(new Server(domain, "mail", 465));
|
||||||
|
smtps.add(new Server(domain, "mx", 465));
|
||||||
|
// STARTTLS
|
||||||
|
smtps.add(new Server(domain, null, 587));
|
||||||
|
smtps.add(new Server(domain, "smtp", 587));
|
||||||
|
smtps.add(new Server(domain, "mail", 587));
|
||||||
|
smtps.add(new Server(domain, "mx", 587));
|
||||||
|
|
||||||
provider.smtp_host = smtp.host;
|
for (Server server : smtps)
|
||||||
provider.smtp_port = smtp.port;
|
if (server.reachable.get()) {
|
||||||
provider.smtp_starttls = (smtp.port == 587);
|
smtp = server;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return provider;
|
if (smtp == null)
|
||||||
}
|
throw new UnknownHostException(domain + " template");
|
||||||
|
}
|
||||||
|
|
||||||
throw new UnknownHostException(domain + " template");
|
|
||||||
|
EmailProvider provider = new EmailProvider();
|
||||||
|
provider.name = domain;
|
||||||
|
|
||||||
|
if (imap != null) {
|
||||||
|
provider.imap_host = imap.host;
|
||||||
|
provider.imap_port = imap.port;
|
||||||
|
provider.imap_starttls = (imap.port == 143);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (smtp != null) {
|
||||||
|
provider.smtp_host = smtp.host;
|
||||||
|
provider.smtp_port = smtp.port;
|
||||||
|
provider.smtp_starttls = (smtp.port == 587);
|
||||||
|
}
|
||||||
|
|
||||||
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addDocumentation(EmailProvider provider, String href, String title) {
|
private static void addDocumentation(EmailProvider provider, String href, String title) {
|
||||||
|
|
|
@ -443,7 +443,7 @@ public class FragmentAccount extends FragmentBase {
|
||||||
@Override
|
@Override
|
||||||
protected EmailProvider onExecute(Context context, Bundle args) throws Throwable {
|
protected EmailProvider onExecute(Context context, Bundle args) throws Throwable {
|
||||||
String domain = args.getString("domain");
|
String domain = args.getString("domain");
|
||||||
return EmailProvider.fromDomain(context, domain);
|
return EmailProvider.fromDomain(context, domain, EmailProvider.Discover.IMAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -472,7 +472,7 @@ public class FragmentIdentity extends FragmentBase {
|
||||||
@Override
|
@Override
|
||||||
protected EmailProvider onExecute(Context context, Bundle args) throws Throwable {
|
protected EmailProvider onExecute(Context context, Bundle args) throws Throwable {
|
||||||
String domain = args.getString("domain");
|
String domain = args.getString("domain");
|
||||||
return EmailProvider.fromDomain(context, domain);
|
return EmailProvider.fromDomain(context, domain, EmailProvider.Discover.SMTP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -235,7 +235,7 @@ public class FragmentQuickSetup extends FragmentBase {
|
||||||
throw new IllegalArgumentException(context.getString(R.string.title_email_invalid));
|
throw new IllegalArgumentException(context.getString(R.string.title_email_invalid));
|
||||||
|
|
||||||
String[] dparts = email.split("@");
|
String[] dparts = email.split("@");
|
||||||
EmailProvider provider = EmailProvider.fromDomain(context, dparts[1]);
|
EmailProvider provider = EmailProvider.fromDomain(context, dparts[1], EmailProvider.Discover.ALL);
|
||||||
|
|
||||||
if (provider.link != null)
|
if (provider.link != null)
|
||||||
args.putString("link", provider.link);
|
args.putString("link", provider.link);
|
||||||
|
|
Loading…
Reference in New Issue