1.邮件发送

1.1传统邮件发送:

  • 传统的邮件是通过邮局投递,从一个邮局到另一个邮局,最终到达用户的邮箱。

1.2电子邮件发送:

  • 与传统邮件类似,它是从用户电脑的邮件软件(如outlook)发送到邮件服务器上,然后经过若干个邮件服务器的中转,到达对方邮件服务器上,收件方就可以用软件或浏览器来接收邮件。
  • MUA(邮件软件,Mail User Agent)——>MTA(邮件服务器,Mail Transfer Agent)——>MTA——>MDA(邮件投递代理,Mail Delivery Agent)<——MUA
  • 邮件一半到达MDA就不再动了,等收件人通过MUA或浏览器查看邮件即可
  • 从MUA发送到MTA使用的协议就是SMTP协议

1.3 SMTP协议:发送电子邮件的协议

  • Simple Mail Transport protocol:SMTP是一个建立在TCP之上的协议。
  • 标准端口:25
  • 加密端口:465/587。如果某个会话需要被加密的话,使用加密端口465/587

2 如何发送EMail:

  • 使用Java Mail API
  • 无需关心SMTP协议原理。

2.1 使用Java Mail API有三个部分

#    创建session
Session session = Session.getInstance(props,new Authenticator(){...});
# 创建message对象
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("from@email.com")); //发件人
message.setRecipient(Message.RecipientType.TO, new IntenetAddress("to@email.com")); //收件人
message.setSubject("RE:how to use JavaEmail","UTF-8"); //邮件主题
message.setText("blablabla...","UTF-8"); //邮件正文
# 发送邮件
Transport.send(message);

示例代码

package com.csj2018;

import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage; public class SendQQMailUtil { public static void main(String[] args) throws AddressException,MessagingException {
Properties properties = new Properties();
properties.put("mail.transport.protocol", "smtp");// 连接协议
properties.put("mail.smtp.host", "smtp.qq.com");// 主机名 网易替换为"smtp.126.com"
properties.put("mail.smtp.port", 465);// 端口号
properties.put("mail.smtp.auth", "true");
properties.put("mail.smtp.ssl.enable", "true");// 设置是否使用ssl安全连接 ---一般都使用
// properties.put("mail.debug", "true");// 设置是否显示debug信息 true 会在控制台显示相关信息,同session.setDebug(true);
// 得到回话对象
Session session = Session.getInstance(properties);
session.setDebug(true);
// 获取邮件对象
Message message = new MimeMessage(session);
// 设置发件人邮箱地址
message.setFrom(new InternetAddress("123456789@qq.com"));
// 设置收件人邮箱地址,多个收件人
message.setRecipients(Message.RecipientType.TO, new InternetAddress[]{new InternetAddress("123456789@qq.com"),new InternetAddress("1234567890@qq.com")});
//message.setRecipient(Message.RecipientType.TO, new InternetAddress("xxx@qq.com"));//一个收件人
// 设置邮件标题
message.setSubject("xmqtest");
// 设置邮件内容
message.setText("邮件内容邮件内容邮件内容xmqtest");
// 得到邮差对象
Transport transport = session.getTransport();
// 连接自己的邮箱账户
transport.connect("123456789@qq.com", "abcdefg");// 密码为QQ邮箱开通的stmp服务后得到的客户端授权码
// 发送邮件
transport.sendMessage(message, message.getAllRecipients());
transport.close();
}
}

2.2 新建maven工程

pom.xml导入依赖

<!-- https://mvnrepository.com/artifact/javax.mail/mail -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
</dependency>

注意:不要导错依赖。详细请参考

        <!-- https://mvnrepository.com/artifact/javax.mail/javax.mail-api -->
<!--导入javax.mail-api,运行时会提示Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/mail/util/MailLogger
-->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>javax.mail-api</artifactId>
<version>1.6.2</version>
</dependency>

2.3 发送一封文本邮件

package com.email;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.security.MessageDigest;
import java.util.Properties; public class SendMail {
final String smtpHost;
final String username;
final String password;
final boolean debug;
public SendMail(String smtpHost,String username,String password){
this.smtpHost = smtpHost;
this.username = username;
this.password = password;
this.debug = true;
}
public static void main(String[] args) throws Exception{
SendMail sender = new SendMail("smtp.qq.com","123456789@qq.com","abcdefg");
Session session = sender.createSSLSession();
Message message = createTextMessage(session,"123456789@qq.com","123456789@126.com","标题吗","Hello,这是一封Javamail测试邮件");
Transport.send(message);
}
//创建一个加密的session对象
private Session createSSLSession(){
Properties props = new Properties();
props.put("mail.transport.protocol","smtp");
props.put("mail.smtp.host",this.smtpHost);//SMTP主机名
props.put("mail.smtp.port",465);//主机端口号
props.put("mail.smtp.auth","true");//是否需要用户认证
//启动SSL
props.put("mail.smtp.socketFactory.class","javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.port","465");
Session session = Session.getInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(SendMail.this.username,SendMail.this.password);
}
});
session.setDebug(this.debug);//显示调试信息
return session;
}
private static Message createTextMessage(Session session,String from,String to,String subject,String body) throws MessagingException {
MimeMessage message= new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setRecipient(Message.RecipientType.TO,new InternetAddress(to));
message.setSubject(subject,"UTF-8");
message.setText(body,"UTF-8");
return message;
}
}

2.4发送一个HTML格式的邮件

package com.email;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage; public class SendMailWithHtml {
public static void main(String[] args) throws Exception{
SendMail sendMail = new SendMail("smtp.qq.com","123456789@qq.com","abcdefg");
Session session = sendMail.createSSLSession();
Message message = createHtmlMessage(session,"123456789@qq.com","123456789@126.com","这是一封html的邮件","\n" +
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" +
"<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" +
"\n" +
"<head>\n" +
"\n" +
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n" +
"<meta http-equiv=\"Cache-Control\" content=\"no-transform\" />\n" +
"<title>剧烈咳嗽就是肺癌?肺癌的这些症状也不可忽视 - 家庭医生在线肿瘤频道</title>\n" +
"<meta name=\"keywords\" content=\"剧烈咳嗽,肺癌,肺癌的症状\" />\n" +
"<meta name=\"description\" content=\"肺癌,一个发病率极其高的癌症,由于目前环境污染日渐严重,导致越来越多的人肺部受到感染而出现病变,导致肺癌的出现,生活中有很多因为肺癌而丧失性命的人。也正是因为如此让很多人对于肺癌都比较重视,对于肺癌也有做相关的了解,而大多数人因为过于谨慎,在身体出现一些成风吹草动的时候就认为是肺癌,特别是在出现剧烈咳嗽的时候,其实出现剧烈咳嗽也并不完全是肺癌发生。\" />\n" +
"<script type=\"text/javascript\">\n" +
"CUSTOMER.setCus([\"channel:cancer\",\"level:page\"]);\n" +
"</script>\n" +
"</head>\n" +
"<body>\n" +
"\t<div class=\"article-titile\">\n" +
"\t\t<h1>剧烈咳嗽就是肺癌?肺癌的这些症状也不可忽视</h1></div>\n" +
"<!--头部模块开始--> \n" +
"<div id=\"viewContent\" class=\"viewContent\"> <p style=\"text-indent:2em;text-align:left;\">肺癌,一个发病率极其高的,由于目前环境污染日渐严重,导致越来越多的人肺部受到而出现病变,导致肺癌的出现,生活中有很多因为肺癌而丧失性命的人。也正是因为如此让很多人对于肺癌都比较重视,对于肺癌也有做相关的了解,而大多数人因为过于谨慎,在身体出现一些成风吹草动的时候就认为是肺癌,特别是在出现剧烈咳嗽的时候,其实出现剧烈咳嗽也并不完全是肺癌发生。</p>\n" +
"\t\t\t</div>\n" +
"</body>\n" +
"</html>");
Transport.send(message);
}
static Message createHtmlMessage(Session session,String from,String to,String subject,String body) throws MessagingException{
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setRecipient(Message.RecipientType.TO,new InternetAddress(to));
message.setSubject(subject,"UTF-8");
message.setText(body,"UTF-8","html");
return message;
}
}


### 2.5发送带附件的邮件
```#java
package com.email;

import javax.activation.DataHandler;

import javax.activation.FileDataSource;

import javax.mail.;

import javax.mail.internet.InternetAddress;

import javax.mail.internet.MimeBodyPart;

import javax.mail.internet.MimeMessage;

import javax.mail.internet.MimeMultipart;

import java.io.
;

public class SendMailWithAttachment {

public static void main(String[] args) throws Exception{

SendMail sender = new SendMail("smtp.qq.com","123456678@qq.com","abcdefghjik");

Session session = sender.createSSLSession();

//创建一个带附件的邮件

Message message = createMessageWithAttachment(session,"123456678@qq.com","红米note5图片","为什么成功了","/src/main/resources/1.jpg","123456789@qq.com","987654321@qq.com","123456789@126.com");

Transport.send(message);

File f = new File(".");

System.out.println(f.getCanonicalFile());

File nf = new File(f.getCanonicalFile()+"/src/main/resources/1.jpg");

if(nf.exists()){

System.out.println(nf+"存在");

}else{

System.out.println(nf+"不存在");

}

}
static Message createMessageWithAttachment(Session session, String from, String subject,String body, String filename, String... to) throws MessagingException,IOException {
//本质上还是一个MimeMessage对象,但不能通过setText设置正文,需要使用MimeMultipart
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
for(String s:to){
message.setRecipient(Message.RecipientType.TO,new InternetAddress(s));
} message.setSubject(subject);
//通过Multipart将内容分为2部分
Multipart multipart = new MimeMultipart();
//text
BodyPart textpart = new MimeBodyPart();
textpart.setContent(body,"text/html;charset=utf-8");//body表示邮件正文
multipart.addBodyPart(textpart);
//再次创建一个MimeBodyPart上传附件
BodyPart imagePart = new MimeBodyPart();
imagePart.setFileName(filename);
DataHandler dh1 = new DataHandler(new FileDataSource(new File(".").getCanonicalPath()+filename));
imagePart.setDataHandler(dh1);//如何获取附件的数据
multipart.addBodyPart(imagePart); message.setContent(multipart);
return message;
}

}

<h1 style="color:blue">使用输入流发送附件</h1>
<p style="color:red">确保图片在resource目录下</p> ```#java
package com.email; import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;
import java.awt.*;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream; public class SendMailWithAttachment {
public static void main(String[] args) throws Exception{
SendMail sender = new SendMail("smtp.qq.com","123456789@qq.com","abcdefghjkik");
Session session = sender.createSSLSession();
//创建一个输入流
try(InputStream input = SendMailWithAttachment.class.getResourceAsStream("/1.jpg")){
//创建一个带附件的邮件
Message message = createMessageWithAttachment(session,"123456789@qq.com","红米note5图片","为什么成功了","1.jpg",input,"123456789@qq.com","987654321@qq.com","123456789@126.com");
Transport.send(message);
}
}
static Message createMessageWithAttachment(Session session, String from, String subject,String body, String filename,InputStream input, String... to) throws MessagingException,IOException {
//本质上还是一个MimeMessage对象,但不能通过setText设置正文,需要使用MimeMultipart
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
for(String s:to){
message.setRecipient(Message.RecipientType.TO,new InternetAddress(s));
} message.setSubject(subject);
//通过Multipart将内容分为2部分
Multipart multipart = new MimeMultipart();
//text
BodyPart textpart = new MimeBodyPart();
textpart.setContent(body,"text/html;charset=utf-8");//body表示邮件正文
multipart.addBodyPart(textpart);
//再次创建一个MimeBodyPart上传附件
BodyPart imagePart = new MimeBodyPart();
imagePart.setFileName(filename);
imagePart.setDataHandler(new DataHandler(new ByteArrayDataSource(input,"Application/octet-stream")));
multipart.addBodyPart(imagePart);
message.setContent(multipart);
return message;
}
}

2.6如何把附件嵌入到正文中

package com.csj2018;

import javax.activation.DataHandler;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;
import java.io.InputStream; public class SendMailWithInnerImage {
public static void main(String[] args) throws Exception{
SendMail sender = new SendMail("smtp.qq.com", "815379479@qq.com", "oovtbkpfvfzobdag");
Session session = sender.createSSLSession();
try(InputStream input = SendMailWithInnerImage.class.getResourceAsStream("/RedmiNote5-1.png")){
Message message = createMessageWithInnerImage(session,"815379479@qq.com","chenshanju01@126.com","带图片测试","<h1><hello/h1><p><img src=\"cid:img01\" ></p><p>这是一封带图片的测试邮件</p>","1.png",input);
Transport.send(message);
}
}
static Message createMessageWithInnerImage(Session session, String from, String to, String subject, String body, String filename, InputStream input) throws Exception{
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setRecipient(Message.RecipientType.TO,new InternetAddress(to));
message.setSubject(subject,"UTF-8");
Multipart multipart = new MimeMultipart();
BodyPart textpart = new MimeBodyPart();
textpart.setContent(body,"text/html;charset=utf-8");
multipart.addBodyPart(textpart); BodyPart imagepart = new MimeBodyPart();
imagepart.setFileName(filename);
imagepart.setDataHandler(new DataHandler(new ByteArrayDataSource(input,"application/x-png")));
//对一个图片内容设置Content-ID,就可以在邮件中引用它,引用方式是<img src="cid:img01">
imagepart.setHeader("Content-ID","<img01>");
multipart.addBodyPart(imagepart);
message.setContent(multipart);
return message;
}
}

content-type类型对应表:http://tool.oschina.net/commons/

3.总结

使用JavaMail API发送邮件本质上是一个MUA软件,类似outlook

Java发送Email:

  • 用Maven引入javamail依赖
  • 确定SMTP服务器信息:域名/端口/使用明文/SSL/TLS
  • 调用相关API发送Email(无需关心底层TCP Socket连接)
  • 设置debug模式可以查看通信详细内容

最新文章

  1. UVALive 7141 BombX(离散化+线段树)(2014 Asia Shanghai Regional Contest)
  2. iOS - 基础面试知识
  3. Javascript 事件(一)
  4. linq和EF查询的用法和区分
  5. iOS 调出storyboard里面起始Controller的箭头
  6. TPLink 备份文件bin文件解析
  7. boa配置文件详解
  8. 线性回归的Spark实现 [Linear Regression / Machine Learning / Spark]
  9. nginx/apache/php隐藏http头部版本信息的实现方法
  10. Javascript 类数组(Array-like)对象
  11. setWillNotDraw和setFillViewport
  12. php后门屌炸天
  13. Solving the Top ERP and CRM Metadata Challenges with erwin &amp; Silwood
  14. C# 以共享只读方式打开被其它程序占用的文件
  15. 嵌入Python | 调用Python模块中无参数的函数
  16. cf787c 博弈论+记忆化搜索
  17. You Don&#39;t Know JS: Async &amp; Performance(第一章, 异步:now &amp; later)
  18. bower failed: UNABLE_TO_VERIFY_LEAF_SIGNATURE
  19. FIFO队列 ADT接口 数组实现
  20. maven scope属性值设置含义

热门文章

  1. 一幅图解决R语言绘制图例的各种问题
  2. 基于三角形与位置指纹识别算法的WiFi定位比较
  3. JS与Jquery的事件委托机制
  4. Java设计模式(一)外观模式(门面模式)- 结构型模式
  5. Codeforces 479【F】div3
  6. WPF datagrid AutoGenerateColumns隐藏部分列
  7. nginx之tcp负载代理
  8. 用PS制作APP的界面图片
  9. IOS中iframe的滚动条不启作用
  10. pandas中axis的含义