package com.fsck.k9.notification; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.content.Intent; import timber.log.Timber; import com.fsck.k9.Account; import com.fsck.k9.K9; import com.fsck.k9.Preferences; import com.fsck.k9.activity.MessageReference; import com.fsck.k9.controller.MessagingController; import com.fsck.k9.mail.Flag; import com.fsck.k9.service.CoreService; import static com.fsck.k9.activity.MessageReferenceHelper.toMessageReferenceList; import static com.fsck.k9.activity.MessageReferenceHelper.toMessageReferenceStringList; public class NotificationActionService extends CoreService { private static final String ACTION_MARK_AS_READ = "ACTION_MARK_AS_READ"; private static final String ACTION_DELETE = "ACTION_DELETE"; private static final String ACTION_ARCHIVE = "ACTION_ARCHIVE"; private static final String ACTION_SPAM = "ACTION_SPAM"; private static final String ACTION_DISMISS = "ACTION_DISMISS"; private static final String EXTRA_ACCOUNT_UUID = "accountUuid"; private static final String EXTRA_MESSAGE_REFERENCE = "messageReference"; private static final String EXTRA_MESSAGE_REFERENCES = "messageReferences"; static Intent createMarkMessageAsReadIntent(Context context, MessageReference messageReference) { Intent intent = new Intent(context, NotificationActionService.class); intent.setAction(ACTION_MARK_AS_READ); intent.putExtra(EXTRA_ACCOUNT_UUID, messageReference.getAccountUuid()); intent.putExtra(EXTRA_MESSAGE_REFERENCES, createSingleItemArrayList(messageReference)); return intent; } static Intent createMarkAllAsReadIntent(Context context, String accountUuid, List<MessageReference> messageReferences) { Intent intent = new Intent(context, NotificationActionService.class); intent.setAction(ACTION_MARK_AS_READ); intent.putExtra(EXTRA_ACCOUNT_UUID, accountUuid); intent.putExtra(EXTRA_MESSAGE_REFERENCES, toMessageReferenceStringList(messageReferences)); return intent; } static Intent createDismissMessageIntent(Context context, MessageReference messageReference) { Intent intent = new Intent(context, NotificationActionService.class); intent.setAction(ACTION_DISMISS); intent.putExtra(EXTRA_ACCOUNT_UUID, messageReference.getAccountUuid()); intent.putExtra(EXTRA_MESSAGE_REFERENCE, messageReference.toIdentityString()); return intent; } static Intent createDismissAllMessagesIntent(Context context, Account account) { Intent intent = new Intent(context, NotificationActionService.class); intent.setAction(ACTION_DISMISS); intent.putExtra(EXTRA_ACCOUNT_UUID, account.getUuid()); return intent; } static Intent createDeleteMessageIntent(Context context, MessageReference messageReference) { Intent intent = new Intent(context, NotificationActionService.class); intent.setAction(ACTION_DELETE); intent.putExtra(EXTRA_ACCOUNT_UUID, messageReference.getAccountUuid()); intent.putExtra(EXTRA_MESSAGE_REFERENCES, createSingleItemArrayList(messageReference)); return intent; } public static Intent createDeleteAllMessagesIntent(Context context, String accountUuid, List<MessageReference> messageReferences) { Intent intent = new Intent(context, NotificationActionService.class); intent.setAction(ACTION_DELETE); intent.putExtra(EXTRA_ACCOUNT_UUID, accountUuid); intent.putExtra(EXTRA_MESSAGE_REFERENCES, toMessageReferenceStringList(messageReferences)); return intent; } static Intent createArchiveMessageIntent(Context context, MessageReference messageReference) { Intent intent = new Intent(context, NotificationActionService.class); intent.setAction(ACTION_ARCHIVE); intent.putExtra(EXTRA_ACCOUNT_UUID, messageReference.getAccountUuid()); intent.putExtra(EXTRA_MESSAGE_REFERENCES, createSingleItemArrayList(messageReference)); return intent; } static Intent createArchiveAllIntent(Context context, Account account, List<MessageReference> messageReferences) { Intent intent = new Intent(context, NotificationActionService.class); intent.setAction(ACTION_ARCHIVE); intent.putExtra(EXTRA_ACCOUNT_UUID, account.getUuid()); intent.putExtra(EXTRA_MESSAGE_REFERENCES, toMessageReferenceStringList(messageReferences)); return intent; } static Intent createMarkMessageAsSpamIntent(Context context, MessageReference messageReference) { Intent intent = new Intent(context, NotificationActionService.class); intent.setAction(ACTION_SPAM); intent.putExtra(EXTRA_ACCOUNT_UUID, messageReference.getAccountUuid()); intent.putExtra(EXTRA_MESSAGE_REFERENCE, messageReference.toIdentityString()); return intent; } private static ArrayList<String> createSingleItemArrayList(MessageReference messageReference) { ArrayList<String> messageReferenceStrings = new ArrayList<>(1); messageReferenceStrings.add(messageReference.toIdentityString()); return messageReferenceStrings; } @Override public int startService(Intent intent, int startId) { Timber.i("NotificationActionService started with startId = %d", startId); String accountUuid = intent.getStringExtra(EXTRA_ACCOUNT_UUID); Preferences preferences = Preferences.getPreferences(this); Account account = preferences.getAccount(accountUuid); if (account == null) { Timber.w("Could not find account for notification action."); return START_NOT_STICKY; } MessagingController controller = MessagingController.getInstance(getApplication()); String action = intent.getAction(); if (ACTION_MARK_AS_READ.equals(action)) { markMessagesAsRead(intent, account, controller); } else if (ACTION_DELETE.equals(action)) { deleteMessages(intent, controller); } else if (ACTION_ARCHIVE.equals(action)) { archiveMessages(intent, account, controller); } else if (ACTION_SPAM.equals(action)) { markMessageAsSpam(intent, account, controller); } else if (ACTION_DISMISS.equals(action)) { Timber.i("Notification dismissed"); } cancelNotifications(intent, account, controller); return START_NOT_STICKY; } private void markMessagesAsRead(Intent intent, Account account, MessagingController controller) { Timber.i("NotificationActionService marking messages as read"); List<String> messageReferenceStrings = intent.getStringArrayListExtra(EXTRA_MESSAGE_REFERENCES); List<MessageReference> messageReferences = toMessageReferenceList(messageReferenceStrings); for (MessageReference messageReference : messageReferences) { String folderName = messageReference.getFolderName(); String uid = messageReference.getUid(); controller.setFlag(account, folderName, uid, Flag.SEEN, true); } } private void deleteMessages(Intent intent, MessagingController controller) { Timber.i("NotificationActionService deleting messages"); List<String> messageReferenceStrings = intent.getStringArrayListExtra(EXTRA_MESSAGE_REFERENCES); List<MessageReference> messageReferences = toMessageReferenceList(messageReferenceStrings); controller.deleteMessages(messageReferences, null); } private void archiveMessages(Intent intent, Account account, MessagingController controller) { Timber.i("NotificationActionService archiving messages"); String archiveFolderName = account.getArchiveFolderName(); if (archiveFolderName == null || (archiveFolderName.equals(account.getSpamFolderName()) && K9.confirmSpam()) || !isMovePossible(controller, account, archiveFolderName)) { Timber.w("Can not archive messages"); return; } List<String> messageReferenceStrings = intent.getStringArrayListExtra(EXTRA_MESSAGE_REFERENCES); List<MessageReference> messageReferences = toMessageReferenceList(messageReferenceStrings); for (MessageReference messageReference : messageReferences) { if (controller.isMoveCapable(messageReference)) { String sourceFolderName = messageReference.getFolderName(); controller.moveMessage(account, sourceFolderName, messageReference, archiveFolderName); } } } private void markMessageAsSpam(Intent intent, Account account, MessagingController controller) { Timber.i("NotificationActionService moving messages to spam"); String messageReferenceString = intent.getStringExtra(EXTRA_MESSAGE_REFERENCE); MessageReference messageReference = MessageReference.parse(messageReferenceString); if (messageReference == null) { Timber.w("Invalid message reference: %s", messageReferenceString); return; } String spamFolderName = account.getSpamFolderName(); if (spamFolderName != null && !K9.confirmSpam() && isMovePossible(controller, account, spamFolderName)) { String sourceFolderName = messageReference.getFolderName(); controller.moveMessage(account, sourceFolderName, messageReference, spamFolderName); } } private void cancelNotifications(Intent intent, Account account, MessagingController controller) { if (intent.hasExtra(EXTRA_MESSAGE_REFERENCE)) { String messageReferenceString = intent.getStringExtra(EXTRA_MESSAGE_REFERENCE); MessageReference messageReference = MessageReference.parse(messageReferenceString); if (messageReference != null) { controller.cancelNotificationForMessage(account, messageReference); } else { Timber.w("Invalid message reference: %s", messageReferenceString); } } else if (intent.hasExtra(EXTRA_MESSAGE_REFERENCES)) { List<String> messageReferenceStrings = intent.getStringArrayListExtra(EXTRA_MESSAGE_REFERENCES); List<MessageReference> messageReferences = toMessageReferenceList(messageReferenceStrings); for (MessageReference messageReference : messageReferences) { controller.cancelNotificationForMessage(account, messageReference); } } else { controller.cancelNotificationsForAccount(account); } } private boolean isMovePossible(MessagingController controller, Account account, String destinationFolderName) { boolean isSpecialFolderConfigured = !K9.FOLDER_NONE.equalsIgnoreCase(destinationFolderName); return isSpecialFolderConfigured && controller.isMoveCapable(account); } }