diff --git a/README.md b/README.md index 85ee90c..1c86a3e 100644 --- a/README.md +++ b/README.md @@ -24,12 +24,16 @@ val invoiceFromXml = reader.extractFromXml(File("XRechnung.xml")) ```kotlin val emailsFetcher = EmailsFetcher() -val mailsWithEInvoices = emailsFetcher.listAllMessagesWithEInvoice(EmailAccount( - username = "", // your mail account username - password = "", // your mail account username +val fetchResult = emailsFetcher.fetchAllEmails(EmailAccount( + username = "", // your email account username + password = "", // your email account username serverAddress = "", // IMAP server address port = null // IMAP server port, can be left null for default port 993 )) + +fetchResult.emails.forEach { email -> + println("${email.sender}: ${email.attachmentsWithEInvoice.firstNotNullOfOrNull { it.invoice }?.totalAmounts?.duePayableAmount}") +} ``` ### Validate eInvoice diff --git a/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/mail/EmailsFetcher.kt b/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/mail/EmailsFetcher.kt index 2b916bc..c6f52ea 100644 --- a/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/mail/EmailsFetcher.kt +++ b/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/mail/EmailsFetcher.kt @@ -29,13 +29,13 @@ open class EmailsFetcher( ) - protected open val mailDispatcher = Executors.newFixedThreadPool(max(24, Runtime.getRuntime().availableProcessors() * 4)).asCoroutineDispatcher() + protected open val coroutineDispatcher = Executors.newFixedThreadPool(max(24, Runtime.getRuntime().availableProcessors() * 4)).asCoroutineDispatcher() protected val log by logger() - open fun listenForNewReceivedEInvoices(account: EmailAccount, downloadMessageBody: Boolean = false, emailFolderName: String = "INBOX", - error: ((FetchEmailsError) -> Unit)? = null, eInvoiceReceived: (EmailWithInvoice) -> Unit) = runBlocking { + open fun listenForNewEmails(account: EmailAccount, downloadMessageBody: Boolean = false, emailFolderName: String = "INBOX", + error: ((FetchEmailsError) -> Unit)? = null, emailReceived: (EmailWithInvoice) -> Unit) = runBlocking { try { connect(account) { store -> val folder = store.getFolder(emailFolderName) @@ -47,26 +47,26 @@ open class EmailsFetcher( override fun messagesAdded(event: MessageCountEvent) { event.messages.forEach { message -> findEInvoice(message, status)?.let { - eInvoiceReceived(it) + emailReceived(it) } } } }) - launch(mailDispatcher) { + launch(coroutineDispatcher) { keepConnectionOpen(account, folder) } } } catch (e: Throwable) { - log.error(e) { "Listening to new received eInvoices of '${account.username}' failed" } + log.error(e) { "Listening to new emails of '${account.username}' failed" } error?.invoke(FetchEmailsError(FetchEmailsErrorType.ListenForNewEmails, null, e)) } - log.info { "Stopped listening to new received eInvoices of '${account.username}'" } + log.info { "Stopped listening to new emails of '${account.username}'" } } protected open suspend fun keepConnectionOpen(account: EmailAccount, folder: Folder) { - log.info { "Listening to new mails of ${account.username}" } + log.info { "Listening to new emails of ${account.username}" } // Use IMAP IDLE to keep the connection alive while (true) { @@ -82,7 +82,7 @@ open class EmailsFetcher( } - open fun listAllMessagesWithEInvoice(account: EmailAccount, downloadMessageBody: Boolean = false, emailFolderName: String = "INBOX"): FetchEmailsResult { + open fun fetchAllEmails(account: EmailAccount, downloadMessageBody: Boolean = false, emailFolderName: String = "INBOX"): FetchEmailsResult { try { return connect(account) { store -> val inbox = store.getFolder(emailFolderName) @@ -90,31 +90,31 @@ open class EmailsFetcher( val status = FetchEmailsStatus(FetchEmailsOptions(downloadMessageBody)) - val mails = listAllMessagesWithEInvoiceInFolder(inbox, status).also { + val emails = fetchAllEmailsInFolder(inbox, status).also { inbox.close(false) } - FetchEmailsResult(mails, null, status.messageSpecificErrors) + FetchEmailsResult(emails, null, status.messageSpecificErrors) } } catch (e: Throwable) { - log.error(e) { "Could not read mails of account $account" } + log.error(e) { "Could not fetch emails of account $account" } return FetchEmailsResult(emptyList(), e) } } - protected open fun listAllMessagesWithEInvoiceInFolder(folder: Folder, status: FetchEmailsStatus): List = runBlocking { + protected open fun fetchAllEmailsInFolder(folder: Folder, status: FetchEmailsStatus): List = runBlocking { val messageCount = folder.messageCount if (messageCount <= 0) { return@runBlocking emptyList() } IntRange(1, messageCount).mapNotNull { messageNumber -> // message numbers start at 1 - async(mailDispatcher) { + async(coroutineDispatcher) { try { findEInvoice(folder.getMessage(messageNumber), status) } catch (e: Throwable) { - log.error(e) { "Could not get message with messageNumber $messageNumber" } + log.error(e) { "Could not get email with messageNumber $messageNumber" } status.addError(FetchEmailsErrorType.GetEmail, messageNumber, e) null } diff --git a/e-invoice-domain/src/test/kotlin/net/codinux/invoicing/Demonstration.kt b/e-invoice-domain/src/test/kotlin/net/codinux/invoicing/Demonstration.kt index 5b7edb3..875ef98 100644 --- a/e-invoice-domain/src/test/kotlin/net/codinux/invoicing/Demonstration.kt +++ b/e-invoice-domain/src/test/kotlin/net/codinux/invoicing/Demonstration.kt @@ -27,12 +27,16 @@ class Demonstration { fun fromEmail() { val emailsFetcher = EmailsFetcher() - val mailsWithEInvoices = emailsFetcher.listAllMessagesWithEInvoice(EmailAccount( - username = "", // your mail account username - password = "", // your mail account username + val fetchResult = emailsFetcher.fetchAllEmails(EmailAccount( + username = "", // your email account username + password = "", // your email account username serverAddress = "", // IMAP server address port = null // IMAP server port, can be left null for default port 993 )) + + fetchResult.emails.forEach { email -> + println("${email.sender}: ${email.attachmentsWithEInvoice.firstNotNullOfOrNull { it.invoice }?.totalAmounts?.duePayableAmount}") + } } fun validate() { diff --git a/e-invoice-domain/src/test/kotlin/net/codinux/invoicing/mail/EmailsFetcherTest.kt b/e-invoice-domain/src/test/kotlin/net/codinux/invoicing/mail/EmailsFetcherTest.kt index e909627..ff2f0a5 100644 --- a/e-invoice-domain/src/test/kotlin/net/codinux/invoicing/mail/EmailsFetcherTest.kt +++ b/e-invoice-domain/src/test/kotlin/net/codinux/invoicing/mail/EmailsFetcherTest.kt @@ -6,11 +6,11 @@ import assertk.assertions.isNotEmpty import org.junit.jupiter.api.Test import kotlin.test.Ignore -@Ignore // not an automatic test, set your mail account settings below +@Ignore // not an automatic test, set your email account settings below class EmailsFetcherTest { companion object { - // specify your mail account here + // specify your email account here private val emailAccount = EmailAccount( username = "", password = "", @@ -24,8 +24,8 @@ class EmailsFetcherTest { @Test - fun listAllMessagesWithEInvoice() { - val result = underTest.listAllMessagesWithEInvoice(emailAccount, true) + fun fetchAllEmails() { + val result = underTest.fetchAllEmails(emailAccount, true) assertThat(result.emails).isNotEmpty()