summaryrefslogtreecommitdiffstats
path: root/src/com/android/email/service/EmailServiceStub.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/email/service/EmailServiceStub.java')
-rw-r--r--src/com/android/email/service/EmailServiceStub.java523
1 files changed, 0 insertions, 523 deletions
diff --git a/src/com/android/email/service/EmailServiceStub.java b/src/com/android/email/service/EmailServiceStub.java
deleted file mode 100644
index 595d524de..000000000
--- a/src/com/android/email/service/EmailServiceStub.java
+++ /dev/null
@@ -1,523 +0,0 @@
-/* Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.service;
-
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.net.TrafficStats;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.RemoteException;
-
-import com.android.email.DebugUtils;
-import com.android.email.NotificationController;
-import com.android.email.mail.Sender;
-import com.android.email.mail.Store;
-import com.android.email.service.EmailServiceUtils.EmailServiceInfo;
-import com.android.emailcommon.Logging;
-import com.android.emailcommon.TrafficFlags;
-import com.android.emailcommon.internet.MimeBodyPart;
-import com.android.emailcommon.internet.MimeHeader;
-import com.android.emailcommon.internet.MimeMultipart;
-import com.android.emailcommon.mail.AuthenticationFailedException;
-import com.android.emailcommon.mail.FetchProfile;
-import com.android.emailcommon.mail.Folder;
-import com.android.emailcommon.mail.Folder.MessageRetrievalListener;
-import com.android.emailcommon.mail.Folder.OpenMode;
-import com.android.emailcommon.mail.Message;
-import com.android.emailcommon.mail.MessagingException;
-import com.android.emailcommon.provider.Account;
-import com.android.emailcommon.provider.EmailContent;
-import com.android.emailcommon.provider.EmailContent.Attachment;
-import com.android.emailcommon.provider.EmailContent.AttachmentColumns;
-import com.android.emailcommon.provider.EmailContent.Body;
-import com.android.emailcommon.provider.EmailContent.BodyColumns;
-import com.android.emailcommon.provider.EmailContent.MailboxColumns;
-import com.android.emailcommon.provider.EmailContent.MessageColumns;
-import com.android.emailcommon.provider.Mailbox;
-import com.android.emailcommon.service.EmailServiceStatus;
-import com.android.emailcommon.service.EmailServiceVersion;
-import com.android.emailcommon.service.HostAuthCompat;
-import com.android.emailcommon.service.IEmailService;
-import com.android.emailcommon.service.IEmailServiceCallback;
-import com.android.emailcommon.service.SearchParams;
-import com.android.emailcommon.utility.AttachmentUtilities;
-import com.android.emailcommon.utility.Utility;
-import com.android.mail.providers.UIProvider;
-import com.android.mail.utils.LogUtils;
-
-import java.util.HashSet;
-
-/**
- * EmailServiceStub is an abstract class representing an EmailService
- *
- * This class provides legacy support for a few methods that are common to both
- * IMAP and POP3, including startSync, loadMore, loadAttachment, and sendMail
- */
-public abstract class EmailServiceStub extends IEmailService.Stub implements IEmailService {
-
- private static final int MAILBOX_COLUMN_ID = 0;
- private static final int MAILBOX_COLUMN_SERVER_ID = 1;
- private static final int MAILBOX_COLUMN_TYPE = 2;
-
- /** Small projection for just the columns required for a sync. */
- private static final String[] MAILBOX_PROJECTION = {
- MailboxColumns._ID,
- MailboxColumns.SERVER_ID,
- MailboxColumns.TYPE,
- };
-
- protected Context mContext;
-
- protected void init(Context context) {
- mContext = context;
- }
-
- @Override
- public Bundle validate(HostAuthCompat hostAuthCom) throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- protected void requestSync(long mailboxId, boolean userRequest, int deltaMessageCount) {
- final Mailbox mailbox = Mailbox.restoreMailboxWithId(mContext, mailboxId);
- if (mailbox == null) return;
- final Account account = Account.restoreAccountWithId(mContext, mailbox.mAccountKey);
- if (account == null) return;
- final EmailServiceInfo info =
- EmailServiceUtils.getServiceInfoForAccount(mContext, account.mId);
- final android.accounts.Account acct = new android.accounts.Account(account.mEmailAddress,
- info.accountType);
- final Bundle extras = Mailbox.createSyncBundle(mailboxId);
- if (userRequest) {
- extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
- extras.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, true);
- extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
- }
- if (deltaMessageCount != 0) {
- extras.putInt(Mailbox.SYNC_EXTRA_DELTA_MESSAGE_COUNT, deltaMessageCount);
- }
- ContentResolver.requestSync(acct, EmailContent.AUTHORITY, extras);
- LogUtils.i(Logging.LOG_TAG, "requestSync EmailServiceStub startSync %s, %s",
- account.toString(), extras.toString());
- }
-
- @Override
- public void loadAttachment(final IEmailServiceCallback cb, final long accountId,
- final long attachmentId, final boolean background) throws RemoteException {
- Folder remoteFolder = null;
- try {
- //1. Check if the attachment is already here and return early in that case
- Attachment attachment =
- Attachment.restoreAttachmentWithId(mContext, attachmentId);
- if (attachment == null) {
- cb.loadAttachmentStatus(0, attachmentId,
- EmailServiceStatus.ATTACHMENT_NOT_FOUND, 0);
- return;
- }
- final long messageId = attachment.mMessageKey;
-
- final EmailContent.Message message =
- EmailContent.Message.restoreMessageWithId(mContext, attachment.mMessageKey);
- if (message == null) {
- cb.loadAttachmentStatus(messageId, attachmentId,
- EmailServiceStatus.MESSAGE_NOT_FOUND, 0);
- return;
- }
-
- // If the message is loaded, just report that we're finished
- if (Utility.attachmentExists(mContext, attachment)
- && attachment.mUiState == UIProvider.AttachmentState.SAVED) {
- cb.loadAttachmentStatus(messageId, attachmentId, EmailServiceStatus.SUCCESS,
- 0);
- return;
- }
-
- // Say we're starting...
- cb.loadAttachmentStatus(messageId, attachmentId, EmailServiceStatus.IN_PROGRESS, 0);
-
- // 2. Open the remote folder.
- final Account account = Account.restoreAccountWithId(mContext, message.mAccountKey);
- Mailbox mailbox = Mailbox.restoreMailboxWithId(mContext, message.mMailboxKey);
- if (mailbox == null) {
- // This could be null if the account is deleted at just the wrong time.
- return;
- }
- if (mailbox.mType == Mailbox.TYPE_OUTBOX) {
- long sourceId = Utility.getFirstRowLong(mContext, Body.CONTENT_URI,
- new String[] {BodyColumns.SOURCE_MESSAGE_KEY},
- BodyColumns.MESSAGE_KEY + "=?",
- new String[] {Long.toString(messageId)}, null, 0, -1L);
- if (sourceId != -1) {
- EmailContent.Message sourceMsg =
- EmailContent.Message.restoreMessageWithId(mContext, sourceId);
- if (sourceMsg != null) {
- mailbox = Mailbox.restoreMailboxWithId(mContext, sourceMsg.mMailboxKey);
- message.mServerId = sourceMsg.mServerId;
- }
- }
- } else if (mailbox.mType == Mailbox.TYPE_SEARCH && message.mMainMailboxKey != 0) {
- mailbox = Mailbox.restoreMailboxWithId(mContext, message.mMainMailboxKey);
- }
-
- if (account == null || mailbox == null) {
- // If the account/mailbox are gone, just report success; the UI handles this
- cb.loadAttachmentStatus(messageId, attachmentId,
- EmailServiceStatus.SUCCESS, 0);
- return;
- }
- TrafficStats.setThreadStatsTag(
- TrafficFlags.getAttachmentFlags(mContext, account));
-
- final Store remoteStore = Store.getInstance(account, mContext);
- remoteFolder = remoteStore.getFolder(mailbox.mServerId);
- remoteFolder.open(OpenMode.READ_WRITE);
-
- // 3. Generate a shell message in which to retrieve the attachment,
- // and a shell BodyPart for the attachment. Then glue them together.
- final Message storeMessage = remoteFolder.createMessage(message.mServerId);
- final MimeBodyPart storePart = new MimeBodyPart();
- storePart.setSize((int)attachment.mSize);
- storePart.setHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA,
- attachment.mLocation);
- storePart.setHeader(MimeHeader.HEADER_CONTENT_TYPE,
- String.format("%s;\n name=\"%s\"",
- attachment.mMimeType,
- attachment.mFileName));
-
- // TODO is this always true for attachments? I think we dropped the
- // true encoding along the way
- storePart.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64");
-
- final MimeMultipart multipart = new MimeMultipart();
- multipart.setSubType("mixed");
- multipart.addBodyPart(storePart);
-
- storeMessage.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "multipart/mixed");
- storeMessage.setBody(multipart);
-
- // 4. Now ask for the attachment to be fetched
- final FetchProfile fp = new FetchProfile();
- fp.add(storePart);
- remoteFolder.fetch(new Message[] { storeMessage }, fp,
- new MessageRetrievalListenerBridge(messageId, attachmentId, cb));
-
- // If we failed to load the attachment, throw an Exception here, so that
- // AttachmentService knows that we failed
- if (storePart.getBody() == null) {
- throw new MessagingException("Attachment not loaded.");
- }
-
- // Save the attachment to wherever it's going
- AttachmentUtilities.saveAttachment(mContext, storePart.getBody().getInputStream(),
- attachment);
-
- // 6. Report success
- cb.loadAttachmentStatus(messageId, attachmentId, EmailServiceStatus.SUCCESS, 0);
-
- } catch (MessagingException me) {
- LogUtils.i(Logging.LOG_TAG, me, "Error loading attachment");
-
- final ContentValues cv = new ContentValues(1);
- cv.put(AttachmentColumns.UI_STATE, UIProvider.AttachmentState.FAILED);
- final Uri uri = ContentUris.withAppendedId(Attachment.CONTENT_URI, attachmentId);
- mContext.getContentResolver().update(uri, cv, null, null);
-
- cb.loadAttachmentStatus(0, attachmentId, EmailServiceStatus.CONNECTION_ERROR, 0);
- } finally {
- if (remoteFolder != null) {
- remoteFolder.close(false);
- }
- }
-
- }
-
- /**
- * Bridge to intercept {@link MessageRetrievalListener#loadAttachmentProgress} and
- * pass down to {@link IEmailServiceCallback}.
- */
- public class MessageRetrievalListenerBridge implements MessageRetrievalListener {
- private final long mMessageId;
- private final long mAttachmentId;
- private final IEmailServiceCallback mCallback;
-
-
- public MessageRetrievalListenerBridge(final long messageId, final long attachmentId,
- final IEmailServiceCallback callback) {
- mMessageId = messageId;
- mAttachmentId = attachmentId;
- mCallback = callback;
- }
-
- @Override
- public void loadAttachmentProgress(int progress) {
- try {
- mCallback.loadAttachmentStatus(mMessageId, mAttachmentId,
- EmailServiceStatus.IN_PROGRESS, progress);
- } catch (final RemoteException e) {
- // No danger if the client is no longer around
- }
- }
-
- @Override
- public void messageRetrieved(com.android.emailcommon.mail.Message message) {
- }
- }
-
- @Override
- public void updateFolderList(final long accountId) throws RemoteException {
- final Account account = Account.restoreAccountWithId(mContext, accountId);
- if (account == null) {
- LogUtils.e(LogUtils.TAG, "Account %d not found in updateFolderList", accountId);
- return;
- };
- long inboxId = -1;
- TrafficStats.setThreadStatsTag(TrafficFlags.getSyncFlags(mContext, account));
- Cursor localFolderCursor = null;
- Store store = null;
- try {
- // Step 0: Make sure the default system mailboxes exist.
- for (final int type : Mailbox.REQUIRED_FOLDER_TYPES) {
- if (Mailbox.findMailboxOfType(mContext, accountId, type) == Mailbox.NO_MAILBOX) {
- final Mailbox mailbox = Mailbox.newSystemMailbox(mContext, accountId, type);
- mailbox.save(mContext);
- if (type == Mailbox.TYPE_INBOX) {
- inboxId = mailbox.mId;
- }
- }
- }
-
- // Step 1: Get remote mailboxes
- store = Store.getInstance(account, mContext);
- final Folder[] remoteFolders = store.updateFolders();
- final HashSet<String> remoteFolderNames = new HashSet<String>();
- for (final Folder remoteFolder : remoteFolders) {
- remoteFolderNames.add(remoteFolder.getName());
- }
-
- // Step 2: Get local mailboxes
- localFolderCursor = mContext.getContentResolver().query(
- Mailbox.CONTENT_URI,
- MAILBOX_PROJECTION,
- EmailContent.MailboxColumns.ACCOUNT_KEY + "=?",
- new String[] { String.valueOf(account.mId) },
- null);
-
- // Step 3: Remove any local mailbox not on the remote list
- while (localFolderCursor.moveToNext()) {
- final String mailboxPath = localFolderCursor.getString(MAILBOX_COLUMN_SERVER_ID);
- // Short circuit if we have a remote mailbox with the same name
- if (remoteFolderNames.contains(mailboxPath)) {
- continue;
- }
-
- final int mailboxType = localFolderCursor.getInt(MAILBOX_COLUMN_TYPE);
- final long mailboxId = localFolderCursor.getLong(MAILBOX_COLUMN_ID);
- switch (mailboxType) {
- case Mailbox.TYPE_INBOX:
- case Mailbox.TYPE_DRAFTS:
- case Mailbox.TYPE_OUTBOX:
- case Mailbox.TYPE_SENT:
- case Mailbox.TYPE_TRASH:
- case Mailbox.TYPE_SEARCH:
- // Never, ever delete special mailboxes
- break;
- default:
- // Drop all attachment files related to this mailbox
- AttachmentUtilities.deleteAllMailboxAttachmentFiles(
- mContext, accountId, mailboxId);
- // Delete the mailbox; database triggers take care of related
- // Message, Body and Attachment records
- Uri uri = ContentUris.withAppendedId(
- Mailbox.CONTENT_URI, mailboxId);
- mContext.getContentResolver().delete(uri, null, null);
- break;
- }
- }
- } catch (MessagingException me) {
- LogUtils.i(Logging.LOG_TAG, me, "Error in updateFolderList");
- // We'll hope this is temporary
- // TODO: Figure out what type of messaging exception it was and return an appropriate
- // result. If we start doing this from sync, it's important to let the sync manager
- // know if the failure was due to IO error or authentication errors.
- } finally {
- if (localFolderCursor != null) {
- localFolderCursor.close();
- }
- if (store != null) {
- store.closeConnections();
- }
- // If we just created the inbox, sync it
- if (inboxId != -1) {
- requestSync(inboxId, true, 0);
- }
- }
- }
-
- @Override
- public void setLogging(final int flags) throws RemoteException {
- // Not required
- }
-
- @Override
- public Bundle autoDiscover(final String userName, final String password)
- throws RemoteException {
- // Not required
- return null;
- }
-
- @Override
- public void sendMeetingResponse(final long messageId, final int response)
- throws RemoteException {
- // Not required
- }
-
- @Override
- public void deleteExternalAccountPIMData(final String emailAddress) throws RemoteException {
- // No need to do anything here, for IMAP and POP accounts none of our data is external.
- }
-
- @Override
- public int searchMessages(final long accountId, final SearchParams params,
- final long destMailboxId)
- throws RemoteException {
- // Not required
- return EmailServiceStatus.SUCCESS;
- }
-
- @Override
- public void pushModify(final long accountId) throws RemoteException {
- LogUtils.e(Logging.LOG_TAG, "pushModify invalid for account type for %d", accountId);
- }
-
- @Override
- public int sync(final long accountId, final Bundle syncExtras) {
- return EmailServiceStatus.SUCCESS;
-
- }
-
- @Override
- public void sendMail(final long accountId) throws RemoteException {
- sendMailImpl(mContext, accountId);
- }
-
- public static void sendMailImpl(final Context context, final long accountId) {
- final Account account = Account.restoreAccountWithId(context, accountId);
- if (account == null) {
- LogUtils.e(LogUtils.TAG, "account %d not found in sendMailImpl", accountId);
- return;
- }
- TrafficStats.setThreadStatsTag(TrafficFlags.getSmtpFlags(context, account));
- final NotificationController nc = NotificationController.getInstance(context);
- // 1. Loop through all messages in the account's outbox
- final long outboxId = Mailbox.findMailboxOfType(context, account.mId, Mailbox.TYPE_OUTBOX);
- if (outboxId == Mailbox.NO_MAILBOX) {
- return;
- }
- final ContentResolver resolver = context.getContentResolver();
- final Cursor c = resolver.query(EmailContent.Message.CONTENT_URI,
- EmailContent.Message.ID_COLUMN_PROJECTION,
- MessageColumns.MAILBOX_KEY + "=?", new String[] { Long.toString(outboxId)},
- null);
- try {
- // 2. exit early
- if (c.getCount() <= 0) {
- return;
- }
- final Sender sender = Sender.getInstance(context, account);
- final Store remoteStore = Store.getInstance(account, context);
- final ContentValues moveToSentValues;
- if (remoteStore.requireCopyMessageToSentFolder()) {
- Mailbox sentFolder =
- Mailbox.restoreMailboxOfType(context, accountId, Mailbox.TYPE_SENT);
- moveToSentValues = new ContentValues();
- moveToSentValues.put(MessageColumns.MAILBOX_KEY, sentFolder.mId);
- } else {
- moveToSentValues = null;
- }
-
- // 3. loop through the available messages and send them
- while (c.moveToNext()) {
- final long messageId;
- if (moveToSentValues != null) {
- moveToSentValues.remove(EmailContent.MessageColumns.FLAGS);
- }
- try {
- messageId = c.getLong(0);
- // Don't send messages with unloaded attachments
- if (Utility.hasUnloadedAttachments(context, messageId)) {
- if (DebugUtils.DEBUG) {
- LogUtils.d(Logging.LOG_TAG, "Can't send #" + messageId +
- "; unloaded attachments");
- }
- continue;
- }
- sender.sendMessage(messageId);
- } catch (MessagingException me) {
- // report error for this message, but keep trying others
- if (me instanceof AuthenticationFailedException) {
- nc.showLoginFailedNotificationSynchronous(account.mId,
- false /* incoming */);
- }
- continue;
- }
- // 4. move to sent, or delete
- final Uri syncedUri =
- ContentUris.withAppendedId(EmailContent.Message.SYNCED_CONTENT_URI, messageId);
- // Delete all cached files
- AttachmentUtilities.deleteAllCachedAttachmentFiles(context, account.mId, messageId);
- if (moveToSentValues != null) {
- // If this is a forwarded message and it has attachments, delete them, as they
- // duplicate information found elsewhere (on the server). This saves storage.
- final EmailContent.Message msg =
- EmailContent.Message.restoreMessageWithId(context, messageId);
- if ((msg.mFlags & EmailContent.Message.FLAG_TYPE_FORWARD) != 0) {
- AttachmentUtilities.deleteAllAttachmentFiles(context, account.mId,
- messageId);
- }
- final int flags = msg.mFlags & ~(EmailContent.Message.FLAG_TYPE_REPLY |
- EmailContent.Message.FLAG_TYPE_FORWARD |
- EmailContent.Message.FLAG_TYPE_REPLY_ALL |
- EmailContent.Message.FLAG_TYPE_ORIGINAL);
-
- moveToSentValues.put(EmailContent.MessageColumns.FLAGS, flags);
- resolver.update(syncedUri, moveToSentValues, null, null);
- } else {
- AttachmentUtilities.deleteAllAttachmentFiles(context, account.mId,
- messageId);
- final Uri uri =
- ContentUris.withAppendedId(EmailContent.Message.CONTENT_URI, messageId);
- resolver.delete(uri, null, null);
- resolver.delete(syncedUri, null, null);
- }
- }
- nc.cancelLoginFailedNotification(account.mId);
- } catch (MessagingException me) {
- if (me instanceof AuthenticationFailedException) {
- nc.showLoginFailedNotificationSynchronous(account.mId, false /* incoming */);
- }
- } finally {
- c.close();
- }
- }
-
- public int getApiVersion() {
- return EmailServiceVersion.CURRENT;
- }
-}