Skip to content

Error handling ​

All failures are typed subclasses of the sealed MailException. Messages are sanitized: they never contain credentials, message content, addresses or provider-supplied text, so they are safe to log and to show to operators.

Cancellation is never classified as a transport failure. A CancellationException always propagates unchanged.

Handling read failures ​

kotlin
suspend fun readSafely(mailbox: Mailbox, location: MessageLocation) {
    try {
        val message = mailbox.messages.get(location)
        println("Read message with ${message.attachments.size} attachments")
    } catch (e: MailException.MessageUnavailable) {
        println("Expunged or moved; skip it")
    } catch (e: MailException.IntegrityViolation) {
        println("UIDVALIDITY or part changed (${e.kind}); rescan the folder")
    } catch (e: MailException.LimitExceeded) {
        println("Larger than ${e.limitBytes} bytes")
    } catch (e: MailException.NotConnected) {
        println("Reconnecting (${e.state}); retry the operation later")
    } catch (e: MailException.AuthenticationRequired) {
        println("Send the user through the authorization flow again")
    } catch (e: MailException.MailboxClosed) {
        println("Mailbox was closed")
    }
}
kotlin
suspend fun listOrExplain(mailbox: Mailbox, folder: FolderPath) {
    try {
        mailbox.messages.page(MessageSelection(folder))
    } catch (e: MailException.FolderNotFound) {
        println("No such folder")
    }
}

What to do ​

ExceptionTypical causeRecommended reaction
AuthenticationRequiredRefresh token revoked or expired.Run the hosted flow again, then reconnect().
AuthorizationFailed(reason)Callback validation failed.Show an error and let the user start again.
ConnectionFailed(recovery)Opening or transport failed.Retry open later.
NotConnected(state)Mailbox is reconnecting or failed.Retry the operation later, or observe state.
MailboxClosedOperation on a closed mailbox.Programming error or shutdown race.
FolderNotFound(folder)Folder missing or not selectable.Re-resolve with folders.list() / special().
MessageUnavailable(location)Message expunged or moved.Skip it.
IntegrityViolation(kind)UIDVALIDITY or part changed.Rescan the folder; drop cached locations.
LimitExceeded(limitBytes)Download larger than the limit.Skip or retry with a larger explicit limit.
MalformedMessageUnparseable MIME or unbuildable draft.Skip, or fix the draft.
InvalidCheckpointCheckpoint from another mailbox, folder or format.Start without a checkpoint.
OutboxUnavailableNo SMTP for this mailbox.Enable sending in the provider config.
DuplicateMailbox(id)Second live mailbox with the same id in a registry.Reuse the existing mailbox.
UnexpectedAnything unclassified.Log and report.

See Exceptions for the full type reference.

Released under the MIT License.