问题描述
最近项目中需要用到office365发送mirror邮件,并且必须要用scala代码解决
以下是scala发送邮件的代码
所用到jar的pom是
<dependency>
<groupId>com.typesafe.play</groupId>
<artifactId>play-mailer_2.11</artifactId>
<version>7.0.0</version>
</dependency>
这是发送邮件的code
val subject = "This is a Mail" //邮件主题
val file = new File("file path") //附件文件
val attachment: Attachment = AttachmentFile(name, file) //附件
val from = "xxxx@xxx.com" //邮件发送地址
val to = Seq("xxxx@xxx.com", "xxxx@xxx.com",...) //邮件送达地址
val bodyHtml = Option(
s"""
|<html>
|<body>
|<h1 align="center">your html text body</h1>
|</body>
|</html>
""".stripMargin)
val charset = Option("utf-8") // 字符编码 默认utf-8
val attachments: Seq[Attachment] = Seq(attachment) // 生成一个seq序列
val email = Email(subject, from, to, None, bodyHtml, charset, attachments = attachments) // 生成邮件
// STMP服务参数
val host = "" // STMP服务地址
val port = "" // STMP服务端口号
val user = Option("") // STMP服务用户邮箱
val password = Option("") // STMP服务邮箱密码
val timeout = Option(10000) //setSocketTimeout 默认60s
val connectionTimeout = Option(10000) //setSocketTimeout 默认60s
val configuration: SMTPConfiguration = new SMTPConfiguration(
host, port, false, false, false,
user, password, false, timeout,
connectionTimeout, ConfigFactory.empty(), false) // STMP服务SMTPConfiguration
val mailer: SMTPMailer = new SMTPMailer(configuration)
mailer.send(email) // 发送邮件
这时候问题来了,以下是SMTPConfiguration class的source code
case class SMTPConfiguration(
host: String,
port: Int,
ssl: Boolean = false,
tls: Boolean = false,
tlsRequired: Boolean = false,
user: Option[String] = None,
password: Option[String] = None,
debugMode: Boolean = false,
timeout: Option[Int] = None,
connectionTimeout: Option[Int] = None,
props: Config = ConfigFactory.empty(),
mock: Boolean = false
)
这是网上找到office365的邮件客户端的配置
可以看到case class SMTPConfiguration对于office365来说只有IMAP加密方法TLS和POP加密方法 TLS,但是官方要求SMTP的加密方式必须是STARTTLS
解决方案
我们知道java mail中使用Properties这个类来设置mail的配置,而scala底层又是用java写的
于是回看SMTPConfiguration这个类
case class SMTPConfiguration(
host: String,
port: Int,
ssl: Boolean = false,
tls: Boolean = false,
tlsRequired: Boolean = false,
user: Option[String] = None,
password: Option[String] = None,
debugMode: Boolean = false,
timeout: Option[Int] = None,
connectionTimeout: Option[Int] = None,
props: Config = ConfigFactory.empty(),
mock: Boolean = false
)
我们会发现有个props是config类
props: Config = ConfigFactory.empty()
点进props中看,会跳到abstract class CommonsMailer的createEmail方法中,有这么一段code
// After the email was set up we can now also manipulate the session properties directly
val mailProperties = email.getMailSession.getProperties();
conf.props.entrySet().asScala.foreach(prop => {
mailProperties.setProperty("mail.smtp." + prop.getKey(), prop.getValue().unwrapped().toString)
mailProperties.setProperty("mail.smtps." + prop.getKey(), prop.getValue().unwrapped().toString)
})
email.setMailSession(Session.getInstance(mailProperties, authenticator.orNull))
发现这其实和java mail中使用Properties的功能非常类似
回到props处,点进ConfigFactory类中,会发现里面有个方法叫做parseProperties,返回的居然就是config类型的Properties
/**
* Like {@link #parseProperties(Properties, ConfigParseOptions)} but uses default
* parse options.
* @param properties
* a Java Properties object
* @return the parsed configuration
*/
public static Config parseProperties(Properties properties) {
return parseProperties(properties, ConfigParseOptions.defaults());
}
可以看到官方注释中表明到这就是java Properties object
于是大胆猜测可以在这里设置STARTTLS属性
以下是解决方案的code
//增加部分
val properties = new Properties()
properties.put("starttls.enable", "true")
val configuration: SMTPConfiguration = new SMTPConfiguration(
mailHost, mailPort, false, false, false,
Option(mailUser), Option(mailPassword), false, Option(timeout),
Option(connectionTimeout), ConfigFactory.parseProperties(properties), false)
new SMTPMailer(configuration)
增加一个properties属性,并做如下设置,使用ConfigFactory.parseProperties(properties)填入SMTP配置中即可解决
后话
本文仅适用于使用office365的SMTP服务发送邮件的情况,笔者在网上没找相应的解决方案后想到发此文,但也应会有比我更好的解决方案。初次写文难免有顾及不周之处,请各位见谅,欢迎各位大佬来讨论和指导!