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模式可以查看通信详细内容

廖雪峰Java13网络编程-2Email编程-1发送email的更多相关文章

  1. 廖雪峰Java13网络编程-2Email编程-2接收Email

    1接收Email协议类型 接收Email:收件人通过MUA软件把邮件从MDA抓取到本地计算机的过程. 1.1 POP3 从MUA到MDA使用最广泛的是协议是POP3 Post Office Proto ...

  2. 廖雪峰Java13网络编程-1Socket编程-2TCP编程

    1. Socket 在开发网络应用程序的时候,会遇到Socket这个概念. Socket是一个抽象概念,一个应用程序通过一个Socket来建立一个远程连接,而Socket内部通过TCP/IP协议把数据 ...

  3. 廖雪峰Java13网络编程-1Socket编程-5UDP编程

    1. UDP编程: 不需要建立连接 可以直接发送和接收数据 1.1 客户端 DatagramSocket sock = new DatagramSocket(){} sock.connect(addr ...

  4. 廖雪峰Java13网络编程-1Socket编程-3TCP多线程编程

    TCP多线程编程 一个ServerSocket可以和多个客户端同时建立连接,所以一个Server可以同时与多个客户端建立好的Socket进行双向通信. 因此服务器端,当我们打开一个Socket以后,通 ...

  5. 廖雪峰Java13网络编程-3其他-2RMI远程调用

    1.RMI远程调用: Remote Method Invocation 目的:把一个接口方法暴露给远程 示例: 定义一个接口Clock,它有一个方法能够获取当前的时间,并编写一个实现类,来实现这个接口 ...

  6. 廖雪峰Java13网络编程-1Socket编程-1网络编程概念

    1.计算机网络 1.1 什么是计算机网络? 两台或更多计算机组成的网络 同一网络内的任意2台计算机都可以直接通信 所有计算机必须遵循同一种网络协议 1.2 什么是互联网 互联网是网络的网络 互联网采用 ...

  7. 廖雪峰Java13网络编程-3其他-1HTTP编程

    1.HTTP协议: Hyper Text Transfer Protocol:超文本传输协议 基于TCP协议之上的请求/响应协议 目前使用最广泛的高级协议 * 使用浏览器浏览网页和服务器交互使用的就是 ...

  8. 廖雪峰Java1-3流程控制-9break、continue

    break跳出循环 int sum=0; for(int i=1; ;i++) { sum =sum + i; if(i == 100) { break; } } System.out.println ...

  9. 廖雪峰Java1-3流程控制-6 do-while循环

    do-while循环 do-while先执行循环,再判断条件. 条件满足时继续循环:条件不满足时退出:至少循环1次 int sum =0; int n = 1; do{ sum = sum + n; ...

随机推荐

  1. ionic-CSS:ionic 按钮

    ylbtech-ionic-CSS:ionic 按钮 1.返回顶部 1. onic 按钮 按钮是移动app不可或缺的一部分,不同风格的app,需要的不同按钮的样式. 默认情况下,按钮显示样式为:dis ...

  2. ionic:创建 APP

    ylbtech-ionic:创建 APP 1.返回顶部 1. ionic 创建 APP 前面的章节中我们已经学会了 ionic 框架如何导入到项目中. 接下来我们将为大家介绍如何创建一个 ionic ...

  3. 14-MySQL-Ubuntu-数据表的查询-范围查询(三)

    范围查询 1,不连续查询-in, not in 查询年龄是12,18,34的学生姓名和年龄信息 select name,age from students where age in (12,18,34 ...

  4. linux 下安装maven私服

    1.下载最新nexus安装包 下载地址:https://www.sonatype.com/download-oss-sonatype 2.下载JDK7,nexus2版本支持JDK7:nexus1版本支 ...

  5. angularJS ng-model与wdatapicker问题记录

    代码: <input type="text" placeholder="开始日期" ng-model="data_start" onF ...

  6. 记录装CDH新增加一些遇到问题的解决

    报错信息:MainThread agent ERROR Heartbeating to localhost:7182 failed.解决:配置CM Agentcm的安装包的server和agent都是 ...

  7. PHP魔方解密

    安装composer参考:https://www.runoob.com/w3cnote/composer-install-and-usage.html 常用的加密类型及特征 加密类型 加密特征 Zen ...

  8. 7python ruturn中的and与or.

    def test(): a = "" return a or "hehe" #如果a为真,输出a; 否则输出右边(比如0, "", [], ...

  9. .net下MVC中使用Tuple分页查询数据

    主要是在DAL层写查询分页的代码. 例如DAL层上代码: public Tuple<List<WxBindDto>, int> GetMbersInfo(int start, ...

  10. luoguP3414 SAC#1 - 组合数

    题目背景 本题由世界上最蒟蒻最辣鸡最撒比的SOL提供. 寂月城网站是完美信息教室的官网.地址:http://191.101.11.174/mgzd . 题目描述 辣鸡蒟蒻SOL是一个傻逼,他居然觉得数 ...