mirror of
https://github.com/M66B/FairEmail.git
synced 2026-01-05 12:24:26 +01:00
Added Mozilla ISPDB lookup
This commit is contained in:
@@ -133,6 +133,7 @@ FairEmail uses:
|
||||
* [OpenPGP API library](https://github.com/open-keychain/openpgp-api). Copyright (C) 2014-2015 Dominik Schürmann. [Apache License 2.0](https://github.com/open-keychain/openpgp-api/blob/master/LICENSE).
|
||||
* [Android SQLite support library](https://github.com/requery/sqlite-android). Copyright (C) 2017 requery.io. [Apache License 2.0](https://github.com/requery/sqlite-android/blob/master/LICENSE).
|
||||
* [App shortcut icon generator](https://romannurik.github.io/AndroidAssetStudio/icons-app-shortcut.html). Copyright ???. [Apache License 2.0](https://github.com/romannurik/AndroidAssetStudio/blob/master/LICENSE).
|
||||
* [Mozilla ISPDB](https://developer.mozilla.org/en-US/docs/Mozilla/Thunderbird/Autoconfiguration#ISPDB). *Free to use for any client.*
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -62,12 +62,7 @@ import com.google.android.material.textfield.TextInputLayout;
|
||||
import com.sun.mail.imap.IMAPFolder;
|
||||
import com.sun.mail.imap.IMAPStore;
|
||||
|
||||
import org.xbill.DNS.Lookup;
|
||||
import org.xbill.DNS.Record;
|
||||
import org.xbill.DNS.SRVRecord;
|
||||
import org.xbill.DNS.SimpleResolver;
|
||||
import org.xbill.DNS.Type;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@@ -267,53 +262,40 @@ public class FragmentAccount extends FragmentEx {
|
||||
btnAutoConfig.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
etDomain.setEnabled(false);
|
||||
btnAutoConfig.setEnabled(false);
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putString("domain", etDomain.getText().toString());
|
||||
|
||||
new SimpleTask<SRVRecord>() {
|
||||
new SimpleTask<Provider>() {
|
||||
@Override
|
||||
protected SRVRecord onLoad(Context context, Bundle args) throws Throwable {
|
||||
// https://tools.ietf.org/html/rfc6186
|
||||
String dns = "_imaps._tcp." + args.getString("domain");
|
||||
Lookup lookup = new Lookup(dns, Type.SRV);
|
||||
// https://dns.watch/
|
||||
SimpleResolver resolver = new SimpleResolver("84.200.69.80");
|
||||
lookup.setResolver(resolver);
|
||||
Log.i("Lookup dns=" + dns + " @" + resolver.getAddress());
|
||||
Record[] records = lookup.run();
|
||||
if (lookup.getResult() != Lookup.SUCCESSFUL)
|
||||
throw new IllegalArgumentException(lookup.getErrorString());
|
||||
Log.i("Found dns=" + (records == null ? -1 : records.length));
|
||||
if (records != null)
|
||||
for (int i = 0; i < records.length; i++) {
|
||||
SRVRecord srv = (SRVRecord) records[i];
|
||||
Log.i("SRV=" + srv);
|
||||
return srv;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(getString(R.string.title_no_settings));
|
||||
protected void onInit(Bundle args) {
|
||||
etDomain.setEnabled(false);
|
||||
btnAutoConfig.setEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLoaded(Bundle args, SRVRecord srv) {
|
||||
protected void onCleanup(Bundle args) {
|
||||
etDomain.setEnabled(true);
|
||||
btnAutoConfig.setEnabled(true);
|
||||
if (srv != null) {
|
||||
etHost.setText(srv.getTarget().toString(true));
|
||||
etPort.setText(Integer.toString(srv.getPort()));
|
||||
cbStartTls.setChecked(srv.getPort() == 143);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Provider onLoad(Context context, Bundle args) throws Throwable {
|
||||
String domain = args.getString("domain");
|
||||
return Provider.fromDomain(context, domain);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLoaded(Bundle args, Provider provider) {
|
||||
etHost.setText(provider.imap_host);
|
||||
etPort.setText(Integer.toString(provider.imap_port));
|
||||
cbStartTls.setChecked(provider.imap_starttls);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onException(Bundle args, Throwable ex) {
|
||||
etDomain.setEnabled(true);
|
||||
btnAutoConfig.setEnabled(true);
|
||||
if (ex instanceof IllegalArgumentException)
|
||||
Snackbar.make(view, ex.getMessage(), Snackbar.LENGTH_LONG).show();
|
||||
if (ex instanceof IOException)
|
||||
Snackbar.make(view, R.string.title_no_settings, Snackbar.LENGTH_LONG).show();
|
||||
else
|
||||
Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex);
|
||||
}
|
||||
|
||||
@@ -58,12 +58,7 @@ import com.android.colorpicker.ColorPickerSwatch;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
|
||||
import org.xbill.DNS.Lookup;
|
||||
import org.xbill.DNS.Record;
|
||||
import org.xbill.DNS.SRVRecord;
|
||||
import org.xbill.DNS.SimpleResolver;
|
||||
import org.xbill.DNS.Type;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
@@ -364,47 +359,36 @@ public class FragmentIdentity extends FragmentEx {
|
||||
Bundle args = new Bundle();
|
||||
args.putString("domain", etDomain.getText().toString());
|
||||
|
||||
new SimpleTask<SRVRecord>() {
|
||||
new SimpleTask<Provider>() {
|
||||
@Override
|
||||
protected SRVRecord onLoad(Context context, Bundle args) throws Throwable {
|
||||
// https://tools.ietf.org/html/rfc6186
|
||||
String dns = "_submission._tcp." + args.getString("domain");
|
||||
Lookup lookup = new Lookup(dns, Type.SRV);
|
||||
// https://dns.watch/
|
||||
SimpleResolver resolver = new SimpleResolver("84.200.69.80");
|
||||
lookup.setResolver(resolver);
|
||||
Log.i("Lookup dns=" + dns + " @" + resolver.getAddress());
|
||||
Record[] records = lookup.run();
|
||||
if (lookup.getResult() != Lookup.SUCCESSFUL)
|
||||
throw new IllegalArgumentException(lookup.getErrorString());
|
||||
Log.i("Found dns=" + (records == null ? -1 : records.length));
|
||||
if (records != null)
|
||||
for (int i = 0; i < records.length; i++) {
|
||||
SRVRecord srv = (SRVRecord) records[i];
|
||||
Log.i("SRV=" + srv);
|
||||
return srv;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(getString(R.string.title_no_settings));
|
||||
protected void onInit(Bundle args) {
|
||||
etDomain.setEnabled(false);
|
||||
btnAutoConfig.setEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLoaded(Bundle args, SRVRecord srv) {
|
||||
protected void onCleanup(Bundle args) {
|
||||
etDomain.setEnabled(true);
|
||||
btnAutoConfig.setEnabled(true);
|
||||
if (srv != null) {
|
||||
etHost.setText(srv.getTarget().toString(true));
|
||||
etPort.setText(Integer.toString(srv.getPort()));
|
||||
cbStartTls.setChecked(srv.getPort() == 587);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Provider onLoad(Context context, Bundle args) throws Throwable {
|
||||
String domain = args.getString("domain");
|
||||
return Provider.fromDomain(context, domain);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLoaded(Bundle args, Provider provider) {
|
||||
etHost.setText(provider.smtp_host);
|
||||
etPort.setText(Integer.toString(provider.smtp_port));
|
||||
cbStartTls.setChecked(provider.smtp_starttls);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onException(Bundle args, Throwable ex) {
|
||||
etDomain.setEnabled(true);
|
||||
btnAutoConfig.setEnabled(true);
|
||||
if (ex instanceof IllegalArgumentException)
|
||||
Snackbar.make(view, ex.getMessage(), Snackbar.LENGTH_LONG).show();
|
||||
if (ex instanceof IOException)
|
||||
Snackbar.make(view, R.string.title_no_settings, Snackbar.LENGTH_LONG).show();
|
||||
else
|
||||
Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex);
|
||||
}
|
||||
|
||||
@@ -22,8 +22,21 @@ package eu.faircode.email;
|
||||
import android.content.Context;
|
||||
import android.content.res.XmlResourceParser;
|
||||
|
||||
import org.xbill.DNS.Lookup;
|
||||
import org.xbill.DNS.Record;
|
||||
import org.xbill.DNS.SRVRecord;
|
||||
import org.xbill.DNS.SimpleResolver;
|
||||
import org.xbill.DNS.TextParseException;
|
||||
import org.xbill.DNS.Type;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlPullParserFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -54,9 +67,9 @@ public class Provider {
|
||||
static List<Provider> loadProfiles(Context context) {
|
||||
List<Provider> result = null;
|
||||
try {
|
||||
Provider provider = null;
|
||||
XmlResourceParser xml = context.getResources().getXml(R.xml.providers);
|
||||
int eventType = xml.getEventType();
|
||||
Provider provider = null;
|
||||
while (eventType != XmlPullParser.END_DOCUMENT) {
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
if ("providers".equals(xml.getName()))
|
||||
@@ -107,6 +120,145 @@ public class Provider {
|
||||
return result;
|
||||
}
|
||||
|
||||
static Provider fromDomain(Context context, String domain) throws IOException, XmlPullParserException {
|
||||
try {
|
||||
return Provider.fromDNS(context, domain);
|
||||
} catch (TextParseException ex) {
|
||||
Log.w(ex);
|
||||
throw new UnknownHostException(domain);
|
||||
} catch (UnknownHostException ex) {
|
||||
Log.w(ex);
|
||||
return Provider.fromConfig(context, domain);
|
||||
}
|
||||
}
|
||||
|
||||
private static Provider fromConfig(Context context, String domain) throws IOException, XmlPullParserException {
|
||||
// https://wiki.mozilla.org/Thunderbird:Autoconfiguration:ConfigFileFormat
|
||||
URL url = new URL("https://autoconfig.thunderbird.net/v1.1/" + domain);
|
||||
Log.i("Fetching " + url);
|
||||
|
||||
HttpURLConnection request = (HttpURLConnection) url.openConnection();
|
||||
request.setReadTimeout(20 * 1000);
|
||||
request.setConnectTimeout(20 * 1000);
|
||||
request.setRequestMethod("GET");
|
||||
request.setDoInput(true);
|
||||
request.connect();
|
||||
|
||||
// https://developer.android.com/reference/org/xmlpull/v1/XmlPullParser
|
||||
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
|
||||
XmlPullParser xml = factory.newPullParser();
|
||||
xml.setInput(new InputStreamReader(request.getInputStream()));
|
||||
|
||||
boolean imap = false;
|
||||
boolean smtp = false;
|
||||
Provider provider = new Provider(domain);
|
||||
int eventType = xml.getEventType();
|
||||
while (eventType != XmlPullParser.END_DOCUMENT) {
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
if ("incomingServer".equals(xml.getName()))
|
||||
imap = "imap".equals(xml.getAttributeValue(null, "type"));
|
||||
|
||||
else if ("outgoingServer".equals(xml.getName()))
|
||||
smtp = "smtp".equals(xml.getAttributeValue(null, "type"));
|
||||
|
||||
else if ("hostname".equals(xml.getName())) {
|
||||
eventType = xml.next();
|
||||
if (eventType == XmlPullParser.TEXT) {
|
||||
String host = xml.getText();
|
||||
Log.i("Host=" + host);
|
||||
if (imap)
|
||||
provider.imap_host = host;
|
||||
else if (smtp)
|
||||
provider.smtp_host = host;
|
||||
}
|
||||
continue;
|
||||
|
||||
} else if ("port".equals(xml.getName())) {
|
||||
eventType = xml.next();
|
||||
if (eventType == XmlPullParser.TEXT) {
|
||||
String port = xml.getText();
|
||||
Log.i("Port=" + port);
|
||||
if (imap) {
|
||||
provider.imap_port = Integer.parseInt(port);
|
||||
provider.imap_starttls = (provider.imap_port == 143);
|
||||
} else if (smtp) {
|
||||
provider.smtp_port = Integer.parseInt(port);
|
||||
provider.smtp_starttls = (provider.smtp_port == 587);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
|
||||
} else if ("socketType".equals(xml.getName())) {
|
||||
eventType = xml.next();
|
||||
if (eventType == XmlPullParser.TEXT) {
|
||||
String socket = xml.getText();
|
||||
Log.i("Socket=" + socket);
|
||||
if ("SSL".equals(socket)) {
|
||||
if (imap)
|
||||
provider.imap_starttls = false;
|
||||
else if (smtp)
|
||||
provider.smtp_starttls = false;
|
||||
} else if ("STARTTLS".equals(socket)) {
|
||||
if (imap)
|
||||
provider.imap_starttls = true;
|
||||
else if (smtp)
|
||||
provider.smtp_starttls = true;
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
} else if (eventType == XmlPullParser.END_TAG) {
|
||||
if ("incomingServer".equals(xml.getName()))
|
||||
imap = false;
|
||||
else if ("outgoingServer".equals(xml.getName()))
|
||||
smtp = false;
|
||||
}
|
||||
|
||||
eventType = xml.next();
|
||||
}
|
||||
|
||||
request.disconnect();
|
||||
|
||||
Log.i("imap=" + provider.imap_host + ":" + provider.imap_port + ":" + provider.imap_starttls);
|
||||
Log.i("smtp=" + provider.smtp_host + ":" + provider.smtp_port + ":" + provider.smtp_starttls);
|
||||
return provider;
|
||||
}
|
||||
|
||||
private static Provider fromDNS(Context context, String domain) throws TextParseException, UnknownHostException {
|
||||
// https://tools.ietf.org/html/rfc6186
|
||||
SRVRecord imap = lookup("_imaps._tcp." + domain);
|
||||
SRVRecord smtp = lookup("_submission._tcp." + domain);
|
||||
|
||||
Provider provider = new Provider(domain);
|
||||
provider.imap_host = imap.getTarget().toString(true);
|
||||
provider.imap_port = imap.getPort();
|
||||
provider.imap_starttls = (provider.imap_port == 143);
|
||||
|
||||
provider.smtp_host = smtp.getTarget().toString(true);
|
||||
provider.smtp_port = smtp.getPort();
|
||||
provider.smtp_starttls = (provider.smtp_port == 587);
|
||||
|
||||
return provider;
|
||||
}
|
||||
|
||||
private static SRVRecord lookup(String dns) throws TextParseException, UnknownHostException {
|
||||
Lookup lookup = new Lookup(dns, Type.SRV);
|
||||
|
||||
// https://dns.watch/
|
||||
SimpleResolver resolver = new SimpleResolver("84.200.69.80");
|
||||
lookup.setResolver(resolver);
|
||||
Log.i("Lookup dns=" + dns + " @" + resolver.getAddress());
|
||||
Record[] records = lookup.run();
|
||||
if (lookup.getResult() != Lookup.SUCCESSFUL)
|
||||
if (lookup.getResult() == Lookup.HOST_NOT_FOUND)
|
||||
throw new UnknownHostException(dns);
|
||||
else
|
||||
throw new IllegalArgumentException(lookup.getErrorString());
|
||||
Log.i("Found dns=" + (records == null ? -1 : records.length));
|
||||
return (records == null || records.length == 0 ? null : (SRVRecord) records[0]);
|
||||
}
|
||||
|
||||
public int getAuthType() {
|
||||
if ("com.google".equals(type))
|
||||
return Helper.AUTH_TYPE_GMAIL;
|
||||
|
||||
Reference in New Issue
Block a user