Use an Account object to create a mail sender
Instead of boiling the account down to an unusable URI, just pass along the Account object. Change-Id: Ida408912de29734c8f4ed9cdf09a4d633dd03002
This commit is contained in:
parent
031527a03e
commit
daf869cf60
|
@ -10,12 +10,7 @@
|
|||
}
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
public *** newInstance(android.content.Context, java.lang.String);
|
||||
}
|
||||
|
||||
# TODO remove after converting Sender#instantiateSender() to use Account instead of URI
|
||||
-keepclasseswithmembers class * {
|
||||
public *** newInstance(java.lang.String, android.content.Context, com.android.email.mail.Store$PersistentDataCallbacks);
|
||||
public *** newInstance(com.android.emailcommon.provider.EmailContent$Account, android.content.Context);
|
||||
}
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
|
@ -60,7 +55,6 @@
|
|||
<init>(java.lang.String);
|
||||
<init>(java.lang.String,java.lang.String);
|
||||
*** parseAndPack(java.lang.String);
|
||||
*** legacyUnpack(java.lang.String);
|
||||
}
|
||||
|
||||
-keepclasseswithmembers class com.android.email.SecurityPolicy {
|
||||
|
|
|
@ -226,20 +226,17 @@ public class MessagingController implements Runnable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Lists folders that are available locally and remotely. This method calls
|
||||
* listFoldersCallback for local folders before it returns, and then for
|
||||
* remote folders at some later point. If there are no local folders
|
||||
* includeRemote is forced by this method. This method should be called from
|
||||
* a Thread as it may take several seconds to list the local folders.
|
||||
* Asynchronously synchronize the folder list. If the specified {@link MessagingListener}
|
||||
* is not {@code null}, it must have been previously added to the set of listeners using the
|
||||
* {@link #addListener(MessagingListener)}. Otherwise, no actions will be performed.
|
||||
*
|
||||
* TODO this needs to cache the remote folder list
|
||||
* TODO break out an inner listFoldersSynchronized which could simplify checkMail
|
||||
*
|
||||
* @param account
|
||||
* @param listener
|
||||
* @throws MessagingException
|
||||
* @param accountId ID of the account for which to list the folders
|
||||
* @param listener A listener to notify
|
||||
*/
|
||||
public void listFolders(final long accountId, MessagingListener listener) {
|
||||
void listFolders(final long accountId, MessagingListener listener) {
|
||||
final EmailContent.Account account =
|
||||
EmailContent.Account.restoreAccountWithId(mContext, accountId);
|
||||
if (account == null) {
|
||||
|
@ -1173,7 +1170,7 @@ public class MessagingController implements Runnable {
|
|||
* @param accountIdArgs
|
||||
*/
|
||||
private void processPendingUploadsSynchronous(EmailContent.Account account,
|
||||
ContentResolver resolver, String[] accountIdArgs) throws MessagingException {
|
||||
ContentResolver resolver, String[] accountIdArgs) {
|
||||
// Find the Sent folder (since that's all we're uploading for now
|
||||
Cursor mailboxes = resolver.query(Mailbox.CONTENT_URI, Mailbox.ID_PROJECTION,
|
||||
MailboxColumns.ACCOUNT_KEY + "=?"
|
||||
|
@ -1878,10 +1875,6 @@ public class MessagingController implements Runnable {
|
|||
|
||||
/**
|
||||
* Attempts to load the attachment specified by id from the given account and message.
|
||||
* @param account
|
||||
* @param message
|
||||
* @param part
|
||||
* @param listener
|
||||
*/
|
||||
public void loadAttachment(final long accountId, final long messageId, final long mailboxId,
|
||||
final long attachmentId, MessagingListener listener, final boolean background) {
|
||||
|
@ -1993,10 +1986,8 @@ public class MessagingController implements Runnable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Attempt to send any messages that are sitting in the Outbox.
|
||||
*
|
||||
* @param account
|
||||
* @param listener
|
||||
* Attempt to send all messages sitting in the given account's outbox. Optionally,
|
||||
* if the server requires it, the message will be moved to the given sent folder.
|
||||
*/
|
||||
public void sendPendingMessagesSynchronous(final EmailContent.Account account,
|
||||
long sentFolderId) {
|
||||
|
@ -2019,7 +2010,7 @@ public class MessagingController implements Runnable {
|
|||
// 3. do one-time setup of the Sender & other stuff
|
||||
mListeners.sendPendingMessagesStarted(account.mId, -1);
|
||||
|
||||
Sender sender = Sender.getInstance(mContext, account.getSenderUri(mContext));
|
||||
Sender sender = Sender.getInstance(mContext, account);
|
||||
Store remoteStore = Store.getInstance(account, mContext, null);
|
||||
boolean requireMoveMessageToSentFolder = remoteStore.requireCopyMessageToSentFolder();
|
||||
ContentValues moveToSentValues = null;
|
||||
|
|
|
@ -392,7 +392,6 @@ public class AccountCheckSettingsFragment extends Fragment {
|
|||
final int mMode;
|
||||
final Account mAccount;
|
||||
final String mStoreHost;
|
||||
final String mSenderUri;
|
||||
final String mCheckEmail;
|
||||
final String mCheckPassword;
|
||||
|
||||
|
@ -406,7 +405,6 @@ public class AccountCheckSettingsFragment extends Fragment {
|
|||
mMode = mode;
|
||||
mAccount = checkAccount;
|
||||
mStoreHost = checkAccount.mHostAuthRecv.mAddress;
|
||||
mSenderUri = checkAccount.getSenderUri(mContext);
|
||||
mCheckEmail = checkAccount.mEmailAddress;
|
||||
mCheckPassword = checkAccount.mHostAuthRecv.mPassword;
|
||||
}
|
||||
|
@ -475,7 +473,7 @@ public class AccountCheckSettingsFragment extends Fragment {
|
|||
if (isCancelled()) return null;
|
||||
Log.d(Logging.LOG_TAG, "Begin check of outgoing email settings");
|
||||
publishProgress(STATE_CHECK_OUTGOING);
|
||||
Sender sender = Sender.getInstance(mContext, mSenderUri);
|
||||
Sender sender = Sender.getInstance(mContext, mAccount);
|
||||
sender.close();
|
||||
sender.open();
|
||||
sender.close();
|
||||
|
|
|
@ -521,7 +521,7 @@ public class AccountSettingsFragment extends PreferenceFragment {
|
|||
Preference prefOutgoing = findPreference(PREFERENCE_OUTGOING);
|
||||
boolean showOutgoing = true;
|
||||
try {
|
||||
Sender sender = Sender.getInstance(mContext, mAccount.getSenderUri(mContext));
|
||||
Sender sender = Sender.getInstance(mContext, mAccount);
|
||||
if (sender != null) {
|
||||
Class<? extends android.app.Activity> setting = sender.getSettingActivityClass();
|
||||
showOutgoing = (setting != null);
|
||||
|
|
|
@ -641,7 +641,7 @@ public class AccountSettingsXL extends PreferenceActivity {
|
|||
*/
|
||||
public void onOutgoingSettings(Account account) {
|
||||
try {
|
||||
Sender sender = Sender.getInstance(getApplication(), account.getSenderUri(this));
|
||||
Sender sender = Sender.getInstance(getApplication(), account);
|
||||
if (sender != null) {
|
||||
Class<? extends android.app.Activity> setting = sender.getSettingActivityClass();
|
||||
if (setting != null) {
|
||||
|
|
|
@ -19,11 +19,14 @@ package com.android.email.mail;
|
|||
import com.android.email.R;
|
||||
import com.android.emailcommon.Logging;
|
||||
import com.android.emailcommon.mail.MessagingException;
|
||||
import com.android.emailcommon.provider.EmailContent.Account;
|
||||
import com.android.emailcommon.provider.EmailContent.HostAuth;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -38,29 +41,30 @@ public abstract class Sender {
|
|||
* Static named constructor. It should be overrode by extending class.
|
||||
* Because this method will be called through reflection, it can not be protected.
|
||||
*/
|
||||
public static Sender newInstance(Context context, String uri)
|
||||
public static Sender newInstance(Context context, Account account)
|
||||
throws MessagingException {
|
||||
throw new MessagingException("Sender.newInstance: Unknown scheme in " + uri);
|
||||
throw new MessagingException("Sender.newInstance: Unknown scheme in "
|
||||
+ account.mDisplayName);
|
||||
}
|
||||
|
||||
private static Sender instantiateSender(Context context, String className, String uri)
|
||||
private static Sender instantiateSender(Context context, String className, Account account)
|
||||
throws MessagingException {
|
||||
Object o = null;
|
||||
try {
|
||||
Class<?> c = Class.forName(className);
|
||||
// and invoke "newInstance" class method and instantiate sender object.
|
||||
java.lang.reflect.Method m =
|
||||
c.getMethod("newInstance", Context.class, String.class);
|
||||
o = m.invoke(null, context, uri);
|
||||
c.getMethod("newInstance", Account.class, Context.class);
|
||||
o = m.invoke(null, account, context);
|
||||
} catch (Exception e) {
|
||||
Log.d(Logging.LOG_TAG, String.format(
|
||||
"exception %s invoking %s.newInstance.(Context, String) method for %s",
|
||||
e.toString(), className, uri));
|
||||
throw new MessagingException("can not instantiate Sender object for " + uri);
|
||||
"exception %s invoking method %s#newInstance(Account, Context) for %s",
|
||||
e.toString(), className, account.mDisplayName));
|
||||
throw new MessagingException("can not instantiate Sender for " + account.mDisplayName);
|
||||
}
|
||||
if (!(o instanceof Sender)) {
|
||||
throw new MessagingException(
|
||||
uri + ": " + className + " create incompatible object");
|
||||
account.mDisplayName + ": " + className + " create incompatible object");
|
||||
}
|
||||
return (Sender) o;
|
||||
}
|
||||
|
@ -68,22 +72,23 @@ public abstract class Sender {
|
|||
/**
|
||||
* Find Sender implementation consulting with sender.xml file.
|
||||
*/
|
||||
private static Sender findSender(Context context, int resourceId, String uri)
|
||||
private static Sender findSender(Context context, int resourceId, Account account)
|
||||
throws MessagingException {
|
||||
Sender sender = null;
|
||||
try {
|
||||
XmlResourceParser xml = context.getResources().getXml(resourceId);
|
||||
int xmlEventType;
|
||||
HostAuth sendAuth = account.getOrCreateHostAuthSend(context);
|
||||
// walk through senders.xml file.
|
||||
while ((xmlEventType = xml.next()) != XmlResourceParser.END_DOCUMENT) {
|
||||
if (xmlEventType == XmlResourceParser.START_TAG &&
|
||||
"sender".equals(xml.getName())) {
|
||||
String scheme = xml.getAttributeValue(null, "scheme");
|
||||
if (uri.startsWith(scheme)) {
|
||||
String xmlScheme = xml.getAttributeValue(null, "scheme");
|
||||
if (sendAuth.mProtocol != null && sendAuth.mProtocol.startsWith(xmlScheme)) {
|
||||
// found sender entry whose scheme is matched with uri.
|
||||
// then load sender class.
|
||||
String className = xml.getAttributeValue(null, "class");
|
||||
sender = instantiateSender(context, className, uri);
|
||||
sender = instantiateSender(context, className, account);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -95,26 +100,57 @@ public abstract class Sender {
|
|||
return sender;
|
||||
}
|
||||
|
||||
public synchronized static Sender getInstance(Context context, String uri)
|
||||
/**
|
||||
* Gets a unique key for the given account.
|
||||
* @throws MessagingException If the account is not setup properly (i.e. there is no address
|
||||
* or login)
|
||||
*/
|
||||
private static String getSenderKey(Context context, Account account) throws MessagingException {
|
||||
final StringBuffer key = new StringBuffer();
|
||||
final HostAuth sendAuth = account.getOrCreateHostAuthSend(context);
|
||||
if (sendAuth.mAddress == null) {
|
||||
throw new MessagingException("Cannot find sender for account " + account.mDisplayName);
|
||||
}
|
||||
final String address = sendAuth.mAddress.trim();
|
||||
if (TextUtils.isEmpty(address)) {
|
||||
throw new MessagingException("Cannot find sender for account " + account.mDisplayName);
|
||||
}
|
||||
key.append(address);
|
||||
if (sendAuth.mLogin != null) {
|
||||
key.append(sendAuth.mLogin.trim());
|
||||
}
|
||||
return key.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of a mail sender for the given account. The account must be valid (i.e. has
|
||||
* at least an outgoing server name).
|
||||
*
|
||||
* @param account The account of the sender.
|
||||
* @return an initialized sender of the appropriate class
|
||||
* @throws MessagingException If the sender cannot be obtained or if the account is invalid.
|
||||
*/
|
||||
public synchronized static Sender getInstance(Context context, Account account)
|
||||
throws MessagingException {
|
||||
Sender sender = sSenders.get(uri);
|
||||
if (sender == null) {
|
||||
context = context.getApplicationContext();
|
||||
sender = findSender(context, R.xml.senders_product, uri);
|
||||
if (sender == null) {
|
||||
sender = findSender(context, R.xml.senders, uri);
|
||||
}
|
||||
String senderKey = getSenderKey(context, account);
|
||||
Sender sender = sSenders.get(senderKey);
|
||||
if (sender == null) {
|
||||
Context appContext = context.getApplicationContext();
|
||||
sender = findSender(appContext, R.xml.senders_product, account);
|
||||
if (sender == null) {
|
||||
sender = findSender(appContext, R.xml.senders, account);
|
||||
}
|
||||
|
||||
if (sender != null) {
|
||||
sSenders.put(uri, sender);
|
||||
}
|
||||
}
|
||||
if (sender != null) {
|
||||
sSenders.put(senderKey, sender);
|
||||
}
|
||||
}
|
||||
|
||||
if (sender == null) {
|
||||
throw new MessagingException("Unable to locate an applicable Transport for " + uri);
|
||||
}
|
||||
if (sender == null) {
|
||||
throw new MessagingException("Cannot find sender for account " + account.mDisplayName);
|
||||
}
|
||||
|
||||
return sender;
|
||||
return sender;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,6 +25,8 @@ import com.android.emailcommon.mail.Address;
|
|||
import com.android.emailcommon.mail.AuthenticationFailedException;
|
||||
import com.android.emailcommon.mail.CertificateValidationException;
|
||||
import com.android.emailcommon.mail.MessagingException;
|
||||
import com.android.emailcommon.provider.EmailContent.Account;
|
||||
import com.android.emailcommon.provider.EmailContent.HostAuth;
|
||||
import com.android.emailcommon.provider.EmailContent.Message;
|
||||
|
||||
import android.content.Context;
|
||||
|
@ -33,8 +35,6 @@ import android.util.Base64;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
|
||||
|
@ -52,56 +52,44 @@ public class SmtpSender extends Sender {
|
|||
/**
|
||||
* Static named constructor.
|
||||
*/
|
||||
public static Sender newInstance(Context context, String uri) throws MessagingException {
|
||||
return new SmtpSender(context, uri);
|
||||
public static Sender newInstance(Account account, Context context) throws MessagingException {
|
||||
return new SmtpSender(context, account);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allowed formats for the Uri:
|
||||
* smtp://user:password@server:port
|
||||
* smtp+tls+://user:password@server:port
|
||||
* smtp+tls+trustallcerts://user:password@server:port
|
||||
* smtp+ssl+://user:password@server:port
|
||||
* smtp+ssl+trustallcerts://user:password@server:port
|
||||
*
|
||||
* @param uriString the Uri containing information to configure this sender
|
||||
* Creates a new sender for the given account.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private SmtpSender(Context context, String uriString) throws MessagingException {
|
||||
private SmtpSender(Context context, Account account) throws MessagingException {
|
||||
mContext = context;
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI(uriString);
|
||||
} catch (URISyntaxException use) {
|
||||
throw new MessagingException("Invalid SmtpTransport URI", use);
|
||||
}
|
||||
|
||||
String scheme = uri.getScheme();
|
||||
if (scheme == null || !scheme.startsWith("smtp")) {
|
||||
HostAuth sendAuth = account.getOrCreateHostAuthSend(context);
|
||||
if (sendAuth == null || !"smtp".equalsIgnoreCase(sendAuth.mProtocol)) {
|
||||
throw new MessagingException("Unsupported protocol");
|
||||
}
|
||||
// defaults, which can be changed by security modifiers
|
||||
int connectionSecurity = Transport.CONNECTION_SECURITY_NONE;
|
||||
int defaultPort = 587;
|
||||
// check for security modifiers and apply changes
|
||||
if (scheme.contains("+ssl")) {
|
||||
|
||||
// check for security flags and apply changes
|
||||
if ((sendAuth.mFlags & HostAuth.FLAG_SSL) != 0) {
|
||||
connectionSecurity = Transport.CONNECTION_SECURITY_SSL;
|
||||
defaultPort = 465;
|
||||
} else if (scheme.contains("+tls")) {
|
||||
} else if ((sendAuth.mFlags & HostAuth.FLAG_TLS) != 0) {
|
||||
connectionSecurity = Transport.CONNECTION_SECURITY_TLS;
|
||||
}
|
||||
boolean trustCertificates = scheme.contains("+trustallcerts");
|
||||
|
||||
mTransport = new MailTransport("SMTP");
|
||||
mTransport.setUri(uri, defaultPort);
|
||||
boolean trustCertificates = ((sendAuth.mFlags & HostAuth.FLAG_TRUST_ALL) != 0);
|
||||
int port = defaultPort;
|
||||
if (sendAuth.mPort != HostAuth.PORT_UNKNOWN) {
|
||||
port = sendAuth.mPort;
|
||||
}
|
||||
mTransport = new MailTransport("IMAP");
|
||||
mTransport.setHost(sendAuth.mAddress);
|
||||
mTransport.setPort(port);
|
||||
mTransport.setSecurity(connectionSecurity, trustCertificates);
|
||||
|
||||
String[] userInfoParts = mTransport.getUserInfoParts();
|
||||
String[] userInfoParts = sendAuth.getLogin();
|
||||
if (userInfoParts != null) {
|
||||
mUsername = userInfoParts[0];
|
||||
if (userInfoParts.length > 1) {
|
||||
mPassword = userInfoParts[1];
|
||||
}
|
||||
mPassword = userInfoParts[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,10 @@ import com.android.email.mail.Transport;
|
|||
import com.android.email.provider.EmailProvider;
|
||||
import com.android.emailcommon.mail.Address;
|
||||
import com.android.emailcommon.mail.MessagingException;
|
||||
import com.android.emailcommon.provider.EmailContent.Account;
|
||||
import com.android.emailcommon.provider.EmailContent.Attachment;
|
||||
import com.android.emailcommon.provider.EmailContent.Body;
|
||||
import com.android.emailcommon.provider.EmailContent.HostAuth;
|
||||
import com.android.emailcommon.provider.EmailContent.Message;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
@ -73,9 +75,13 @@ public class SmtpSenderUnitTests extends AndroidTestCase {
|
|||
getContext());
|
||||
mContext = getContext();
|
||||
|
||||
// These are needed so we can get at the inner classes
|
||||
mSender = (SmtpSender) SmtpSender.newInstance(mProviderContext,
|
||||
"smtp://user:password@server:999");
|
||||
HostAuth testAuth = new HostAuth();
|
||||
Account testAccount = new Account();
|
||||
|
||||
testAuth.setLogin("user", "password");
|
||||
testAuth.setConnection("smtp", "server", 999);
|
||||
testAccount.mHostAuthSend = testAuth;
|
||||
mSender = (SmtpSender) SmtpSender.newInstance(testAccount, mProviderContext);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue