2019-07-29 09:17:12 +00:00
|
|
|
package eu.faircode.email;
|
|
|
|
|
2019-09-18 14:34:07 +00:00
|
|
|
import android.accounts.Account;
|
|
|
|
import android.accounts.AccountManager;
|
2019-07-29 09:17:12 +00:00
|
|
|
import android.content.Context;
|
2019-10-21 11:26:15 +00:00
|
|
|
import android.content.SharedPreferences;
|
2019-09-18 14:34:07 +00:00
|
|
|
import android.text.TextUtils;
|
2019-07-29 09:17:12 +00:00
|
|
|
|
2019-10-21 11:26:15 +00:00
|
|
|
import androidx.preference.PreferenceManager;
|
|
|
|
|
2019-09-18 14:34:07 +00:00
|
|
|
import com.sun.mail.imap.IMAPFolder;
|
2019-07-29 09:17:12 +00:00
|
|
|
import com.sun.mail.imap.IMAPStore;
|
|
|
|
import com.sun.mail.smtp.SMTPTransport;
|
|
|
|
import com.sun.mail.util.MailConnectException;
|
|
|
|
|
|
|
|
import java.net.Inet4Address;
|
|
|
|
import java.net.Inet6Address;
|
|
|
|
import java.net.InetAddress;
|
|
|
|
import java.net.UnknownHostException;
|
2019-09-18 14:34:07 +00:00
|
|
|
import java.util.ArrayList;
|
2019-11-08 17:07:06 +00:00
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.Collections;
|
2019-07-29 09:17:12 +00:00
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.LinkedHashMap;
|
2019-09-18 14:34:07 +00:00
|
|
|
import java.util.List;
|
2019-07-29 09:17:12 +00:00
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Properties;
|
2019-07-30 18:53:37 +00:00
|
|
|
import java.util.concurrent.ExecutorService;
|
2019-07-29 09:17:12 +00:00
|
|
|
|
2019-09-18 14:34:07 +00:00
|
|
|
import javax.mail.AuthenticationFailedException;
|
|
|
|
import javax.mail.Folder;
|
2019-07-29 09:17:12 +00:00
|
|
|
import javax.mail.MessagingException;
|
|
|
|
import javax.mail.NoSuchProviderException;
|
|
|
|
import javax.mail.Service;
|
|
|
|
import javax.mail.Session;
|
2019-09-19 15:41:26 +00:00
|
|
|
import javax.mail.Store;
|
2019-07-29 09:17:12 +00:00
|
|
|
|
|
|
|
public class MailService implements AutoCloseable {
|
|
|
|
private Context context;
|
|
|
|
private String protocol;
|
2019-07-30 16:50:42 +00:00
|
|
|
private boolean useip;
|
2019-07-29 09:17:12 +00:00
|
|
|
private boolean debug;
|
|
|
|
private Properties properties;
|
|
|
|
private Session isession;
|
|
|
|
private Service iservice;
|
|
|
|
|
2019-10-10 11:26:44 +00:00
|
|
|
private ExecutorService executor = Helper.getBackgroundExecutor(0, "mail");
|
2019-07-30 18:53:37 +00:00
|
|
|
|
2019-09-18 14:34:07 +00:00
|
|
|
static final int AUTH_TYPE_PASSWORD = 1;
|
|
|
|
static final int AUTH_TYPE_GMAIL = 2;
|
2019-10-20 16:25:21 +00:00
|
|
|
static final int AUTH_TYPE_OUTLOOK = 3;
|
2019-09-18 14:34:07 +00:00
|
|
|
|
2019-10-19 08:05:43 +00:00
|
|
|
private final static int CHECK_TIMEOUT = 15 * 1000; // milliseconds
|
2019-07-29 14:42:17 +00:00
|
|
|
private final static int CONNECT_TIMEOUT = 20 * 1000; // milliseconds
|
|
|
|
private final static int WRITE_TIMEOUT = 60 * 1000; // milliseconds
|
|
|
|
private final static int READ_TIMEOUT = 60 * 1000; // milliseconds
|
|
|
|
private final static int FETCH_SIZE = 256 * 1024; // bytes, default 16K
|
|
|
|
private final static int POOL_TIMEOUT = 45 * 1000; // milliseconds, default 45 sec
|
|
|
|
|
|
|
|
private static final int APPEND_BUFFER_SIZE = 4 * 1024 * 1024; // bytes
|
|
|
|
|
2019-07-29 09:17:12 +00:00
|
|
|
private MailService() {
|
|
|
|
}
|
|
|
|
|
2019-10-19 08:05:43 +00:00
|
|
|
MailService(Context context, String protocol, String realm, boolean insecure, boolean check, boolean debug) throws NoSuchProviderException {
|
2019-07-29 14:42:17 +00:00
|
|
|
this.context = context.getApplicationContext();
|
2019-07-29 09:17:12 +00:00
|
|
|
this.protocol = protocol;
|
|
|
|
this.debug = debug;
|
2019-10-03 09:39:14 +00:00
|
|
|
|
2019-07-30 16:53:18 +00:00
|
|
|
properties = MessageHelper.getSessionProperties();
|
2019-07-29 14:42:17 +00:00
|
|
|
|
2019-10-21 11:26:15 +00:00
|
|
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
|
|
|
boolean socks_enabled = prefs.getBoolean("socks_enabled", false);
|
|
|
|
String socks_proxy = prefs.getString("socks_proxy", "localhost:9050");
|
|
|
|
|
|
|
|
// SOCKS proxy
|
|
|
|
if (socks_enabled) {
|
|
|
|
String[] address = socks_proxy.split(":");
|
|
|
|
String host = (address.length > 0 ? address[0] : null);
|
|
|
|
String port = (address.length > 1 ? address[1] : null);
|
|
|
|
if (TextUtils.isEmpty(host))
|
|
|
|
host = "localhost";
|
|
|
|
if (TextUtils.isEmpty(port))
|
|
|
|
port = "9050";
|
|
|
|
properties.put("mail." + protocol + ".socks.host", host);
|
|
|
|
properties.put("mail." + protocol + ".socks.port", port);
|
|
|
|
Log.i("Using SOCKS proxy=" + host + ":" + port);
|
|
|
|
}
|
|
|
|
|
2019-07-30 16:53:18 +00:00
|
|
|
properties.put("mail.event.scope", "folder");
|
2019-07-30 18:53:37 +00:00
|
|
|
properties.put("mail.event.executor", executor);
|
2019-07-29 14:42:17 +00:00
|
|
|
|
2019-09-29 18:25:01 +00:00
|
|
|
properties.put("mail." + protocol + ".sasl.realm", realm == null ? "" : realm);
|
|
|
|
properties.put("mail." + protocol + ".auth.ntlm.domain", realm == null ? "" : realm);
|
|
|
|
|
2019-10-19 08:05:43 +00:00
|
|
|
// TODO: make timeouts configurable?
|
|
|
|
properties.put("mail." + protocol + ".connectiontimeout", Integer.toString(check ? CHECK_TIMEOUT : CONNECT_TIMEOUT));
|
|
|
|
properties.put("mail." + protocol + ".writetimeout", Integer.toString(check ? CHECK_TIMEOUT : WRITE_TIMEOUT)); // one thread overhead
|
|
|
|
properties.put("mail." + protocol + ".timeout", Integer.toString(check ? CHECK_TIMEOUT : READ_TIMEOUT));
|
|
|
|
|
2019-10-03 09:39:14 +00:00
|
|
|
if (debug && BuildConfig.DEBUG)
|
|
|
|
properties.put("mail.debug.auth", "true");
|
2019-07-29 14:42:17 +00:00
|
|
|
|
2019-09-19 15:41:26 +00:00
|
|
|
if ("pop3".equals(protocol) || "pop3s".equals(protocol)) {
|
2019-09-20 07:45:36 +00:00
|
|
|
this.debug = true;
|
|
|
|
|
2019-09-19 15:41:26 +00:00
|
|
|
// https://javaee.github.io/javamail/docs/api/com/sun/mail/pop3/package-summary.html#properties
|
2019-10-03 09:39:14 +00:00
|
|
|
properties.put("mail." + protocol + ".ssl.checkserveridentity", Boolean.toString(!insecure));
|
2019-09-19 15:41:26 +00:00
|
|
|
properties.put("mail." + protocol + ".ssl.trust", "*");
|
|
|
|
|
|
|
|
properties.put("mail.pop3s.starttls.enable", "false");
|
|
|
|
|
|
|
|
properties.put("mail.pop3.starttls.enable", "true");
|
2019-10-03 09:39:14 +00:00
|
|
|
properties.put("mail.pop3.starttls.required", Boolean.toString(!insecure));
|
2019-09-19 15:41:26 +00:00
|
|
|
|
|
|
|
} else if ("imap".equals(protocol) || "imaps".equals(protocol)) {
|
2019-07-29 14:42:17 +00:00
|
|
|
// https://javaee.github.io/javamail/docs/api/com/sun/mail/imap/package-summary.html#properties
|
2019-10-03 09:39:14 +00:00
|
|
|
properties.put("mail." + protocol + ".ssl.checkserveridentity", Boolean.toString(!insecure));
|
2019-07-30 16:53:18 +00:00
|
|
|
properties.put("mail." + protocol + ".ssl.trust", "*");
|
2019-07-29 14:42:17 +00:00
|
|
|
|
2019-07-30 16:53:18 +00:00
|
|
|
properties.put("mail.imaps.starttls.enable", "false");
|
2019-07-29 14:42:17 +00:00
|
|
|
|
2019-07-30 16:53:18 +00:00
|
|
|
properties.put("mail.imap.starttls.enable", "true");
|
2019-10-03 09:39:14 +00:00
|
|
|
properties.put("mail.imap.starttls.required", Boolean.toString(!insecure));
|
2019-07-29 14:42:17 +00:00
|
|
|
|
2019-07-30 16:53:18 +00:00
|
|
|
properties.put("mail." + protocol + ".connectionpool.debug", "true");
|
2019-12-09 13:03:18 +00:00
|
|
|
properties.put("mail." + protocol + ".connectionpoolsize", "1");
|
2019-07-30 16:53:18 +00:00
|
|
|
properties.put("mail." + protocol + ".connectionpooltimeout", Integer.toString(POOL_TIMEOUT));
|
2019-07-29 14:42:17 +00:00
|
|
|
|
2019-07-30 16:53:18 +00:00
|
|
|
properties.put("mail." + protocol + ".finalizecleanclose", "false");
|
2019-10-13 07:54:13 +00:00
|
|
|
//properties.put("mail." + protocol + ".closefoldersonstorefailure", "false");
|
2019-07-29 14:42:17 +00:00
|
|
|
|
|
|
|
// https://tools.ietf.org/html/rfc4978
|
|
|
|
// https://docs.oracle.com/javase/8/docs/api/java/util/zip/Deflater.html
|
2019-07-30 16:53:18 +00:00
|
|
|
properties.put("mail." + protocol + ".compress.enable", "true");
|
|
|
|
//properties.put("mail.imaps.compress.level", "-1");
|
|
|
|
//properties.put("mail.imaps.compress.strategy", "0");
|
2019-07-29 14:42:17 +00:00
|
|
|
|
2019-07-30 16:53:18 +00:00
|
|
|
properties.put("mail." + protocol + ".throwsearchexception", "true");
|
|
|
|
properties.put("mail." + protocol + ".fetchsize", Integer.toString(FETCH_SIZE));
|
|
|
|
properties.put("mail." + protocol + ".peek", "true");
|
|
|
|
properties.put("mail." + protocol + ".appendbuffersize", Integer.toString(APPEND_BUFFER_SIZE));
|
2019-07-29 14:42:17 +00:00
|
|
|
|
|
|
|
} else if ("smtp".equals(protocol) || "smtps".equals(protocol)) {
|
|
|
|
// https://javaee.github.io/javamail/docs/api/com/sun/mail/smtp/package-summary.html#properties
|
2019-10-03 09:39:14 +00:00
|
|
|
properties.put("mail." + protocol + ".ssl.checkserveridentity", Boolean.toString(!insecure));
|
2019-07-30 16:53:18 +00:00
|
|
|
properties.put("mail." + protocol + ".ssl.trust", "*");
|
2019-07-29 14:42:17 +00:00
|
|
|
|
2019-07-30 16:53:18 +00:00
|
|
|
properties.put("mail.smtps.starttls.enable", "false");
|
2019-07-29 14:42:17 +00:00
|
|
|
|
2019-07-30 16:53:18 +00:00
|
|
|
properties.put("mail.smtp.starttls.enable", "true");
|
2019-10-03 09:39:14 +00:00
|
|
|
properties.put("mail.smtp.starttls.required", Boolean.toString(!insecure));
|
2019-07-29 14:42:17 +00:00
|
|
|
|
2019-07-30 16:53:18 +00:00
|
|
|
properties.put("mail." + protocol + ".auth", "true");
|
2019-07-29 14:42:17 +00:00
|
|
|
|
|
|
|
} else
|
|
|
|
throw new NoSuchProviderException(protocol);
|
2019-07-29 09:17:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void setPartialFetch(boolean enabled) {
|
2019-10-09 12:01:26 +00:00
|
|
|
properties.put("mail." + protocol + ".partialfetch", Boolean.toString(enabled));
|
|
|
|
}
|
|
|
|
|
|
|
|
void setIgnoreBodyStructureSize(boolean enabled) {
|
|
|
|
properties.put("mail." + protocol + ".ignorebodystructuresize", Boolean.toString(enabled));
|
2019-07-29 09:17:12 +00:00
|
|
|
}
|
|
|
|
|
2019-07-30 16:50:42 +00:00
|
|
|
void setUseIp(boolean enabled) {
|
2019-07-30 16:53:18 +00:00
|
|
|
useip = enabled;
|
2019-07-29 09:17:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void setSeparateStoreConnection() {
|
2019-07-30 16:53:18 +00:00
|
|
|
properties.put("mail." + protocol + ".separatestoreconnection", "true");
|
2019-07-29 09:17:12 +00:00
|
|
|
}
|
|
|
|
|
2019-09-25 11:26:56 +00:00
|
|
|
void setLeaveOnServer(boolean keep) {
|
|
|
|
properties.put("mail." + protocol + ".rsetbeforequit", Boolean.toString(keep));
|
|
|
|
}
|
|
|
|
|
2019-07-29 09:17:12 +00:00
|
|
|
public void connect(EntityAccount account) throws MessagingException {
|
2019-09-19 11:21:37 +00:00
|
|
|
String password = connect(account.host, account.port, account.auth_type, account.user, account.password);
|
|
|
|
if (password != null) {
|
|
|
|
DB db = DB.getInstance(context);
|
|
|
|
int count = db.account().setAccountPassword(account.id, account.password);
|
|
|
|
Log.i(account.name + " token refreshed=" + count);
|
|
|
|
}
|
2019-07-29 09:17:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void connect(EntityIdentity identity) throws MessagingException {
|
2019-09-19 11:21:37 +00:00
|
|
|
String password = connect(identity.host, identity.port, identity.auth_type, identity.user, identity.password);
|
|
|
|
if (password != null) {
|
|
|
|
DB db = DB.getInstance(context);
|
|
|
|
int count = db.identity().setIdentityPassword(identity.id, identity.password);
|
|
|
|
Log.i(identity.email + " token refreshed=" + count);
|
|
|
|
}
|
2019-07-29 09:17:12 +00:00
|
|
|
}
|
|
|
|
|
2019-09-19 11:21:37 +00:00
|
|
|
public String connect(String host, int port, int auth, String user, String password) throws MessagingException {
|
2019-07-29 09:17:12 +00:00
|
|
|
try {
|
2019-10-20 16:25:21 +00:00
|
|
|
if (auth == AUTH_TYPE_GMAIL || auth == AUTH_TYPE_OUTLOOK)
|
2019-09-18 14:34:07 +00:00
|
|
|
properties.put("mail." + protocol + ".auth.mechanisms", "XOAUTH2");
|
|
|
|
|
2019-07-29 16:23:25 +00:00
|
|
|
//if (BuildConfig.DEBUG)
|
|
|
|
// throw new MailConnectException(new SocketConnectException("Debug", new Exception(), host, port, 0));
|
2019-09-18 14:34:07 +00:00
|
|
|
|
2019-07-29 09:17:12 +00:00
|
|
|
_connect(context, host, port, user, password);
|
2019-09-19 11:21:37 +00:00
|
|
|
return null;
|
2019-09-18 14:34:07 +00:00
|
|
|
} catch (AuthenticationFailedException ex) {
|
|
|
|
// Refresh token
|
|
|
|
if (auth == AUTH_TYPE_GMAIL)
|
|
|
|
try {
|
|
|
|
String type = "com.google";
|
|
|
|
AccountManager am = AccountManager.get(context);
|
|
|
|
Account[] accounts = am.getAccountsByType(type);
|
|
|
|
for (Account account : accounts)
|
|
|
|
if (user.equals(account.name)) {
|
|
|
|
Log.i("Refreshing token user=" + user);
|
|
|
|
am.invalidateAuthToken(type, password);
|
2019-09-18 20:11:48 +00:00
|
|
|
String token = am.blockingGetAuthToken(account, getAuthTokenType(type), true);
|
|
|
|
if (token == null)
|
2019-09-24 12:52:46 +00:00
|
|
|
throw new IllegalArgumentException("No token on refresh");
|
2019-09-18 14:34:07 +00:00
|
|
|
|
2019-09-18 20:11:48 +00:00
|
|
|
_connect(context, host, port, user, token);
|
2019-09-19 11:21:37 +00:00
|
|
|
return token;
|
2019-09-18 14:34:07 +00:00
|
|
|
}
|
2019-09-19 11:21:37 +00:00
|
|
|
|
2019-09-24 12:52:46 +00:00
|
|
|
throw new IllegalArgumentException("Account not found");
|
2019-09-24 13:34:39 +00:00
|
|
|
} catch (Exception ex1) {
|
2019-09-18 14:34:07 +00:00
|
|
|
Log.e(ex1);
|
2019-09-24 13:34:39 +00:00
|
|
|
throw new AuthenticationFailedException(ex.getMessage(), ex1);
|
2019-09-18 14:34:07 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
throw ex;
|
2019-07-29 09:17:12 +00:00
|
|
|
} catch (MailConnectException ex) {
|
2019-07-30 15:33:20 +00:00
|
|
|
try {
|
|
|
|
// Some devices resolve IPv6 addresses while not having IPv6 connectivity
|
2019-07-30 16:53:18 +00:00
|
|
|
properties.put("mail." + protocol + ".ssl.checkserveridentity", "false");
|
2019-07-30 15:33:20 +00:00
|
|
|
InetAddress[] iaddrs = InetAddress.getAllByName(host);
|
|
|
|
if (iaddrs.length > 1)
|
|
|
|
for (InetAddress iaddr : iaddrs)
|
|
|
|
try {
|
|
|
|
Log.i("Falling back to " + iaddr.getHostAddress());
|
|
|
|
_connect(context, iaddr.getHostAddress(), port, user, password);
|
2019-09-19 11:21:37 +00:00
|
|
|
return null;
|
2019-07-30 15:33:20 +00:00
|
|
|
} catch (MessagingException ex1) {
|
|
|
|
Log.w(ex1);
|
|
|
|
}
|
|
|
|
} catch (Throwable ex1) {
|
|
|
|
Log.w(ex1);
|
|
|
|
}
|
2019-07-29 14:23:25 +00:00
|
|
|
|
|
|
|
throw ex;
|
2019-07-29 09:17:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void _connect(Context context, String host, int port, String user, String password) throws MessagingException {
|
|
|
|
isession = Session.getInstance(properties, null);
|
|
|
|
isession.setDebug(debug);
|
|
|
|
//System.setProperty("mail.socket.debug", Boolean.toString(debug));
|
|
|
|
|
2019-09-19 15:41:26 +00:00
|
|
|
if ("pop3".equals(protocol) || "pop3s".equals(protocol)) {
|
2019-09-27 13:04:16 +00:00
|
|
|
isession.setDebug(true);
|
2019-09-19 15:41:26 +00:00
|
|
|
iservice = isession.getStore(protocol);
|
|
|
|
iservice.connect(host, port, user, password);
|
|
|
|
|
|
|
|
} else if ("imap".equals(protocol) || "imaps".equals(protocol)) {
|
2019-07-29 09:17:12 +00:00
|
|
|
iservice = isession.getStore(protocol);
|
|
|
|
iservice.connect(host, port, user, password);
|
|
|
|
|
|
|
|
// https://www.ietf.org/rfc/rfc2971.txt
|
2019-09-19 15:41:26 +00:00
|
|
|
IMAPStore istore = (IMAPStore) getStore();
|
|
|
|
if (istore.hasCapability("ID"))
|
2019-07-29 09:17:12 +00:00
|
|
|
try {
|
|
|
|
Map<String, String> id = new LinkedHashMap<>();
|
|
|
|
id.put("name", context.getString(R.string.app_name));
|
|
|
|
id.put("version", BuildConfig.VERSION_NAME);
|
2019-09-19 15:41:26 +00:00
|
|
|
Map<String, String> sid = istore.id(id);
|
2019-07-29 09:17:12 +00:00
|
|
|
if (sid != null) {
|
|
|
|
Map<String, String> crumb = new HashMap<>();
|
|
|
|
for (String key : sid.keySet()) {
|
|
|
|
crumb.put(key, sid.get(key));
|
|
|
|
EntityLog.log(context, "Server " + key + "=" + sid.get(key));
|
|
|
|
}
|
2019-08-12 11:07:14 +00:00
|
|
|
Log.breadcrumb("server", crumb);
|
2019-07-29 09:17:12 +00:00
|
|
|
}
|
|
|
|
} catch (MessagingException ex) {
|
|
|
|
Log.w(ex);
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if ("smtp".equals(protocol) || "smtps".equals(protocol)) {
|
2019-11-08 17:07:06 +00:00
|
|
|
String[] c = BuildConfig.APPLICATION_ID.split("\\.");
|
|
|
|
Collections.reverse(Arrays.asList(c));
|
|
|
|
String haddr = TextUtils.join(".", c);
|
2019-07-30 16:50:42 +00:00
|
|
|
|
|
|
|
if (useip)
|
|
|
|
try {
|
|
|
|
// This assumes getByName always returns the same address (type)
|
|
|
|
InetAddress addr = InetAddress.getByName(host);
|
|
|
|
if (addr instanceof Inet4Address)
|
|
|
|
haddr = "[" + Inet4Address.getLocalHost().getHostAddress() + "]";
|
|
|
|
else
|
|
|
|
haddr = "[IPv6:" + Inet6Address.getLocalHost().getHostAddress() + "]";
|
|
|
|
} catch (UnknownHostException ex) {
|
|
|
|
Log.w(ex);
|
|
|
|
}
|
|
|
|
|
|
|
|
Log.i("Using localhost=" + haddr);
|
2019-07-30 16:53:18 +00:00
|
|
|
properties.put("mail." + protocol + ".localhost", haddr);
|
2019-07-30 16:50:42 +00:00
|
|
|
|
2019-07-29 09:17:12 +00:00
|
|
|
iservice = isession.getTransport(protocol);
|
|
|
|
iservice.connect(host, port, user, password);
|
|
|
|
} else
|
|
|
|
throw new NoSuchProviderException(protocol);
|
|
|
|
}
|
|
|
|
|
2019-09-18 14:34:07 +00:00
|
|
|
static String getAuthTokenType(String type) {
|
|
|
|
// https://developers.google.com/gmail/imap/xoauth2-protocol
|
|
|
|
if ("com.google".equals(type))
|
|
|
|
return "oauth2:https://mail.google.com/";
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
List<EntityFolder> getFolders() throws MessagingException {
|
|
|
|
List<EntityFolder> folders = new ArrayList<>();
|
|
|
|
List<EntityFolder> guesses = new ArrayList<>();
|
|
|
|
|
|
|
|
for (Folder ifolder : getStore().getDefaultFolder().list("*")) {
|
|
|
|
String fullName = ifolder.getFullName();
|
|
|
|
String[] attrs = ((IMAPFolder) ifolder).getAttributes();
|
|
|
|
String type = EntityFolder.getType(attrs, fullName, true);
|
|
|
|
Log.i(fullName + " attrs=" + TextUtils.join(" ", attrs) + " type=" + type);
|
|
|
|
|
|
|
|
if (type != null) {
|
|
|
|
EntityFolder folder = new EntityFolder(fullName, type);
|
|
|
|
folders.add(folder);
|
|
|
|
|
|
|
|
if (EntityFolder.USER.equals(type)) {
|
|
|
|
String guess = EntityFolder.guessType(fullName);
|
|
|
|
if (guess != null)
|
|
|
|
guesses.add(folder);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (EntityFolder guess : guesses) {
|
|
|
|
boolean has = false;
|
|
|
|
String gtype = EntityFolder.guessType(guess.name);
|
|
|
|
for (EntityFolder folder : folders)
|
|
|
|
if (folder.type.equals(gtype)) {
|
|
|
|
has = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!has) {
|
|
|
|
guess.type = gtype;
|
|
|
|
Log.i(guess.name + " guessed type=" + gtype);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
boolean inbox = false;
|
|
|
|
boolean drafts = false;
|
|
|
|
for (EntityFolder folder : folders)
|
|
|
|
if (EntityFolder.INBOX.equals(folder.type))
|
|
|
|
inbox = true;
|
|
|
|
else if (EntityFolder.DRAFTS.equals(folder.type))
|
|
|
|
drafts = true;
|
|
|
|
|
|
|
|
if (!inbox || !drafts)
|
|
|
|
return null;
|
|
|
|
|
|
|
|
return folders;
|
|
|
|
}
|
|
|
|
|
2019-09-19 15:41:26 +00:00
|
|
|
Store getStore() {
|
|
|
|
return (Store) iservice;
|
2019-07-29 09:17:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SMTPTransport getTransport() {
|
2019-07-30 16:53:18 +00:00
|
|
|
return (SMTPTransport) iservice;
|
2019-07-29 09:17:12 +00:00
|
|
|
}
|
|
|
|
|
2019-09-19 15:41:26 +00:00
|
|
|
boolean hasCapability(String capability) throws MessagingException {
|
|
|
|
Store store = getStore();
|
|
|
|
if (store instanceof IMAPStore)
|
|
|
|
return ((IMAPStore) getStore()).hasCapability(capability);
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-07-29 09:17:12 +00:00
|
|
|
public void close() throws MessagingException {
|
|
|
|
try {
|
2019-10-08 19:59:49 +00:00
|
|
|
if (iservice != null && iservice.isConnected())
|
2019-07-29 09:17:12 +00:00
|
|
|
iservice.close();
|
|
|
|
} finally {
|
2019-07-30 16:53:18 +00:00
|
|
|
context = null;
|
2019-07-29 09:17:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|