Avid developer who has a passion for | 

Learn more about myself and what makes me so passionate about various forms of software development.

Simple Mailgun Integration using Kotlin

Posted On 2025-04-07

Hello Everyone,

I've been playing around with using Kotlin to make an API and so far it's been a lot of fun.

One problem I ran into was finding a way to send out emails, I ended up picking mailgun, they have a nice api and are generally pretty developer-friendly.

One small hitch was they don't have a kotlin wrapper, they do have a Java client, which is fine, but the library felt a bit difficult to use for a simple task of sending out an email.

for simple use, you can make a simple wrapper, and today I'll show off how I made my own.

Libraries I used

Here is what I used to assist me with this task:

You by no means need to use the exact same libraries, if you have a preference for similar libraries, feel free to replace what I used with whichever libraries you prefer for these tasks.

Serialized Response Object

First I needed to make an object that serializes the result of mailgun's api. The endpoint for sending out emails thankfully has a fairly simple response body, so this is a simple task.

import kotlinx.serialization.Serializable

@Serializable
data class MailgunMessageResponse(val id: String?, val message: String)

Our Mailgun Service Layer Object

We Then have our service layer that handles our email processing.

import com.myapp.entities.MailgunMessageResponse
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.engine.java.*
import io.ktor.client.plugins.*
import io.ktor.client.plugins.auth.*
import io.ktor.client.plugins.auth.providers.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.request.forms.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.pebbletemplates.pebble.PebbleEngine
import io.pebbletemplates.pebble.template.PebbleTemplate
import kotlinx.serialization.json.Json
import java.io.StringWriter

class MailService {
    private val apiKey = "API_KEY_FROM_MAILGUN"
    private val client = HttpClient(Java) {
        install(Auth) {
            basic {
                credentials {
                    BasicAuthCredentials(username = "api", password = apiKey)
                }
            }
        }
        install(ContentNegotiation) {
            json(Json {
                ignoreUnknownKeys = true
                isLenient = true
            })
        }
        install(DefaultRequest) {
            url("https://api.mailgun.net/v3/")
        }
    }

    suspend fun sendUserFeedback(email: String, message: String) {
        val writer = StringWriter()

        loadTemplateFile("userFeedback").evaluate(writer, mapOf("msg" to message))
        send(email, "User Feedback", writer.toString())
    }

    private suspend fun send(email: String, subject: String, emailContent: String) {
        val domain = "YOUR_APP_DOMAIN"
        val fromName = "YOUR_APP_NAME"
        val fromEmail = "[email protected]"
        val resp = client.submitForm(
            url = "$domain/messages",
            formParameters = parameters {
                append("from", "$fromName <$fromEmail>")
                append("to", email)
                append("subject", subject)
                append("html", emailContent)
            }
        )

        // report failure.
        if (!resp.status.isSuccess()) {
            val respBody: MailgunMessageResponse = resp.body()

            throw Exception(respBody.message)
        }
    }

    private fun loadTemplateFile(tpl: String): PebbleTemplate = PebbleEngine
        .Builder()
        .build().
        getTemplate("templates/${tpl}.peb")
}

This service layer will use a pebble template file as a means of making our emails look nice. The endpoint I'm using to send out emails can do far more, but for what I needed, I just used the basics, if you need to do something more advanced, please refer to their docs for what other parameters the endpoint supports.

Summary

There you have it, mailgun has other api endpoints if you wish to expand onto this, but for me, this does the job and also reduce the amount of dependencies my project requires.

If you were to expand onto this, I'd suggest making a base class that holds the endpoint bits to keep your objects clean.

I hope this article was helpful for anyone looking for a simple way to send out emails using Kotlin.