Implemented checkCredentials()

This commit is contained in:
dankito 2024-11-30 21:05:59 +01:00
parent 1024346b5f
commit 51d9bdd617
4 changed files with 78 additions and 2 deletions

View File

@ -12,10 +12,14 @@ import net.codinux.invoicing.model.Invoice
import net.codinux.invoicing.pdf.PdfInvoiceData import net.codinux.invoicing.pdf.PdfInvoiceData
import net.codinux.invoicing.pdf.PdfInvoiceDataExtractor import net.codinux.invoicing.pdf.PdfInvoiceDataExtractor
import net.codinux.invoicing.reader.EInvoiceReader import net.codinux.invoicing.reader.EInvoiceReader
import net.codinux.invoicing.util.ExceptionHelper
import net.codinux.log.logger import net.codinux.log.logger
import org.eclipse.angus.mail.imap.IMAPFolder import org.eclipse.angus.mail.imap.IMAPFolder
import org.eclipse.angus.mail.imap.IMAPMessage import org.eclipse.angus.mail.imap.IMAPMessage
import org.eclipse.angus.mail.util.MailConnectException
import java.io.File import java.io.File
import java.net.ConnectException
import java.net.UnknownHostException
import java.time.Instant import java.time.Instant
import java.util.* import java.util.*
import java.util.concurrent.Executors import java.util.concurrent.Executors
@ -24,7 +28,8 @@ import kotlin.math.max
open class EmailsFetcher( open class EmailsFetcher(
protected open val eInvoiceReader: EInvoiceReader = EInvoiceReader(), protected open val eInvoiceReader: EInvoiceReader = EInvoiceReader(),
protected open val pdfInvoiceDataExtractor: PdfInvoiceDataExtractor = PdfInvoiceDataExtractor(), protected open val pdfInvoiceDataExtractor: PdfInvoiceDataExtractor = PdfInvoiceDataExtractor(),
protected open val coroutineDispatcher: CoroutineDispatcher = Executors.newFixedThreadPool(max(24, Runtime.getRuntime().availableProcessors() * 4)).asCoroutineDispatcher() protected open val coroutineDispatcher: CoroutineDispatcher = Executors.newFixedThreadPool(max(24, Runtime.getRuntime().availableProcessors() * 4)).asCoroutineDispatcher(),
protected open val exceptionHelper: ExceptionHelper = ExceptionHelper()
) { ) {
protected data class MessagePart( protected data class MessagePart(
@ -43,6 +48,38 @@ open class EmailsFetcher(
protected val log by logger() protected val log by logger()
open fun checkCredentials(account: EmailAccount): CheckCredentialsResult {
try {
val status = connect(account, FetchEmailsOptions(showDebugOutputOnConsole = true))
close(status)
return CheckCredentialsResult.Ok
} catch (e: Throwable) {
log.info(e) { "Could not connect to account '$account'" }
return mapConnectResultError(e)
}
}
protected open fun mapConnectResultError(exception: Throwable): CheckCredentialsResult {
if (exception is AuthenticationFailedException) {
return CheckCredentialsResult.WrongUsername
} else if (exception is MailConnectException) {
val innerInnerException = exceptionHelper.getInnerException(exception, 1)
if (innerInnerException is UnknownHostException) {
return CheckCredentialsResult.InvalidImapServerAddress
} else if (innerInnerException is ConnectException) {
return CheckCredentialsResult.InvalidImapServerPort
}
} else if (exception is MessagingException) { // MessagingException is derived from MailConnectException, so place after MailConnectException
return CheckCredentialsResult.WrongPassword
}
return CheckCredentialsResult.UnknownError // fallback for cases i am not aware of
}
open fun listenForNewEmails(account: EmailAccount, options: ListenForNewMailsOptions) = runBlocking { open fun listenForNewEmails(account: EmailAccount, options: ListenForNewMailsOptions) = runBlocking {
try { try {
val status = connect(account, options) val status = connect(account, options)
@ -336,6 +373,8 @@ open class EmailsFetcher(
val properties = mapAccountToJavaMailProperties(account, options) val properties = mapAccountToJavaMailProperties(account, options)
val session = Session.getInstance(properties) val session = Session.getInstance(properties)
session.debug = options.showDebugOutputOnConsole
val store = session.getStore("imap") val store = session.getStore("imap")
store.connect(account.serverAddress, account.username, account.password) store.connect(account.serverAddress, account.username, account.password)
@ -345,7 +384,7 @@ open class EmailsFetcher(
return FetchEmailsStatus(account, store, folder, options) return FetchEmailsStatus(account, store, folder, options)
} }
protected open fun mapAccountToJavaMailProperties(account: EmailAccount, options: FetchEmailsOptions) = Properties().apply { protected open fun mapAccountToJavaMailProperties(account: EmailAccount, options: FetchEmailsOptions = FetchEmailsOptions()) = Properties().apply {
// the documentation of all properties can be found here: https://javaee.github.io/javamail/docs/api/com/sun/mail/imap/package-summary.html // the documentation of all properties can be found here: https://javaee.github.io/javamail/docs/api/com/sun/mail/imap/package-summary.html
put("mail.store.protocol", "imap") put("mail.store.protocol", "imap")

View File

@ -29,6 +29,8 @@ open class FetchEmailsOptions(
val emailFolderName: String = "INBOX", val emailFolderName: String = "INBOX",
val connectTimeoutSeconds: Int = 5, val connectTimeoutSeconds: Int = 5,
val showDebugOutputOnConsole: Boolean = false,
val onError: ((FetchEmailError) -> Unit)? = null, val onError: ((FetchEmailError) -> Unit)? = null,
val onEmailReceived: ((Email) -> Unit)? = null val onEmailReceived: ((Email) -> Unit)? = null
) { ) {

View File

@ -0,0 +1,18 @@
package net.codinux.invoicing.email.model
enum class CheckCredentialsResult {
Ok,
WrongUsername,
WrongPassword,
InvalidImapServerAddress,
InvalidImapServerPort,
UnknownError
}

View File

@ -0,0 +1,17 @@
package net.codinux.invoicing.util
open class ExceptionHelper {
open fun getInnerException(exception: Exception, maxDepth: Int = 3): Exception {
var innerException = exception
var depth = 0
while(innerException.cause is Exception && depth < maxDepth) {
innerException = innerException.cause as Exception
depth++
}
return innerException
}
}