Scala发邮件(带附件,无论是本地文件和hdfs文件或df或rdd)
Posted 羲凡丞相
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala发邮件(带附件,无论是本地文件和hdfs文件或df或rdd)相关的知识,希望对你有一定的参考价值。
@羲凡——只为了更好的活着
Scala发邮件(带附件,无论是本地文件和hdfs文件或df或rdd)
在有些spark任务执行完后需要通知我们该任务已经执行结束,发邮件到某个邮箱是最直接的方式。那如何用scala发邮件呢,我在网上没有找到一个案例,我研究了一天终于被我解决了。下面字节上代码:
import java.io.File
import com.typesafe.config.ConfigFactory
import org.apache.spark.sql.SparkSession
import play.api.libs.mailer._
object TestSendMail
def main(args: Array[String]): Unit =
val spark = SparkSession.builder()
.appName("TestSendMail")
.master("local[*]")
.getOrCreate()
// 将hdfs上的文件生成rdd
val rdd = spark.sparkContext.textFile("/aarontest/data/wc.txt")
val subject = "羲凡-Scala发邮件" //邮件主题
val from = "aaa@qq.com" //邮件发送地址
val to = Seq("bbb@qq.com", "ccc@163.com") //邮件接收地址
//val bodyText = Option("==========scala发邮件成功啦!!!==========")
val bodyhtml = Option(
"""
|<html>
|<body>
|<h1 align="center">Scala发邮件成功啦</h1>
|<h2 align="center">Get busy living, Or get busy dying</h2>
|<h3 align="center">Get busy living, Or get busy dying</h3>
|</body>
|</html>
""".stripMargin)
val charset = Option("utf-8") // 字符编码 默认utf-8
// 以本地文件为附件相关参数
val name = "以本地文件为附件"
val file = new File("D:\\\\AaronProject\\\\SparkTest227\\\\data\\\\wc.txt")
val attachment: Attachment = AttachmentFile(name, file)
// 以hdfs文件或rdd或df为附件相关参数
val name2 = "以hdfs文件为附件"
val data: Array[Byte] = rdd.collect().mkString("\\n").getBytes()
val mimetype = "text/plain" // 根据文件类型选择MimeTypes对应的值
val attachment2: Attachment = AttachmentData(name2, data, mimetype)
// 将两个附件生成一个seq序列
val attachments: Seq[Attachment] = Seq(attachment, attachment2)
// 生成邮件
val email = Email(subject,from,to,None,bodyHtml,charset,attachments = attachments)
// STMP服务参数
val host = "smtp.qq.com" // STMP服务地址
val port = 587 // STMP服务端口号
val user = Option("aaa@qq.com") // STMP服务用户邮箱
val password = Option("rjnsjyalufzwbebd") // STMP服务邮箱密码
val timeout = Option(10000) //setSocketTimeout 默认60s
val connectionTimeout = Option(10000) //setSocketConnectionTimeout 默认60s
// STMP服务SMTPConfiguration
val configuration: SMTPConfiguration = new SMTPConfiguration(
host, port, false, false, false,
user, password, false, timeout,
connectionTimeout, ConfigFactory.empty(), false)
val mailer: SMTPMailer = new SMTPMailer(configuration)
// 发送邮件
mailer.send(email)
println("==========scala发邮件成功啦!!!==========")
spark.stop()
结果展示:
注意事项
1.pom.xml 文件中添加依赖,依赖的版本不同代码会有略微的变化(我亲测5.0.0的版本和7.0.0的就不一样)
<dependency>
<groupId>com.typesafe.play</groupId>
<artifactId>play-mailer_2.11</artifactId>
<version>7.0.0</version>
</dependency>
2.如果用QQ邮箱发邮件给别的邮箱,需要先开启QQ邮箱的SMTP服务且邮箱的登录密码换成你邮箱的授权码。什么是授权码,它又是如何设置?官网:https://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=1001256 。两者缺一不可,否则会报如下错误
Exception in thread "main" org.apache.commons.mail.EmailException: Sending the email to the following server failed : smtp.qq.com:587
at org.apache.commons.mail.Email.sendMimeMessage(Email.java:1469)
at org.apache.commons.mail.Email.send(Email.java:1496)
at play.api.libs.mailer.SMTPMailer$$anon$1.send(SMTPMailer.scala:14)
at play.api.libs.mailer.CommonsMailer.send(CommonsMailer.scala:23)
at play.api.libs.mailer.SMTPMailer.send(SMTPMailer.scala:24)
at scalatest.TestSendMail$.main(TestSendMail.scala:39)
at scalatest.TestSendMail.main(TestSendMail.scala)
Caused by: javax.mail.AuthenticationFailedException: 535 Error: ÇëʹÓÃÊÚȨÂëµÇ¼¡£ÏêÇéÇë¿´: http://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=1001256
at com.sun.mail.smtp.SMTPTransport$Authenticator.authenticate(SMTPTransport.java:932)
at com.sun.mail.smtp.SMTPTransport.authenticate(SMTPTransport.java:843)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:748)
at javax.mail.Service.connect(Service.java:388)
at javax.mail.Service.connect(Service.java:246)
at javax.mail.Service.connect(Service.java:195)
at javax.mail.Transport.send0(Transport.java:254)
at javax.mail.Transport.send(Transport.java:124)
at org.apache.commons.mail.Email.sendMimeMessage(Email.java:1459)
... 6 more
3.如果邮件发送给多个邮箱,每个邮箱间用逗号分隔,见如上代码
4.如果bodyText参数和bodyHtml参数同事有,则只会显示bodyHtml中的内容,一般情况下这两个参数也只会用一个,另一个用None,见如上代码
5.发邮件添加本地文件和非本地文件作为附件的样例类不同,分别是AttachmentFile和AttachmentData。如果直接用AttachmentFile来添加hdfs上文件作附件,报错找不到文件,具体如下
Exception in thread "main" org.apache.commons.mail.EmailException: Cannot attach file "\\aarontest\\data\\wc.txt"
at org.apache.commons.mail.MultiPartEmail.attach(MultiPartEmail.java:333)
at play.api.libs.mailer.CommonsMailer.play$api$libs$mailer$CommonsMailer$$handleAttachmentFile(CommonsMailer.scala:154)
at play.api.libs.mailer.CommonsMailer$$anonfun$createEmail$10.apply(CommonsMailer.scala:43)
at play.api.libs.mailer.CommonsMailer$$anonfun$createEmail$10.apply(CommonsMailer.scala:39)
at scala.collection.immutable.List.foreach(List.scala:392)
at play.api.libs.mailer.CommonsMailer.createEmail(CommonsMailer.scala:39)
at play.api.libs.mailer.CommonsMailer.send(CommonsMailer.scala:23)
at play.api.libs.mailer.SMTPMailer.send(SMTPMailer.scala:24)
at scalatest.TestSendMail$.main(TestSendMail.scala:49)
at scalatest.TestSendMail.main(TestSendMail.scala)
Caused by: java.io.IOException: "\\aarontest\\data\\wc.txt" does not exist
at org.apache.commons.mail.MultiPartEmail.attach(MultiPartEmail.java:322)
... 9 more
6.以非本地文件为附件时,一定要将AttachmentData中data参数变成Array[Byte]格式。否则会报错Exception in thread "main" java.lang.NumberFormatException
。如果出现这个错误则说明你的data的数据类型不对或转换的方式出错了。比如我将data的值改成 rdd.collect().map(_.toByte) ,虽然data的数据类型变成了Array[Byte],但还是会报如上的错误,因为转换的方式不对。
7.以非本地文件为附件时,AttachmentData中mimetype参数要根据自己的需要设置,常见的MIME类型如下:
普通文本 text/plain
超文本标记语言文本 text/html
JPEG图形 image/jpeg
csv文件 text/csv
xml文件 application/xml
如果想了解更多的MIME类型可参考 https://blog.csdn.net/qq_19916577/article/details/46502761
====================================================================
@羲凡——只为了更好的活着
若对博客中有任何问题,欢迎留言交流
以上是关于Scala发邮件(带附件,无论是本地文件和hdfs文件或df或rdd)的主要内容,如果未能解决你的问题,请参考以下文章