Как отправить электронное письмо в Scala

20 марта 2013

В этой заметке будет показано, как в Scala послать письмо через гугловые SMTP-сервера с помощью пакета JavaMail. Притом не какое-нибудь простое письмо, а с прикрепленным файлом, в кодировке UTF-8 и с HTML, содержащим картинки. Функциональщины как таковой не будет, зато мы увидим, как выглядит использование Java-библиотек из Scala, а также ознакомимся с той частью Scala, которая «почти как Java, только лучше».

Нам понадобится файл build.sbt следующего содержания:

name := "gmail-sender"

version := "0.2"

scalaVersion := "2.10.1"

libraryDependencies += "javax.mail" % "mail" % "1.5.0-b01"

scalacOptions ++= Seq("-unchecked", "-deprecation")

Если у вас не установлена Scala 2.10.1, не беспокойтесь, sbt самостоятельно подтянет и скомпилирует ее. Это не займет много времени.

В простейшем случае работа с JavaMail выглядит следующим образом:

import javax.mail._
import javax.mail.internet._
import java.util._

object GmailSenderSimple extends App {
  if(args.size < 2) {
    println("Usage: gmail-sender-simple gmail-user gmail-password")
    sys.exit(1)
  }

  val Array(username, password, _*) = args

  val properties = new Properties()
  properties.put("mail.smtp.host", "smtp.gmail.com")
  properties.put("mail.smtp.starttls.enable","true")
  val session = Session.getDefaultInstance(properties)
  val message = new MimeMessage(session)

  message.setFrom(s"User Name <$username>")
  message.addRecipients(Message.RecipientType.TO,
                        s"User Name <$username>")
  message.setSubject("Greetings!")
  message.setText("Hello!")

  Transport.send(message, username, password)
}

Если передать программе в качестве аргументов ваш электронный адрес на GMail и пароль к нему, вы отправите сами себе простое текстовое письмо.

Обратите внимание на использование экстракторов, которые удобны не только при объявлении переменных, но и в сопоставлении с образцом:

scala> val Array(x, y, z @ _*) = Array(1,2,3,4,5)
x: Int = 1
y: Int = 2
z: Seq[Int] = Vector(3, 4, 5)

scala> List(1,2,3) match { case List() => "Empty list"; case List (1, _, _) => "1 _ _"; case _ => "Whatever" }
res0: String = 1 _ _

…, а также на интерполяцию строк, которая появилась в Scala 2.10:

scala> val str = s"x = $x, y = $y"
str: String = x = 1, y = 2

Полагаю, тут все понятно, и можно перейти к более сложному примеру:

import javax.mail._
import javax.mail.internet._
import java.util._

object GmailSender extends App {
  if(args.size < 2) {
    println("Usage: gmail-sender gmail-user gmail-password")
    sys.exit(1)
  }

  val Array(username, password, _*) = args

  val properties = new Properties()
  properties.put("mail.smtp.host", "smtp.gmail.com")
  properties.put("mail.smtp.starttls.enable","true")

  val message = new MimeMessage(Session.getDefaultInstance(properties))
  val multipart = new MimeMultipart()
  val alternative = new MimeMultipart("alternative")

  val imageId = UUID.randomUUID.toString
  val textPart, htmlPart, wrap, attachmentPart, imagePart
          = new MimeBodyPart()
  textPart.setText("Тело письма")
  alternative.addBodyPart(textPart)
  htmlPart.setContent(
      s"""|А это - тело письма в <strong>HTML</strong>
          | с картинкой: <img src="cid:$imageId" alt="" />
          |"""
.stripMargin,
      "text/html; charset=UTF-8")
  alternative.addBodyPart(htmlPart)

  wrap.setContent(alternative)

  multipart.addBodyPart(wrap)
  attachmentPart.attachFile("./build.sbt")
  multipart.addBodyPart(attachmentPart)

  imagePart.attachFile("./afiskon.jpg")
  imagePart.setContentID(s"<$imageId>")
  multipart.addBodyPart(imagePart)

  message.setFrom(s"User Name <$username>")
  message.addRecipients(Message.RecipientType.TO,
                        s"User Name <$username>")
  message.setSubject("Сабжект")
  message.setContent(multipart)

  Transport.send(message, username, password)
}

Я надеюсь, что вы знаете, что такое multipart/alternative и прочее в этом духе, поскольку этот вопрос выходит за рамки поста. Если теперь запустить приведенную программу:

sbt "run user@gmail.com password"

… то вам придет примерно такое электронное письмо:

Отправка e-mail на Scala

Все, как обещано — юникод, прикрепленный файл, HTML c картинкой. Полную версию исходного кода вы найдете в этом архиве.

Дополнение: Работа с регулярными выражениями в Scala

Метки: , .


Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.