package com.fsck.k9; import android.content.Context; import android.content.SharedPreferences; import android.net.ConnectivityManager; import android.net.Uri; import android.util.Log; import com.fsck.k9.crypto.Apg; import com.fsck.k9.crypto.CryptoProvider; import com.fsck.k9.helper.Utility; import com.fsck.k9.mail.Address; import com.fsck.k9.mail.MessagingException; import com.fsck.k9.mail.Store; import com.fsck.k9.mail.store.LocalStore; import com.fsck.k9.mail.store.StorageManager; import com.fsck.k9.mail.store.StorageManager.StorageProvider; import com.fsck.k9.view.ColorChip; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Random; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; /** * Account stores all of the settings for a single account defined by the user. It is able to save * and delete itself given a Preferences to work with. Each account is defined by a UUID. */ public class Account implements BaseAccount { /** * Default value for the inbox folder (never changes for POP3 and IMAP) */ public static final String INBOX = "INBOX"; /** * This local folder is used to store messages to be sent. */ public static final String OUTBOX = "K9MAIL_INTERNAL_OUTBOX"; public static final String EXPUNGE_IMMEDIATELY = "EXPUNGE_IMMEDIATELY"; public static final String EXPUNGE_MANUALLY = "EXPUNGE_MANUALLY"; public static final String EXPUNGE_ON_POLL = "EXPUNGE_ON_POLL"; public static final int DELETE_POLICY_NEVER = 0; public static final int DELETE_POLICY_7DAYS = 1; public static final int DELETE_POLICY_ON_DELETE = 2; public static final int DELETE_POLICY_MARK_AS_READ = 3; public static final String TYPE_WIFI = "WIFI"; public static final String TYPE_MOBILE = "MOBILE"; public static final String TYPE_OTHER = "OTHER"; private static final String[] networkTypes = { TYPE_WIFI, TYPE_MOBILE, TYPE_OTHER }; public static final MessageFormat DEFAULT_MESSAGE_FORMAT = MessageFormat.HTML; public static final boolean DEFAULT_MESSAGE_FORMAT_AUTO = false; public static final boolean DEFAULT_MESSAGE_READ_RECEIPT = false; public static final QuoteStyle DEFAULT_QUOTE_STYLE = QuoteStyle.PREFIX; public static final String DEFAULT_QUOTE_PREFIX = ">"; public static final boolean DEFAULT_QUOTED_TEXT_SHOWN = true; public static final boolean DEFAULT_REPLY_AFTER_QUOTE = false; public static final boolean DEFAULT_STRIP_SIGNATURE = true; public static final String ACCOUNT_DESCRIPTION_KEY = "description"; public static final String STORE_URI_KEY = "storeUri"; public static final String TRANSPORT_URI_KEY = "transportUri"; public static final String IDENTITY_NAME_KEY = "name"; public static final String IDENTITY_EMAIL_KEY = "email"; public static final String IDENTITY_DESCRIPTION_KEY = "description"; /** *
* 0 - Never (DELETE_POLICY_NEVER) * 1 - After 7 days (DELETE_POLICY_7DAYS) * 2 - When I delete from inbox (DELETE_POLICY_ON_DELETE) * 3 - Mark as read (DELETE_POLICY_MARK_AS_READ) **/ private int mDeletePolicy; private final String mUuid; private String mStoreUri; /** * Storage provider ID, used to locate and manage the underlying DB/file * storage */ private String mLocalStorageProviderId; private String mTransportUri; private String mDescription; private String mAlwaysBcc; private int mAutomaticCheckIntervalMinutes; private int mDisplayCount; private int mChipColor; private long mLastAutomaticCheckTime; private long mLatestOldMessageSeenTime; private boolean mNotifyNewMail; private boolean mNotifySelfNewMail; private String mInboxFolderName; private String mDraftsFolderName; private String mSentFolderName; private String mTrashFolderName; private String mArchiveFolderName; private String mSpamFolderName; private String mAutoExpandFolderName; private FolderMode mFolderDisplayMode; private FolderMode mFolderSyncMode; private FolderMode mFolderPushMode; private FolderMode mFolderTargetMode; private int mAccountNumber; private boolean mSaveAllHeaders; private boolean mPushPollOnConnect; private boolean mNotifySync; private ScrollButtons mScrollMessageViewButtons; private ScrollButtons mScrollMessageViewMoveButtons; private ShowPictures mShowPictures; private boolean mEnableMoveButtons; private boolean mIsSignatureBeforeQuotedText; private String mExpungePolicy = EXPUNGE_IMMEDIATELY; private int mMaxPushFolders; private int mIdleRefreshMinutes; private boolean goToUnreadMessageSearch; private boolean mNotificationShowsUnreadCount; private final Map
* Right now newly imported accounts are disabled if the settings file didn't contain a * password for the incoming and/or outgoing server. *
*/ private boolean mEnabled; /** * Name of the folder that was last selected for a copy or move operation. * * Note: For now this value isn't persisted. So it will be reset when * K-9 Mail is restarted. */ private String lastSelectedFolderName = null; private Listnull
if not available
* @throws MessagingException
* @see {@link #isAvailable(Context)}
*/
public AccountStats getStats(Context context) throws MessagingException {
if (!isAvailable(context)) {
return null;
}
long startTime = System.currentTimeMillis();
AccountStats stats = new AccountStats();
LocalStore localStore = getLocalStore();
if (K9.measureAccounts()) {
stats.size = localStore.getSize();
}
localStore.getMessageCounts(stats);
long endTime = System.currentTimeMillis();
if (K9.DEBUG)
Log.d(K9.LOG_TAG, "Account.getStats() on " + getDescription() + " took " + (endTime - startTime) + " ms;");
return stats;
}
public synchronized void setChipColor(int color) {
mChipColor = color;
}
public synchronized int getChipColor() {
return mChipColor;
}
public ColorChip generateColorChip() {
return new ColorChip(mChipColor);
}
public String getUuid() {
return mUuid;
}
public Uri getContentUri() {
return Uri.parse("content://accounts/" + getUuid());
}
public synchronized String getStoreUri() {
return mStoreUri;
}
public synchronized void setStoreUri(String storeUri) {
this.mStoreUri = storeUri;
}
public synchronized String getTransportUri() {
return mTransportUri;
}
public synchronized void setTransportUri(String transportUri) {
this.mTransportUri = transportUri;
}
public synchronized String getDescription() {
return mDescription;
}
public synchronized void setDescription(String description) {
this.mDescription = description;
}
public synchronized String getName() {
return identities.get(0).getName();
}
public synchronized void setName(String name) {
identities.get(0).setName(name);
}
public synchronized boolean getSignatureUse() {
return identities.get(0).getSignatureUse();
}
public synchronized void setSignatureUse(boolean signatureUse) {
identities.get(0).setSignatureUse(signatureUse);
}
public synchronized String getSignature() {
return identities.get(0).getSignature();
}
public synchronized void setSignature(String signature) {
identities.get(0).setSignature(signature);
}
public synchronized String getEmail() {
return identities.get(0).getEmail();
}
public synchronized void setEmail(String email) {
identities.get(0).setEmail(email);
}
public synchronized String getAlwaysBcc() {
return mAlwaysBcc;
}
public synchronized void setAlwaysBcc(String alwaysBcc) {
this.mAlwaysBcc = alwaysBcc;
}
/* Have we sent a new mail notification on this account */
public boolean isRingNotified() {
return mRingNotified;
}
public void setRingNotified(boolean ringNotified) {
mRingNotified = ringNotified;
}
public String getLocalStorageProviderId() {
return mLocalStorageProviderId;
}
public void setLocalStorageProviderId(String id) {
if (!mLocalStorageProviderId.equals(id)) {
boolean successful = false;
try {
switchLocalStorage(id);
successful = true;
} catch (MessagingException e) {
Log.e(K9.LOG_TAG, "Switching local storage provider from " +
mLocalStorageProviderId + " to " + id + " failed.", e);
} finally {
// if migration to/from SD-card failed once, it will fail again.
if (!successful) {
return;
}
}
mLocalStorageProviderId = id;
}
}
// public synchronized void setLocalStoreUri(String localStoreUri)
// {
// this.mLocalStoreUri = localStoreUri;
// }
/**
* Returns -1 for never.
*/
public synchronized int getAutomaticCheckIntervalMinutes() {
return mAutomaticCheckIntervalMinutes;
}
/**
* @param automaticCheckIntervalMinutes or -1 for never.
*/
public synchronized boolean setAutomaticCheckIntervalMinutes(int automaticCheckIntervalMinutes) {
int oldInterval = this.mAutomaticCheckIntervalMinutes;
this.mAutomaticCheckIntervalMinutes = automaticCheckIntervalMinutes;
return (oldInterval != automaticCheckIntervalMinutes);
}
public synchronized int getDisplayCount() {
return mDisplayCount;
}
public synchronized void setDisplayCount(int displayCount) {
if (displayCount != -1) {
this.mDisplayCount = displayCount;
} else {
this.mDisplayCount = K9.DEFAULT_VISIBLE_LIMIT;
}
resetVisibleLimits();
}
public synchronized long getLastAutomaticCheckTime() {
return mLastAutomaticCheckTime;
}
public synchronized void setLastAutomaticCheckTime(long lastAutomaticCheckTime) {
this.mLastAutomaticCheckTime = lastAutomaticCheckTime;
}
public synchronized long getLatestOldMessageSeenTime() {
return mLatestOldMessageSeenTime;
}
public synchronized void setLatestOldMessageSeenTime(long latestOldMessageSeenTime) {
this.mLatestOldMessageSeenTime = latestOldMessageSeenTime;
}
public synchronized boolean isNotifyNewMail() {
return mNotifyNewMail;
}
public synchronized void setNotifyNewMail(boolean notifyNewMail) {
this.mNotifyNewMail = notifyNewMail;
}
public synchronized int getDeletePolicy() {
return mDeletePolicy;
}
public synchronized void setDeletePolicy(int deletePolicy) {
this.mDeletePolicy = deletePolicy;
}
public boolean isSpecialFolder(String folderName) {
if (folderName != null && (folderName.equalsIgnoreCase(getInboxFolderName()) ||
folderName.equals(getTrashFolderName()) ||
folderName.equals(getDraftsFolderName()) ||
folderName.equals(getArchiveFolderName()) ||
folderName.equals(getSpamFolderName()) ||
folderName.equals(getOutboxFolderName()) ||
folderName.equals(getSentFolderName()) ||
folderName.equals(getErrorFolderName()))) {
return true;
} else {
return false;
}
}
public synchronized String getDraftsFolderName() {
return mDraftsFolderName;
}
public synchronized void setDraftsFolderName(String draftsFolderName) {
mDraftsFolderName = draftsFolderName;
}
public synchronized String getSentFolderName() {
return mSentFolderName;
}
public synchronized String getErrorFolderName() {
return K9.ERROR_FOLDER_NAME;
}
public synchronized void setSentFolderName(String sentFolderName) {
mSentFolderName = sentFolderName;
}
public synchronized String getTrashFolderName() {
return mTrashFolderName;
}
public synchronized void setTrashFolderName(String trashFolderName) {
mTrashFolderName = trashFolderName;
}
public synchronized String getArchiveFolderName() {
return mArchiveFolderName;
}
public synchronized void setArchiveFolderName(String archiveFolderName) {
mArchiveFolderName = archiveFolderName;
}
public synchronized String getSpamFolderName() {
return mSpamFolderName;
}
public synchronized void setSpamFolderName(String spamFolderName) {
mSpamFolderName = spamFolderName;
}
public synchronized String getOutboxFolderName() {
return OUTBOX;
}
public synchronized String getAutoExpandFolderName() {
return mAutoExpandFolderName;
}
public synchronized void setAutoExpandFolderName(String autoExpandFolderName) {
mAutoExpandFolderName = autoExpandFolderName;
}
public synchronized int getAccountNumber() {
return mAccountNumber;
}
public synchronized FolderMode getFolderDisplayMode() {
return mFolderDisplayMode;
}
public synchronized boolean setFolderDisplayMode(FolderMode displayMode) {
FolderMode oldDisplayMode = mFolderDisplayMode;
mFolderDisplayMode = displayMode;
return oldDisplayMode != displayMode;
}
public synchronized FolderMode getFolderSyncMode() {
return mFolderSyncMode;
}
public synchronized boolean setFolderSyncMode(FolderMode syncMode) {
FolderMode oldSyncMode = mFolderSyncMode;
mFolderSyncMode = syncMode;
if (syncMode == FolderMode.NONE && oldSyncMode != FolderMode.NONE) {
return true;
}
if (syncMode != FolderMode.NONE && oldSyncMode == FolderMode.NONE) {
return true;
}
return false;
}
public synchronized FolderMode getFolderPushMode() {
return mFolderPushMode;
}
public synchronized boolean setFolderPushMode(FolderMode pushMode) {
FolderMode oldPushMode = mFolderPushMode;
mFolderPushMode = pushMode;
return pushMode != oldPushMode;
}
public synchronized boolean isShowOngoing() {
return mNotifySync;
}
public synchronized void setShowOngoing(boolean showOngoing) {
this.mNotifySync = showOngoing;
}
public synchronized ScrollButtons getScrollMessageViewButtons() {
return mScrollMessageViewButtons;
}
public synchronized void setScrollMessageViewButtons(ScrollButtons scrollMessageViewButtons) {
mScrollMessageViewButtons = scrollMessageViewButtons;
}
public synchronized ScrollButtons getScrollMessageViewMoveButtons() {
return mScrollMessageViewMoveButtons;
}
public synchronized void setScrollMessageViewMoveButtons(ScrollButtons scrollMessageViewButtons) {
mScrollMessageViewMoveButtons = scrollMessageViewButtons;
}
public synchronized ShowPictures getShowPictures() {
return mShowPictures;
}
public synchronized void setShowPictures(ShowPictures showPictures) {
mShowPictures = showPictures;
}
public synchronized FolderMode getFolderTargetMode() {
return mFolderTargetMode;
}
public synchronized void setFolderTargetMode(FolderMode folderTargetMode) {
mFolderTargetMode = folderTargetMode;
}
public synchronized boolean isSignatureBeforeQuotedText() {
return mIsSignatureBeforeQuotedText;
}
public synchronized void setSignatureBeforeQuotedText(boolean mIsSignatureBeforeQuotedText) {
this.mIsSignatureBeforeQuotedText = mIsSignatureBeforeQuotedText;
}
public synchronized boolean isNotifySelfNewMail() {
return mNotifySelfNewMail;
}
public synchronized void setNotifySelfNewMail(boolean notifySelfNewMail) {
mNotifySelfNewMail = notifySelfNewMail;
}
public synchronized String getExpungePolicy() {
return mExpungePolicy;
}
public synchronized void setExpungePolicy(String expungePolicy) {
mExpungePolicy = expungePolicy;
}
public synchronized int getMaxPushFolders() {
return mMaxPushFolders;
}
public synchronized boolean setMaxPushFolders(int maxPushFolders) {
int oldMaxPushFolders = mMaxPushFolders;
mMaxPushFolders = maxPushFolders;
return oldMaxPushFolders != maxPushFolders;
}
public LocalStore getLocalStore() throws MessagingException {
return Store.getLocalInstance(this, K9.app);
}
public Store getRemoteStore() throws MessagingException {
return Store.getRemoteInstance(this);
}
// It'd be great if this actually went into the store implementation
// to get this, but that's expensive and not easily accessible
// during initialization
public boolean isSearchByDateCapable() {
if (getStoreUri().startsWith("imap")) {
return true;
} else {
return false;
}
}
@Override
public synchronized String toString() {
return mDescription;
}
public synchronized void setCompression(String networkType, boolean useCompression) {
compressionMap.put(networkType, useCompression);
}
public synchronized boolean useCompression(String networkType) {
Boolean useCompression = compressionMap.get(networkType);
if (useCompression == null) {
return true;
} else {
return useCompression;
}
}
public boolean useCompression(int type) {
String networkType = TYPE_OTHER;
switch (type) {
case ConnectivityManager.TYPE_MOBILE:
networkType = TYPE_MOBILE;
break;
case ConnectivityManager.TYPE_WIFI:
networkType = TYPE_WIFI;
break;
}
return useCompression(networkType);
}
@Override
public boolean equals(Object o) {
if (o instanceof Account) {
return ((Account)o).mUuid.equals(mUuid);
}
return super.equals(o);
}
@Override
public int hashCode() {
return mUuid.hashCode();
}
private synchronized Listnull
.
* @throws MessagingException
*/
public void switchLocalStorage(final String newStorageProviderId) throws MessagingException {
if (!mLocalStorageProviderId.equals(newStorageProviderId)) {
getLocalStore().switchLocalStorage(newStorageProviderId);
}
}
public synchronized boolean goToUnreadMessageSearch() {
return goToUnreadMessageSearch;
}
public synchronized void setGoToUnreadMessageSearch(boolean goToUnreadMessageSearch) {
this.goToUnreadMessageSearch = goToUnreadMessageSearch;
}
public boolean isNotificationShowsUnreadCount() {
return mNotificationShowsUnreadCount;
}
public void setNotificationShowsUnreadCount(boolean notificationShowsUnreadCount) {
this.mNotificationShowsUnreadCount = notificationShowsUnreadCount;
}
public synchronized boolean subscribedFoldersOnly() {
return subscribedFoldersOnly;
}
public synchronized void setSubscribedFoldersOnly(boolean subscribedFoldersOnly) {
this.subscribedFoldersOnly = subscribedFoldersOnly;
}
public synchronized int getMaximumPolledMessageAge() {
return maximumPolledMessageAge;
}
public synchronized void setMaximumPolledMessageAge(int maximumPolledMessageAge) {
this.maximumPolledMessageAge = maximumPolledMessageAge;
}
public synchronized int getMaximumAutoDownloadMessageSize() {
return maximumAutoDownloadMessageSize;
}
public synchronized void setMaximumAutoDownloadMessageSize(int maximumAutoDownloadMessageSize) {
this.maximumAutoDownloadMessageSize = maximumAutoDownloadMessageSize;
}
public Date getEarliestPollDate() {
int age = getMaximumPolledMessageAge();
if (age >= 0) {
Calendar now = Calendar.getInstance();
now.set(Calendar.HOUR_OF_DAY, 0);
now.set(Calendar.MINUTE, 0);
now.set(Calendar.SECOND, 0);
now.set(Calendar.MILLISECOND, 0);
if (age < 28) {
now.add(Calendar.DATE, age * -1);
} else switch (age) {
case 28:
now.add(Calendar.MONTH, -1);
break;
case 56:
now.add(Calendar.MONTH, -2);
break;
case 84:
now.add(Calendar.MONTH, -3);
break;
case 168:
now.add(Calendar.MONTH, -6);
break;
case 365:
now.add(Calendar.YEAR, -1);
break;
}
return now.getTime();
} else {
return null;
}
}
public MessageFormat getMessageFormat() {
return mMessageFormat;
}
public void setMessageFormat(MessageFormat messageFormat) {
this.mMessageFormat = messageFormat;
}
public synchronized boolean isMessageReadReceiptAlways() {
return mMessageReadReceipt;
}
public synchronized void setMessageReadReceipt(boolean messageReadReceipt) {
mMessageReadReceipt = messageReadReceipt;
}
public QuoteStyle getQuoteStyle() {
return mQuoteStyle;
}
public void setQuoteStyle(QuoteStyle quoteStyle) {
this.mQuoteStyle = quoteStyle;
}
public synchronized String getQuotePrefix() {
return mQuotePrefix;
}
public synchronized void setQuotePrefix(String quotePrefix) {
mQuotePrefix = quotePrefix;
}
public synchronized boolean isDefaultQuotedTextShown() {
return mDefaultQuotedTextShown;
}
public synchronized void setDefaultQuotedTextShown(boolean shown) {
mDefaultQuotedTextShown = shown;
}
public synchronized boolean isReplyAfterQuote() {
return mReplyAfterQuote;
}
public synchronized void setReplyAfterQuote(boolean replyAfterQuote) {
mReplyAfterQuote = replyAfterQuote;
}
public synchronized boolean isStripSignature() {
return mStripSignature;
}
public synchronized void setStripSignature(boolean stripSignature) {
mStripSignature = stripSignature;
}
public boolean getEnableMoveButtons() {
return mEnableMoveButtons;
}
public void setEnableMoveButtons(boolean enableMoveButtons) {
mEnableMoveButtons = enableMoveButtons;
}
public String getCryptoApp() {
return mCryptoApp;
}
public void setCryptoApp(String cryptoApp) {
mCryptoApp = cryptoApp;
// invalidate the provider
mCryptoProvider = null;
}
public boolean getCryptoAutoSignature() {
return mCryptoAutoSignature;
}
public void setCryptoAutoSignature(boolean cryptoAutoSignature) {
mCryptoAutoSignature = cryptoAutoSignature;
}
public boolean isCryptoAutoEncrypt() {
return mCryptoAutoEncrypt;
}
public void setCryptoAutoEncrypt(boolean cryptoAutoEncrypt) {
mCryptoAutoEncrypt = cryptoAutoEncrypt;
}
public String getInboxFolderName() {
return mInboxFolderName;
}
public void setInboxFolderName(String mInboxFolderName) {
this.mInboxFolderName = mInboxFolderName;
}
public synchronized boolean syncRemoteDeletions() {
return mSyncRemoteDeletions;
}
public synchronized void setSyncRemoteDeletions(boolean syncRemoteDeletions) {
mSyncRemoteDeletions = syncRemoteDeletions;
}
public synchronized String getLastSelectedFolderName() {
return lastSelectedFolderName;
}
public synchronized void setLastSelectedFolderName(String folderName) {
lastSelectedFolderName = folderName;
}
public synchronized CryptoProvider getCryptoProvider() {
if (mCryptoProvider == null) {
mCryptoProvider = CryptoProvider.createInstance(getCryptoApp());
}
return mCryptoProvider;
}
public synchronized NotificationSetting getNotificationSetting() {
return mNotificationSetting;
}
/**
* @return true
if our {@link StorageProvider} is ready. (e.g.
* card inserted)
*/
public boolean isAvailable(Context context) {
String localStorageProviderId = getLocalStorageProviderId();
if (localStorageProviderId == null) {
return true; // defaults to internal memory
}
return StorageManager.getInstance(K9.app).isReady(localStorageProviderId);
}
public synchronized boolean isEnabled() {
return mEnabled;
}
public synchronized void setEnabled(boolean enabled) {
mEnabled = enabled;
}
}