0%

发送邮件

邮件收发

使用Javaweb,实现邮件收发。

要在网络上实现邮件功能,必须要有专门的邮件服务器。电子邮箱(E-Mail地址)的获得需要在邮件服务器上进行申请。比如我们要使用QQ邮箱,就需要开通邮箱功能;

传输协议

邮件发送与接收,使用到的传输协议有SMTP、POP3/IMAP等。(POP3与IMAP的区别,可以查看这里:传送门

SMTP协议

发送邮件:我们通常把处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器)。

SMTP服务器地址:一般是smtp.xxx.com,比如163邮箱是smtp.163.com,qq邮箱是smtp.qq.com

POP3协议

接收邮件:我们通常把处理pop3请求(邮件接收请求)的服务器称之为POP3服务器(邮件接收服务器)。

例如A使用网易的SMTP服务器发送邮件给B,B使用的是QQ邮箱📮。

  1. A开通一个网易邮箱账号。
  2. A使用本地邮箱客户端,通过SMTP协议使用网易的SMTP服务器向B发送一封邮件。(客户端发送邮件给网易服务器,网易服务器再将邮件发送给B邮箱地址对应的服务器。均使用SMTP协议)
  3. 服务器根据B的邮箱地址,将邮件投递到QQ的POP3/SMTP服务器中的B账户空间下。
  4. B使用本地邮箱客户端通过POP3协议从POP3/SMTP服务器中下载邮件(取出)
  5. 如果在服务器中没有查找到A发来的邮件,有可能被服务器当作垃圾邮件放到了垃圾箱中。需要到垃圾箱中去找找看。

Java发送邮件

我们将用代码完成邮件的发送。这在实际项目中应用的非常广泛,比如注册需要发送邮件进行账号激活,再比如OA项目中利用邮件进行任务提醒等等。

使用Java发送E-Mail十分简单,但是首先要准备JavaMail API和Java Activation Framework。使用到两个jar包:mail.jaractivation.jar

1
2
3
4
5
6
7
8
9
10
11
12
<!-- https://mvnrepository.com/artifact/javax.mail/mail -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.5.0-b01</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.activation/activation -->
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>

JavaMail是sun公司为方便Java开发人员在应用程序中实现邮件发送和接收功能而提供的一套标准开发包,它支持一些常用的邮件协议,比如前面所讲的SMTP、POP3、IMAP,还有MIME等。我们在使用JavaMail API编写邮件时,无须考虑邮件的底层实现细节,只要调用JavaMail开发包中相应的API类就可以了。

步骤:

  • 创建包含邮件服务器的网络连接信息的Session对象
  • 创建代表邮件内容的Message对象
  • 创建Transport对象,连接服务器,发送Message,关闭连接

主要有四个核心类,我们在编写程序时,记住这四个核心类,就很容易编写出Java邮件处理程序。

获取授权码

我们需要使用邮件服务器来发送邮件,可以申请QQ邮箱或网易邮箱等免费邮箱,开启POP3/SMTP服务并获得授权码。

QQ邮箱获取授权码:

网易邮箱获取授权码:

发送简单邮件

使用JavaMail发送一封简单的邮件,纯文本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package com.qsdbl.jspdemo;
import com.sun.mail.util.MailSSLSocketFactory;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.security.GeneralSecurityException;
import java.util.Properties;
//发送一封简单的邮件
public class MailDemo01 {
public static void main(String[] args) throws GeneralSecurityException, MessagingException {

Properties prop = new Properties();
prop.setProperty("mail.host","smtp.qq.com");//设置QQ邮件服务器,网易为smtp.163.com
prop.setProperty("mail.transport.protocol","smtp");//邮件发送协议
prop.setProperty("mail.smtp.auth","true");//需要验证用户名密码

//QQ邮箱,还要设置SSL加密(其他邮箱不需要)
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
prop.put("mail.smtp.ssl.enable","true");
prop.put("mail.smtp.ssl.socketFactory",sf);

//使用JavaMail发送邮件的5个步骤
//1、创建定义整个应用程序所需的环境信息的Session对象
Session session = Session.getDefaultInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
//实参为发件人的账号与密码,密码填写授权码即可
return new PasswordAuthentication("113xxxxx51@qq.com","授权码");
}
});
//开启Session的debug模式,这样可以实时查看Email的运行状态
session.setDebug(true);
//2、通过Session对象得到transport对象
Transport ts = session.getTransport();
//3、使用邮箱的用户名 和 授权码 连上邮件服务器
ts.connect("smtp.qq.com","113xxxxx51@qq.com","授权码");
//4、创建邮件:写邮件
//注意需要传递Session
MimeMessage message = new MimeMessage(session);
//指明邮件的发件人
message.setFrom(new InternetAddress("113xxxxx51@qq.com"));
//指明邮件的收件人,若发件人与收件人一样则是发给自己(可以群发)
message.setRecipient(Message.RecipientType.TO,new InternetAddress("qsxxxxx@163.com"));
//邮件的标题
message.setSubject("测试JavaMail");//网易163邮箱对标题要求比较严格,若报错可以使用"注册成功®️"试试。
//邮件的文本内容
message.setContent("你好,这是使用<span style='color:red'>JavaMail</span>发送的一封邮件!","text/html;charset=utf-8");//html文本,可设置样式

//5、发送邮件
ts.sendMessage(message, message.getAllRecipients());
//6、关闭连接
ts.close();
}
}

测试

发送复杂邮件

MIME(多用途互联网邮件扩展类型)

MimeBodyPart类

  • Javax.mail.internet.MimeBodyPart类,表示的是一个MIME消息,它和MimeMessage类一样都是从Part接口继承过来。

MimeMultipart类

  • Javax.mail.internet.MimeMultipart是抽象类Multipart的实现子类,它用来组合多个MIME消息。一个MimeMultipart对象可以包含多个代表MIME消息的MimeBodyPart对象。

文本+图片

文本+内嵌资源(图片),需要指定multipart的类型为related。

将48行代码替换为下边的即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//发送纯文本的邮件:
//邮件的文本内容
message.setContent("你好,这是使用<span style='color:red'>JavaMail</span>发送的一封邮件!","text/html;charset=utf-8");//html文本,可设置样式

//更换为:

//= = = = = 发送带有内嵌资源(例如:图片)的邮件(例如:文本+图片)= = = = =
//准备图片数据
String imgPath = "/Users/qsdbl/Documents/Java/workspace/JSP-study/jsp_base/src/main/resources/img/xhr.gif";
String imgName = imgPath.substring(imgPath.lastIndexOf("/")+1);
MimeBodyPart image = new MimeBodyPart();
DataHandler dh = new DataHandler(new FileDataSource(imgPath));//图片需要经过数据处理,Datahandler:数据处理
image.setDataHandler(dh);//在我们的body中放入这个处理的图片数据
image.setContentID(imgName);//给图片设置一个ID,我们在后边可以使用。cid:id名

//准备正文数据
MimeBodyPart text = new MimeBodyPart();
text.setContent("这是一封正文带有图片的的邮件。<br><img src='cid:"+imgName+"'/><img src='../../../images/markdown_img/2020/20201205130141.jpg'/>","text/html;charset=utf-8");//第二个img使用的src是网络URL不是本地图片资源,不属于内嵌图片资源

//描述数据关系
MimeMultipart mm = new MimeMultipart();
mm.addBodyPart(text);
mm.addBodyPart(image);
mm.setSubType("related");

//设置到信息中,保存修改
message.setContent(mm);//把最后编辑好的邮件放到消息当中
message.saveChanges();//保存修改
//= = = = = = = = = =

带附件

注意

  • 注意看上图,附件不是跟文本、内嵌资源封装在一个multipart中的。
  • 文本+图片,组装为一个MimeMultipart,构成邮件正文
  • 将文本+图片组成的MimeMultipart(邮件正文),放到bodyPart中再与附件一块 组装在一个MimeMultipart
  • 将邮件正文 与 附件,组装在一个MimeMultipart中,并指定multipart的类型为mixed。

将48行代码替换为下边的即可(代码过长,封装在方法mixedMail中):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
//3、带有附件
mixedMail(message);//封装在方法中


public static void mixedMail(MimeMessage message) throws MessagingException {
/*
* 编写邮件内容
* 1、图片
* 2、文本
* 3、附件
* */
//图片
String imgPath = "/Users/qsdbl/Documents/Java/workspace/JSP-study/jsp_base/src/main/resources/img/xhr.gif";
String imgName = imgPath.substring(imgPath.lastIndexOf("/")+1);
MimeBodyPart image = new MimeBodyPart();
DataHandler dh = new DataHandler(new FileDataSource(imgPath));//图片需要经过数据处理,Datahandler:数据处理
image.setDataHandler(dh);//在我们的body中放入这个处理的图片数据
image.setContentID(imgName);//给图片设置一个ID,我们在后边可以使用。cid:id名

//准备正文数据
MimeBodyPart text = new MimeBodyPart();
text.setContent("这是一封正文即带有图片又带有附件的的邮件。<br><img src='cid:"+imgName+"'/>","text/html;charset=utf-8");

//附件
//附件1,一张图片
String mixed01Path = "/Users/qsdbl/Documents/Java/workspace/JSP-study/jsp_base/src/main/resources/img/xhr.gif";
String mixed01Name = mixed01Path.substring(mixed01Path.lastIndexOf("/")+1);
MimeBodyPart mixed01 = new MimeBodyPart();
mixed01.setDataHandler(new DataHandler(new FileDataSource(mixed01Path)));
mixed01.setFileName(mixed01Name);//附件名

//附件2,一个txt文件
String mixed02Path = "/Users/qsdbl/Documents/个人资料/备份/手机/MIUI养老计划/养老方案1.txt";
String mixed02Name = mixed02Path.substring(mixed02Path.lastIndexOf("/")+1);
MimeBodyPart mixed02 = new MimeBodyPart();
mixed02.setDataHandler(new DataHandler(new FileDataSource(mixed02Path)));
mixed02.setFileName(mixed02Name);//附件名

//描述数据关系(拼装邮件正文内容,文本+图片+附件)
//1、文本+图片,组装为一个MimeMultipart,构成邮件正文
MimeMultipart multipart1 = new MimeMultipart();
multipart1.addBodyPart(text);
multipart1.addBodyPart(image);
multipart1.setSubType("related");
//将文本+图片组成的MimeMultipart(邮件正文),放到bodyPart中再与附件一块 组装在一个MimeMultipart
MimeBodyPart contentText = new MimeBodyPart();
contentText.setContent(multipart1);

//2、将邮件正文 与 附件,组装在一个MimeMultipart中
MimeMultipart allFile = new MimeMultipart();
allFile.addBodyPart(mixed01);//附件1
allFile.addBodyPart(mixed02);//附件2
allFile.addBodyPart(contentText);//邮件正文
allFile.setSubType("mixed");//带有附件,所以类型设置为mixed


//设置到信息中,保存修改
message.setContent(allFile);//把最后编辑好的邮件放到消息当中
message.saveChanges();//保存修改
}

测试

案例

JavaMail应用案例,见注册/登陆模块

学习自B站遇见狂神说

若图片不能正常显示,请在浏览器中打开

欢迎关注我的其它发布渠道