A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

简介

1.本文只针对基础代码解析整理,原理不想过多解释

2.写这篇博客是为了理清思路

3.本文的测试对象为qq邮箱

发送Email

1.发送原理

发送方发送到邮件服务器,接收方从服务器读取内容的过程

2.协议

1.MUA到MTA发送邮件的协议就是SMTP协议,它是Simple Mail Transport Protocol的缩写

使用标准端口25,也可以使用加密端口465或587

2.SMTP协议是一个建立在TCP之上的协议,任何程序发送邮件都必须遵守SMTP协议

1

2

3

3.MSTP登录信息

QQ邮箱:SMTP服务器是smtp.qq.com,端口是465/587

163邮箱:SMTP服务器是smtp.163.com,端口是465

Gmail邮箱:SMTP服务器是smtp.gmail.com,端口是465/587

4.实例

1、首先是最简单发送纯文本Email实例

//纯文本发送

public class MailService {

public static void main(String[] args) throws GeneralSecurityException, MessagingException {

//创建一个配置文件并保存

Properties properties = new Properties();

properties.setProperty("mail.host", "smtp.qq.com"); // SMTP主机名

properties.setProperty("mail.transport.protocol","smtp");

properties.setProperty("mail.smtp.auth","true");// 是否需要用户认证

//QQ存在一个特性设置SSL加密

MailSSLSocketFactory sf = new MailSSLSocketFactory();

sf.setTrustAllHosts(true);

properties.put("mail.smtp.ssl.enable", "true");//开启ssl安全连接

properties.put("mail.smtp.ssl.socketFactory", sf);

//创建一个session对象

Session session = Session.getDefaultInstance(properties, new Authenticator() {

@Override

protected PasswordAuthentication getPasswordAuthentication() {

return new PasswordAuthentication("发送方邮箱",

"qq邮箱smtp服务授权码");

//在邮箱的设置-》账户-》POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务中获取

}

});

// 设置debug模式便于调试:

session.setDebug(true);

//TODO:构建Message对象

MimeMessage message = new MimeMessage(session);

//设置发送方地址:

try {

message.setFrom(new InternetAddress("发送方地址"));

} catch (MessagingException e) {

e.printStackTrace();

}

// 设置接收方地址:

message.setRecipients(Message.RecipientType.TO,

String.valueOf(new InternetAddress("接收方地址")));

//设置邮件主题

message.setSubject("Hello","UTF-8");

//设置邮件正文

message.setText("hello","UTF-8","html");

//发送

Transport.send(message);

}

}

2、然后是正文有所改变的纯文字HTML代码

//纯文本发送

public class MailService {

public static void main(String[] args) throws GeneralSecurityException, MessagingException {

//创建一个配置文件并保存

Properties properties = new Properties();

properties.setProperty("mail.host", "smtp.qq.com"); // SMTP主机名

properties.setProperty("mail.transport.protocol","smtp");

properties.setProperty("mail.smtp.auth","true");// 是否需要用户认证

//QQ存在一个特性设置SSL加密

MailSSLSocketFactory sf = new MailSSLSocketFactory();

sf.setTrustAllHosts(true);

properties.put("mail.smtp.ssl.enable", "true");//开启ssl安全连接

properties.put("mail.smtp.ssl.socketFactory", sf);

//创建一个session对象

Session session = Session.getDefaultInstance(properties, new Authenticator() {

@Override

protected PasswordAuthentication getPasswordAuthentication() {

return new PasswordAuthentication("发送方邮箱",

"qq邮箱smtp服务授权码");

//在邮箱的设置-》账户-》POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务中获取

}

});

// 设置debug模式便于调试:

session.setDebug(true);

//TODO:构建Message对象

MimeMessage message = new MimeMessage(session);

//设置发送方地址:

try {

message.setFrom(new InternetAddress("发送方地址"));

} catch (MessagingException e) {

e.printStackTrace();

}

// 设置接收方地址:

message.setRecipients(Message.RecipientType.TO,

String.valueOf(new InternetAddress("接收方地址")));

//设置邮件主题

message.setSubject("Hello","UTF-8");

//设置邮件正文

message.setText("

Hello
Hi, xxx

","UTF-8","html");

//发送

Transport.send(message);

}

}

3、添加附件的Email邮件

//纯文本发送

public class MailService {

public static void main(String[] args) throws GeneralSecurityException, MessagingException {

//创建一个配置文件并保存

Properties properties = new Properties();

properties.setProperty("mail.host", "smtp.qq.com"); // SMTP主机名

properties.setProperty("mail.transport.protocol","smtp");

properties.setProperty("mail.smtp.auth","true");// 是否需要用户认证

//QQ存在一个特性设置SSL加密

MailSSLSocketFactory sf = new MailSSLSocketFactory();

sf.setTrustAllHosts(true);

properties.put("mail.smtp.ssl.enable", "true");//开启ssl安全连接

properties.put("mail.smtp.ssl.socketFactory", sf);

//创建一个session对象

Session session = Session.getDefaultInstance(properties, new Authenticator() {

@Override

protected PasswordAuthentication getPasswordAuthentication() {

return new PasswordAuthentication("发送方邮箱",

"qq邮箱smtp服务授权码");

//在邮箱的设置-》账户-》POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务中获取

}

});

// 设置debug模式便于调试:

session.setDebug(true);

//TODO:构建Message对象

MimeMessage message = new MimeMessage(session);

//设置发送方地址:

try {

message.setFrom(new InternetAddress("发送方地址"));

} catch (MessagingException e) {

e.printStackTrace();

}

// 设置接收方地址:

message.setRecipients(Message.RecipientType.TO,

String.valueOf(new InternetAddress("接收方地址")));

//设置邮件主题

message.setSubject("Hello","UTF-8");

//设置邮件正文

message.setText("hello","UTF-8","html");

//Multipart对象包含若干个bodpart

//bodpart中可以添加各种附件

Multipart multipart = new MimeMultipart();

//TODO:添加text

BodyPart textPart = new MimeBodyPart();

//数据源

DataSource dataSource = new FileDataSource(new

File("D:\\..\\text.txt"));//绝对路径

//数据处理器

DataHandler dataHandler = new DataHandler(dataSource);

//设置第一个附件的数据

textPart.setDataHandler(dataHandler);

textPart.setFileName("text");

multipart.addBodyPart(textPart);

//TODO:添加image

BodyPart imagePart = new MimeBodyPart();

imagePart.setFileName("1.gif");

imagePart.setDataHandler(new DataHandler(new FileDataSource(new

File("D:\\..\\preview.gif"))));//绝对路径

multipart.addBodyPart(imagePart);

//设置邮件内容为multipaet

message.setContent(multipart);

//发送

Transport.send(message);

}

}

测试后邮件正文消失,只包含邮件附件,可能与发送机制有关

4.发送内嵌图片的HTML邮件

注意:如果给一个< img src=“http://example.com/test.jpg”>,这样的外部图片链接通常会被邮件客户端过滤,并提示用户显示图片并不安全。只有内嵌的图片才能正常在邮件中显示
外汇常见问题https://www.fx61.com/faq

//纯文本发送

public class MailService {

public static void main(String[] args) throws GeneralSecurityException, MessagingException {

//创建一个配置文件并保存

Properties properties = new Properties();

properties.setProperty("mail.host", "smtp.qq.com"); // SMTP主机名

properties.setProperty("mail.transport.protocol","smtp");

properties.setProperty("mail.smtp.auth","true");// 是否需要用户认证

//QQ存在一个特性设置SSL加密

MailSSLSocketFactory sf = new MailSSLSocketFactory();

sf.setTrustAllHosts(true);

properties.put("mail.smtp.ssl.enable", "true");//开启ssl安全连接

properties.put("mail.smtp.ssl.socketFactory", sf);

//创建一个session对象

Session session = Session.getDefaultInstance(properties, new Authenticator() {

@Override

protected PasswordAuthentication getPasswordAuthentication() {

return new PasswordAuthentication("发送方邮箱",

"qq邮箱smtp服务授权码");

//在邮箱的设置-》账户-》POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务中获取

}

});

// 设置debug模式便于调试:

session.setDebug(true);

//Multipart对象包含若干个bodpart

//bodpart中可以添加各种附件

//内嵌图片实际上也是一个附件,即邮件本身也是Multipart

Multipart multipart = new MimeMultipart();

//TODO:构建Message对象

MimeMessage message = new MimeMessage(session);

//设置发送方地址:

try {

message.setFrom(new InternetAddress("发送方地址"));

} catch (MessagingException e) {

e.printStackTrace();

}

// 设置接收方地址:

message.setRecipients(Message.RecipientType.TO,

String.valueOf(new InternetAddress("接收方地址")));

//设置邮件主题

message.setSubject("Hello","UTF-8");

//设置邮件正文

message.setText("

Hello
Hi, xxx

","UTF-8","html");

//TODO:发送内嵌图片的HTML邮件

Map imagesMap = new HashMap<>();

//采用hashmap可以以满足html表达式

imagesMap.put("image","D:\\..\\preview.gif");

// 添加text:

BodyPart textpart = new MimeBodyPart();

textpart.setContent(

"

我老婆发给你了


",

"text/html;charset=utf-8");

multipart.addBodyPart(textpart);

// 添加image:

BodyPart imagepart = new MimeBodyPart();

imagepart.setFileName("1.gif");

imagepart.setDataHandler(new DataHandler(new FileDataSource(new

File("D:\\..\\preview.gif"))));

// 与HTML的关联:

imagepart.setHeader("Content-ID", "image");

multipart.addBodyPart(imagepart);

//发送

Transport.send(message);

}

}

5.小结

1.使用JavaMail API发送邮件本质上是一个MUA软件通过SMTP协议发送邮件至MTA服务器

2.打开调试模式可以看到详细的SMTP交互信息

3.某些邮件服务商需要开启SMTP,并需要独立的SMTP登录密码

4.当然老婆是不会给你们看的

接收Email

1.接收Email就是从MTA服务器读取文件的过程

2.因为qq邮箱应该是有新旧两个文件夹或者其它管理机制,从"INBOX"(一般MTA服务器存放邮件的文件夹)读取的

邮件都是之前的邮件,到最近的邮件就没有访问成功过,都是抛出异常,小白我估计是触发了某种机制

3.qq邮箱的发送与接收都需要ssl加密

协议特点

1.使用最广泛的协议是POP3:Post Office Protocol version 3

它是一个建立在TCP连接之上的协议

POP3服务器的标准端口是110,如果整个会话需要加密,那么使用加密端口995

2.另一种接收邮件的协议是IMAP :Internet Mail Access Protocol

它使用标准端口143和加密端口993

IMAP协议在本地的所有操作都会自动同步到服务器上

IMAP可以允许用户在邮件服务器的收件箱中创建文件夹

实例

一看就懂的那种

//接收邮件

public class MailReceive {

public static void main(String[] args) throws GeneralSecurityException, MessagingException {

// 准备登录信息:

String host = "pop.qq.com";

int port = 995;

String username = "发送方邮箱";

String password = "授权码";

//创建一个配置文件并保存

Properties properties = new Properties();

properties.setProperty("mail.store.protocol", "pop3");// 协议名称

properties.setProperty("mail.pop3.host",host); // SMTP主机名

properties.setProperty("mail.pop3.port", String.valueOf(port)); // 端口号

properties.setProperty("mail.pop3.auth","true");// 是否需要用户认证

//QQ存在一个特性设置SSL加密,注释掉的和代码也是开启ssl加密的方法

// props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");

// props.put("mail.smtp.socketFactory.port", String.valueOf(port));

MailSSLSocketFactory sf = new MailSSLSocketFactory();

sf.setTrustAllHosts(true);

properties.put("mail.pop3.ssl.enable", "true");//开启ssl安全连接

properties.put("mail.pop3.ssl.socketFactory", sf);

// 连接到Store:

URLName urlName = new URLName("pop3",host,port,"",username,password);

Session session = Session.getInstance(properties,null);

session.setDebug(true);

Store store = new POP3SSLStore(session,urlName);

store.connect();

Folder folder = null;

try {

folder = store.getFolder("INBOX");// 获取收件箱:

folder.open(Folder.READ_WRITE);// 以读写方式打开:

System.out.println("Total messages: " + folder.getMessageCount());

System.out.println("New messages: " + folder.getNewMessageCount());

System.out.println("Unread messages: " + folder.getUnreadMessageCount());

System.out.println("Deleted messages: " + folder.getDeletedMessageCount());

Message[] messages = folder.getMessages();

for (Message message : messages) {

printMessage((MimeMessage) message);

}

} catch (IOException e) {

e.printStackTrace();

} finally {

if (folder != null) {

try {

folder.close(true);

} catch (MessagingException e) {

e.printStackTrace();

}

}

if (store != null) {

try {

store.close();

} catch (MessagingException e) {

e.printStackTrace();

}

}

}

}

//一封邮件的结构

//大部分商业邮件都是HTML邮件,所以下载的邮件可以将body作为HTML文件查看,但只能加载出图片

//因为传输协议加密内容都有都有==结尾,经过博主测试外面都有外包base64加密

//有一些纯文本甚至可以直接由base64解码查看,所以一定不要让你的授权码外泄

static void printMessage(MimeMessage msg) throws IOException, MessagingException {

System.out.println("--------------------");

System.out.println("Subject: " + MimeUtility.decodeText(msg.getSubject()));

System.out.println("From: " + getFrom(msg));

System.out.println("To: " + getTo(msg));

System.out.println("Sent: " + msg.getSentDate().toString());

System.out.println("Seen: " + msg.getFlags().contains(Flags.Flag.SEEN));

System.out.println("Priority: " + getPriority(msg));

System.out.println("Size: " + msg.getSize() / 1024 + "kb");

System.out.println("Body: " + getBody(msg));

System.out.println("--------------------");

System.out.println();

}

static String getFrom(MimeMessage msg) throws IOException, MessagingException {

Address[] froms = msg.getFrom();

return addressToString(froms[0]);

}

static String getTo(MimeMessage msg) throws MessagingException, IOException {

// 使用 msg.getAllRecipients() 获取所有收件人

Address[] tos = msg.getRecipients(MimeMessage.RecipientType.TO);

List list = new ArrayList<>();

for (Address to : tos) {

list.add(addressToString(to));

}

return String.join(", ", list);

}

static String addressToString(Address addr) throws IOException {

InternetAddress address = (InternetAddress) addr;

String personal = address.getPersonal();

return personal == null ? address.getAddress()

: (MimeUtility.decodeText(personal) + " <" + address.getAddress() + ">");

}

static String getPriority(MimeMessage msg) throws MessagingException {

String priority = "Normal";

String[] headers = msg.getHeader("X-Priority");

if (headers != null) {

String header = headers[0];

if ("1".equals(header) || "high".equalsIgnoreCase(header)) {

priority = "High";

} else if ("5".equals(header) || "low".equalsIgnoreCase(header)) {

priority = "Low";

}

}

return priority;

}

static String getBody(Part part) throws MessagingException, IOException {

if (part.isMimeType("text/*")) {

return part.getContent().toString();

}

if (part.isMimeType("multipart/*")) {

Multipart multipart = (Multipart) part.getContent();

for (int i = 0; i < multipart.getCount(); i++) {

BodyPart bodyPart = multipart.getBodyPart(i);

String body = getBody(bodyPart);

if (!body.isEmpty()) {

return body;

}

}

}

return "";

}

}

小结

使用POP3协议时,需要用Maven引入JavaMail依赖,并确定POP3服务器的域名/端口/是否使用SSL等,然后,调用相关API接收Email

大结

1.可以通过线程池实现批量发送邮件

2.发送邮件前要在xml中引入项目,你们需要我可以写个博客做个小结,毕竟有不少坑

3.喜欢就点个赞呗

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马