Skip to content
Matthew Cory edited this page Apr 20, 2016 · 1 revision

kotlin-mail

Kotlin-mail is intended to (eventually) serve as a replacement to JavaMail. JavaMail is an awesome library, but it's also rather old and it's Java, not Kotlin. The goal of kotlin-mail is to 1, wrap JavaMail in a more Kotlin-esque wrapper, and B, eventually replace JavaMail completely.

Getting Started

Kotlin-mail is available in Maven Central; to get started with it, add the following dependency to your pom.xml file:

    <dependency>
        <groupId>io.github.slothLabs</groupId>
        <artifactId>kotlin-mail</artifactId>
        <version>0.1.0</version>
    </dependency>

Right now, kotlin-mail is version 0.1.0, which loosely translates to "I do nothing." Well, not exactly, but it's close - functionality is extremely limited at this point. For starters, we're only working with IMAP at the moment (that's what I work with mostly at my day job, so that's what I'm most familiar with. Which translates to the part of JavaMail I'm most frustrated with). There's also only rather basic functionality with IMAP too: searching on folders, sorting messages from folders, and accessing individual messages from folders. No moving, no deleting, no get-by-UID or anything fun. BUT I hope we can get you moving a little bit here anyways. At least enough to pique your interest in the project ;)

Here's a quick snippet of how kotlin-mail works:

    val conInfo = ConnectionInformation(host, port, emailAddress, password)
    val msgList = mutableListOf<Message>()
    imap(conInfo) {
        folder("INBOX", FolderModes.ReadOnly) {
            preFetchBy(FetchProfileItem.MESSAGE)
            val results = search {
                +from(fromAddress)
                +to(emailAddress)
                -subject("Testing")

                +sentOnOrBefore(Date())

                sortedBy {
                    +From
                    +To
                    -Sort.Size
                    -Subject
                }
            }
            msgList.addAll(results)
        }
    }

Let's go over that real quick to see what we're doing:

    val conInfo = ConnectionInformation(host, port, emailAddress, password)

That creates a ConnectionInformation data class that contains the bare info we need to communicate with an IMAP server. We use that in the imap function, which will do all the server access dirty work for us.

If you want to do baby-steps into kotlin-mail, there's an extension function for the JavaMail Store class that takes a ConnectionInformation instance and works with that.

Next we create a mutable list to hold our messages (here, Message is the kotlin-mail Message class, not JavaMail's). We need to do this because the imap function manages all of the connection stuff - it opens, does our work, then closes the connection for us. IOW, everything we do inside the imap function stays in the imap function, unless we have something to store it in. So, next:

    imap(conInfo) {
        folder("INBOX", FolderModes.ReadOnly) {
            preFetchBy(FetchProfileItem.MESSAGE)
            // blah blah blah
        }
    }

Now the magic's starting. Kinda. Here, we're opening the connection to the IMAP server, and then we're opening up the INBOX folder in ReadOnly mode. (FolderModes is an enum class in kotlin-mail to wrap the mode constants from JavaMail.) After that, we indicate we want to prefetch full messages from the IMAP server. The two closing brackets at the end close the folder and the IMAP connection respectively.

Prefetch is important in this case, since we want to use the messages outside of the imap or folder blocks. Messages in JavaMail are lazy-loaded; pretty much anything useful in them is only retrieved from the server the first time you access them. If the folder or server connection are closed, you get a pleasant little MessagingException if you try to access something the first time. However, if we were going to do all of our work in these blocks, it'd be unnecessary. A little slower, perhaps, depending on what you're doing, but you won't get exceptions at least.

Okay, back to the guts of the snippet:

            val results = search {
                +from(fromAddress)
                +to(emailAddress)
                -subject("Testing")

                +sentOnOrBefore(Date())

                sortedBy {
                    +From
                    +To
                    -Sort.Size
                    -Subject
                }
            }
            msgList.addAll(results)

Here we're executing a search (probably a 'duh'? I think it's a 'duh'). And this might almost be self explanatory, but I'll skim it anyways. The first four actions are telling it to search for emails with a matching "from" address, a matching "to" address, without the specified subject, and that were sent on or before the given date (in this case, today). Then we tell it we want the search results sorted, by from and to in natural order, then by size and subject in reversed order.

We store those in our original list of messages, and bam! Bob's your uncle.

Clone this wiki locally