Sending email in Kotlin: overview of tools and code examples
Sending emails is a common task in web development, notifications, and background services. In the Kotlin ecosystem running on the JVM, you can use both classic Java libraries and modern Kotlin-oriented solutions. In this article, we will cover three main approaches: javax.mail (Jakarta Mail), Ktor Client, and Apache Commons Email. You will learn how to configure an SMTP client, send a simple email, and add attachments.
1. javax.mail (Jakarta Mail) — the classic standard
The most common library for working with email in Java and Kotlin. It fully supports SMTP, IMAP, and POP3 protocols. For a Kotlin project, simply add the dependency to build.gradle.kts:
dependencies { implementation("com.sun.mail:javax.mail:1.6.2")}Example of sending a simple text email:
import javax.mail.*import javax.mail.internet.InternetAddressimport javax.mail.internet.MimeMessageimport java.util.Properties
fun sendSimpleEmail() { val props = Properties().apply { put("mail.smtp.auth", "true") put("mail.smtp.starttls.enable", "true") put("mail.smtp.host", "smtp.gmail.com") put("mail.smtp.port", "587") }
val session = Session.getInstance(props, object : Authenticator() { override fun getPasswordAuthentication(): PasswordAuthentication { return PasswordAuthentication("your-email@gmail.com", "your-password") } })
val message = MimeMessage(session).apply { setFrom(InternetAddress("from-email@gmail.com")) setRecipients(Message.RecipientType.TO, InternetAddress.parse("to-email@example.com")) subject = "Hello from Kotlin!" setText("This is a test email sent using javax.mail.") }
Transport.send(message) println("Email sent successfully!")}Important: for Gmail you will need an app password or OAuth2. Do not store credentials in the code — use environment variables.
Sending an email with an attachment
import javax.activation.DataHandlerimport javax.activation.FileDataSourceimport javax.mail.internet.MimeBodyPartimport javax.mail.internet.MimeMultipart
fun sendEmailWithAttachment() { // ... session setup as above ... val message = MimeMessage(session).apply { setFrom(InternetAddress("from@gmail.com")) setRecipients(Message.RecipientType.TO, InternetAddress.parse("to@example.com")) subject = "Email with attachment" }
val multipart = MimeMultipart()
// Text part val textPart = MimeBodyPart().apply { setText("See the attachment.") } multipart.addBodyPart(textPart)
// Attachment val attachmentPart = MimeBodyPart().apply { dataHandler = DataHandler(FileDataSource("/path/to/file.pdf")) fileName = "document.pdf" } multipart.addBodyPart(attachmentPart)
message.setContent(multipart) Transport.send(message)}2. Ktor Client — a modern asynchronous approach
If your project already uses Ktor for HTTP requests, you can send email via SMTP using the ktor-client-smtp plugin. This provides the benefits of coroutines and asynchronous execution. Dependency:
dependencies { implementation("io.ktor:ktor-client-core:2.3.0") implementation("io.ktor:ktor-client-smtp:2.3.0")}Example of sending:
import io.ktor.client.*import io.ktor.client.smtp.*import io.ktor.client.request.*import io.ktor.client.statement.*
suspend fun sendViaKtor() { val client = HttpClient {