summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--proguard.flags8
-rw-r--r--src/com/android/email/MessagingController.java29
-rw-r--r--src/com/android/email/activity/setup/AccountCheckSettingsFragment.java4
-rw-r--r--src/com/android/email/activity/setup/AccountSettingsFragment.java2
-rw-r--r--src/com/android/email/activity/setup/AccountSettingsXL.java2
-rw-r--r--src/com/android/email/mail/Sender.java100
-rw-r--r--src/com/android/email/mail/transport/SmtpSender.java56
-rw-r--r--tests/src/com/android/email/mail/transport/SmtpSenderUnitTests.java12
8 files changed, 113 insertions, 100 deletions
diff --git a/proguard.flags b/proguard.flags
index 7ed8d21de..0f6c90aaf 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -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 {
diff --git a/src/com/android/email/MessagingController.java b/src/com/android/email/MessagingController.java
index 8976b177c..5bd0c7542 100644
--- a/src/com/android/email/MessagingController.java
+++ b/src/com/android/email/MessagingController.java
@@ -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;
diff --git a/src/com/android/email/activity/setup/AccountCheckSettingsFragment.java b/src/com/android/email/activity/setup/AccountCheckSettingsFragment.java
index 2313d75d2..2ca214b50 100644
--- a/src/com/android/email/activity/setup/AccountCheckSettingsFragment.java
+++ b/src/com/android/email/activity/setup/AccountCheckSettingsFragment.java
@@ -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();
diff --git a/src/com/android/email/activity/setup/AccountSettingsFragment.java b/src/com/android/email/activity/setup/AccountSettingsFragment.java
index f82da2890..2bd98b3b2 100644
--- a/src/com/android/email/activity/setup/AccountSettingsFragment.java
+++ b/src/com/android/email/activity/setup/AccountSettingsFragment.java
@@ -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);
diff --git a/src/com/android/email/activity/setup/AccountSettingsXL.java b/src/com/android/email/activity/setup/AccountSettingsXL.java
index 9f2df3189..1558f184e 100644
--- a/src/com/android/email/activity/setup/AccountSettingsXL.java
+++ b/src/com/android/email/activity/setup/AccountSettingsXL.java
@@ -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) {
diff --git a/src/com/android/email/mail/Sender.java b/src/com/android/email/mail/Sender.java
index 43a4b778c..ddd85700f 100644
--- a/src/com/android/email/mail/Sender.java
+++ b/src/com/android/email/mail/Sender.java
@@ -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);
- }
-
- if (sender != null) {
- sSenders.put(uri, sender);
- }
- }
-
- if (sender == null) {
- throw new MessagingException("Unable to locate an applicable Transport for " + uri);
- }
-
- return sender;
+ 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(senderKey, sender);
+ }
+ }
+
+ if (sender == null) {
+ throw new MessagingException("Cannot find sender for account " + account.mDisplayName);
+ }
+
+ return sender;
}
/**
diff --git a/src/com/android/email/mail/transport/SmtpSender.java b/src/com/android/email/mail/transport/SmtpSender.java
index b2cdead52..bbd3a0f59 100644
--- a/src/com/android/email/mail/transport/SmtpSender.java
+++ b/src/com/android/email/mail/transport/SmtpSender.java
@@ -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];
}
}
diff --git a/tests/src/com/android/email/mail/transport/SmtpSenderUnitTests.java b/tests/src/com/android/email/mail/transport/SmtpSenderUnitTests.java
index 540803304..d4b1c0a67 100644
--- a/tests/src/com/android/email/mail/transport/SmtpSenderUnitTests.java
+++ b/tests/src/com/android/email/mail/transport/SmtpSenderUnitTests.java
@@ -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);
}
/**