Syntax Utilities

The emil-common module doesn’t provide utilities for parsing mails or mail addresses from text. This is provided by the emil-javamail module, because the implementation from JavaMail is used.

There is a syntax object that has some common utilities when reading/writing e-mail.

Parsing MimeType from String

import emil.javamail.syntax._
import emil._

MimeType.parse("text/html; charset=utf-8")
// res0: Either[String, MimeType] = Right(
//   value = MimeType(
//     primary = "text",
//     sub = "html",
//     params = Map("charset" -> "utf-8")
//   )
// )

Reading/Writing E-Mail addresses

Parse a string into an e-mail address:

MailAddress.parse("John Doe <jdoe@gmail.com>")
// res1: Either[String, MailAddress] = Right(
//   value = MailAddress(
//     name = Some(value = "John Doe"),
//     address = "jdoe@gmail.com"
//   )
// )
MailAddress.parse("John Doe doe@com")
// res2: Either[String, MailAddress] = Left(
//   value = "Invalid mail address 'John Doe doe@com' - Local address contains control or whitespace"
// )

Write the mail address as unicode or ascii-only string:

val ma = MailAddress.parse("Örtlich <über.uns@test.com>").toOption.get
// ma: MailAddress = MailAddress(
//   name = Some(value = "Örtlich"),
//   address = "über.uns@test.com"
// )
val ascii = ma.asAsciiString
// ascii: String = "\"Örtlich\" <über.uns@test.com>"
MailAddress.parse(ascii)
// res3: Either[String, MailAddress] = Right(
//   value = MailAddress(
//     name = Some(value = "Örtlich"),
//     address = "über.uns@test.com"
//   )
// )
val unicode = ma.asUnicodeString
// unicode: String = "\"Örtlich\" <über.uns@test.com>"

E-Mail from/to String

E-Mail as string:

import cats.effect._
import emil._, emil.builder._
import cats.effect.unsafe.implicits.global

val mail = MailBuilder.build[IO](
  From("test@test.com"),
  To("test@test.com"),
  Subject("Hello"),
  HtmlBody("<p>This is html</p>")
)
// mail: Mail[IO] = Mail(
//   header = MailHeader(
//     id = "",
//     messageId = None,
//     folder = None,
//     recipients = Recipients(
//       to = List(MailAddress(name = None, address = "test@test.com")),
//       cc = List(),
//       bcc = List()
//     ),
//     sender = None,
//     from = Some(value = MailAddress(name = None, address = "test@test.com")),
//     replyTo = None,
//     originationDate = None,
//     subject = "Hello",
//     received = List(),
//     flags = Set()
//   ),
//   additionalHeaders = Headers(all = List()),
//   body = Html(
//     html = Pure(value = StringContent(asString = "<p>This is html</p>"))
//   ),
//   attachments = Attachments(all = Vector())
// )

import emil.javamail.syntax._

val mailStr = mail.serialize.unsafeRunSync()
// mailStr: String = """Date: Sat, 18 Nov 2023 12:56:18 +0100 (CET)
// From: test@test.com
// To: test@test.com
// Message-ID: <1821892477.0.1700308578568@kalamos>
// Subject: Hello
// MIME-Version: 1.0
// Content-Type: text/html; charset=utf-8
// Content-Transfer-Encoding: 7bit
// 
// <p>This is html</p>"""

Deserialize:

val mail2 = Mail.deserialize[IO](mailStr).unsafeRunSync()
// mail2: Mail[IO] = Mail(
//   header = MailHeader(
//     id = "messageId:<1821892477.0.1700308578568@kalamos>",
//     messageId = Some(value = "<1821892477.0.1700308578568@kalamos>"),
//     folder = None,
//     recipients = Recipients(
//       to = List(MailAddress(name = None, address = "test@test.com")),
//       cc = List(),
//       bcc = List()
//     ),
//     sender = None,
//     from = Some(value = MailAddress(name = None, address = "test@test.com")),
//     replyTo = None,
//     originationDate = Some(value = 2023-11-18T11:56:18Z),
//     subject = "Hello",
//     received = List(),
//     flags = Set()
//   ),
//   additionalHeaders = Headers(
//     all = List(
//       Header(
//         name = "MIME-Version",
//         value = NonEmptyList(head = "1.0", tail = List())
//       ),
//       Header(
//         name = "Content-Type",
//         value = NonEmptyList(head = "text/html; charset=utf-8", tail = List())
//       ),
//       Header(
//         name = "Content-Transfer-Encoding",
//         value = NonEmptyList(head = "7bit", tail = List())
//       )
//     )
//   ),
//   body = Html(
//     html = Pure(
//       value = ByteContent(
//         bytes = Chunk(
//           bytes = View(
//             at = scodec.bits.ByteVector$AtArray@b9286ad,
//             offset = 0L,
//             size = 19L
//           )
//         ),
//         charset = Some(value = UTF-8)
//       )
//     )
//   ),
//   attachments = Attachments(all = Vector())
// )