eikek / emil

Emil is a library for dealing with E-Mail in Scala.

Version Matrix

Emil - Email without a

Build Status Scaladex Scala Steward badge

[\/] Emil is a library for working with E-Mail in Scala. The api builds on Cats and FS2. It comes with a backend implementation that is based on the well known Java Mail library. As such it is just another wrapper library, but also a bit different:

  • Extensible DSL for creating mails in code.
  • Conveniently send mails via SMTP.
  • Search mail boxes via IMAP.
  • The data structures model a simplified E-Mail structure. Instead of adhering to the recursive structure of a mime message, a mail here is flat, consisting of a header, a body (text, html or both) and a list of attachments.
  • The data structures and api are in a separate module, that doesn't depend on a concrete implementation library, like Java Mail. An implementation based on fs2-mail or even EWS can be created without affecting the user code of this library.

Write your e-mail related code once and then decide how to execute.


With sbt, add the dependencies:

"com.github.eikek" %% "emil-common" % "0.10.0-M1"  // the core library
"com.github.eikek" %% "emil-javamail" % "0.10.0-M1" // implementation module
// … optionally, other modules analog

Emil is provided for Scala 2.12, 2.13 and 3. Note: from 0.10.0 emil is builta against CE3. Also from this version onwards, support for scala3 has been added.


Send a mail (returning its messageID):

import cats.effect._
import cats.data.NonEmptyList
import emil._, emil.builder._
import emil.javamail._

val mail: Mail[IO] = MailBuilder.build(
  CustomHeader(Header("User-Agent", "my-email-client")),
  TextBody("Hello!\n\nThis is a mail."),
  HtmlBody("<h1>Hello!</h1>\n<p>This <b>is</b> a mail.</p>"),

val myemil = JavaMailEmil[IO]()
val smtpConf = MailConfig("smtp://devmail:25", "dev", "dev", SSLType.NoEncryption)

val sendIO: IO[NonEmptyList[String]] = myemil(smtpConf).send(mail)

Searching for mails:

import java.time._
import cats.effect._
import emil._
import emil.SearchQuery._
import emil.javamail._

val myemil = JavaMailEmil[IO]()
val imapConf = MailConfig("imap://devmail:143", "dev", "dev", SSLType.NoEncryption)

def searchInbox[C](a: Access[IO, C], q: SearchQuery): MailOp[IO, C, SearchResult[MailHeader]] =
  for {
    inbox  <- a.getInbox
    mails  <- a.search(inbox, 20)(q)
  } yield mails

val q = (ReceivedDate >= Instant.now.minusSeconds(60)) && (Subject =*= "test")
val searchIO: IO[SearchResult[MailHeader]] = myemil(imapConf).run(searchInbox(myemil.access, q))


More information can be found here.