From d70a748ad040ecaf82051f84a34d0dd87635bd12 Mon Sep 17 00:00:00 2001 From: dankito Date: Tue, 26 Nov 2024 03:47:55 +0100 Subject: [PATCH] Returning now all mails and attachments, not only those with eInvoices --- README.md | 2 +- .../codinux/invoicing/email/EmailsFetcher.kt | 44 +++++++++---------- .../invoicing/email/FetchEmailsOptions.kt | 6 +-- .../invoicing/email/FetchEmailsResult.kt | 4 +- .../email/ListenForNewMailsOptions.kt | 4 +- .../model/{EmailWithInvoice.kt => Email.kt} | 6 +-- ...mentWithEInvoice.kt => EmailAttachment.kt} | 4 +- .../net/codinux/invoicing/Demonstration.kt | 2 +- 8 files changed, 34 insertions(+), 38 deletions(-) rename e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/model/{EmailWithInvoice.kt => Email.kt} (87%) rename e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/model/{EmailAttachmentWithEInvoice.kt => EmailAttachment.kt} (86%) diff --git a/README.md b/README.md index 1c86a3e..d633480 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ val fetchResult = emailsFetcher.fetchAllEmails(EmailAccount( )) fetchResult.emails.forEach { email -> - println("${email.sender}: ${email.attachmentsWithEInvoice.firstNotNullOfOrNull { it.invoice }?.totalAmounts?.duePayableAmount}") + println("${email.sender}: ${email.attachments.firstNotNullOfOrNull { it.invoice }?.totalAmounts?.duePayableAmount}") } ``` diff --git a/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/EmailsFetcher.kt b/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/EmailsFetcher.kt index d775b09..27757d5 100644 --- a/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/EmailsFetcher.kt +++ b/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/EmailsFetcher.kt @@ -10,8 +10,8 @@ import jakarta.mail.event.MessageCountAdapter import jakarta.mail.event.MessageCountEvent import kotlinx.coroutines.* import net.codinux.invoicing.email.model.EmailAccount -import net.codinux.invoicing.email.model.EmailAttachmentWithEInvoice -import net.codinux.invoicing.email.model.EmailWithInvoice +import net.codinux.invoicing.email.model.EmailAttachment +import net.codinux.invoicing.email.model.Email import net.codinux.invoicing.model.Invoice import net.codinux.invoicing.reader.EInvoiceReader import net.codinux.log.logger @@ -47,7 +47,7 @@ open class EmailsFetcher( folder.addMessageCountListener(object : MessageCountAdapter() { override fun messagesAdded(event: MessageCountEvent) { event.messages.forEach { message -> - findEInvoice(message, status) + getEmail(message, status) } } }) @@ -102,7 +102,7 @@ open class EmailsFetcher( } } - protected open fun fetchAllEmailsInFolder(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() @@ -111,7 +111,7 @@ open class EmailsFetcher( IntRange(1, messageCount).mapNotNull { messageNumber -> // message numbers start at 1 async(coroutineDispatcher) { try { - findEInvoice(folder.getMessage(messageNumber), status) + getEmail(folder.getMessage(messageNumber), status) } catch (e: Throwable) { log.error(e) { "Could not get email with messageNumber $messageNumber" } status.addError(FetchEmailsErrorType.GetEmail, messageNumber, e) @@ -123,43 +123,39 @@ open class EmailsFetcher( .filterNotNull() } - protected open fun findEInvoice(message: Message, status: FetchEmailsStatus): EmailWithInvoice? { + protected open fun getEmail(message: Message, status: FetchEmailsStatus): Email? { val parts = getAllMessageParts(message) - val attachmentsWithEInvoice = parts.mapNotNull { part -> - findEInvoice(part, status) + val attachments = parts.mapNotNull { part -> + findAttachment(part, status) } - if (attachmentsWithEInvoice.isNotEmpty()) { - val email = EmailWithInvoice( - message.from?.joinToString(), message.subject ?: "", - message.sentDate?.let { map(it) }, map(message.receivedDate), message.messageNumber, - parts.any { it.mediaType == "application/pgp-encrypted" }, - getPlainTextBody(parts, status), getHtmlBody(parts, status), - attachmentsWithEInvoice - ) + val email = Email( + message.from?.joinToString(), message.subject ?: "", + message.sentDate?.let { map(it) }, map(message.receivedDate), message.messageNumber, + parts.any { it.mediaType == "application/pgp-encrypted" }, + getPlainTextBody(parts, status), getHtmlBody(parts, status), + attachments + ) - status.options.emailReceived(email) + status.options.emailReceived(email) - return email - } - - return null + return email } - protected open fun findEInvoice(messagePart: MessagePart, status: FetchEmailsStatus): EmailAttachmentWithEInvoice? { + protected open fun findAttachment(messagePart: MessagePart, status: FetchEmailsStatus): EmailAttachment? { try { val part = messagePart.part val invoice = tryToReadEInvoice(part, messagePart.mediaType, status) - if (invoice != null) { + if (invoice != null || Part.ATTACHMENT.equals(part.description, ignoreCase = true)) { val filename = File(part.fileName) val file = File.createTempFile(filename.nameWithoutExtension, "." + filename.extension).also { file -> part.inputStream.use { it.copyTo(file.outputStream()) } file.deleteOnExit() } - return EmailAttachmentWithEInvoice(part.fileName, messagePart.mediaType, invoice, file) + return EmailAttachment(part.fileName, messagePart.mediaType, invoice, file) } } catch (e: Throwable) { log.error(e) { "Could not check attachment '${messagePart.part.fileName}' (${messagePart.mediaType}) for eInvoice" } diff --git a/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/FetchEmailsOptions.kt b/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/FetchEmailsOptions.kt index 878b5e4..182eeac 100644 --- a/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/FetchEmailsOptions.kt +++ b/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/FetchEmailsOptions.kt @@ -1,15 +1,15 @@ package net.codinux.invoicing.email -import net.codinux.invoicing.email.model.EmailWithInvoice +import net.codinux.invoicing.email.model.Email open class FetchEmailsOptions( val downloadMessageBody: Boolean = false, val emailFolderName: String = "INBOX", val onError: ((FetchEmailsError) -> Unit)? = null, - val onEmailReceived: ((EmailWithInvoice) -> Unit)? = null + val onEmailReceived: ((Email) -> Unit)? = null ) { - fun emailReceived(email: EmailWithInvoice) { + fun emailReceived(email: Email) { onEmailReceived?.invoke(email) } } \ No newline at end of file diff --git a/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/FetchEmailsResult.kt b/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/FetchEmailsResult.kt index 9bb30a7..86360e7 100644 --- a/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/FetchEmailsResult.kt +++ b/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/FetchEmailsResult.kt @@ -1,9 +1,9 @@ package net.codinux.invoicing.email -import net.codinux.invoicing.email.model.EmailWithInvoice +import net.codinux.invoicing.email.model.Email data class FetchEmailsResult( - val emails: List, + val emails: List, val overallError: Throwable?, val messageSpecificErrors: List = emptyList() ) \ No newline at end of file diff --git a/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/ListenForNewMailsOptions.kt b/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/ListenForNewMailsOptions.kt index 4c40df8..e70930a 100644 --- a/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/ListenForNewMailsOptions.kt +++ b/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/ListenForNewMailsOptions.kt @@ -1,6 +1,6 @@ package net.codinux.invoicing.email -import net.codinux.invoicing.email.model.EmailWithInvoice +import net.codinux.invoicing.email.model.Email import java.util.concurrent.atomic.AtomicBoolean open class ListenForNewMailsOptions( @@ -10,5 +10,5 @@ open class ListenForNewMailsOptions( emailFolderName: String = "INBOX", onError: ((FetchEmailsError) -> Unit)? = null, - onEmailReceived: (EmailWithInvoice) -> Unit + onEmailReceived: (Email) -> Unit ) : FetchEmailsOptions(downloadMessageBody, emailFolderName, onError, onEmailReceived) \ No newline at end of file diff --git a/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/model/EmailWithInvoice.kt b/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/model/Email.kt similarity index 87% rename from e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/model/EmailWithInvoice.kt rename to e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/model/Email.kt index 7ae85c1..9d531ce 100644 --- a/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/model/EmailWithInvoice.kt +++ b/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/model/Email.kt @@ -3,7 +3,7 @@ package net.codinux.invoicing.email.model import java.time.Instant import java.time.ZoneId -class EmailWithInvoice( +class Email( val sender: String?, val subject: String, val sent: Instant?, @@ -19,9 +19,9 @@ class EmailWithInvoice( val isEncrypted: Boolean = false, val plainTextBody: String?, val htmlBody: String?, - val attachmentsWithEInvoice: List + val attachments: List ) { val plainTextOrHtmlBody: String? by lazy { plainTextBody ?: htmlBody } - override fun toString() = "${(sent ?: received).atZone(ZoneId.systemDefault()).toLocalDate()} $sender: $subject, ${attachmentsWithEInvoice.size} invoice(s)" + override fun toString() = "${(sent ?: received).atZone(ZoneId.systemDefault()).toLocalDate()} $sender: $subject, ${attachments.size} attachment(s)" } \ No newline at end of file diff --git a/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/model/EmailAttachmentWithEInvoice.kt b/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/model/EmailAttachment.kt similarity index 86% rename from e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/model/EmailAttachmentWithEInvoice.kt rename to e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/model/EmailAttachment.kt index e83dd52..a89a012 100644 --- a/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/model/EmailAttachmentWithEInvoice.kt +++ b/e-invoice-domain/src/main/kotlin/net/codinux/invoicing/email/model/EmailAttachment.kt @@ -3,7 +3,7 @@ package net.codinux.invoicing.email.model import net.codinux.invoicing.model.Invoice import java.io.File -class EmailAttachmentWithEInvoice( +class EmailAttachment( val filename: String, /** * Attachment's media type like "application/xml", "application/pdf", ... @@ -11,7 +11,7 @@ class EmailAttachmentWithEInvoice( * Should always be non-null, but can theoretically be null. */ val mediaType: String?, - val invoice: Invoice, + val invoice: Invoice?, val file: File ) { override fun toString() = "$filename: $invoice" 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 2009aac..51d6990 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 @@ -35,7 +35,7 @@ class Demonstration { )) fetchResult.emails.forEach { email -> - println("${email.sender}: ${email.attachmentsWithEInvoice.firstNotNullOfOrNull { it.invoice }?.totalAmounts?.duePayableAmount}") + println("${email.sender}: ${email.attachments.firstNotNullOfOrNull { it.invoice }?.totalAmounts?.duePayableAmount}") } }