Merge pull request #4716 from k9mail/remove_StoreConfig

Remove StoreConfig
This commit is contained in:
cketti 2020-05-01 18:11:18 +02:00 committed by GitHub
commit 26b7823382
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
40 changed files with 281 additions and 254 deletions

View file

@ -17,7 +17,6 @@ import android.text.TextUtils;
import com.fsck.k9.backend.api.SyncConfig.ExpungePolicy;
import com.fsck.k9.mail.Address;
import com.fsck.k9.mail.NetworkType;
import com.fsck.k9.mail.store.StoreConfig;
import com.fsck.k9.mailstore.StorageManager;
import com.fsck.k9.mailstore.StorageManager.StorageProvider;
import org.jetbrains.annotations.NotNull;
@ -27,7 +26,7 @@ import org.jetbrains.annotations.Nullable;
/**
* Account stores all of the settings for a single account defined by the user. Each account is defined by a UUID.
*/
public class Account implements BaseAccount, StoreConfig {
public class Account implements BaseAccount {
/**
* This local folder is used to store messages to be sent.
*/

View file

@ -476,7 +476,9 @@ public class MessagingController {
Backend backend = getBackend(acct);
List<String> messageServerIds = backend.search(folderServerId, query, requiredFlags, forbiddenFlags);
boolean performFullTextSearch = acct.isRemoteSearchFullText();
List<String> messageServerIds = backend.search(folderServerId, query, requiredFlags, forbiddenFlags,
performFullTextSearch);
Timber.i("Remote search got %d results", messageServerIds.size());
@ -560,7 +562,8 @@ public class MessagingController {
LocalMessage localMessage = localFolder.getMessage(messageServerId);
if (localMessage == null) {
Message message = backend.fetchMessage(folderServerId, messageServerId, fetchProfile);
int maxDownloadSize = account.getMaximumAutoDownloadMessageSize();
Message message = backend.fetchMessage(folderServerId, messageServerId, fetchProfile, maxDownloadSize);
localFolder.appendMessages(Collections.singletonList(message));
}
}
@ -1257,7 +1260,8 @@ public class MessagingController {
FetchProfile fp = new FetchProfile();
fp.add(FetchProfile.Item.BODY);
fp.add(FetchProfile.Item.FLAGS);
Message remoteMessage = backend.fetchMessage(folder, uid, fp);
int maxDownloadSize = account.getMaximumAutoDownloadMessageSize();
Message remoteMessage = backend.fetchMessage(folder, uid, fp, maxDownloadSize);
localFolder.appendMessages(Collections.singletonList(remoteMessage));
}

View file

@ -244,7 +244,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
when(localNewMessage1.getUid()).thenReturn("newMessageUid1");
when(localNewMessage2.getUid()).thenReturn("newMessageUid2");
when(backend.search(eq(FOLDER_NAME), anyString(), nullable(Set.class), nullable(Set.class)))
when(backend.search(eq(FOLDER_NAME), anyString(), nullable(Set.class), nullable(Set.class), eq(false)))
.thenReturn(remoteMessages);
when(localFolder.extractNewMessages(ArgumentMatchers.<String>anyList())).thenReturn(newRemoteMessages);
when(localFolder.getMessage("newMessageUid1")).thenReturn(localNewMessage1);
@ -269,7 +269,8 @@ public class MessagingControllerTest extends K9RobolectricTest {
}).when(backend).fetchMessage(
eq(FOLDER_NAME),
eq("newMessageUid2"),
any(FetchProfile.class));
any(FetchProfile.class),
eq(MAXIMUM_SMALL_MESSAGE_SIZE));
reqFlags = Collections.singleton(Flag.ANSWERED);
forbiddenFlags = Collections.singleton(Flag.DELETED);
@ -291,7 +292,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(backend).search(FOLDER_NAME, "query", reqFlags, forbiddenFlags);
verify(backend).search(FOLDER_NAME, "query", reqFlags, forbiddenFlags, false);
}
@Test
@ -327,7 +328,8 @@ public class MessagingControllerTest extends K9RobolectricTest {
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(backend).fetchMessage(eq(FOLDER_NAME), eq("newMessageUid2"), fetchProfileCaptor.capture());
verify(backend).fetchMessage(eq(FOLDER_NAME), eq("newMessageUid2"), fetchProfileCaptor.capture(),
eq(MAXIMUM_SMALL_MESSAGE_SIZE));
}
@Test
@ -336,13 +338,14 @@ public class MessagingControllerTest extends K9RobolectricTest {
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(backend, never()).fetchMessage(eq(FOLDER_NAME), eq("newMessageUid1"), fetchProfileCaptor.capture());
verify(backend, never()).fetchMessage(eq(FOLDER_NAME), eq("newMessageUid1"), fetchProfileCaptor.capture(),
eq(MAXIMUM_SMALL_MESSAGE_SIZE));
}
@Test
public void searchRemoteMessagesSynchronous_shouldNotifyOnFailure() throws Exception {
setupRemoteSearch();
when(backend.search(anyString(), anyString(), nullable(Set.class), nullable(Set.class)))
when(backend.search(anyString(), anyString(), nullable(Set.class), nullable(Set.class), eq(false)))
.thenThrow(new MessagingException("Test"));
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
@ -353,7 +356,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
@Test
public void searchRemoteMessagesSynchronous_shouldNotifyOnFinish() throws Exception {
setupRemoteSearch();
when(backend.search(anyString(), nullable(String.class), nullable(Set.class), nullable(Set.class)))
when(backend.search(anyString(), nullable(String.class), nullable(Set.class), nullable(Set.class), eq(false)))
.thenThrow(new MessagingException("Test"));
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);

View file

@ -8,11 +8,13 @@ import com.fsck.k9.backend.api.Backend
import com.fsck.k9.backend.imap.ImapBackend
import com.fsck.k9.backend.imap.ImapStoreUriCreator
import com.fsck.k9.backend.imap.ImapStoreUriDecoder
import com.fsck.k9.mail.NetworkType
import com.fsck.k9.mail.ServerSettings
import com.fsck.k9.mail.oauth.OAuth2TokenProvider
import com.fsck.k9.mail.power.PowerManager
import com.fsck.k9.mail.ssl.TrustedSocketFactory
import com.fsck.k9.mail.store.imap.ImapStore
import com.fsck.k9.mail.store.imap.ImapStoreConfig
import com.fsck.k9.mail.transport.smtp.SmtpTransport
import com.fsck.k9.mail.transport.smtp.SmtpTransportUriCreator
import com.fsck.k9.mail.transport.smtp.SmtpTransportUriDecoder
@ -37,15 +39,27 @@ class ImapBackendFactory(
private fun createImapStore(account: Account): ImapStore {
val oAuth2TokenProvider: OAuth2TokenProvider? = null
val serverSettings = ImapStoreUriDecoder.decode(account.storeUri)
val config = createImapStoreConfig(account)
return ImapStore(
serverSettings,
account,
config,
trustedSocketFactory,
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager,
oAuth2TokenProvider
)
}
private fun createImapStoreConfig(account: Account): ImapStoreConfig {
return object : ImapStoreConfig {
override val logLabel
get() = account.description
override fun isSubscribedFoldersOnly() = account.isSubscribedFoldersOnly
override fun useCompression(type: NetworkType) = account.useCompression(type)
}
}
private fun createSmtpTransport(account: Account): SmtpTransport {
val serverSettings = decodeTransportUri(account.transportUri)
val oauth2TokenProvider: OAuth2TokenProvider? = null

View file

@ -31,7 +31,7 @@ class Pop3BackendFactory(
private fun createPop3Store(account: Account): Pop3Store {
val serverSettings = decodeStoreUri(account.storeUri)
return Pop3Store(serverSettings, account, trustedSocketFactory)
return Pop3Store(serverSettings, trustedSocketFactory)
}
private fun createSmtpTransport(account: Account): SmtpTransport {

View file

@ -8,8 +8,8 @@ import com.fsck.k9.backend.webdav.WebDavStoreUriCreator
import com.fsck.k9.backend.webdav.WebDavStoreUriDecoder
import com.fsck.k9.mail.ServerSettings
import com.fsck.k9.mail.ssl.TrustManagerFactory
import com.fsck.k9.mail.store.webdav.DraftsFolderProvider
import com.fsck.k9.mail.store.webdav.WebDavStore
import com.fsck.k9.mail.store.webdav.WebDavStoreSettings
import com.fsck.k9.mail.transport.WebDavTransport
import com.fsck.k9.mailstore.K9BackendStorageFactory
@ -23,13 +23,16 @@ class WebDavBackendFactory(
val accountName = account.displayName
val backendStorage = backendStorageFactory.createBackendStorage(account)
val serverSettings = WebDavStoreUriDecoder.decode(account.storeUri)
val webDavStore = createWebDavStore(serverSettings, account)
val webDavTransport = WebDavTransport(trustManagerFactory, serverSettings, account)
val draftsFolderProvider = createDraftsFolderProvider(account)
val webDavStore = WebDavStore(trustManagerFactory, serverSettings, draftsFolderProvider)
val webDavTransport = WebDavTransport(trustManagerFactory, serverSettings, draftsFolderProvider)
return WebDavBackend(accountName, backendStorage, webDavStore, webDavTransport)
}
private fun createWebDavStore(serverSettings: WebDavStoreSettings, account: Account): WebDavStore {
return WebDavStore(trustManagerFactory, serverSettings, account)
private fun createDraftsFolderProvider(account: Account): DraftsFolderProvider {
return DraftsFolderProvider {
account.draftsFolder ?: error("No Drafts folder configured")
}
}
override fun decodeStoreUri(storeUri: String): ServerSettings {

View file

@ -8,11 +8,13 @@ import com.fsck.k9.backend.api.Backend
import com.fsck.k9.backend.imap.ImapBackend
import com.fsck.k9.backend.imap.ImapStoreUriCreator
import com.fsck.k9.backend.imap.ImapStoreUriDecoder
import com.fsck.k9.mail.NetworkType
import com.fsck.k9.mail.ServerSettings
import com.fsck.k9.mail.oauth.OAuth2TokenProvider
import com.fsck.k9.mail.power.PowerManager
import com.fsck.k9.mail.ssl.TrustedSocketFactory
import com.fsck.k9.mail.store.imap.ImapStore
import com.fsck.k9.mail.store.imap.ImapStoreConfig
import com.fsck.k9.mail.transport.smtp.SmtpTransport
import com.fsck.k9.mail.transport.smtp.SmtpTransportUriCreator
import com.fsck.k9.mail.transport.smtp.SmtpTransportUriDecoder
@ -37,15 +39,27 @@ class ImapBackendFactory(
private fun createImapStore(account: Account): ImapStore {
val oAuth2TokenProvider: OAuth2TokenProvider? = null
val serverSettings = ImapStoreUriDecoder.decode(account.storeUri)
val config = createImapStoreConfig(account)
return ImapStore(
serverSettings,
account,
config,
trustedSocketFactory,
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager,
oAuth2TokenProvider
)
}
private fun createImapStoreConfig(account: Account): ImapStoreConfig {
return object : ImapStoreConfig {
override val logLabel
get() = account.description
override fun isSubscribedFoldersOnly() = account.isSubscribedFoldersOnly
override fun useCompression(type: NetworkType) = account.useCompression(type)
}
}
private fun createSmtpTransport(account: Account): SmtpTransport {
val serverSettings = decodeTransportUri(account.transportUri)
val oauth2TokenProvider: OAuth2TokenProvider? = null

View file

@ -31,7 +31,7 @@ class Pop3BackendFactory(
private fun createPop3Store(account: Account): Pop3Store {
val serverSettings = decodeStoreUri(account.storeUri)
return Pop3Store(serverSettings, account, trustedSocketFactory)
return Pop3Store(serverSettings, trustedSocketFactory)
}
private fun createSmtpTransport(account: Account): SmtpTransport {

View file

@ -8,8 +8,8 @@ import com.fsck.k9.backend.webdav.WebDavStoreUriCreator
import com.fsck.k9.backend.webdav.WebDavStoreUriDecoder
import com.fsck.k9.mail.ServerSettings
import com.fsck.k9.mail.ssl.TrustManagerFactory
import com.fsck.k9.mail.store.webdav.DraftsFolderProvider
import com.fsck.k9.mail.store.webdav.WebDavStore
import com.fsck.k9.mail.store.webdav.WebDavStoreSettings
import com.fsck.k9.mail.transport.WebDavTransport
import com.fsck.k9.mailstore.K9BackendStorageFactory
@ -23,13 +23,16 @@ class WebDavBackendFactory(
val accountName = account.displayName
val backendStorage = backendStorageFactory.createBackendStorage(account)
val serverSettings = WebDavStoreUriDecoder.decode(account.storeUri)
val webDavStore = createWebDavStore(serverSettings, account)
val webDavTransport = WebDavTransport(trustManagerFactory, serverSettings, account)
val draftsFolderProvider = createDraftsFolderProvider(account)
val webDavStore = WebDavStore(trustManagerFactory, serverSettings, draftsFolderProvider)
val webDavTransport = WebDavTransport(trustManagerFactory, serverSettings, draftsFolderProvider)
return WebDavBackend(accountName, backendStorage, webDavStore, webDavTransport)
}
private fun createWebDavStore(serverSettings: WebDavStoreSettings, account: Account): WebDavStore {
return WebDavStore(trustManagerFactory, serverSettings, account)
private fun createDraftsFolderProvider(account: Account): DraftsFolderProvider {
return DraftsFolderProvider {
account.draftsFolder ?: error("No Drafts folder configured")
}
}
override fun decodeStoreUri(storeUri: String): ServerSettings {

View file

@ -71,11 +71,17 @@ interface Backend {
folderServerId: String,
query: String?,
requiredFlags: Set<Flag>?,
forbiddenFlags: Set<Flag>?
forbiddenFlags: Set<Flag>?,
performFullTextSearch: Boolean
): List<String>
@Throws(MessagingException::class)
fun fetchMessage(folderServerId: String, messageServerId: String, fetchProfile: FetchProfile): Message
fun fetchMessage(
folderServerId: String,
messageServerId: String,
fetchProfile: FetchProfile,
maxDownloadSize: Int
): Message
@Throws(MessagingException::class)
fun fetchPart(folderServerId: String, messageServerId: String, part: Part, bodyFactory: BodyFactory)

View file

@ -10,7 +10,12 @@ import com.fsck.k9.mail.store.imap.ImapStore
internal class CommandFetchMessage(private val imapStore: ImapStore) {
fun fetchMessage(folderServerId: String, messageServerId: String, fetchProfile: FetchProfile): Message {
fun fetchMessage(
folderServerId: String,
messageServerId: String,
fetchProfile: FetchProfile,
maxDownloadSize: Int
): Message {
val folder = imapStore.getFolder(folderServerId)
try {
folder.open(ImapFolder.OPEN_MODE_RO)
@ -23,10 +28,10 @@ internal class CommandFetchMessage(private val imapStore: ImapStore) {
val headerFetchProfile = fetchProfile.without(FetchProfile.Item.STRUCTURE)
val structureFetchProfile = FetchProfile().apply { add(FetchProfile.Item.STRUCTURE) }
fetchMessage(folder, message, headerFetchProfile)
fetchMessage(folder, message, structureFetchProfile)
fetchMessage(folder, message, headerFetchProfile, maxDownloadSize)
fetchMessage(folder, message, structureFetchProfile, maxDownloadSize)
} else {
fetchMessage(folder, message, fetchProfile)
fetchMessage(folder, message, fetchProfile, maxDownloadSize)
}
return message
@ -41,14 +46,19 @@ internal class CommandFetchMessage(private val imapStore: ImapStore) {
folder.open(ImapFolder.OPEN_MODE_RW)
val message = folder.getMessage(messageServerId)
folder.fetchPart(message, part, null, bodyFactory)
folder.fetchPart(message, part, null, bodyFactory, -1)
} finally {
folder.close()
}
}
private fun fetchMessage(remoteFolder: ImapFolder, message: ImapMessage, fetchProfile: FetchProfile) {
remoteFolder.fetch(listOf(message), fetchProfile, null)
private fun fetchMessage(
remoteFolder: ImapFolder,
message: ImapMessage,
fetchProfile: FetchProfile,
maxDownloadSize: Int
) {
remoteFolder.fetch(listOf(message), fetchProfile, null, maxDownloadSize)
}
private fun FetchProfile.without(item: FetchProfile.Item) = FetchProfile().apply {

View file

@ -9,11 +9,12 @@ internal class CommandSearch(private val imapStore: ImapStore) {
folderServerId: String,
query: String?,
requiredFlags: Set<Flag>?,
forbiddenFlags: Set<Flag>?
forbiddenFlags: Set<Flag>?,
performFullTextSearch: Boolean
): List<String> {
val folder = imapStore.getFolder(folderServerId)
try {
return folder.search(query, requiredFlags, forbiddenFlags)
return folder.search(query, requiredFlags, forbiddenFlags, performFullTextSearch)
.sortedWith(UidReverseComparator())
.map { it.uid }
} finally {

View file

@ -182,16 +182,16 @@ public class ImapBackend implements Backend {
@NotNull
@Override
public List<String> search(@NotNull String folderServerId, @Nullable String query,
@Nullable Set<? extends Flag> requiredFlags, @Nullable Set<? extends Flag> forbiddenFlags)
throws MessagingException {
return commandSearch.search(folderServerId, query, requiredFlags, forbiddenFlags);
@Nullable Set<? extends Flag> requiredFlags, @Nullable Set<? extends Flag> forbiddenFlags,
boolean performFullTextSearch) {
return commandSearch.search(folderServerId, query, requiredFlags, forbiddenFlags, performFullTextSearch);
}
@NotNull
@Override
public Message fetchMessage(@NotNull String folderServerId, @NotNull String messageServerId,
@NotNull FetchProfile fetchProfile) throws MessagingException {
return commandFetchMessage.fetchMessage(folderServerId, messageServerId, fetchProfile);
@NotNull FetchProfile fetchProfile, int maxDownloadSize) {
return commandFetchMessage.fetchMessage(folderServerId, messageServerId, fetchProfile, maxDownloadSize);
}
@Override

View file

@ -348,6 +348,7 @@ class ImapSync {
* be very fast and at very worst will be a single up of a few bytes and a single
* download of 625k.
*/
int maxDownloadSize = syncConfig.getMaximumAutoDownloadMessageSize();
FetchProfile fp = new FetchProfile();
//TODO: Only fetch small and large messages if we have some
fp.add(FetchProfile.Item.BODY);
@ -362,7 +363,7 @@ class ImapSync {
fp = new FetchProfile();
fp.add(FetchProfile.Item.STRUCTURE);
downloadLargeMessages(remoteFolder, backendFolder, largeMessages, progress, newMessages, todo, fp,
lastUid, listener);
lastUid, listener, maxDownloadSize);
largeMessages.clear();
/*
@ -478,7 +479,8 @@ class ImapSync {
// FIXME this method is almost never invoked by various Stores! Don't rely on it unless fixed!!
}
});
},
syncConfig.getMaximumAutoDownloadMessageSize());
}
private void downloadSmallMessages(
@ -532,7 +534,8 @@ class ImapSync {
@Override
public void messagesFinished(int total) {
}
});
},
-1);
Timber.d("SYNC: Done fetching small messages for folder %s", folder);
}
@ -546,17 +549,18 @@ class ImapSync {
final int todo,
FetchProfile fp,
Long lastUid,
SyncListener listener) throws MessagingException {
SyncListener listener,
int maxDownloadSize) throws MessagingException {
final String folder = remoteFolder.getServerId();
Timber.d("SYNC: Fetching large messages for folder %s", folder);
remoteFolder.fetch(largeMessages, fp, null);
remoteFolder.fetch(largeMessages, fp, null, maxDownloadSize);
for (ImapMessage message : largeMessages) {
if (message.getBody() == null) {
downloadSaneBody(remoteFolder, backendFolder, message);
downloadSaneBody(remoteFolder, backendFolder, message, maxDownloadSize);
} else {
downloadPartial(remoteFolder, backendFolder, message);
downloadPartial(remoteFolder, backendFolder, message, maxDownloadSize);
}
String messageServerId = message.getUid();
@ -606,7 +610,8 @@ class ImapSync {
}
}
remoteFolder.fetch(undeletedMessages, fp, null);
int maxDownloadSize = syncConfig.getMaximumAutoDownloadMessageSize();
remoteFolder.fetch(undeletedMessages, fp, null, maxDownloadSize);
for (ImapMessage remoteMessage : syncFlagMessages) {
boolean messageChanged = syncFlags(syncConfig, backendFolder, remoteMessage);
if (messageChanged) {
@ -617,8 +622,8 @@ class ImapSync {
}
}
private void downloadSaneBody(ImapFolder remoteFolder, BackendFolder backendFolder, ImapMessage message)
throws MessagingException {
private void downloadSaneBody(ImapFolder remoteFolder, BackendFolder backendFolder, ImapMessage message,
int maxDownloadSize) throws MessagingException {
/*
* The provider was unable to get the structure of the message, so
* we'll download a reasonable portion of the messge and mark it as
@ -633,14 +638,14 @@ class ImapSync {
* they equal we can mark this SYNCHRONIZED instead of PARTIALLY_SYNCHRONIZED
*/
remoteFolder.fetch(Collections.singletonList(message), fp, null);
remoteFolder.fetch(Collections.singletonList(message), fp, null, maxDownloadSize);
// Store the updated message locally
backendFolder.savePartialMessage(message);
}
private void downloadPartial(ImapFolder remoteFolder, BackendFolder backendFolder, ImapMessage message)
throws MessagingException {
private void downloadPartial(ImapFolder remoteFolder, BackendFolder backendFolder, ImapMessage message,
int maxDownloadSize) throws MessagingException {
/*
* We have a structure to deal with, from which
* we can pull down the parts we want to actually store.
@ -655,7 +660,7 @@ class ImapSync {
*/
BodyFactory bodyFactory = new DefaultBodyFactory();
for (Part part : viewables) {
remoteFolder.fetchPart(message, part, null, bodyFactory);
remoteFolder.fetchPart(message, part, null, bodyFactory, maxDownloadSize);
}
// Store the updated message locally
backendFolder.savePartialMessage(message);

View file

@ -211,7 +211,7 @@ public class ImapSyncTest {
imapSync.sync(FOLDER_NAME, syncConfig, listener);
verify(remoteFolder, atLeastOnce()).fetch(any(List.class), fetchProfileCaptor.capture(),
nullable(MessageRetrievalListener.class));
nullable(MessageRetrievalListener.class), anyInt());
assertTrue(fetchProfileCaptor.getAllValues().get(0).contains(FetchProfile.Item.FLAGS));
assertTrue(fetchProfileCaptor.getAllValues().get(0).contains(FetchProfile.Item.ENVELOPE));
assertEquals(2, fetchProfileCaptor.getAllValues().get(0).size());
@ -227,7 +227,7 @@ public class ImapSyncTest {
imapSync.sync(FOLDER_NAME, syncConfig, listener);
verify(remoteFolder, atLeast(2)).fetch(any(List.class), fetchProfileCaptor.capture(),
nullable(MessageRetrievalListener.class));
nullable(MessageRetrievalListener.class), anyInt());
assertEquals(1, fetchProfileCaptor.getAllValues().get(1).size());
assertTrue(fetchProfileCaptor.getAllValues().get(1).contains(FetchProfile.Item.BODY));
}
@ -243,7 +243,7 @@ public class ImapSyncTest {
//TODO: Don't bother fetching messages of a size we don't have
verify(remoteFolder, atLeast(4)).fetch(any(List.class), fetchProfileCaptor.capture(),
nullable(MessageRetrievalListener.class));
nullable(MessageRetrievalListener.class), anyInt());
assertEquals(1, fetchProfileCaptor.getAllValues().get(2).size());
assertEquals(FetchProfile.Item.STRUCTURE, fetchProfileCaptor.getAllValues().get(2).get(0));
assertEquals(1, fetchProfileCaptor.getAllValues().get(3).size());
@ -294,7 +294,8 @@ public class ImapSyncTest {
}
return null;
}
}).when(remoteFolder).fetch(any(List.class), any(FetchProfile.class), nullable(MessageRetrievalListener.class));
}).when(remoteFolder).fetch(any(List.class), any(FetchProfile.class), nullable(MessageRetrievalListener.class),
anyInt());
}
private ImapMessage buildSmallNewMessage() {

View file

@ -99,11 +99,22 @@ class JmapBackend(
return messageServerIds.associateWith { it }
}
override fun search(folderServerId: String, query: String?, requiredFlags: Set<Flag>?, forbiddenFlags: Set<Flag>?): List<String> {
override fun search(
folderServerId: String,
query: String?,
requiredFlags: Set<Flag>?,
forbiddenFlags: Set<Flag>?,
performFullTextSearch: Boolean
): List<String> {
throw UnsupportedOperationException("not implemented")
}
override fun fetchMessage(folderServerId: String, messageServerId: String, fetchProfile: FetchProfile): Message {
override fun fetchMessage(
folderServerId: String,
messageServerId: String,
fetchProfile: FetchProfile,
maxDownloadSize: Int
): Message {
throw UnsupportedOperationException("not implemented")
}

View file

@ -6,13 +6,18 @@ import com.fsck.k9.mail.store.pop3.Pop3Store
internal class CommandFetchMessage(private val pop3Store: Pop3Store) {
fun fetchMessage(folderServerId: String, messageServerId: String, fetchProfile: FetchProfile): Message {
fun fetchMessage(
folderServerId: String,
messageServerId: String,
fetchProfile: FetchProfile,
maxDownloadSize: Int
): Message {
val folder = pop3Store.getFolder(folderServerId)
try {
folder.open()
val message = folder.getMessage(messageServerId)
folder.fetch(listOf(message), fetchProfile, null)
folder.fetch(listOf(message), fetchProfile, null, maxDownloadSize)
return message
} finally {

View file

@ -97,13 +97,19 @@ class Pop3Backend(
folderServerId: String,
query: String?,
requiredFlags: Set<Flag>?,
forbiddenFlags: Set<Flag>?
forbiddenFlags: Set<Flag>?,
performFullTextSearch: Boolean
): List<String> {
throw UnsupportedOperationException("not supported")
}
override fun fetchMessage(folderServerId: String, messageServerId: String, fetchProfile: FetchProfile): Message {
return commandFetchMessage.fetchMessage(folderServerId, messageServerId, fetchProfile)
override fun fetchMessage(
folderServerId: String,
messageServerId: String,
fetchProfile: FetchProfile,
maxDownloadSize: Int
): Message {
return commandFetchMessage.fetchMessage(folderServerId, messageServerId, fetchProfile, maxDownloadSize)
}
override fun fetchPart(folderServerId: String, messageServerId: String, part: Part, bodyFactory: BodyFactory) {

View file

@ -6,7 +6,6 @@ import java.net.URISyntaxException;
import com.fsck.k9.mail.AuthType;
import com.fsck.k9.mail.ServerSettings;
import com.fsck.k9.mail.store.StoreConfig;
import static com.fsck.k9.mail.helper.UrlEncodingHelper.encodeUtf8;

View file

@ -449,7 +449,8 @@ class Pop3Sync {
// FIXME this method is almost never invoked by various Stores! Don't rely on it unless fixed!!
}
});
},
syncConfig.getMaximumAutoDownloadMessageSize());
}
private void downloadSmallMessages(
@ -502,7 +503,8 @@ class Pop3Sync {
@Override
public void messagesFinished(int total) {
}
});
},
-1);
Timber.d("SYNC: Done fetching small messages for folder %s", folder);
}
@ -525,7 +527,8 @@ class Pop3Sync {
Timber.d("SYNC: Fetching large messages for folder %s", folder);
remoteFolder.fetch(largeMessages, fp, null);
int maxDownloadSize = syncConfig.getMaximumAutoDownloadMessageSize();
remoteFolder.fetch(largeMessages, fp, null, maxDownloadSize);
for (Pop3Message message : largeMessages) {
downloadSaneBody(syncConfig, remoteFolder, backendFolder, message);
@ -570,7 +573,8 @@ class Pop3Sync {
* they equal we can mark this SYNCHRONIZED instead of PARTIALLY_SYNCHRONIZED
*/
remoteFolder.fetch(Collections.singletonList(message), fp, null);
int maxDownloadSize = syncConfig.getMaximumAutoDownloadMessageSize();
remoteFolder.fetch(Collections.singletonList(message), fp, null, maxDownloadSize);
boolean completeMessage = false;
// Certain (POP3) servers give you the whole message even when you ask for only the first x Kb

View file

@ -6,12 +6,17 @@ import com.fsck.k9.mail.store.webdav.WebDavStore
internal class CommandFetchMessage(private val webDavStore: WebDavStore) {
fun fetchMessage(folderServerId: String, messageServerId: String, fetchProfile: FetchProfile): Message {
fun fetchMessage(
folderServerId: String,
messageServerId: String,
fetchProfile: FetchProfile,
maxDownloadSize: Int
): Message {
val folder = webDavStore.getFolder(folderServerId)
try {
val message = folder.getMessage(messageServerId)
folder.fetch(listOf(message), fetchProfile, null)
folder.fetch(listOf(message), fetchProfile, null, maxDownloadSize)
return message
} finally {

View file

@ -107,13 +107,19 @@ class WebDavBackend(
folderServerId: String,
query: String?,
requiredFlags: Set<Flag>?,
forbiddenFlags: Set<Flag>?
forbiddenFlags: Set<Flag>?,
performFullTextSearch: Boolean
): List<String> {
throw UnsupportedOperationException("not supported")
}
override fun fetchMessage(folderServerId: String, messageServerId: String, fetchProfile: FetchProfile): Message {
return commandFetchMessage.fetchMessage(folderServerId, messageServerId, fetchProfile)
override fun fetchMessage(
folderServerId: String,
messageServerId: String,
fetchProfile: FetchProfile,
maxDownloadSize: Int
): Message {
return commandFetchMessage.fetchMessage(folderServerId, messageServerId, fetchProfile, maxDownloadSize)
}
override fun fetchPart(folderServerId: String, messageServerId: String, part: Part, bodyFactory: BodyFactory) {

View file

@ -1,7 +1,6 @@
package com.fsck.k9.backend.webdav;
import com.fsck.k9.mail.ServerSettings;
import com.fsck.k9.mail.store.StoreConfig;
import com.fsck.k9.mail.store.webdav.WebDavStoreSettings;
import java.net.URI;

View file

@ -457,7 +457,8 @@ class WebDavSync {
// FIXME this method is almost never invoked by various Stores! Don't rely on it unless fixed!!
}
});
},
syncConfig.getMaximumAutoDownloadMessageSize());
}
private void downloadSmallMessages(
@ -509,7 +510,8 @@ class WebDavSync {
@Override
public void messagesFinished(int total) {
}
});
},
-1);
Timber.d("SYNC: Done fetching small messages for folder %s", folder);
}
@ -528,7 +530,8 @@ class WebDavSync {
Timber.d("SYNC: Fetching large messages for folder %s", folder);
remoteFolder.fetch(largeMessages, fp, null);
int maxDownloadSize = syncConfig.getMaximumAutoDownloadMessageSize();
remoteFolder.fetch(largeMessages, fp, null, maxDownloadSize);
for (WebDavMessage message : largeMessages) {
downloadSaneBody(syncConfig, remoteFolder, backendFolder, message);
@ -571,7 +574,8 @@ class WebDavSync {
* they equal we can mark this SYNCHRONIZED instead of PARTIALLY_SYNCHRONIZED
*/
remoteFolder.fetch(Collections.singletonList(message), fp, null);
int maxDownloadSize = syncConfig.getMaximumAutoDownloadMessageSize();
remoteFolder.fetch(Collections.singletonList(message), fp, null, maxDownloadSize);
boolean completeMessage = false;
// Certain (POP3) servers give you the whole message even when you ask for only the first x Kb
@ -622,7 +626,8 @@ class WebDavSync {
}
}
remoteFolder.fetch(undeletedMessages, fp, null);
int maxDownloadSize = syncConfig.getMaximumAutoDownloadMessageSize();
remoteFolder.fetch(undeletedMessages, fp, null, maxDownloadSize);
for (WebDavMessage remoteMessage : syncFlagMessages) {
boolean messageChanged = syncFlags(syncConfig, backendFolder, remoteMessage);
if (messageChanged) {

View file

@ -1,18 +0,0 @@
package com.fsck.k9.mail.store;
import com.fsck.k9.mail.NetworkType;
public interface StoreConfig {
boolean isSubscribedFoldersOnly();
boolean useCompression(NetworkType type);
String getInboxFolder();
String getOutboxFolder();
String getDraftsFolder();
int getMaximumAutoDownloadMessageSize();
boolean isAllowRemoteSearch();
boolean isRemoteSearchFullText();
}

View file

@ -607,7 +607,7 @@ public class ImapFolder {
}
public void fetch(List<ImapMessage> messages, FetchProfile fetchProfile,
MessageRetrievalListener<ImapMessage> listener) throws MessagingException {
MessageRetrievalListener<ImapMessage> listener, int maxDownloadSize) throws MessagingException {
if (messages == null || messages.isEmpty()) {
return;
}
@ -641,9 +641,8 @@ public class ImapFolder {
}
if (fetchProfile.contains(FetchProfile.Item.BODY_SANE)) {
int maximumAutoDownloadMessageSize = store.getStoreConfig().getMaximumAutoDownloadMessageSize();
if (maximumAutoDownloadMessageSize > 0) {
fetchFields.add(String.format(Locale.US, "BODY.PEEK[]<0.%d>", maximumAutoDownloadMessageSize));
if (maxDownloadSize > 0) {
fetchFields.add(String.format(Locale.US, "BODY.PEEK[]<0.%d>", maxDownloadSize));
} else {
fetchFields.add("BODY.PEEK[]");
}
@ -735,15 +734,14 @@ public class ImapFolder {
}
public void fetchPart(ImapMessage message, Part part, MessageRetrievalListener<ImapMessage> listener,
BodyFactory bodyFactory) throws MessagingException {
BodyFactory bodyFactory, int maxDownloadSize) throws MessagingException {
checkOpen();
String partId = part.getServerExtra();
String fetch;
if ("TEXT".equalsIgnoreCase(partId)) {
int maximumAutoDownloadMessageSize = store.getStoreConfig().getMaximumAutoDownloadMessageSize();
fetch = String.format(Locale.US, "BODY.PEEK[TEXT]<0.%d>", maximumAutoDownloadMessageSize);
fetch = String.format(Locale.US, "BODY.PEEK[TEXT]<0.%d>", maxDownloadSize);
} else {
fetch = String.format("BODY.PEEK[%s]", partId);
}
@ -1315,7 +1313,7 @@ public class ImapFolder {
}
protected String getLogId() {
String id = store.getStoreConfig().toString() + ":" + getServerId() + "/" + Thread.currentThread().getName();
String id = store.getLogLabel() + ":" + getServerId() + "/" + Thread.currentThread().getName();
if (connection != null) {
id += "/" + connection.getLogId();
}
@ -1332,11 +1330,7 @@ public class ImapFolder {
* @throws MessagingException On any error.
*/
public List<ImapMessage> search(final String queryString, final Set<Flag> requiredFlags,
final Set<Flag> forbiddenFlags) throws MessagingException {
if (!store.getStoreConfig().isAllowRemoteSearch()) {
throw new MessagingException("Your settings do not allow remote searching of this account");
}
final Set<Flag> forbiddenFlags, boolean performFullTextSearch) throws MessagingException {
try {
open(OPEN_MODE_RO);
@ -1346,7 +1340,7 @@ public class ImapFolder {
String searchCommand = new UidSearchCommandBuilder()
.queryString(queryString)
.performFullTextSearch(store.getStoreConfig().isRemoteSearchFullText())
.performFullTextSearch(performFullTextSearch)
.requiredFlags(requiredFlags)
.forbiddenFlags(forbiddenFlags)
.build();

View file

@ -24,7 +24,6 @@ import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.NetworkType;
import com.fsck.k9.mail.oauth.OAuth2TokenProvider;
import com.fsck.k9.mail.ssl.TrustedSocketFactory;
import com.fsck.k9.mail.store.StoreConfig;
import timber.log.Timber;
@ -34,7 +33,7 @@ import timber.log.Timber;
* </pre>
*/
public class ImapStore {
private final StoreConfig storeConfig;
private final ImapStoreConfig config;
private final TrustedSocketFactory trustedSocketFactory;
private Set<Flag> permanentFlagsIndex = EnumSet.noneOf(Flag.class);
private ConnectivityManager connectivityManager;
@ -62,10 +61,10 @@ public class ImapStore {
private final Map<String, ImapFolder> folderCache = new HashMap<>();
public ImapStore(ImapStoreSettings serverSettings, StoreConfig storeConfig,
public ImapStore(ImapStoreSettings serverSettings, ImapStoreConfig config,
TrustedSocketFactory trustedSocketFactory, ConnectivityManager connectivityManager,
OAuth2TokenProvider oauthTokenProvider) {
this.storeConfig = storeConfig;
this.config = config;
this.trustedSocketFactory = trustedSocketFactory;
host = serverSettings.host;
@ -125,7 +124,7 @@ public class ImapStore {
try {
List<FolderListItem> folders = listFolders(connection, false);
if (!storeConfig.isSubscribedFoldersOnly()) {
if (!config.isSubscribedFoldersOnly()) {
return folders;
}
@ -187,7 +186,7 @@ public class ImapStore {
if (ImapFolder.INBOX.equalsIgnoreCase(serverId)) {
continue;
} else if (serverId.equals(storeConfig.getOutboxFolder())) {
} else if (serverId.equals("K9MAIL_INTERNAL_OUTBOX")) {
/*
* There is a folder on the server with the same name as our local
* outbox. Until we have a good plan to deal with this situation
@ -329,8 +328,8 @@ public class ImapStore {
return folderNameCodec;
}
StoreConfig getStoreConfig() {
return storeConfig;
String getLogLabel() {
return config.getLogLabel();
}
Set<Flag> getPermanentFlagsIndex() {
@ -376,7 +375,7 @@ public class ImapStore {
@Override
public boolean useCompression(final NetworkType type) {
return storeConfig.useCompression(type);
return config.useCompression(type);
}
@Override

View file

@ -0,0 +1,9 @@
package com.fsck.k9.mail.store.imap
import com.fsck.k9.mail.NetworkType
interface ImapStoreConfig {
val logLabel: String
fun isSubscribedFoldersOnly(): Boolean
fun useCompression(type: NetworkType): Boolean
}

View file

@ -23,7 +23,6 @@ import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.Part;
import com.fsck.k9.mail.internet.BinaryTempFileBody;
import com.fsck.k9.mail.internet.MimeHeader;
import com.fsck.k9.mail.store.StoreConfig;
import okio.Buffer;
import org.apache.james.mime4j.util.MimeUtil;
import org.junit.Before;
@ -63,18 +62,17 @@ import static org.mockito.internal.util.collections.Sets.newSet;
@RunWith(K9LibRobolectricTestRunner.class)
public class ImapFolderTest {
private static final int MAX_DOWNLOAD_SIZE = -1;
private ImapStore imapStore;
private ImapConnection imapConnection;
private StoreConfig storeConfig;
@Before
public void setUp() throws Exception {
BinaryTempFileBody.setTempDirectory(RuntimeEnvironment.application.getCacheDir());
imapStore = mock(ImapStore.class);
storeConfig = mock(StoreConfig.class);
when(storeConfig.getInboxFolder()).thenReturn("INBOX");
when(imapStore.getCombinedPrefix()).thenReturn("");
when(imapStore.getStoreConfig()).thenReturn(storeConfig);
when(imapStore.getLogLabel()).thenReturn("Account");
imapConnection = mock(ImapConnection.class);
}
@ -702,7 +700,7 @@ public class ImapFolderTest {
ImapFolder folder = createFolder("Folder");
FetchProfile fetchProfile = createFetchProfile();
folder.fetch(null, fetchProfile, null);
folder.fetch(null, fetchProfile, null, MAX_DOWNLOAD_SIZE);
verifyNoMoreInteractions(imapStore);
}
@ -712,7 +710,7 @@ public class ImapFolderTest {
ImapFolder folder = createFolder("Folder");
FetchProfile fetchProfile = createFetchProfile();
folder.fetch(Collections.<ImapMessage>emptyList(), fetchProfile, null);
folder.fetch(Collections.<ImapMessage>emptyList(), fetchProfile, null, MAX_DOWNLOAD_SIZE);
verifyNoMoreInteractions(imapStore);
}
@ -726,7 +724,7 @@ public class ImapFolderTest {
List<ImapMessage> messages = createImapMessages("1");
FetchProfile fetchProfile = createFetchProfile(Item.FLAGS);
folder.fetch(messages, fetchProfile, null);
folder.fetch(messages, fetchProfile, null, MAX_DOWNLOAD_SIZE);
verify(imapConnection).sendCommand("UID FETCH 1 (UID FLAGS)", false);
}
@ -740,7 +738,7 @@ public class ImapFolderTest {
List<ImapMessage> messages = createImapMessages("1");
FetchProfile fetchProfile = createFetchProfile(Item.ENVELOPE);
folder.fetch(messages, fetchProfile, null);
folder.fetch(messages, fetchProfile, null, MAX_DOWNLOAD_SIZE);
verify(imapConnection).sendCommand("UID FETCH 1 (UID INTERNALDATE RFC822.SIZE BODY.PEEK[HEADER.FIELDS " +
"(date subject from content-type to cc reply-to message-id references in-reply-to X-K9mail-Identity)]" +
@ -756,7 +754,7 @@ public class ImapFolderTest {
List<ImapMessage> messages = createImapMessages("1");
FetchProfile fetchProfile = createFetchProfile(Item.STRUCTURE);
folder.fetch(messages, fetchProfile, null);
folder.fetch(messages, fetchProfile, null, MAX_DOWNLOAD_SIZE);
verify(imapConnection).sendCommand("UID FETCH 1 (UID BODYSTRUCTURE)", false);
}
@ -773,7 +771,7 @@ public class ImapFolderTest {
List<ImapMessage> messages = createImapMessages("1");
FetchProfile fetchProfile = createFetchProfile(Item.STRUCTURE);
folder.fetch(messages, fetchProfile, null);
folder.fetch(messages, fetchProfile, null, MAX_DOWNLOAD_SIZE);
verify(messages.get(0)).setHeader(MimeHeader.HEADER_CONTENT_TYPE, "text/plain;\r\n CHARSET=\"US-ASCII\"");
}
@ -786,9 +784,8 @@ public class ImapFolderTest {
when(imapConnection.readResponse(nullable(ImapResponseCallback.class))).thenReturn(createImapResponse("x OK"));
List<ImapMessage> messages = createImapMessages("1");
FetchProfile fetchProfile = createFetchProfile(Item.BODY_SANE);
when(storeConfig.getMaximumAutoDownloadMessageSize()).thenReturn(4096);
folder.fetch(messages, fetchProfile, null);
folder.fetch(messages, fetchProfile, null, 4096);
verify(imapConnection).sendCommand("UID FETCH 1 (UID BODY.PEEK[]<0.4096>)", false);
}
@ -801,9 +798,8 @@ public class ImapFolderTest {
when(imapConnection.readResponse(nullable(ImapResponseCallback.class))).thenReturn(createImapResponse("x OK"));
List<ImapMessage> messages = createImapMessages("1");
FetchProfile fetchProfile = createFetchProfile(Item.BODY_SANE);
when(storeConfig.getMaximumAutoDownloadMessageSize()).thenReturn(0);
folder.fetch(messages, fetchProfile, null);
folder.fetch(messages, fetchProfile, null, 0);
verify(imapConnection).sendCommand("UID FETCH 1 (UID BODY.PEEK[])", false);
}
@ -817,7 +813,7 @@ public class ImapFolderTest {
List<ImapMessage> messages = createImapMessages("1");
FetchProfile fetchProfile = createFetchProfile(Item.BODY);
folder.fetch(messages, fetchProfile, null);
folder.fetch(messages, fetchProfile, null, MAX_DOWNLOAD_SIZE);
verify(imapConnection).sendCommand("UID FETCH 1 (UID BODY.PEEK[])", false);
}
@ -833,7 +829,7 @@ public class ImapFolderTest {
.thenReturn(createImapResponse("* 1 FETCH (FLAGS (\\Seen) UID 1)"))
.thenReturn(createImapResponse("x OK"));
folder.fetch(messages, fetchProfile, null);
folder.fetch(messages, fetchProfile, null, MAX_DOWNLOAD_SIZE);
ImapMessage imapMessage = messages.get(0);
verify(imapMessage).setFlag(Flag.SEEN, true);
@ -843,13 +839,12 @@ public class ImapFolderTest {
public void fetchPart_withTextSection_shouldIssueRespectiveCommand() throws Exception {
ImapFolder folder = createFolder("Folder");
prepareImapFolderForOpen(OPEN_MODE_RO);
when(storeConfig.getMaximumAutoDownloadMessageSize()).thenReturn(4096);
folder.open(OPEN_MODE_RO);
ImapMessage message = createImapMessage("1");
Part part = createPart("TEXT");
when(imapConnection.readResponse(nullable(ImapResponseCallback.class))).thenReturn(createImapResponse("x OK"));
folder.fetchPart(message, part, null, null);
folder.fetchPart(message, part, null, null, 4096);
verify(imapConnection).sendCommand("UID FETCH 1 (UID BODY.PEEK[TEXT]<0.4096>)", false);
}
@ -863,7 +858,7 @@ public class ImapFolderTest {
Part part = createPart("1.1");
when(imapConnection.readResponse(nullable(ImapResponseCallback.class))).thenReturn(createImapResponse("x OK"));
folder.fetchPart(message, part, null, null);
folder.fetchPart(message, part, null, null, MAX_DOWNLOAD_SIZE);
verify(imapConnection).sendCommand("UID FETCH 1 (UID BODY.PEEK[1.1])", false);
}
@ -877,7 +872,7 @@ public class ImapFolderTest {
Part part = createPlainTextPart("1.1");
setupSingleFetchResponseToCallback();
folder.fetchPart(message, part, null, new DefaultBodyFactory());
folder.fetchPart(message, part, null, new DefaultBodyFactory(), MAX_DOWNLOAD_SIZE);
ArgumentCaptor<Body> bodyArgumentCaptor = ArgumentCaptor.forClass(Body.class);
verify(part).setBody(bodyArgumentCaptor.capture());
@ -970,11 +965,9 @@ public class ImapFolderTest {
public void search_withFullTextSearchEnabled_shouldIssueRespectiveCommand() throws Exception {
ImapFolder folder = createFolder("Folder");
prepareImapFolderForOpen(OPEN_MODE_RO);
when(storeConfig.isAllowRemoteSearch()).thenReturn(true);
when(storeConfig.isRemoteSearchFullText()).thenReturn(true);
setupUidSearchResponses("1 OK SEARCH completed");
folder.search("query", newSet(Flag.SEEN), Collections.<Flag>emptySet());
folder.search("query", newSet(Flag.SEEN), Collections.<Flag>emptySet(), true);
assertCommandIssued("UID SEARCH TEXT \"query\" SEEN");
}
@ -983,28 +976,13 @@ public class ImapFolderTest {
public void search_withFullTextSearchDisabled_shouldIssueRespectiveCommand() throws Exception {
ImapFolder folder = createFolder("Folder");
prepareImapFolderForOpen(OPEN_MODE_RO);
when(storeConfig.isAllowRemoteSearch()).thenReturn(true);
when(storeConfig.isRemoteSearchFullText()).thenReturn(false);
setupUidSearchResponses("1 OK SEARCH completed");
folder.search("query", Collections.<Flag>emptySet(), Collections.<Flag>emptySet());
folder.search("query", Collections.<Flag>emptySet(), Collections.<Flag>emptySet(), false);
assertCommandIssued("UID SEARCH OR SUBJECT \"query\" FROM \"query\"");
}
@Test
public void search_withRemoteSearchDisabled_shouldThrow() throws Exception {
ImapFolder folder = createFolder("Folder");
when(storeConfig.isAllowRemoteSearch()).thenReturn(false);
try {
folder.search("query", Collections.<Flag>emptySet(), Collections.<Flag>emptySet());
fail("Expected exception");
} catch (MessagingException e) {
assertEquals("Your settings do not allow remote searching of this account", e.getMessage());
}
}
@Test
public void getMessageByUid_returnsNewImapMessageWithUid() throws Exception {
ImapFolder folder = createFolder("Folder");

View file

@ -20,7 +20,6 @@ import com.fsck.k9.mail.FolderType;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.oauth.OAuth2TokenProvider;
import com.fsck.k9.mail.ssl.TrustedSocketFactory;
import com.fsck.k9.mail.store.StoreConfig;
import org.junit.Before;
import org.junit.Test;
import org.mockito.internal.util.collections.Sets;
@ -39,18 +38,17 @@ import static org.mockito.Mockito.when;
public class ImapStoreTest {
private StoreConfig storeConfig;
private ImapStoreConfig config = mock(ImapStoreConfig.class);
private TestImapStore imapStore;
@Before
public void setUp() throws Exception {
ImapStoreSettings serverSettings = createImapStoreSettings();
storeConfig = createStoreConfig();
TrustedSocketFactory trustedSocketFactory = mock(TrustedSocketFactory.class);
ConnectivityManager connectivityManager = mock(ConnectivityManager.class);
OAuth2TokenProvider oauth2TokenProvider = mock(OAuth2TokenProvider.class);
imapStore = new TestImapStore(serverSettings, storeConfig, trustedSocketFactory, connectivityManager,
imapStore = new TestImapStore(serverSettings, config, trustedSocketFactory, connectivityManager,
oauth2TokenProvider);
}
@ -156,7 +154,7 @@ public class ImapStoreTest {
@Test
public void getFolders_withoutSubscribedFoldersOnly() throws Exception {
when(storeConfig.isSubscribedFoldersOnly()).thenReturn(false);
when(config.isSubscribedFoldersOnly()).thenReturn(false);
ImapConnection imapConnection = mock(ImapConnection.class);
List<ImapResponse> imapResponses = Arrays.asList(
createImapResponse("* LIST (\\HasNoChildren) \".\" \"INBOX\""),
@ -176,7 +174,7 @@ public class ImapStoreTest {
@Test
public void getFolders_withSubscribedFoldersOnly_shouldOnlyReturnExistingSubscribedFolders()
throws Exception {
when(storeConfig.isSubscribedFoldersOnly()).thenReturn(true);
when(config.isSubscribedFoldersOnly()).thenReturn(true);
ImapConnection imapConnection = mock(ImapConnection.class);
List<ImapResponse> lsubResponses = Arrays.asList(
createImapResponse("* LSUB (\\HasNoChildren) \".\" \"INBOX\""),
@ -378,13 +376,6 @@ public class ImapStoreTest {
null);
}
private StoreConfig createStoreConfig() {
StoreConfig storeConfig = mock(StoreConfig.class);
when(storeConfig.getInboxFolder()).thenReturn("INBOX");
return storeConfig;
}
private Set<String> extractFolderServerIds(List<FolderListItem> folders) {
Set<String> folderServerIds = new HashSet<>(folders.size());
for (FolderListItem folder : folders) {
@ -438,10 +429,10 @@ public class ImapStoreTest {
private Deque<ImapConnection> imapConnections = new ArrayDeque<>();
private String testCombinedPrefix;
public TestImapStore(ImapStoreSettings serverSettings, StoreConfig storeConfig,
public TestImapStore(ImapStoreSettings serverSettings, ImapStoreConfig config,
TrustedSocketFactory trustedSocketFactory, ConnectivityManager connectivityManager,
OAuth2TokenProvider oauth2TokenProvider) {
super(serverSettings, storeConfig, trustedSocketFactory, connectivityManager, oauth2TokenProvider);
super(serverSettings, config, trustedSocketFactory, connectivityManager, oauth2TokenProvider);
}
@Override

View file

@ -290,7 +290,7 @@ public class Pop3Folder {
* @param fp The contents to populate
*/
public void fetch(List<Pop3Message> messages, FetchProfile fp,
MessageRetrievalListener<Pop3Message> listener)
MessageRetrievalListener<Pop3Message> listener, int maxDownloadSize)
throws MessagingException {
if (messages == null || messages.isEmpty()) {
return;
@ -330,9 +330,8 @@ public class Pop3Folder {
* To convert the suggested download size we take the size
* divided by the maximum line size (76).
*/
if (pop3Store.getConfig().getMaximumAutoDownloadMessageSize() > 0) {
fetchBody(pop3Message,
(pop3Store.getConfig().getMaximumAutoDownloadMessageSize() / 76));
if (maxDownloadSize > 0) {
fetchBody(pop3Message, maxDownloadSize / 76);
} else {
fetchBody(pop3Message, -1);
}

View file

@ -11,11 +11,9 @@ import com.fsck.k9.mail.ConnectionSecurity;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.ServerSettings;
import com.fsck.k9.mail.ssl.TrustedSocketFactory;
import com.fsck.k9.mail.store.StoreConfig;
public class Pop3Store {
private final StoreConfig storeConfig;
private final TrustedSocketFactory trustedSocketFactory;
private final String host;
private final int port;
@ -27,8 +25,7 @@ public class Pop3Store {
private Map<String, Pop3Folder> mFolders = new HashMap<>();
public Pop3Store(ServerSettings serverSettings, StoreConfig storeConfig, TrustedSocketFactory socketFactory) {
this.storeConfig = storeConfig;
public Pop3Store(ServerSettings serverSettings, TrustedSocketFactory socketFactory) {
trustedSocketFactory = socketFactory;
host = serverSettings.host;
port = serverSettings.port;
@ -60,10 +57,6 @@ public class Pop3Store {
}
}
StoreConfig getConfig() {
return storeConfig;
}
public Pop3Connection createConnection() throws MessagingException {
return new Pop3Connection(new StorePop3Settings(), trustedSocketFactory);
}

View file

@ -6,7 +6,6 @@ import com.fsck.k9.mail.FetchProfile.Item;
import com.fsck.k9.mail.MessageRetrievalListener;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.internet.BinaryTempFileBody;
import com.fsck.k9.mail.store.StoreConfig;
import org.junit.Before;
import org.junit.Test;
@ -30,9 +29,10 @@ import static org.mockito.Mockito.when;
public class Pop3FolderTest {
private static final int MAX_DOWNLOAD_SIZE = -1;
private Pop3Store mockStore;
private Pop3Connection mockConnection;
private StoreConfig mockStoreConfig;
private MessageRetrievalListener<Pop3Message> mockListener;
private Pop3Folder folder;
@ -40,10 +40,7 @@ public class Pop3FolderTest {
public void before() throws MessagingException {
mockStore = mock(Pop3Store.class);
mockConnection = mock(Pop3Connection.class);
mockStoreConfig = mock(StoreConfig.class);
mockListener = mock(MessageRetrievalListener.class);
when(mockStore.getConfig()).thenReturn(mockStoreConfig);
when(mockStoreConfig.getInboxFolder()).thenReturn(Pop3Folder.INBOX);
when(mockStore.createConnection()).thenReturn(mockConnection);
when(mockConnection.executeSimpleCommand(Pop3Commands.STAT_COMMAND)).thenReturn("+OK 10 0");
folder = new Pop3Folder(mockStore, Pop3Folder.INBOX);
@ -225,7 +222,7 @@ public class Pop3FolderTest {
fetchProfile.add(Item.ENVELOPE);
when(mockConnection.readLine()).thenReturn("1 100").thenReturn(".");
folder.fetch(messageList, fetchProfile, mockListener);
folder.fetch(messageList, fetchProfile, mockListener, MAX_DOWNLOAD_SIZE);
assertEquals(100, messageList.get(0).getSize());
}
@ -248,7 +245,7 @@ public class Pop3FolderTest {
when(mockConnection.readLine()).thenReturn("1 100").thenReturn(".");
when(mockConnection.getInputStream()).thenReturn(messageInputStream);
folder.fetch(messageList, fetchProfile, mockListener);
folder.fetch(messageList, fetchProfile, mockListener, MAX_DOWNLOAD_SIZE);
ByteArrayOutputStream bodyData = new ByteArrayOutputStream();
messageList.get(0).getBody().writeTo(bodyData);

View file

@ -14,7 +14,6 @@ import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.ServerSettings;
import com.fsck.k9.mail.filter.Base64;
import com.fsck.k9.mail.ssl.TrustedSocketFactory;
import com.fsck.k9.mail.store.StoreConfig;
import org.junit.Before;
import org.junit.Test;
@ -52,7 +51,6 @@ public class Pop3StoreTest {
private Pop3Store store;
private StoreConfig mockStoreConfig = mock(StoreConfig.class);
private TrustedSocketFactory mockTrustedSocketFactory = mock(TrustedSocketFactory.class);
private Socket mockSocket = mock(Socket.class);
private OutputStream mockOutputStream = mock(OutputStream.class);
@ -61,13 +59,12 @@ public class Pop3StoreTest {
@Before
public void setUp() throws Exception {
ServerSettings serverSettings = createServerSettings();
when(mockStoreConfig.getInboxFolder()).thenReturn(Pop3Folder.INBOX);
when(mockTrustedSocketFactory.createSocket(null, "server", 12345, null)).thenReturn(mockSocket);
when(mockSocket.isConnected()).thenReturn(true);
when(mockSocket.isClosed()).thenReturn(false);
when(mockSocket.getOutputStream()).thenReturn(mockOutputStream);
store = new Pop3Store(serverSettings, mockStoreConfig, mockTrustedSocketFactory);
store = new Pop3Store(serverSettings, mockTrustedSocketFactory);
}
@Test

View file

@ -0,0 +1,5 @@
package com.fsck.k9.mail.store.webdav;
public interface DraftsFolderProvider {
String getDraftsFolder();
}

View file

@ -267,10 +267,9 @@ public class WebDavFolder {
return dataset.getUidToUrl();
}
public void fetch(List<WebDavMessage> messages, FetchProfile fp, MessageRetrievalListener<WebDavMessage> listener)
throws MessagingException {
if (messages == null ||
messages.isEmpty()) {
public void fetch(List<WebDavMessage> messages, FetchProfile fp, MessageRetrievalListener<WebDavMessage> listener,
int maxDownloadSize) throws MessagingException {
if (messages == null || messages.isEmpty()) {
return;
}
@ -288,9 +287,8 @@ public class WebDavFolder {
}
if (fp.contains(FetchProfile.Item.BODY_SANE)) {
int maximumAutoDownloadSize = store.getStoreConfig().getMaximumAutoDownloadMessageSize();
if (maximumAutoDownloadSize > 0) {
fetchMessages(messages, listener, (maximumAutoDownloadSize / 76));
if (maxDownloadSize > 0) {
fetchMessages(messages, listener, (maxDownloadSize / 76));
} else {
fetchMessages(messages, listener, -1);
}

View file

@ -24,7 +24,6 @@ import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.filter.Base64;
import com.fsck.k9.mail.ssl.TrustManagerFactory;
import com.fsck.k9.mail.store.StoreConfig;
import com.fsck.k9.mail.store.webdav.WebDavHttpClient.WebDavHttpClientFactory;
import javax.net.ssl.SSLException;
import javax.xml.parsers.ParserConfigurationException;
@ -60,7 +59,7 @@ import static com.fsck.k9.mail.helper.UrlEncodingHelper.decodeUtf8;
*/
@SuppressWarnings("deprecation")
public class WebDavStore {
private final StoreConfig storeConfig;
private final DraftsFolderProvider draftsFolderProvider;
private ConnectionSecurity mConnectionSecurity;
private String username;
private String alias;
@ -84,13 +83,14 @@ public class WebDavStore {
private WebDavFolder sendFolder = null;
private Map<String, WebDavFolder> folderList = new HashMap<>();
public WebDavStore(TrustManagerFactory trustManagerFactory, WebDavStoreSettings serverSettings, StoreConfig storeConfig) {
this(trustManagerFactory, serverSettings, storeConfig, new WebDavHttpClient.WebDavHttpClientFactory());
public WebDavStore(TrustManagerFactory trustManagerFactory, WebDavStoreSettings serverSettings,
DraftsFolderProvider draftsFolderProvider) {
this(trustManagerFactory, serverSettings, draftsFolderProvider, new WebDavHttpClient.WebDavHttpClientFactory());
}
public WebDavStore(TrustManagerFactory trustManagerFactory, WebDavStoreSettings serverSettings, StoreConfig storeConfig,
WebDavHttpClientFactory clientFactory) {
this.storeConfig = storeConfig;
public WebDavStore(TrustManagerFactory trustManagerFactory, WebDavStoreSettings serverSettings,
DraftsFolderProvider draftsFolderProvider, WebDavHttpClientFactory clientFactory) {
this.draftsFolderProvider = draftsFolderProvider;
httpClientFactory = clientFactory;
this.trustManagerFactory = trustManagerFactory;
@ -152,10 +152,6 @@ public class WebDavStore {
return authenticationType;
}
StoreConfig getStoreConfig() {
return storeConfig;
}
public void checkSettings() throws MessagingException {
authenticate();
}
@ -935,7 +931,7 @@ public class WebDavStore {
}
public void sendMessages(List<Message> messages) throws MessagingException {
WebDavFolder tmpFolder = getFolder(storeConfig.getDraftsFolder());
WebDavFolder tmpFolder = getFolder(draftsFolderProvider.getDraftsFolder());
try {
tmpFolder.open();
List<WebDavMessage> retMessages = tmpFolder.appendWebDavMessages(messages);

View file

@ -8,7 +8,7 @@ import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.Transport;
import com.fsck.k9.mail.ssl.TrustManagerFactory;
import com.fsck.k9.mail.store.StoreConfig;
import com.fsck.k9.mail.store.webdav.DraftsFolderProvider;
import com.fsck.k9.mail.store.webdav.WebDavStore;
import com.fsck.k9.mail.store.webdav.WebDavStoreSettings;
import timber.log.Timber;
@ -16,8 +16,9 @@ import timber.log.Timber;
public class WebDavTransport extends Transport {
private WebDavStore store;
public WebDavTransport(TrustManagerFactory trustManagerFactory, WebDavStoreSettings serverSettings, StoreConfig storeConfig) {
store = new WebDavStore(trustManagerFactory, serverSettings, storeConfig);
public WebDavTransport(TrustManagerFactory trustManagerFactory, WebDavStoreSettings serverSettings,
DraftsFolderProvider draftsFolderProvider) {
store = new WebDavStore(trustManagerFactory, serverSettings, draftsFolderProvider);
if (K9MailLib.isDebug())
Timber.d(">>> New WebDavTransport creation complete");

View file

@ -16,7 +16,6 @@ import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.MessageRetrievalListener;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.internet.BinaryTempFileBody;
import com.fsck.k9.mail.store.StoreConfig;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.HttpUriRequest;
@ -52,6 +51,8 @@ import static org.mockito.Mockito.when;
@SuppressWarnings("deprecation")
public class WebDavFolderTest {
private static final int MAX_DOWNLOAD_SIZE = 1900;
@Mock
private MessageRetrievalListener<WebDavMessage> listener;
@Mock
@ -60,12 +61,6 @@ public class WebDavFolderTest {
private DataSet mockDataSet;
@Mock
private WebDavHttpClient mockHttpClient;
@Mock
private StoreConfig mockStoreConfig;
@Mock
private HttpResponse mockHttpResponse;
@Mock
private StatusLine mockStatusLine;
@Captor
private ArgumentCaptor<Map<String, String>> headerCaptor;
@Captor
@ -87,7 +82,6 @@ public class WebDavFolderTest {
MockitoAnnotations.initMocks(this);
when(mockStore.getUrl()).thenReturn(storeUrl);
when(mockStore.getHttpClient()).thenReturn(mockHttpClient);
when(mockStore.getStoreConfig()).thenReturn(mockStoreConfig);
when(mockStore.getMessageEnvelopeXml(any(String[].class))).thenReturn("mockEnvelopeXml");
when(mockStore.getMessageFlagsXml(any(String[].class))).thenReturn("mockFlagsXml");
folder = new WebDavFolder(mockStore, folderName);
@ -156,7 +150,7 @@ public class WebDavFolderTest {
FetchProfile profile = new FetchProfile();
profile.add(FetchProfile.Item.ENVELOPE);
folder.fetch(messages, profile, listener);
folder.fetch(messages, profile, listener, MAX_DOWNLOAD_SIZE);
}
@Test
@ -172,7 +166,7 @@ public class WebDavFolderTest {
}
FetchProfile profile = new FetchProfile();
profile.add(FetchProfile.Item.ENVELOPE);
folder.fetch(messages, profile, listener);
folder.fetch(messages, profile, listener, MAX_DOWNLOAD_SIZE);
}
@Test
@ -188,7 +182,7 @@ public class WebDavFolderTest {
}
FetchProfile profile = new FetchProfile();
profile.add(FetchProfile.Item.FLAGS);
folder.fetch(messages, profile, listener);
folder.fetch(messages, profile, listener, MAX_DOWNLOAD_SIZE);
}
@Test
@ -205,7 +199,7 @@ public class WebDavFolderTest {
FetchProfile profile = new FetchProfile();
profile.add(FetchProfile.Item.FLAGS);
folder.fetch(messages, profile, listener);
folder.fetch(messages, profile, listener, MAX_DOWNLOAD_SIZE);
}
@Test
@ -233,7 +227,7 @@ public class WebDavFolderTest {
FetchProfile profile = new FetchProfile();
profile.add(FetchProfile.Item.BODY_SANE);
folder.fetch(messages, profile, listener);
folder.fetch(messages, profile, listener, MAX_DOWNLOAD_SIZE);
verify(listener, times(25)).messageStarted(any(String.class), anyInt(), eq(25));
verify(listener, times(25)).messageFinished(any(WebDavMessage.class), anyInt(), eq(25));
}
@ -266,14 +260,13 @@ public class WebDavFolderTest {
FetchProfile profile = new FetchProfile();
profile.add(FetchProfile.Item.FLAGS);
profile.add(FetchProfile.Item.BODY);
folder.fetch(messages, profile, listener);
folder.fetch(messages, profile, listener, MAX_DOWNLOAD_SIZE);
verify(listener, times(25)).messageStarted(any(String.class), anyInt(), anyInt());
verify(listener, times(25)).messageFinished(any(WebDavMessage.class), anyInt(), anyInt());
}
private void setupStoreForMessageFetching() {
String authString = "authString";
when(mockStoreConfig.getMaximumAutoDownloadMessageSize()).thenReturn(1900);
when(mockStore.getAuthentication()).thenReturn(WebDavConstants.AUTH_TYPE_BASIC);
when(mockStore.getAuthString()).thenReturn(authString);
}
@ -308,7 +301,7 @@ public class WebDavFolderTest {
FetchProfile profile = new FetchProfile();
profile.add(FetchProfile.Item.BODY_SANE);
folder.fetch(messages, profile, listener);
folder.fetch(messages, profile, listener, MAX_DOWNLOAD_SIZE);
verify(listener, times(25)).messageStarted(any(String.class), anyInt(), eq(25));
verify(listener, times(25)).messageFinished(any(WebDavMessage.class), anyInt(), eq(25));
}
@ -339,7 +332,7 @@ public class WebDavFolderTest {
FetchProfile profile = new FetchProfile();
profile.add(FetchProfile.Item.BODY_SANE);
folder.fetch(messages, profile, listener);
folder.fetch(messages, profile, listener, MAX_DOWNLOAD_SIZE);
verify(listener, times(25)).messageStarted(any(String.class), anyInt(), eq(25));
verify(listener, times(25)).messageFinished(any(WebDavMessage.class), anyInt(), eq(25));
}

View file

@ -16,7 +16,7 @@ import com.fsck.k9.mail.K9LibRobolectricTestRunner;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.filter.Base64;
import com.fsck.k9.mail.ssl.TrustManagerFactory;
import com.fsck.k9.mail.store.StoreConfig;
import javax.net.ssl.SSLException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
@ -47,12 +47,10 @@ import org.mockito.stubbing.OngoingStubbing;
import static junit.framework.Assert.assertSame;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@SuppressWarnings("deprecation")
@RunWith(K9LibRobolectricTestRunner.class)
public class WebDavStoreTest {
private static final HttpResponse OK_200_RESPONSE = createOkResponse();
@ -70,10 +68,11 @@ public class WebDavStoreTest {
private SchemeRegistry mockSchemeRegistry;
@Mock
private TrustManagerFactory trustManagerFactory;
@Mock
private DraftsFolderProvider draftsFolderProvider;
private ArgumentCaptor<HttpGeneric> requestCaptor;
private StoreConfig storeConfig;
private WebDavStoreSettings serverSettings;
private WebDavStore webDavStore;
@ -88,7 +87,6 @@ public class WebDavStoreTest {
when(mockHttpClient.getConnectionManager()).thenReturn(mockClientConnectionManager);
when(mockClientConnectionManager.getSchemeRegistry()).thenReturn(mockSchemeRegistry);
storeConfig = createStoreConfig();
serverSettings = createWebDavStoreSettings(ConnectionSecurity.SSL_TLS_REQUIRED);
webDavStore = createWebDavStore();
}
@ -338,12 +336,6 @@ public class WebDavStoreTest {
};
}
private StoreConfig createStoreConfig() {
StoreConfig storeConfig = mock(StoreConfig.class);
when(storeConfig.getInboxFolder()).thenReturn("INBOX");
return storeConfig;
}
private WebDavStoreSettings createWebDavStoreSettings(ConnectionSecurity connectionSecurity) {
return new WebDavStoreSettings(
"webdav.example.org",
@ -360,12 +352,12 @@ public class WebDavStoreTest {
}
private WebDavStore createWebDavStore() {
return new WebDavStore(trustManagerFactory, serverSettings, storeConfig, mockHttpClientFactory);
return new WebDavStore(trustManagerFactory, serverSettings, draftsFolderProvider, mockHttpClientFactory);
}
private WebDavStore createWebDavStore(ConnectionSecurity connectionSecurity) {
WebDavStoreSettings serverSettings = createWebDavStoreSettings(connectionSecurity);
return new WebDavStore(trustManagerFactory, serverSettings, storeConfig, mockHttpClientFactory);
return new WebDavStore(trustManagerFactory, serverSettings, draftsFolderProvider, mockHttpClientFactory);
}
private void configureHttpResponses(HttpResponse... responses) throws IOException {