# java实现邮件发送
# 简单邮件和复杂邮件
简单的邮件就是内容是存文本,没有图片等等其他附件文件
而复杂文件,除了含有存文本外,还有附件,图片等等
# 步骤
# 配置对象
创建一个Properties类,这个类是必须的,发送邮件的服务器,还有协议等等信息都是通过这个配置对象进行获取的
调用props.setProperty("mail.host","smtp.qq.com")
方法就可以将邮箱的服务器,邮箱协议等等信息保存在对象中
props.setProperty("mail.smtp.auth","true")
这个方法参数为true,代表需要验证用户名密码(授权码
),但是注释之后,同样也是可以的,可能的原因就是在后面
transport.connect("smtp.qq.com","2291308094@qq.com","zitcvhazptfjeccf")
也是需要进行传用户名和密码
必须需要配置的
邮箱服务器:
setProperty("mail.host","smtp.qq.com")
邮件发送的协议:
setProperty("mail.transport.protocol","smtp");
在有些的博客中,这里设置协议是
setProperty("mail.transport)
,如果是这样的话,那么session.getTransport()
就拿不到这个协议的信息,因为默认是通过键mail.transport.protocol
从properties对象进行拿到的public Transport getTransport() throws NoSuchProviderException { return this.getTransport(this.getProperty("mail.transport.protocol")); }
1
2
3
如果是QQ邮箱的话,那么还需要进行ssl的验证,但是注释之后还是可以,只是在他们之间的连接并不是ssl,通过打印信息就可以知道
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
props.put("mail.smtp.ssl.enable","true");
props.put("mail.smtp.socketFactory",sf);
2
3
4
如果开启上面代码,那么他们之间的连接是ssl
DEBUG SMTP: useEhlo true, useAuth false
DEBUG SMTP: trying to connect to host "smtp.qq.com", port 465, isSSL true
2
# 获取session对象
Session.getDefaultInstance(props)
通过这个方法进行获取
获取session对象就相当于我们和邮件的服务器进行了通信,也就相当于我们点开了邮件的写邮件页面
需要传入一个properties对象,还可以使用匿名内部类的方式创建一个
Session session = Session.getDefaultInstance(props , new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication () {
//发件人邮件用户名,密码
return new PasswordAuthentication("2291308094@qq.com","zitcvhazptfjeccf");
});
2
3
4
5
6
开启debug模式,
session.setDebug(true)
开启可以在控制台打印信息,时候发送情况,还有很多邮件的协议,内容等等,如果为false的话,那么就不会展示DEBUG: setDebug: JavaMail version 1.4.7 DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle] DEBUG SMTP: useEhlo true, useAuth false DEBUG SMTP: trying to connect to host "smtp.qq.com", port 25, isSSL false //是否为ssl连接 220 newxmesmtplogicsvrszb5.qq.com XMail Esmtp QQ Mail Server. DEBUG SMTP: connected to host "smtp.qq.com", port: 25 //port是邮件服务器的端口 //host是主机 EHLO DESKTOP-JD7N6TI 250-newxmesmtplogicsvrszb5.qq.com 250-PIPELINING 250-SIZE 73400320 250-STARTTLS 250-AUTH LOGIN PLAIN 250-AUTH=LOGIN 250-MAILCOMPRESS 250 8BITMIME DEBUG SMTP: Found extension "PIPELINING", arg "" DEBUG SMTP: Found extension "SIZE", arg "73400320" DEBUG SMTP: Found extension "STARTTLS", arg "" DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN" DEBUG SMTP: Found extension "AUTH=LOGIN", arg "" DEBUG SMTP: Found extension "MAILCOMPRESS", arg "" DEBUG SMTP: Found extension "8BITMIME", arg "" DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM DEBUG SMTP: AUTH LOGIN command trace suppressed DEBUG SMTP: AUTH LOGIN succeeded DEBUG SMTP: use8bit false MAIL FROM:<2291308094@qq.com> 250 OK. RCPT TO:<2291308006@qq.com> 250 OK DEBUG SMTP: Verified Addresses DEBUG SMTP: 2291308006@qq.com DATA 354 End data with <CR><LF>.<CR><LF>. From: 2291308094@qq.com To: 2291308006@qq.com Message-ID: <472654579.0.1615476952207.JavaMail."Rk��"@smtp.qq.com> Subject: this is a title MIME-Version: 1.0 Content-Type: text/html;charset=utf-8 Content-Transfer-Encoding: quoted-printable this is a test =E5=86=85=E5=AE=B9 . 250 OK: queued as.
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
开启debug模式,如果是在transport.connect()
之前开启的话,那么打印的信息会很少,因为大多数信息都是在这一个过程产生的
# transport
session对象就是我们点击邮件进入,书写邮件的那个页面,但是我们想要将邮件发送出去,还需要transport对象的支持
Transport transport = session.getTransport();
通过这个transport对象,可以和邮件服务器建立连接,以此俩确定
transport.connect("smtp.qq.com","2291308094@qq.com","zitcvhazptfjeccf")
通过建立连接俩确定是不是你自己使用你的账号进行发送邮件,只是程序代替了打开邮件,编写邮件,发送邮件的过程,将这些过程都使用程序就行完成
# 编写邮件内容
既然已经进入邮件页面(session
),那么我们就需要进行邮件的编写
创建消息对象
MimeMessage message = new MimeMessage(session);
1需要传入一个session,这个过程就是,编写邮件内容,是在哪个打开的邮件中进行编写(
session就是一个打开的邮件面板
)设置发件人
注意,发件人不能使用中文,就是不存在的地址,必须是和你邮箱的授权码相匹配的邮箱
message.setFrom(new InternetAddress("初尘博客")); //报错
1
2//正确 message.setFrom(new InternetAddress("2291308094@qq.com"));
1
2指明邮件的收件人
message.setRecipient(MimeMessage.RecipientType.TO,new InternetAddress("2291308006@qq.com"))
1Message.RecipientType.TO:消息接受者 Message.RecipientType.CC:消息抄送者 Message.RecipientType.BCC:匿名抄送接收者(其他接受者看不到这个接受者的姓名和地址)
设置发送的日期
message.setSentDate(java.util.Date theDate);
设置邮件内容
message.setContent("this is a test 内容","text/html;charset=utf-8");
1邮件的内容可以是HTML文档
发送邮件
transport.sendMessage(message,message.getAllRecipients())
如果设置message的信息
message.setContent("中午好","text/html;charset=utf-8");
message.setSentDate(new Date(33445456));
message.setDescription("this is a descript");
message.setFileName("文件名字");
message.setText("text");
2
3
4
5
# 发送给多个用户
如果想要发送给多个用户,那么就必须使用此方法
public abstract void setRecipients(Message.RecipientType var1, Address[] var2)
参数需要传入一个Address[]
数组,切记不可以这样设置发送给多个用户
//错误代码
message.setRecipient(MimeMessage.RecipientType.TO,new InternetAddress("2291308006@qq.com"));
message.setRecipient(Message.RecipientType.TO,new InternetAddress("sdfs567@163.com"));
2
3
如果是使用这种形式,那么最后写的那个地址将会覆盖上一个2291308094@qq.com
的地址
# 发送附件
附件的发送,其实就相当于是一个框,将其一部分一部分的组合起来,就形成了一封邮件里面的多个内容
如果我们的邮件里面,只有存文本的话,那么就会将
multipart设置为alternative
如果邮件里面还有图片,文本,没有附件的话,需要将
multipart设置为related
如果邮件里面有图片,文本,附件的话,需要将
multipart设置为mixed
实现步骤
创建一个properties对象,并且将需要使用到的服务器配置存入到里面
创建一个session
创建transport对象
获取消息对象message
获取
MimeBodyPart
对象,并且获取需要发送的图片数据获取text文本节点信息
MimeBodyPart
,使用setContent()
方法设置内容获取
MimeMultipart
对象,并且将MimeBodyPart
对象调用MimeMultipart
的addBodyPart
添加到MimeMultipart
中设置
MimeMultipart
对象的setSubType("related");
将
MimeMultipart
添加到message对象中message.setContent(part);
获取
MimeBodyPart
对象
因为尽管是简单的邮件(就只是存文本),他也是使用一个节点
multipart
套起来的,然后再设置multipart
的格式为alternative
,就是一个文本
一封邮件,带有图片,还有附件,就是一个一个节点进行组合起来,就形成了一封带有图片,附件的邮件,并且是按照顺序进行拼接的
所以如果想要发送图片也是一样,需要创建一个节点容器,用来存放这张图片的数据,然后在将这个节点和其他的节点(图片,文字,附件)按照自己想要的顺序进行组合
//装备图片数据
MimeBodyPart img_part = new MimeBodyPart();
//MimeBodyPart对象就相当于是一个容器节点,用来存放图片的数据
DataHandler handler = new DataHandler(new FileDataSource(
new File("C:\\Users\\chuchen\\Pictures\\好看动漫图片\\2.jpg")));
//将一个图片数据存入容器节点中(MimeBodyPart对象)
img_part.setDataHandler(handler);
img_part.setContentID("1.jpg");
2
3
4
5
6
7
8
img_part.setDataHandler(handler);
不能使用InputStream
类,因为参数指定必须使用DataHandler
对象
用来存放的对象是
MimeBodyPart
,不能直接使用MimeMultipart
,因为MimeMultipart
相当于这两个的整体
,每一张图片保存的容器相当于
MimeMultipart
的每一个身体部分,
img_part.setContentID("1.jpg")
相当于定义了这张图片在发送时的图片名称,这个参数名称可以代表着这张图片的数据,1.jpg保存了这张图片的数据,通过这个参数就可以拿到这张图片(在当前邮件中)
设置文本内容
//准备正文数据
//因为一封带有图片的邮件,其是文本和图片节点的组合,上面的那个是图片节点,这个text是一个文本节点
MimeBodyPart text = new MimeBodyPart();
text.setContent("只是一封带有<img src='cid:1.jpg' />的图片邮件","text/html;charset=utf-8");
2
3
4
如果想要发送带有图片的邮件,那么就必须添加上文本内容,并且文本内容中一定要有<img src='cid=...' />
text.setContent("只是一封带有<img src='cid:1.jpg' />的图片邮件","text/html;charset=utf-8");
的目的就是将图片显示在邮件中进行展示
如果没有设置
text.setContent("只是一封带有<img src='cid:1.jpg' />的图片邮件","text/html;charset=utf-8")
那么
MimeMultipart part = new MimeMultipart(); part.addBodyPart(img_part); part.setSubType("alternative"); message.setContent(part); transport.sendMessage(message,message.getAllRecipients());
1
2
3
4
5
6
7
8那么最终的效果会在邮件中展示一个附件的下载方式,不会以图片后缀结尾
如果
MimeMultipart part = new MimeMultipart(); part.addBodyPart(img_part); part.setSubType("alternative"); //将这个组合的节点,添加到消息中 message.setContent("<img src='cid:1.jpg' />","text/html;charset=utf-8"); transport.sendMessage(message,message.getAllRecipients());
1
2
3
4
5
6
7
8如果
message.setContent
没有将part作为内容,而是<img src='cid:1.jpg' />
使用这种方式,那么邮件的内容是空白的,因为根本不知道cid:1.jpg
的路径,找不到图片,这里只是一个img
标签MimeBodyPart text = new MimeBodyPart(); text.setContent("只是一封带有<img src='cid:1.jpg' />的图片邮件","text/html;charset=utf-8");
1
2这样才能代表我们刚才设置的那张图片
# 完整代码
package com.chu.mail;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.File;
import java.util.Properties;
public class Demon4 {
public static void main (String[] args) throws Exception {
//此类是邮件的发送图片,还有附件
Properties pro = new Properties();
pro.setProperty("mail.host","smtp.qq.com");
pro.setProperty("mail.transport.protocol","smtp");
Session session = Session.getDefaultInstance(pro);
session.setDebug(true);
Transport transport = session.getTransport();
transport.connect("smtp.qq.com","2291308094@qq.com","zitcvhazptfjeccf");
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("2291308094@qq.com"));
message.setRecipient(Message.RecipientType.TO,new InternetAddress("2291308006@qq.com"));
message.setSubject("这是一封标题");
//装备图片数据
MimeBodyPart img_part = new MimeBodyPart();
//MimeBodyPart对象就相当于是一个容器节点,用来存放图片的数据
DataHandler handler = new DataHandler(new FileDataSource(
new File("C:\\Users\\chuchen\\Pictures\\好看动漫图片\\2.jpg")));
//将一个图片数据存入容器节点中(MimeBodyPart对象)
img_part.setDataHandler(handler);
img_part.setContentID("1.jpg");
//准备正文数据
//因为一封带有图片的邮件,其是文本和图片节点的组合,上面的那个是图片节点,这个text是一个文本节点
MimeBodyPart text = new MimeBodyPart();
text.setContent("只是一封带有<img src='cid:1.jpg' />的图片邮件","text/html;charset=utf-8");
//描述数据关系
MimeMultipart part = new MimeMultipart();
part.addBodyPart(img_part);
part.addBodyPart(text);
part.setSubType("related");
//将这个组合的节点,添加到消息中
message.setContent(part);
transport.sendMessage(message,message.getAllRecipients());
}
}
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
# 邮件发送工具类
package com.chu.util;
import com.sun.mail.util.MailSSLSocketFactory;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.util.Properties;
public class MailUtil {
//此类是邮件发送的工具类,提供返回message对象,transport对象、
//transport对象已经连接到服务器
private static Session session;//session对象
private static Properties pro;//配置文件对象
protected static Transport transport;
protected static boolean debug;//debug模式
protected static Message message;//message对象
protected static String username;
protected static String password;
protected static String auth;//是否开启登录验证
protected static String host;//服务器
protected MailUtil(){};//私有化构造方法
//静态代码块用于初始化properties类的参数
static {
InputStream stream = MailUtil.class.getClassLoader().getResourceAsStream("mail.properties");
pro = new Properties();
try {
pro.load(stream);
} catch (IOException e) {
e.printStackTrace();
}
//设置邮件所需的配置信息 通过配置文件获取,然后在将值设置
//初始化用户名和密码
username = pro.getProperty("username");
password = pro.getProperty("password");
host = pro.getProperty("host");
debug = Boolean.parseBoolean(pro.getProperty("debug"));
pro.setProperty("mail.host", host);//设置服务器
pro.setProperty("mail.transport.protocol", pro.getProperty("protocol"));//设置邮箱协议
auth = pro.getProperty("auth");
pro.setProperty("mail.smtp.auth", auth);//是否开启用户名密码验证
//初始化session
session = Session.getDefaultInstance(pro, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication () {
//发件人邮件用户名,密码
return new PasswordAuthentication(username, password);
}
});
//qq邮箱的话 进行ssl验证
if (pro.getProperty("host").contains("qq")) {
//是QQ服务器
MailSSLSocketFactory sf = null;
try {
sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
pro.put("mail.smtp.ssl.enable","true");
pro.put("mail.smtp.socketFactory",sf);
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
}
}
public static Session getSession () throws MessagingException {
setTransport(session);
return session;
}
public static void setSession () {
MailUtil.session = session;
}
public static Transport getTransport () {
return transport;
}
public static void setTransport (Session session) throws MessagingException {
//初始化transport对象
session.setDebug(debug);
transport = session.getTransport();
transport.connect(host,username,password);
setMessage(session);
}
public static Message getMessage () {
return message;
}
public static void setMessage (Session session) {
//初始化message对象
message = new MimeMessage(session);
//设置发送人,因为发件人邮箱和用户邮箱相同
try {
message.setFrom(new InternetAddress(username));
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# 测试代码
package com.chu.mail;
import com.chu.util.MailUtil;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
public class UtilTest2 {
public static void main (String[] args) throws Exception {
Session session = MailUtil.getSession();
Message message = MailUtil.getMessage();
message.setRecipient(Message.RecipientType.TO,new InternetAddress("2291308006@qq.com"));
message.setSubject("title");
message.setContent("content","text/html;charset=utf-8");
Transport transport = MailUtil.getTransport();
transport.sendMessage(message,message.getAllRecipients());
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21





