Add send message functionality to Backend interface

This commit is contained in:
cketti 2018-07-11 19:41:13 +02:00
parent fc6c47159b
commit 6e18375d19
11 changed files with 62 additions and 29 deletions

View file

@ -10,6 +10,7 @@ import com.fsck.k9.mail.oauth.OAuth2TokenProvider
import com.fsck.k9.mail.power.PowerManager import com.fsck.k9.mail.power.PowerManager
import com.fsck.k9.mail.ssl.DefaultTrustedSocketFactory import com.fsck.k9.mail.ssl.DefaultTrustedSocketFactory
import com.fsck.k9.mail.store.imap.ImapStore import com.fsck.k9.mail.store.imap.ImapStore
import com.fsck.k9.mail.transport.smtp.SmtpTransport
import com.fsck.k9.mailstore.K9BackendStorage import com.fsck.k9.mailstore.K9BackendStorage
class ImapBackendFactory( class ImapBackendFactory(
@ -22,7 +23,8 @@ class ImapBackendFactory(
val accountName = account.description val accountName = account.description
val backendStorage = K9BackendStorage(preferences, account, account.localStore) val backendStorage = K9BackendStorage(preferences, account, account.localStore)
val imapStore = createImapStore(account) val imapStore = createImapStore(account)
return ImapBackend(accountName, backendStorage, imapStore, powerManager) val smtpTransport = createSmtpTransport(account)
return ImapBackend(accountName, backendStorage, imapStore, powerManager, smtpTransport)
} }
private fun createImapStore(account: Account): ImapStore { private fun createImapStore(account: Account): ImapStore {
@ -34,4 +36,9 @@ class ImapBackendFactory(
oAuth2TokenProvider oAuth2TokenProvider
) )
} }
private fun createSmtpTransport(account: Account): SmtpTransport {
val oauth2TokenProvider: OAuth2TokenProvider? = null
return SmtpTransport(account, DefaultTrustedSocketFactory(context), oauth2TokenProvider)
}
} }

View file

@ -5,8 +5,10 @@ import com.fsck.k9.Account
import com.fsck.k9.Preferences import com.fsck.k9.Preferences
import com.fsck.k9.backend.api.Backend import com.fsck.k9.backend.api.Backend
import com.fsck.k9.backend.pop3.Pop3Backend import com.fsck.k9.backend.pop3.Pop3Backend
import com.fsck.k9.mail.oauth.OAuth2TokenProvider
import com.fsck.k9.mail.ssl.DefaultTrustedSocketFactory import com.fsck.k9.mail.ssl.DefaultTrustedSocketFactory
import com.fsck.k9.mail.store.pop3.Pop3Store import com.fsck.k9.mail.store.pop3.Pop3Store
import com.fsck.k9.mail.transport.smtp.SmtpTransport
import com.fsck.k9.mailstore.K9BackendStorage import com.fsck.k9.mailstore.K9BackendStorage
class Pop3BackendFactory(private val context: Context, private val preferences: Preferences) : BackendFactory { class Pop3BackendFactory(private val context: Context, private val preferences: Preferences) : BackendFactory {
@ -15,10 +17,16 @@ class Pop3BackendFactory(private val context: Context, private val preferences:
val accountName = account.description val accountName = account.description
val backendStorage = K9BackendStorage(preferences, account, account.localStore) val backendStorage = K9BackendStorage(preferences, account, account.localStore)
val pop3Store = createPop3Store(account) val pop3Store = createPop3Store(account)
return Pop3Backend(accountName, backendStorage, pop3Store) val smtpTransport = createSmtpTransport(account)
return Pop3Backend(accountName, backendStorage, pop3Store, smtpTransport)
} }
private fun createPop3Store(account: Account): Pop3Store { private fun createPop3Store(account: Account): Pop3Store {
return Pop3Store(account, DefaultTrustedSocketFactory(context)) return Pop3Store(account, DefaultTrustedSocketFactory(context))
} }
private fun createSmtpTransport(account: Account): SmtpTransport {
val oauth2TokenProvider: OAuth2TokenProvider? = null
return SmtpTransport(account, DefaultTrustedSocketFactory(context), oauth2TokenProvider)
}
} }

View file

@ -5,6 +5,7 @@ import com.fsck.k9.Preferences
import com.fsck.k9.backend.api.Backend import com.fsck.k9.backend.api.Backend
import com.fsck.k9.backend.webdav.WebDavBackend import com.fsck.k9.backend.webdav.WebDavBackend
import com.fsck.k9.mail.store.webdav.WebDavStore import com.fsck.k9.mail.store.webdav.WebDavStore
import com.fsck.k9.mail.transport.WebDavTransport
import com.fsck.k9.mailstore.K9BackendStorage import com.fsck.k9.mailstore.K9BackendStorage
class WebDavBackendFactory(private val preferences: Preferences) : BackendFactory { class WebDavBackendFactory(private val preferences: Preferences) : BackendFactory {
@ -13,7 +14,8 @@ class WebDavBackendFactory(private val preferences: Preferences) : BackendFactor
val accountName = account.description val accountName = account.description
val backendStorage = K9BackendStorage(preferences, account, account.localStore) val backendStorage = K9BackendStorage(preferences, account, account.localStore)
val webDavStore = createWebDavStore(account) val webDavStore = createWebDavStore(account)
return WebDavBackend(accountName, backendStorage, webDavStore) val webDavTransport = WebDavTransport(account)
return WebDavBackend(accountName, backendStorage, webDavStore, webDavTransport)
} }
private fun createWebDavStore(account: Account): WebDavStore { private fun createWebDavStore(account: Account): WebDavStore {

View file

@ -71,8 +71,6 @@ import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.Part; import com.fsck.k9.mail.Part;
import com.fsck.k9.mail.PushReceiver; import com.fsck.k9.mail.PushReceiver;
import com.fsck.k9.mail.Pusher; import com.fsck.k9.mail.Pusher;
import com.fsck.k9.mail.Transport;
import com.fsck.k9.mail.TransportProvider;
import com.fsck.k9.mail.internet.MessageExtractor; import com.fsck.k9.mail.internet.MessageExtractor;
import com.fsck.k9.mail.internet.MimeUtility; import com.fsck.k9.mail.internet.MimeUtility;
import com.fsck.k9.mailstore.LocalFolder; import com.fsck.k9.mailstore.LocalFolder;
@ -128,7 +126,6 @@ public class MessagingController {
private final ConcurrentHashMap<Account, Pusher> pushers = new ConcurrentHashMap<>(); private final ConcurrentHashMap<Account, Pusher> pushers = new ConcurrentHashMap<>();
private final ExecutorService threadPool = Executors.newCachedThreadPool(); private final ExecutorService threadPool = Executors.newCachedThreadPool();
private final MemorizingMessagingListener memorizingMessagingListener = new MemorizingMessagingListener(); private final MemorizingMessagingListener memorizingMessagingListener = new MemorizingMessagingListener();
private final TransportProvider transportProvider;
private final AccountStatsCollector accountStatsCollector; private final AccountStatsCollector accountStatsCollector;
private final CoreResourceProvider resourceProvider; private final CoreResourceProvider resourceProvider;
@ -142,10 +139,9 @@ public class MessagingController {
Context appContext = context.getApplicationContext(); Context appContext = context.getApplicationContext();
NotificationController notificationController = DI.get(NotificationController.class); NotificationController notificationController = DI.get(NotificationController.class);
Contacts contacts = Contacts.getInstance(context); Contacts contacts = Contacts.getInstance(context);
TransportProvider transportProvider = TransportProvider.getInstance();
AccountStatsCollector accountStatsCollector = new DefaultAccountStatsCollector(context); AccountStatsCollector accountStatsCollector = new DefaultAccountStatsCollector(context);
CoreResourceProvider resourceProvider = DI.get(CoreResourceProvider.class); CoreResourceProvider resourceProvider = DI.get(CoreResourceProvider.class);
inst = new MessagingController(appContext, notificationController, contacts, transportProvider, inst = new MessagingController(appContext, notificationController, contacts,
accountStatsCollector, resourceProvider); accountStatsCollector, resourceProvider);
} }
return inst; return inst;
@ -154,12 +150,10 @@ public class MessagingController {
@VisibleForTesting @VisibleForTesting
MessagingController(Context context, NotificationController notificationController, Contacts contacts, MessagingController(Context context, NotificationController notificationController, Contacts contacts,
TransportProvider transportProvider, AccountStatsCollector accountStatsCollector, AccountStatsCollector accountStatsCollector, CoreResourceProvider resourceProvider) {
CoreResourceProvider resourceProvider) {
this.context = context; this.context = context;
this.notificationController = notificationController; this.notificationController = notificationController;
this.contacts = contacts; this.contacts = contacts;
this.transportProvider = transportProvider;
this.accountStatsCollector = accountStatsCollector; this.accountStatsCollector = accountStatsCollector;
this.resourceProvider = resourceProvider; this.resourceProvider = resourceProvider;
@ -1603,7 +1597,7 @@ public class MessagingController {
Timber.i("Scanning folder '%s' (%d) for messages to send", Timber.i("Scanning folder '%s' (%d) for messages to send",
account.getOutboxFolder(), localFolder.getDatabaseId()); account.getOutboxFolder(), localFolder.getDatabaseId());
Transport transport = transportProvider.getTransport(context, account); Backend backend = getBackend(account);
for (LocalMessage message : localMessages) { for (LocalMessage message : localMessages) {
if (message.isSet(Flag.DELETED)) { if (message.isSet(Flag.DELETED)) {
@ -1638,7 +1632,7 @@ public class MessagingController {
message.setFlag(Flag.X_SEND_IN_PROGRESS, true); message.setFlag(Flag.X_SEND_IN_PROGRESS, true);
Timber.i("Sending message with UID %s", message.getUid()); Timber.i("Sending message with UID %s", message.getUid());
transport.sendMessage(message); backend.sendMessage(message);
message.setFlag(Flag.X_SEND_IN_PROGRESS, false); message.setFlag(Flag.X_SEND_IN_PROGRESS, false);
message.setFlag(Flag.SEEN, true); message.setFlag(Flag.SEEN, true);

View file

@ -26,8 +26,6 @@ import com.fsck.k9.mail.Flag;
import com.fsck.k9.mail.Folder; import com.fsck.k9.mail.Folder;
import com.fsck.k9.mail.MessageRetrievalListener; import com.fsck.k9.mail.MessageRetrievalListener;
import com.fsck.k9.mail.MessagingException; import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.Transport;
import com.fsck.k9.mail.TransportProvider;
import com.fsck.k9.mailstore.LocalFolder; import com.fsck.k9.mailstore.LocalFolder;
import com.fsck.k9.mailstore.LocalMessage; import com.fsck.k9.mailstore.LocalMessage;
import com.fsck.k9.mailstore.LocalStore; import com.fsck.k9.mailstore.LocalStore;
@ -97,10 +95,6 @@ public class MessagingControllerTest extends K9RobolectricTest {
private LocalStore localStore; private LocalStore localStore;
@Mock @Mock
private NotificationController notificationController; private NotificationController notificationController;
@Mock
private TransportProvider transportProvider;
@Mock
private Transport transport;
@Captor @Captor
private ArgumentCaptor<List<LocalFolder>> localFolderListCaptor; private ArgumentCaptor<List<LocalFolder>> localFolderListCaptor;
@Captor @Captor
@ -144,7 +138,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
MessagingControllerTestExtra.backendManagerProvides(backend); MessagingControllerTestExtra.backendManagerProvides(backend);
controller = new MessagingController(appContext, notificationController, contacts, transportProvider, controller = new MessagingController(appContext, notificationController, contacts,
accountStatsCollector, mock(CoreResourceProvider.class)); accountStatsCollector, mock(CoreResourceProvider.class));
configureAccount(); configureAccount();
@ -537,7 +531,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
controller.sendPendingMessagesSynchronous(account); controller.sendPendingMessagesSynchronous(account);
verify(transport).sendMessage(localMessageToSend1); verify(backend).sendMessage(localMessageToSend1);
} }
@Test @Test
@ -546,9 +540,9 @@ public class MessagingControllerTest extends K9RobolectricTest {
controller.sendPendingMessagesSynchronous(account); controller.sendPendingMessagesSynchronous(account);
InOrder ordering = inOrder(localMessageToSend1, transport); InOrder ordering = inOrder(localMessageToSend1, backend);
ordering.verify(localMessageToSend1).setFlag(Flag.X_SEND_IN_PROGRESS, true); ordering.verify(localMessageToSend1).setFlag(Flag.X_SEND_IN_PROGRESS, true);
ordering.verify(transport).sendMessage(localMessageToSend1); ordering.verify(backend).sendMessage(localMessageToSend1);
ordering.verify(localMessageToSend1).setFlag(Flag.X_SEND_IN_PROGRESS, false); ordering.verify(localMessageToSend1).setFlag(Flag.X_SEND_IN_PROGRESS, false);
} }
@ -582,7 +576,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
@Test @Test
public void sendPendingMessagesSynchronous_withAuthenticationFailure_shouldNotify() throws MessagingException { public void sendPendingMessagesSynchronous_withAuthenticationFailure_shouldNotify() throws MessagingException {
setupAccountWithMessageToSend(); setupAccountWithMessageToSend();
doThrow(new AuthenticationFailedException("Test")).when(transport).sendMessage(localMessageToSend1); doThrow(new AuthenticationFailedException("Test")).when(backend).sendMessage(localMessageToSend1);
controller.sendPendingMessagesSynchronous(account); controller.sendPendingMessagesSynchronous(account);
@ -592,7 +586,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
@Test @Test
public void sendPendingMessagesSynchronous_withCertificateFailure_shouldNotify() throws MessagingException { public void sendPendingMessagesSynchronous_withCertificateFailure_shouldNotify() throws MessagingException {
setupAccountWithMessageToSend(); setupAccountWithMessageToSend();
doThrow(new CertificateValidationException("Test")).when(transport).sendMessage(localMessageToSend1); doThrow(new CertificateValidationException("Test")).when(backend).sendMessage(localMessageToSend1);
controller.sendPendingMessagesSynchronous(account); controller.sendPendingMessagesSynchronous(account);
@ -615,7 +609,6 @@ public class MessagingControllerTest extends K9RobolectricTest {
when(localStore.getFolder(SENT_FOLDER_NAME)).thenReturn(sentFolder); when(localStore.getFolder(SENT_FOLDER_NAME)).thenReturn(sentFolder);
when(sentFolder.getDatabaseId()).thenReturn(1L); when(sentFolder.getDatabaseId()).thenReturn(1L);
when(localFolder.exists()).thenReturn(true); when(localFolder.exists()).thenReturn(true);
when(transportProvider.getTransport(appContext, account)).thenReturn(transport);
when(localFolder.getMessages(null)).thenReturn(Collections.singletonList(localMessageToSend1)); when(localFolder.getMessages(null)).thenReturn(Collections.singletonList(localMessageToSend1));
when(localMessageToSend1.getUid()).thenReturn("localMessageToSend1"); when(localMessageToSend1.getUid()).thenReturn("localMessageToSend1");
when(localMessageToSend1.getHeader(K9.IDENTITY_HEADER)).thenReturn(new String[]{}); when(localMessageToSend1.getHeader(K9.IDENTITY_HEADER)).thenReturn(new String[]{});

View file

@ -83,4 +83,7 @@ interface Backend {
@Throws(MessagingException::class) @Throws(MessagingException::class)
fun checkServerSettings() fun checkServerSettings()
@Throws(MessagingException::class)
fun sendMessage(message: Message)
} }

View file

@ -13,6 +13,7 @@ dependencies {
api project(":backend:api") api project(":backend:api")
implementation project(":mail:protocols:imap") implementation project(":mail:protocols:imap")
implementation project(":mail:protocols:smtp")
implementation "com.jakewharton.timber:timber:${versions.timber}" implementation "com.jakewharton.timber:timber:${versions.timber}"

View file

@ -22,6 +22,7 @@ import com.fsck.k9.mail.Pusher;
import com.fsck.k9.mail.power.PowerManager; import com.fsck.k9.mail.power.PowerManager;
import com.fsck.k9.mail.store.imap.ImapPusher; import com.fsck.k9.mail.store.imap.ImapPusher;
import com.fsck.k9.mail.store.imap.ImapStore; import com.fsck.k9.mail.store.imap.ImapStore;
import com.fsck.k9.mail.transport.smtp.SmtpTransport;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -29,6 +30,7 @@ import org.jetbrains.annotations.Nullable;
public class ImapBackend implements Backend { public class ImapBackend implements Backend {
private final ImapStore imapStore; private final ImapStore imapStore;
private final PowerManager powerManager; private final PowerManager powerManager;
private final SmtpTransport smtpTransport;
private final ImapSync imapSync; private final ImapSync imapSync;
private final CommandGetFolders commandGetFolders; private final CommandGetFolders commandGetFolders;
private final CommandSetFlag commandSetFlag; private final CommandSetFlag commandSetFlag;
@ -43,9 +45,10 @@ public class ImapBackend implements Backend {
public ImapBackend(String accountName, BackendStorage backendStorage, ImapStore imapStore, public ImapBackend(String accountName, BackendStorage backendStorage, ImapStore imapStore,
PowerManager powerManager) { PowerManager powerManager, SmtpTransport smtpTransport) {
this.imapStore = imapStore; this.imapStore = imapStore;
this.powerManager = powerManager; this.powerManager = powerManager;
this.smtpTransport = smtpTransport;
imapSync = new ImapSync(accountName, backendStorage, imapStore); imapSync = new ImapSync(accountName, backendStorage, imapStore);
commandSetFlag = new CommandSetFlag(imapStore); commandSetFlag = new CommandSetFlag(imapStore);
@ -197,4 +200,9 @@ public class ImapBackend implements Backend {
public void checkServerSettings() throws MessagingException { public void checkServerSettings() throws MessagingException {
imapStore.checkSettings(); imapStore.checkSettings();
} }
@Override
public void sendMessage(@NotNull Message message) throws MessagingException {
smtpTransport.sendMessage(message);
}
} }

View file

@ -13,6 +13,7 @@ dependencies {
api project(":backend:api") api project(":backend:api")
implementation project(":mail:protocols:pop3") implementation project(":mail:protocols:pop3")
implementation project(":mail:protocols:smtp")
implementation "com.jakewharton.timber:timber:${versions.timber}" implementation "com.jakewharton.timber:timber:${versions.timber}"

View file

@ -14,8 +14,14 @@ import com.fsck.k9.mail.Part
import com.fsck.k9.mail.PushReceiver import com.fsck.k9.mail.PushReceiver
import com.fsck.k9.mail.Pusher import com.fsck.k9.mail.Pusher
import com.fsck.k9.mail.store.pop3.Pop3Store import com.fsck.k9.mail.store.pop3.Pop3Store
import com.fsck.k9.mail.transport.smtp.SmtpTransport
class Pop3Backend(accountName: String, backendStorage: BackendStorage, private val pop3Store: Pop3Store) : Backend { class Pop3Backend(
accountName: String,
backendStorage: BackendStorage,
private val pop3Store: Pop3Store,
private val smtpTransport: SmtpTransport
) : Backend {
private val pop3Sync: Pop3Sync = Pop3Sync(accountName, backendStorage, pop3Store) private val pop3Sync: Pop3Sync = Pop3Sync(accountName, backendStorage, pop3Store)
private val commandGetFolders = CommandGetFolders() private val commandGetFolders = CommandGetFolders()
private val commandSetFlag = CommandSetFlag(pop3Store) private val commandSetFlag = CommandSetFlag(pop3Store)
@ -110,4 +116,8 @@ class Pop3Backend(accountName: String, backendStorage: BackendStorage, private v
override fun checkServerSettings() { override fun checkServerSettings() {
pop3Store.checkSettings() pop3Store.checkSettings()
} }
override fun sendMessage(message: Message) {
smtpTransport.sendMessage(message)
}
} }

View file

@ -15,11 +15,13 @@ import com.fsck.k9.mail.Part
import com.fsck.k9.mail.PushReceiver import com.fsck.k9.mail.PushReceiver
import com.fsck.k9.mail.Pusher import com.fsck.k9.mail.Pusher
import com.fsck.k9.mail.store.webdav.WebDavStore import com.fsck.k9.mail.store.webdav.WebDavStore
import com.fsck.k9.mail.transport.WebDavTransport
class WebDavBackend( class WebDavBackend(
accountName: String, accountName: String,
backendStorage: BackendStorage, backendStorage: BackendStorage,
private val webDavStore: WebDavStore private val webDavStore: WebDavStore,
private val webDavTransport: WebDavTransport
) : Backend { ) : Backend {
private val webDavSync: WebDavSync = WebDavSync(accountName, backendStorage, webDavStore) private val webDavSync: WebDavSync = WebDavSync(accountName, backendStorage, webDavStore)
private val commandGetFolders = CommandGetFolders(webDavStore) private val commandGetFolders = CommandGetFolders(webDavStore)
@ -119,4 +121,8 @@ class WebDavBackend(
override fun checkServerSettings() { override fun checkServerSettings() {
webDavStore.checkSettings() webDavStore.checkSettings()
} }
override fun sendMessage(message: Message) {
webDavTransport.sendMessage(message)
}
} }