diff --git a/app/core/src/main/java/com/fsck/k9/backend/ImapBackendFactory.kt b/app/core/src/main/java/com/fsck/k9/backend/ImapBackendFactory.kt index 79b4a2409..226ed2269 100644 --- a/app/core/src/main/java/com/fsck/k9/backend/ImapBackendFactory.kt +++ b/app/core/src/main/java/com/fsck/k9/backend/ImapBackendFactory.kt @@ -10,6 +10,7 @@ import com.fsck.k9.mail.oauth.OAuth2TokenProvider import com.fsck.k9.mail.power.PowerManager import com.fsck.k9.mail.ssl.DefaultTrustedSocketFactory import com.fsck.k9.mail.store.imap.ImapStore +import com.fsck.k9.mail.transport.smtp.SmtpTransport import com.fsck.k9.mailstore.K9BackendStorage class ImapBackendFactory( @@ -22,7 +23,8 @@ class ImapBackendFactory( val accountName = account.description val backendStorage = K9BackendStorage(preferences, account, account.localStore) 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 { @@ -34,4 +36,9 @@ class ImapBackendFactory( oAuth2TokenProvider ) } + + private fun createSmtpTransport(account: Account): SmtpTransport { + val oauth2TokenProvider: OAuth2TokenProvider? = null + return SmtpTransport(account, DefaultTrustedSocketFactory(context), oauth2TokenProvider) + } } diff --git a/app/core/src/main/java/com/fsck/k9/backend/Pop3BackendFactory.kt b/app/core/src/main/java/com/fsck/k9/backend/Pop3BackendFactory.kt index b5e65f953..5b6088563 100644 --- a/app/core/src/main/java/com/fsck/k9/backend/Pop3BackendFactory.kt +++ b/app/core/src/main/java/com/fsck/k9/backend/Pop3BackendFactory.kt @@ -5,8 +5,10 @@ import com.fsck.k9.Account import com.fsck.k9.Preferences import com.fsck.k9.backend.api.Backend 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.store.pop3.Pop3Store +import com.fsck.k9.mail.transport.smtp.SmtpTransport import com.fsck.k9.mailstore.K9BackendStorage 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 backendStorage = K9BackendStorage(preferences, account, account.localStore) 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 { return Pop3Store(account, DefaultTrustedSocketFactory(context)) } + + private fun createSmtpTransport(account: Account): SmtpTransport { + val oauth2TokenProvider: OAuth2TokenProvider? = null + return SmtpTransport(account, DefaultTrustedSocketFactory(context), oauth2TokenProvider) + } } diff --git a/app/core/src/main/java/com/fsck/k9/backend/WebDavBackendFactory.kt b/app/core/src/main/java/com/fsck/k9/backend/WebDavBackendFactory.kt index f8466c665..5fdddc6fd 100644 --- a/app/core/src/main/java/com/fsck/k9/backend/WebDavBackendFactory.kt +++ b/app/core/src/main/java/com/fsck/k9/backend/WebDavBackendFactory.kt @@ -5,6 +5,7 @@ import com.fsck.k9.Preferences import com.fsck.k9.backend.api.Backend import com.fsck.k9.backend.webdav.WebDavBackend import com.fsck.k9.mail.store.webdav.WebDavStore +import com.fsck.k9.mail.transport.WebDavTransport import com.fsck.k9.mailstore.K9BackendStorage class WebDavBackendFactory(private val preferences: Preferences) : BackendFactory { @@ -13,7 +14,8 @@ class WebDavBackendFactory(private val preferences: Preferences) : BackendFactor val accountName = account.description val backendStorage = K9BackendStorage(preferences, account, account.localStore) 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 { diff --git a/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java b/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java index 130eb544f..8784713d8 100644 --- a/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java +++ b/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java @@ -71,8 +71,6 @@ import com.fsck.k9.mail.MessagingException; import com.fsck.k9.mail.Part; import com.fsck.k9.mail.PushReceiver; 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.MimeUtility; import com.fsck.k9.mailstore.LocalFolder; @@ -128,7 +126,6 @@ public class MessagingController { private final ConcurrentHashMap pushers = new ConcurrentHashMap<>(); private final ExecutorService threadPool = Executors.newCachedThreadPool(); private final MemorizingMessagingListener memorizingMessagingListener = new MemorizingMessagingListener(); - private final TransportProvider transportProvider; private final AccountStatsCollector accountStatsCollector; private final CoreResourceProvider resourceProvider; @@ -142,10 +139,9 @@ public class MessagingController { Context appContext = context.getApplicationContext(); NotificationController notificationController = DI.get(NotificationController.class); Contacts contacts = Contacts.getInstance(context); - TransportProvider transportProvider = TransportProvider.getInstance(); AccountStatsCollector accountStatsCollector = new DefaultAccountStatsCollector(context); CoreResourceProvider resourceProvider = DI.get(CoreResourceProvider.class); - inst = new MessagingController(appContext, notificationController, contacts, transportProvider, + inst = new MessagingController(appContext, notificationController, contacts, accountStatsCollector, resourceProvider); } return inst; @@ -154,12 +150,10 @@ public class MessagingController { @VisibleForTesting MessagingController(Context context, NotificationController notificationController, Contacts contacts, - TransportProvider transportProvider, AccountStatsCollector accountStatsCollector, - CoreResourceProvider resourceProvider) { + AccountStatsCollector accountStatsCollector, CoreResourceProvider resourceProvider) { this.context = context; this.notificationController = notificationController; this.contacts = contacts; - this.transportProvider = transportProvider; this.accountStatsCollector = accountStatsCollector; this.resourceProvider = resourceProvider; @@ -1603,7 +1597,7 @@ public class MessagingController { Timber.i("Scanning folder '%s' (%d) for messages to send", account.getOutboxFolder(), localFolder.getDatabaseId()); - Transport transport = transportProvider.getTransport(context, account); + Backend backend = getBackend(account); for (LocalMessage message : localMessages) { if (message.isSet(Flag.DELETED)) { @@ -1638,7 +1632,7 @@ public class MessagingController { message.setFlag(Flag.X_SEND_IN_PROGRESS, true); 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.SEEN, true); diff --git a/app/core/src/test/java/com/fsck/k9/controller/MessagingControllerTest.java b/app/core/src/test/java/com/fsck/k9/controller/MessagingControllerTest.java index 846686a25..53fc5676e 100644 --- a/app/core/src/test/java/com/fsck/k9/controller/MessagingControllerTest.java +++ b/app/core/src/test/java/com/fsck/k9/controller/MessagingControllerTest.java @@ -26,8 +26,6 @@ import com.fsck.k9.mail.Flag; import com.fsck.k9.mail.Folder; import com.fsck.k9.mail.MessageRetrievalListener; 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.LocalMessage; import com.fsck.k9.mailstore.LocalStore; @@ -97,10 +95,6 @@ public class MessagingControllerTest extends K9RobolectricTest { private LocalStore localStore; @Mock private NotificationController notificationController; - @Mock - private TransportProvider transportProvider; - @Mock - private Transport transport; @Captor private ArgumentCaptor> localFolderListCaptor; @Captor @@ -144,7 +138,7 @@ public class MessagingControllerTest extends K9RobolectricTest { MessagingControllerTestExtra.backendManagerProvides(backend); - controller = new MessagingController(appContext, notificationController, contacts, transportProvider, + controller = new MessagingController(appContext, notificationController, contacts, accountStatsCollector, mock(CoreResourceProvider.class)); configureAccount(); @@ -537,7 +531,7 @@ public class MessagingControllerTest extends K9RobolectricTest { controller.sendPendingMessagesSynchronous(account); - verify(transport).sendMessage(localMessageToSend1); + verify(backend).sendMessage(localMessageToSend1); } @Test @@ -546,9 +540,9 @@ public class MessagingControllerTest extends K9RobolectricTest { 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(transport).sendMessage(localMessageToSend1); + ordering.verify(backend).sendMessage(localMessageToSend1); ordering.verify(localMessageToSend1).setFlag(Flag.X_SEND_IN_PROGRESS, false); } @@ -582,7 +576,7 @@ public class MessagingControllerTest extends K9RobolectricTest { @Test public void sendPendingMessagesSynchronous_withAuthenticationFailure_shouldNotify() throws MessagingException { setupAccountWithMessageToSend(); - doThrow(new AuthenticationFailedException("Test")).when(transport).sendMessage(localMessageToSend1); + doThrow(new AuthenticationFailedException("Test")).when(backend).sendMessage(localMessageToSend1); controller.sendPendingMessagesSynchronous(account); @@ -592,7 +586,7 @@ public class MessagingControllerTest extends K9RobolectricTest { @Test public void sendPendingMessagesSynchronous_withCertificateFailure_shouldNotify() throws MessagingException { setupAccountWithMessageToSend(); - doThrow(new CertificateValidationException("Test")).when(transport).sendMessage(localMessageToSend1); + doThrow(new CertificateValidationException("Test")).when(backend).sendMessage(localMessageToSend1); controller.sendPendingMessagesSynchronous(account); @@ -615,7 +609,6 @@ public class MessagingControllerTest extends K9RobolectricTest { when(localStore.getFolder(SENT_FOLDER_NAME)).thenReturn(sentFolder); when(sentFolder.getDatabaseId()).thenReturn(1L); when(localFolder.exists()).thenReturn(true); - when(transportProvider.getTransport(appContext, account)).thenReturn(transport); when(localFolder.getMessages(null)).thenReturn(Collections.singletonList(localMessageToSend1)); when(localMessageToSend1.getUid()).thenReturn("localMessageToSend1"); when(localMessageToSend1.getHeader(K9.IDENTITY_HEADER)).thenReturn(new String[]{}); diff --git a/backend/api/src/main/java/com/fsck/k9/backend/api/Backend.kt b/backend/api/src/main/java/com/fsck/k9/backend/api/Backend.kt index ab92f3350..3a0dd7490 100644 --- a/backend/api/src/main/java/com/fsck/k9/backend/api/Backend.kt +++ b/backend/api/src/main/java/com/fsck/k9/backend/api/Backend.kt @@ -83,4 +83,7 @@ interface Backend { @Throws(MessagingException::class) fun checkServerSettings() + + @Throws(MessagingException::class) + fun sendMessage(message: Message) } diff --git a/backend/imap/build.gradle b/backend/imap/build.gradle index 107cd73af..1360526dd 100644 --- a/backend/imap/build.gradle +++ b/backend/imap/build.gradle @@ -13,6 +13,7 @@ dependencies { api project(":backend:api") implementation project(":mail:protocols:imap") + implementation project(":mail:protocols:smtp") implementation "com.jakewharton.timber:timber:${versions.timber}" diff --git a/backend/imap/src/main/java/com/fsck/k9/backend/imap/ImapBackend.java b/backend/imap/src/main/java/com/fsck/k9/backend/imap/ImapBackend.java index 021edf9e3..a391e47cc 100644 --- a/backend/imap/src/main/java/com/fsck/k9/backend/imap/ImapBackend.java +++ b/backend/imap/src/main/java/com/fsck/k9/backend/imap/ImapBackend.java @@ -22,6 +22,7 @@ import com.fsck.k9.mail.Pusher; import com.fsck.k9.mail.power.PowerManager; import com.fsck.k9.mail.store.imap.ImapPusher; 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.Nullable; @@ -29,6 +30,7 @@ import org.jetbrains.annotations.Nullable; public class ImapBackend implements Backend { private final ImapStore imapStore; private final PowerManager powerManager; + private final SmtpTransport smtpTransport; private final ImapSync imapSync; private final CommandGetFolders commandGetFolders; private final CommandSetFlag commandSetFlag; @@ -43,9 +45,10 @@ public class ImapBackend implements Backend { public ImapBackend(String accountName, BackendStorage backendStorage, ImapStore imapStore, - PowerManager powerManager) { + PowerManager powerManager, SmtpTransport smtpTransport) { this.imapStore = imapStore; this.powerManager = powerManager; + this.smtpTransport = smtpTransport; imapSync = new ImapSync(accountName, backendStorage, imapStore); commandSetFlag = new CommandSetFlag(imapStore); @@ -197,4 +200,9 @@ public class ImapBackend implements Backend { public void checkServerSettings() throws MessagingException { imapStore.checkSettings(); } + + @Override + public void sendMessage(@NotNull Message message) throws MessagingException { + smtpTransport.sendMessage(message); + } } diff --git a/backend/pop3/build.gradle b/backend/pop3/build.gradle index aebdf2638..b9da24d5e 100644 --- a/backend/pop3/build.gradle +++ b/backend/pop3/build.gradle @@ -13,6 +13,7 @@ dependencies { api project(":backend:api") implementation project(":mail:protocols:pop3") + implementation project(":mail:protocols:smtp") implementation "com.jakewharton.timber:timber:${versions.timber}" diff --git a/backend/pop3/src/main/java/com/fsck/k9/backend/pop3/Pop3Backend.kt b/backend/pop3/src/main/java/com/fsck/k9/backend/pop3/Pop3Backend.kt index 26f6fb779..377d5e7aa 100644 --- a/backend/pop3/src/main/java/com/fsck/k9/backend/pop3/Pop3Backend.kt +++ b/backend/pop3/src/main/java/com/fsck/k9/backend/pop3/Pop3Backend.kt @@ -14,8 +14,14 @@ import com.fsck.k9.mail.Part import com.fsck.k9.mail.PushReceiver import com.fsck.k9.mail.Pusher 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 commandGetFolders = CommandGetFolders() private val commandSetFlag = CommandSetFlag(pop3Store) @@ -110,4 +116,8 @@ class Pop3Backend(accountName: String, backendStorage: BackendStorage, private v override fun checkServerSettings() { pop3Store.checkSettings() } + + override fun sendMessage(message: Message) { + smtpTransport.sendMessage(message) + } } diff --git a/backend/webdav/src/main/java/com/fsck/k9/backend/webdav/WebDavBackend.kt b/backend/webdav/src/main/java/com/fsck/k9/backend/webdav/WebDavBackend.kt index 6cf478164..e1ea4e0ff 100644 --- a/backend/webdav/src/main/java/com/fsck/k9/backend/webdav/WebDavBackend.kt +++ b/backend/webdav/src/main/java/com/fsck/k9/backend/webdav/WebDavBackend.kt @@ -15,11 +15,13 @@ import com.fsck.k9.mail.Part import com.fsck.k9.mail.PushReceiver import com.fsck.k9.mail.Pusher import com.fsck.k9.mail.store.webdav.WebDavStore +import com.fsck.k9.mail.transport.WebDavTransport class WebDavBackend( accountName: String, backendStorage: BackendStorage, - private val webDavStore: WebDavStore + private val webDavStore: WebDavStore, + private val webDavTransport: WebDavTransport ) : Backend { private val webDavSync: WebDavSync = WebDavSync(accountName, backendStorage, webDavStore) private val commandGetFolders = CommandGetFolders(webDavStore) @@ -119,4 +121,8 @@ class WebDavBackend( override fun checkServerSettings() { webDavStore.checkSettings() } + + override fun sendMessage(message: Message) { + webDavTransport.sendMessage(message) + } }