当前位置: 首页 > news >正文

Spring 邮件发送

Spring 邮件发送

1. 主要内容(了解)

2. JavaMail 概述(了解)

  JavaMail,顾名思义,提供给开发者处理电⼦邮件相关的编程接⼝。JavaMail 是由 Sun 定义的⼀套收发电⼦邮件的 API,它可以⽅便地执⾏⼀些常⽤的邮件传输,不同的⼚商可以提供⾃⼰的实现类。但它并没有包含在 JDK 中,⽽是作为 JavaEE 的⼀部分。

  ⼚商所提供的 JavaMail 服务程序可以有选择地实现某些邮件协议,常⻅的邮件协议包括:

SMTP:简单邮件传输协议,⽤于发送电⼦邮件的传输协议;

POP3:⽤于接收电⼦邮件的标准协议;

IMAP:互联⽹消息协议, POP3 的替代协议。

  这三种协议都有对应 SSL 加密传输的协议,分别是 SMTPSPOP3S  IMAPS。除 JavaMail 服务提供程序之外, JavaMail 还需要 JAF(JavaBeans Activation Framework)来处理不是纯⽂本的邮件内容,这包 MIME(多⽤途互联⽹邮件扩展)、URL ⻚⾯和⽂件附件等内容。另外,JavaMail 依赖 JAF(JavaBeans Activation Framework)JAF  Java6 之后已经合并到 JDK 中,⽽ JDK5 之前需要另外下载 JAF 的类库。

2.1. 协议介绍

  在研究 JavaMail API 的细则之前,⾸先需要对于 API ⽤到的协议有个认识。对于 java mail 来说⽤到的协议有常⻅的⼏种: SMTPPOPIMAPMIME

2.1.1. SMTP

  简单邮件传输协议(Simple Mail Transfer ProtocolSMTP)由 RFC 821 定义。它定义了发送电⼦邮件的机制。在 JavaMail API 环境中,您基于 JavaMail 的程序将和您的公司或因特⽹服务供应商的(Internet Service
Provider'sISP'sSMTP 服务器通信。SMTP 服务器会中转消息给接收⽅ SMTP 服务器以便最终让⽤户经由 POP  IMAP 获得。

2.1.2. POP

  POP 代表邮局协议(Post Office Protocol)。⽬前⽤的是版本 3,也称 POP3RFC 1939 定义了这个协议。POP 是⼀种机制,因特⽹上⼤多数⼈⽤它得到邮件。它规定每个⽤户⼀个邮箱的⽀持。这就是它所能做的,⽽这也造成了许多混淆。使⽤ POP3 时,⽤户熟悉的许多性能并不是由 POP 协议⽀持的,如查看有⼏封新邮件消息这⼀性能。这些性能内建于如 Eudora  Microsoft Outlook 之类的程序中,它们能记住⼀些事,诸如最近⼀次收到的邮件,还能计算出有多少是新的。所以当使⽤ JavaMail API 时,如果您想要这类信息,您就必须⾃⼰算。

2.1.3. IMAP

  IMAP 是更⾼级的⽤于接收消息的协议。在 RFC 2060 中被定义,IMAP 代表因特⽹消息访问协议(Internet Message Access Protocol),⽬前⽤的是版本 4,也称 IMAP4。在⽤到 IMAP 时,邮件服务器必需⽀持这个协议。不能仅仅把使⽤ POP 的程序⽤于 IMAP,并指望它⽀持 IMAP 所有性能。假设邮件服务器⽀持 IMAP,基于 JavaMail 的程序可以利⽤这种情况  ⽤户在服务器上有多个⽂件夹(folder),并且这些⽂件夹可以被多个⽤户共享。因为有这⼀更⾼级的性能,您也许会认为所有⽤户都会使⽤ IMAP。事实并不是这样。要求服务器接收新消息,在⽤户请求时发送到⽤户⼿中,还要在每个⽤户的多个⽂件夹中维护消息。这样虽然能将消息集中备份,但随着⽤户⻓期的邮件夹越来越⼤,到磁盘空间耗尽时,每个⽤户都会受到损失。使⽤ POP,就能卸载邮件服务器上保存的消息了。

2.1.4. MIME

  MIME 代表多⽤途因特⽹邮件扩展标准(Multipurpose Internet Mail Extensions)。它不是邮件传输协议。但对传输内容的消息、附件及其它的内容定义了格式。这⾥有很多不同的有效⽂档:RFC 822RFC 2045RFC
2046  RFC 2047。作为⼀个 JavaMail API 的⽤户,您通常不必对这些格式操⼼。⽆论如何,⼀定存在这些格式⽽且程序会⽤到它。

2.2. JavaMail 的关键对象

  JavaMail 对收发邮件进⾏了⾼级的抽象,形成了⼀些关键的的接⼝和类,它们构成了程序的基础,下⾯我们分别来了解⼀下这些最常⻅的对象。

2.2.1. Properties 属性对象

  由于 JavaMail 需要和邮件服务器进⾏通信,这就要求程序提供许多诸如服务器地址、端⼝、⽤户名、密码等信息,JavaMail 通过 Properties 对象封装这些属性信息。如下⾯的代码封装了两个属性信息:

Properties props = new Properties();

props.put("mail.smtp.host", "smtp.sina.com.cn");

props.put("mail.smtp.auth", "true");

  针对不同的的邮件协议,JavaMail 规定了服务提供者必须⽀持⼀系列属性,下表是针对 SMTP 协议的⼀些常⻅属性(属性值都以 String 类型进⾏设置,属性类型栏仅表示属性是如何被解析的):

属性名

类型

说明

mail.smtp.host

String

SMTP 服务器地址,如smtp.sina.com.cn

mail.smtp.port

int

SMTP 服务器端⼝号,默认为 25

mail.smtp.auth

boolean

SMTP 服务器是否需要⽤户认证,默认为 false

mail.smtp.user

String

SMTP 默认的登陆⽤户名

mail.smtp.from

String

默认的邮件发送源地址

mail.smtp.socketFactory.class

String

socket ⼯⼚类类名
通过设置该属性可以覆盖提供者默认的实现,必须实现javax.NET.SocketFactory接⼝

mail.smtp.socketFactory.port

int

指定 socket ⼯⼚类所⽤的端⼝号

如果没有规定,则使⽤默认的端⼝号

mail.smtp.socketFactory.fallback

boolean

设置为 true 时,当使⽤指定的socket 类创建 socket 失败后,将使⽤

Java.net.Socket 创建socket,默认为 true

mail.smtp.timeout

int

I/O 连接超时时间,单位为毫秒,默认为永不超时

 其他⼏个协议也有类似的⼀系列属性,如 POP3  mail.pop3.hostmail.pop3.port 以及IMAP  mail.imap.hostmail.imap.host 等。

2.2.2. Session 会话对象

  Session 是⼀个很容易被误解的类,这归咎于混淆视听的类名。千万不要以为这⾥的 Session  HttpSession ⼀样代表真实的交互会话,但创建 Session 对象时,并没有对应的物理连接,它只不过是⼀对配置信息的集合。

  Session 的主要作⽤,包括两个⽅⾯:

1.  接收各种配置属性信息:通过 Properties 对象设置的属性信息;
2.  初始化 JavaMail 环境:根据 JavaMail 的配置⽂件,初始化 JavaMail 环境,以便通过 Session 对象 创建其他重要类的实例。

2.2.3. Transport  Store 传输和存储

  邮件操作只有发送或接收两种处理⽅式,JavaMail 将这两种不同操作描述为传输
javax.mail.Transport)和存储(javax.mail.Store),传输对应邮件的发送,⽽存储对应邮件的接收。

2.2.4. Message 消息对象

  ⼀旦获得 Session 对象,就可以继续创建要发送的消息。这由 Message 类来完成。因为 Message 是个抽象类,您必需⽤⼀个⼦类,多数情况下为 javax.mail.internet.MimeMessageMimeMessage 是个能理 MIME 类型和头的电⼦邮件消息,正如不同 RFC 中所定义的。虽然在某些头部域⾮ ASCII 字符也能被译码,但 Message 头只能被限制为⽤ US-ASCII 字符。

2.2.5. Address 地址

  ⼀旦您创建了 Session  Message,并将内容填⼊消息后,就可以⽤ Address 确定信件地址了。 Message ⼀样,Address 也是个抽象类。您⽤的是 javax.mail.internet.InternetAddress 类。若创建的地址只包含电⼦邮件地址,只要传递电⼦邮件地址到构造器就⾏了。

2.2.6. Authenticator 认证者

   java 类⼀样,JavaMail API 也可以利⽤ Authenticator 通过⽤户名和密码访问受保护的资源。对 JavaMail API 来说,这些资源就是邮件服务器。JavaMail Authenticator  javax.mail 包中,⽽且它 java.net 中同名的类 Authenticator 不同。两者并不共享同⼀个 Authenticator,因为 JavaMail API  Java 1.1,它没有 java.net 类别。要使⽤ Authenticator,先创建⼀个抽象类的⼦类,并 
getPasswordAuthentication() ⽅法中返回 PasswordAuthentication 实例。创建完成后,您必需向 session 注册 Authenticator。然后,在需要认证的时候,就会通知 Authenticator。您可以弹出窗⼝,也可以从配置⽂件中(虽然没有加密是不安全的)读取⽤户名和密码,将它们作为 PasswordAuthentication 对象返回给调⽤程序。

3. Java Mail 环境准备(操作)

3.1. 设置邮箱服务

这⾥是以163邮箱为例

注册 163 邮箱,登录 163 邮箱后,设置邮箱账户开通 smtp 服务

  需要根据注册时的⼿机号发送的验证码来开通获取邮箱客户端授权码。开通成功后,会显示个⼈授权访问码,该授权码是后⾯通过 Java mail 发送邮件的认证密码,⾮常重要。

3.2. 添加依赖

创建 Maven 项⽬,在 pom.xml 配置⽂件中添加 mail 的所需的依赖

<!-- Java Mail -->

<dependency>

 <groupId>com.sun.mail</groupId>

 <artifactId>javax.mail</artifactId>

 <version>1.6.2</version>

</dependency>

<dependency>

 <groupId>javax.mail</groupId>

 <artifactId>javax.mail-api</artifactId>

 <version>1.6.2</version>

</dependency>

4. Java Mail 发送邮件(操作)

4.1. 发送普通⽂本的邮件

package com.xxxx.mail;
import javax.activation.DataHandler;import javax.activation.FileDataSource;import javax.mail.*;import javax.mail.internet.*;import java.io.UnsupportedEncodingException;import java.util.Date;import java.util.Properties;/*** 发送普通⽂本的邮件*/public class MailTest01 {public static void main(String[] args) throws Exception {// 定义邮箱服务器配置Properties prop = new Properties();// 设置邮件服务器主机名 (163 邮件服务器地址:"mail.smtp.host"  "smtp.163.com") prop.setProperty("mail.smtp.host", "smtp.163.com");// 设置邮件服务器的端⼝prop.setProperty("mail.smtp.port", "25");// 设置邮件服务器认证属性 (设置为true表示发送服务器需要身份验证) prop.setProperty("mail.smtp.auth", "true");// 某些邮箱服务器要求 SMTP 连接需要使⽤ SSL 安全认证// prop.setProperty("mail.smtp.port", "465");// prop.setProperty("mail.smtp.socketFactory.class","javax.net.ssl.SSLSocketFactory");// prop.setProperty("mail.smtp.socketFactory.fallback", "false"); // prop.setProperty("mail.smtp.socketFactory.port", "465");// 使⽤JavaMail发送邮件的5个步骤// 1. 创建sessionSession session = Session.getInstance(prop);// 开启Session的debug模式,这样就可以查看到程序发送Email的运⾏状态 session.setDebug(true);// 2. 通过session得到transport对象Transport ts = session.getTransport();// 3. 使⽤邮箱的⽤户名和密码连上邮件服务器(⽤户名只需写@前⾯的即可,密码是指授权码) ts.connect("smtp.163.com", "⽤户名", "密码");// 4. 创建邮件// 发送普通⽂本的邮件Message message = createSimpleTxtMail(session);// 5. 发送邮件ts.sendMessage(message, message.getAllRecipients()); // 关闭transport对象ts.close();}/*** 普通⽂本邮件*      创建⼀封只包含⽂本的邮件* @param session* @return*/public static MimeMessage createSimpleTxtMail(Session session) throws MessagingException {// 创建邮件对象MimeMessage message = new MimeMessage(session);// 设置邮件的发件⼈的邮箱地址message.setFrom(new InternetAddress("发件⼈的邮箱地址"));// 设置邮件的收件⼈的邮箱地址 (现在发件⼈和收件⼈是⼀样的,那就是⾃⼰给⾃⼰发)message.setRecipient(Message.RecipientType.TO, new InternetAddress("收件⼈的邮箱地址"));// 发送给多个收件⼈// message.setRecipients(Message.RecipientType.TO, new InternetAddress[] {}); // Cc: 抄送(可选)// message.setRecipient(MimeMessage.RecipientType.CC, newInternetAddress(""));// Bcc: 密送(可选)// message.setRecipient(MimeMessage.RecipientType.BCC, newInternetAddress(""));// 邮件的主题message.setSubject("测试⽂本邮件");// 设置发送⽇期message.setSentDate(new Date());// 邮件的⽂本内容 (setText():纯⽂本内容)message.setText("你好,这是⼀封测试邮件!");// 返回创建好的邮件对象return message;}}

效果如下:

4.2. 发送HTML内容的邮件

package com.xxxx.mail;import javax.activation.DataHandler;import javax.activation.FileDataSource;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.MimeBodyPart;import javax.mail.internet.MimeMessage;import javax.mail.internet.MimeMultipart;import java.util.Date;import java.util.Properties;/*** 发送HTML内容的邮件*/public class MailTest02 {public static void main(String[] args) throws Exception {// 定义邮箱服务器配置Properties prop = new Properties();// 设置邮件服务器主机名 (163 邮件服务器地址:"mail.smtp.host"  "smtp.163.com") prop.setProperty("mail.smtp.host", "smtp.163.com");// 设置邮件服务器的端⼝prop.setProperty("mail.smtp.port", "25");// 设置邮件服务器认证属性 (设置为true表示发送服务器需要身份验证) prop.setProperty("mail.smtp.auth", "true");// 使⽤JavaMail发送邮件的5个步骤// 1. 创建sessionSession session = Session.getInstance(prop);// 开启Session的debug模式,这样就可以查看到程序发送Email的运⾏状态 session.setDebug(true);// 2. 通过session得到transport对象Transport ts = session.getTransport();// 3. 使⽤邮箱的⽤户名和密码连上邮件服务器(⽤户名只需写@前⾯的即可,密码是指授权码) ts.connect("smtp.163.com", "⽤户名", "密码");// 4. 创建邮件// 发送HTML内容的邮件Message message = createHtmlMail(session);// 5. 发送邮件ts.sendMessage(message, message.getAllRecipients()); // 关闭transport对象ts.close();}/*** HTML内容邮件*      创建⼀封包含html内容的邮件*/public static MimeMessage createHtmlMail(Session session) throws Exception {// 创建邮件对象MimeMessage message = new MimeMessage(session);// 设置邮件的发件⼈的邮箱地址message.setFrom(new InternetAddress("发件⼈的邮箱地址"));// 设置邮件的收件⼈的邮箱地址 (现在发件⼈和收件⼈是⼀样的,那就是⾃⼰给⾃⼰发)message.setRecipient(Message.RecipientType.TO, new InternetAddress("收件⼈的邮箱地址"));// 邮件的主题message.setSubject("测试HTML邮件");// 设置发送⽇期message.setSentDate(new Date());// 准备邮件数据/*** Message表示⼀个邮件,messgaes.getContent()返回⼀个Multipart对象。* ⼀个Multipart对象包含⼀个或多个BodyPart对象,来组成邮件的正⽂部分(包括附件)。*/// 创建多媒体对象MimeMultipart multipart = new MimeMultipart();// 创建邮件体对象MimeBodyPart bodyPart = new MimeBodyPart();// 设置HTML内容StringBuffer sb = new StringBuffer();sb.append("<html><body><a href='http://www.baidu.com'>百度⼀下</a></body></html>");bodyPart.setContent(sb.toString(), "text/html;charset=UTF-8");// 将bodyPart对象设置到multipart对象中multipart.addBodyPart(bodyPart);// 将multipart对象设置到message对象中 (setContent():) message.setContent(multipart);// 返回创建好的邮件对象return message;}   }

效果如下:

4.3. 发送包含附件的邮件

package com.xxxx.mail;import javax.activation.DataHandler;import javax.activation.FileDataSource;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.MimeBodyPart;import javax.mail.internet.MimeMessage;import javax.mail.internet.MimeMultipart;import java.util.Date;import java.util.Properties;/*** 发送包含附件的邮件*/public class MailTest03 {public static void main(String[] args) throws Exception {// 定义邮箱服务器配置Properties prop = new Properties();// 设置邮件服务器主机名 (163 邮件服务器地址:"mail.smtp.host"  "smtp.163.com") prop.setProperty("mail.smtp.host", "smtp.163.com");// 设置邮件服务器的端⼝prop.setProperty("mail.smtp.port", "25");// 设置邮件服务器认证属性 (设置为true表示发送服务器需要身份验证) prop.setProperty("mail.smtp.auth", "true");// 使⽤JavaMail发送邮件的5个步骤// 1. 创建sessionSession session = Session.getInstance(prop);// 开启Session的debug模式,这样就可以查看到程序发送Email的运⾏状态 session.setDebug(true);// 2. 通过session得到transport对象Transport ts = session.getTransport();// 3. 使⽤邮箱的⽤户名和密码连上邮件服务器(⽤户名只需写@前⾯的即可,密码是指授权码) ts.connect("smtp.163.com", "⽤户名", "密码");// 4. 创建邮件// 发送包含附件的邮件Message message = createAttachMail(session);// 5. 发送邮件ts.sendMessage(message, message.getAllRecipients()); // 关闭transport对象ts.close();}/*** 包含附件的邮件*      创建⼀封包含附件的邮件* @param session* @return* @throws MessagingException*/public static MimeMessage createAttachMail(Session session) throws MessagingException {// 创建邮件对象MimeMessage message = new MimeMessage(session);// 设置邮件的发件⼈的邮箱地址message.setFrom(new InternetAddress("发件⼈的邮箱地址"));// 设置邮件的收件⼈的邮箱地址 (现在发件⼈和收件⼈是⼀样的,那就是⾃⼰给⾃⼰发)message.setRecipient(Message.RecipientType.TO, new InternetAddress("收件⼈的邮箱地址"));// 邮件的主题message.setSubject("测试包含附件的邮件");// 设置发送⽇期message.setSentDate(new Date());// 创建邮件正⽂MimeBodyPart bodyPart = new MimeBodyPart();bodyPart.setContent("使⽤JavaMail创建的带附件的邮件", "text/html;charset=UTF-8");// 创建附件MimeBodyPart attachPart = new MimeBodyPart();// 本地⽂件DataHandler dh = new DataHandler(new FileDataSource("C:\\work\\邮件附件.txt")); attachPart.setDataHandler(dh);// 附件名attachPart.setFileName(dh.getName());// 创建容器描述数据关系MimeMultipart multipart = new MimeMultipart();// 添加正⽂multipart.addBodyPart(bodyPart);// 添加附件multipart.addBodyPart(attachPart);// 如果在邮件中要添加附件,设置为mixed;。multipart.setSubType("mixed");// 设置邮件的内容message.setContent(multipart);// 返回创建好的邮件对象return message;}}

效果如下:

4.4. Java Mail 邮件发送封装

4.4.1. 创建邮件发送信息类

package com.xxxx.mail;import java.util.List;/*** 邮件发送信息类*   定义发送邮件时 邮件服务器 端⼝ 发送⽅⽤户名 密码等字段*/public class MailSendInfo {private String serverHost; // 服务器主机private String serverPort; // 服务器端⼝private String fromAddress;// 发送⽅邮箱地址private List<String> toAddress; // 接收⽅邮箱地址private String userName; // 邮件服务器⽤户名private String userPwd; // 邮件服务器密码(授权密码)private String subject; // 邮件主题private String content; // 邮件内容private Boolean flag = true; // 是否需要身份认证private List<String> attachFileNames; // 附件⽂件名public Boolean getFlag() {return flag;}public void setFlag(Boolean flag) {this.flag = flag;}public String getServerHost() {return serverHost;}public void setServerHost(String serverHost) {this.serverHost = serverHost;}public String getServerPort() {return serverPort;}public void setServerPort(String serverPort) {this.serverPort = serverPort;}public String getFromAddress() {return fromAddress;}public void setFromAddress(String fromAddress) {this.fromAddress = fromAddress;}public List<String> getToAddress() {return toAddress;}public void setToAddress(List<String> toAddress) {this.toAddress = toAddress;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getUserPwd() {return userPwd;}public void setUserPwd(String userPwd) {this.userPwd = userPwd;}public String getSubject() {return subject;}public void setSubject(String subject) {this.subject = subject;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public List<String> getAttachFileNames() {return attachFileNames;}public void setAttachFileNames(List<String> attachFileNames) {  this.attachFileNames = attachFileNames;}}

4.4.2. 创建认证类

package com.xxxx.mail;import javax.mail.Authenticator;import javax.mail.PasswordAuthentication;/*** 认证类*/public class MyAuthenticator extends Authenticator {private String userName; // 邮箱private String userPwd; // 密码(授权码)public MyAuthenticator(String userName, String userPwd) {  this.userName = userName;this.userPwd = userPwd;}/*** 邮件服务器发送邮件时,进⾏身份验证* @return*/@Overrideprotected PasswordAuthentication getPasswordAuthentication() {return new PasswordAuthentication(userName, userPwd);}}

4.4.3. 创建邮件发送器

package com.xxxx.mail;import javax.activation.DataHandler;import javax.activation.FileDataSource;import javax.mail.*;import javax.mail.internet.*;import java.io.File;import java.util.Date;import java.util.List;import java.util.Properties;public class MailSender {public void sendMail(MailSendInfo mailSendInfo){Message message = null;Session session = null;try {// 定义邮箱服务器配置Properties props = new Properties();// 163 邮件服务器地址props.put("mail.smtp.host", mailSendInfo.getServerHost());// 163 邮件服务器端⼝props.put("mail.smtp.port",mailSendInfo.getServerPort());// 163 邮件服务器认证属性props.put("mail.smtp.auth", mailSendInfo.getFlag());// 身份认证类MyAuthenticator authenticator = new MyAuthenticator(mailSendInfo.getUserName(), mailSendInfo.getUserPwd());// 创建sessionsession = Session.getDefaultInstance(props, authenticator);// 开启Session的debug模式,这样就可以查看到程序发送Email的运⾏状态session.setDebug(true);// 创建message邮件对象message = new MimeMessage(session);// 设置发送⽅的邮箱地址Address from = new InternetAddress(mailSendInfo.getFromAddress());message.setFrom(from);// 设置发送时间message.setSentDate(new Date());// 判断接收⽅的邮箱地址if(null != mailSendInfo.getToAddress() && mailSendInfo.getToAddress().size() > 0){// 定义数组Address[] addresses = new Address[mailSendInfo.getToAddress().size()];// 循环获取接收⽅的邮箱地址,并设置到对应的address数组中for(int i = 0; i < mailSendInfo.getToAddress().size(); i++){  Address address = new InternetAddress(mailSendInfo.getToAddress().get(i));addresses[i] = address;}// 设置接收⽅的邮箱地址message.setRecipients(Message.RecipientType.TO, addresses); // 设置邮件主题message.setSubject(mailSendInfo.getSubject());// 创建多媒体对象容器Multipart multipart = new MimeMultipart();// 创建正⽂内容BodyPart bodyPart =new MimeBodyPart();bodyPart.setContent(mailSendInfo.getContent(),"text/html;charset=utf-8");// 添加正⽂ (将正⽂内容设置到多媒体对象容器中)multipart.addBodyPart(bodyPart);// 获取所有的附件内容List<String> files = mailSendInfo.getAttachFileNames(); // 判断是否包含附件内容if(null != files && files.size() > 0){for(int i = 0; i < files.size(); i++){// 获取对应的附件对象File tempFile = new File(files.get(i));// 判断附件是否存在if(tempFile.exists()){// 如果附件存在,创建附件对象BodyPart attachPart = new MimeBodyPart();attachPart.setDataHandler(new DataHandler(new FileDataSource(tempFile)));// 设置⽂件名 (解决附件名乱码)attachPart.setFileName(MimeUtility.encodeText(tempFile.getName()));// 添加附件 (将附件内容添加到多媒体对象容器中)multipart.addBodyPart(attachPart);}}}// 设置邮件内容message.setContent(multipart);// 发送邮件Transport.send(message);}} catch (Exception e) {e.printStackTrace();}}}

4.4.4. 邮件发送测试
4.4.4.1. 发送HTML内容的邮件
/*** 发送HTML内容的邮件*/public static void testHtmlMail() {MailSendInfo mailSendInfo = new MailSendInfo();mailSendInfo.setServerHost("smtp.163.com");mailSendInfo.setServerPort("25");mailSendInfo.setUserName("邮箱⽤户名");mailSendInfo.setUserPwd("密码(授权码)");mailSendInfo.setSubject("邮件封装");mailSendInfo.setFromAddress("发件⼈的邮箱地址");mailSendInfo.setContent("<h2>这是封装后发送的邮件</h2>");List<String> users = new ArrayList<>();users.add("收件⼈的邮箱地址");mailSendInfo.setToAddress(users);MailSender mailSender=new MailSender();mailSender.sendMail(mailSendInfo);}

效果如下:

4.4.4.2. 发送包含附件的邮件

/*** 发送包含附件的邮件*/public static void testAttachMail() {MailSendInfo mailSendInfo = new MailSendInfo();mailSendInfo.setServerHost("smtp.163.com");mailSendInfo.setServerPort("25");mailSendInfo.setUserName("⽤户名");mailSendInfo.setUserPwd("密码(授权码)");mailSendInfo.setSubject("邮件封装");mailSendInfo.setFromAddress("发件⼈的邮箱地址");mailSendInfo.setContent("<h2>包含附件的邮件</h2>");List<String> users = new ArrayList<>();users.add("收件⼈的邮箱地址");mailSendInfo.setToAddress(users);// 添加附件List<String> files=new ArrayList<String>();files.add("C:\\work\\邮件附件.txt");files.add("C:\\work\\名单.xlsx");mailSendInfo.setAttachFileNames(files);MailSender mailSender=new MailSender();mailSender.sendMail(mailSendInfo);}

效果如下:

5. 使⽤ Spring API 实现邮件发送(操作)

5.1. 环境准备

创建 Maven 项⽬,在 pom.xml ⽂件中添加依赖

<!-- spring核⼼ jar 依赖 -->

<dependency>

 <groupId>org.springframework</groupId>

 <artifactId>spring-context</artifactId>

 <version>5.2.4.RELEASE</version>

</dependency>

<!--spring 上下⽂环境 ⽀持-->

<dependency>

 <groupId>org.springframework</groupId>

 <artifactId>spring-context-support</artifactId>

 <version>5.2.4.RELEASE</version>

</dependency>

<dependency>

 <groupId>org.springframework</groupId>

 <artifactId>spring-test</artifactId>

 <version>5.2.4.RELEASE</version>

 <scope>test</scope>

</dependency>

<!-- Java Mail坐标依赖 -->

<dependency>

 <groupId>com.sun.mail</groupId>

 <artifactId>javax.mail</artifactId>

 <version>1.6.2</version>

</dependency>

5.2. 配置邮件发送 bean

 spring.xml 配置⽂件中设置邮件发送对应的bean标签

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:context="http://www.springframework.org/schema/context"  xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsd  http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context.xsd">

 <!-- 开启⾃动化扫描  -->

 <context:component-scan base-package="com.xxxx"/>

 <!-- 邮件发送器(提供了邮件发送接⼝、透明创建Java MailMimeMessage、及邮件发送的配置) -->  <bean id="mailSender" 
class="org.springframework.mail.javamail.JavaMailSenderImpl">

 <property name="host" value="smtp.163.com" />

 <property name="port" value="25" />
 <property name="defaultEncoding" value="utf-8"></property> <property name="username" value="⽤户名"></property>

 <property name="password" value="密码"></property>

 </bean>

 <!-- 普通⽂本邮件对象 -->
 <bean id="templateMessage" class="org.springframework.mail.SimpleMailMessage">  <property name="from" value="发件⼈的邮箱地址" />

 <property name="subject" value="spring_mail" />

 </bean>

</beans>

5.3. 定义接⼝与实现类

定义接⼝

package com.xxxx.springMail;/*** 定义接⼝*/public interface OrderManager {void placeOrder();}

定义实现类

package com.xxxx.springMail;import org.springframework.mail.MailException;import org.springframework.mail.SimpleMailMessage;import org.springframework.mail.javamail.JavaMailSenderImpl;import org.springframework.stereotype.Service;import javax.annotation.Resource;@Servicepublic class SimpleOrderManager implements OrderManager {@Resourceprivate JavaMailSenderImpl mailSender;@Resourceprivate SimpleMailMessage templateMessage;@Overridepublic void placeOrder() {// 获取邮件对象SimpleMailMessage msg = new SimpleMailMessage(this.templateMessage); // 设置邮件收件⼈的邮箱地址msg.setTo("收件⼈的邮箱地址");// 设置邮件内容msg.setText("Hello Spring Mail");try{// 发送邮件this.mailSender.send(msg);} catch (MailException ex) {System.err.println(ex.getMessage());}}}

5.4. 邮件发送测试

/***  发送邮件* @param args*/public static void main(String[] args) {ApplicationContext ac=new ClassPathXmlApplicationContext("spring.xml");  SimpleOrderManager simpleOrderManager = (SimpleOrderManager) ac.getBean("simpleOrderManager");simpleOrderManager.placeOrder();}

5.5. 发送附件

/***  发送包含附件的邮件* @param args* @throws MessagingException*/
public static void main(String[] args) throws MessagingException {ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");  JavaMailSender mailSender= (JavaMailSender) ac.getBean("mailSender");  MimeMessage message= mailSender.createMimeMessage();message.setSubject("spring_mail"); // 邮件主题// 创建带有附件的消息帮组类MimeMessageHelper helper = new MimeMessageHelper(message,true,"utf-8"); helper.setTo(new InternetAddress("收件⼈的邮箱地址"));//设置接收⼈helper.setText("Thank you for ordering!"); // 邮件内容helper.setFrom("发件⼈的邮箱地址"); // 发件⼈// 设置附件File file = new File("C:\\work\\邮件附件.txt");// 添加附件helper.addAttachment(file.getName(), file);// 发送邮件mailSender.send(message);}

相关文章:

Spring 邮件发送

Spring 邮件发送 1. 主要内容&#xff08;了解&#xff09; 2. JavaMail 概述&#xff08;了解&#xff09; JavaMail&#xff0c;顾名思义&#xff0c;提供给开发者处理电⼦邮件相关的编程接⼝。JavaMail 是由 Sun 定义的⼀套收发电⼦邮件的 API&#xff0c;它可以⽅便地执⾏⼀…...

利用 360 安全卫士极速版关闭电脑开机自启动软件教程

在使用电脑的过程中&#xff0c;过多的开机自启动软件会严重拖慢电脑的开机速度&#xff0c;影响我们的使用体验。本教程中简鹿办公将详细介绍如何使用 360 安全卫士极速版关闭电脑开机自启动软件&#xff0c;让您的电脑开机更加迅速流畅。 一、打开 360 安全卫士极速版 在电…...

楼房销售系统

文末获取源码和万字论文&#xff0c;制作不易&#xff0c;感谢点赞支持。 毕 业 设 计&#xff08;论 文&#xff09; 题目&#xff1a;楼房销售系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xf…...

UML箭线图的理解和实践

在软件开发的世界里&#xff0c;UML&#xff08;统一建模语言&#xff09;作为一种标准化的建模语言&#xff0c;扮演着举足轻重的角色。UML类图更是软件开发设计和架构过程中的核心工具&#xff0c;它不仅能帮助开发者明确系统中的类及其关系&#xff0c;还能为后续的代码实现…...

Qt入门8——Qt文件

1. Qt文件概述 文件操作是应用程序必不可少的部分。Qt作为⼀个通用开发库&#xff0c;提供了跨平台的文件操作能力。Qt 提供了很多关于文件的类&#xff0c;通过这些类能够对文件系统进行操作&#xff0c;如文件读写、文件信息获取、文件复制或重命名等。 2. 输入输出设备类 在…...

鸿翼受邀出席2024海峡两岸档案暨缩微学术交流会

近日&#xff0c;由中国档案学会、中国文献影像技术协会共同主办&#xff0c;中华档案暨资讯微缩管理学会参加的2024年海峡两岸档案暨缩微学术交流会在乌鲁木齐召开。鸿翼联合创始人兼CTO罗永秀受邀出席本次交流会并作主题分享。 自1992年以来&#xff0c;该学术交流会已连续举…...

支持win7系统的onnxruntime

在win7 X86系统上&#xff0c;使用了onnxruntime.dll库做AI识别&#xff0c;但是在win7上运行报0xc0000005的错误 经查&#xff0c;ONNX Runtime从v1.15.0版本开始不再支持Windows 7及其之前的操作系统&#xff0c;即便尝试重新编译源代码亦无法在这些老系统上运行&#xff0c;…...

如何利用内链策略提升网站的整体权重?

内链是谷歌SEO中常常被低估的部分&#xff0c;实际上&#xff0c;合理的内链策略不仅能帮助提升页面间的关联性&#xff0c;还可以增强网站的整体权重。通过正确的内链布局&#xff0c;用户可以更流畅地浏览你的网站&#xff0c;谷歌爬虫也能更快地抓取到更多页面&#xff0c;有…...

鸿蒙分享(二):引入zrouter路由跳转+封装

码仓库&#xff1a;https://gitee.com/linguanzhong/share_harmonyos 鸿蒙api:12 鸿蒙第三方库地址&#xff1a;OpenHarmony三方库中心仓 zrouter地址&#xff1a;OpenHarmony三方库中心仓 1.引入zrouter 1.打开终端界面&#xff1a;输入 ohpm install hzw/zrouter 2.在项目…...

【计算机网络】实验11:边界网关协议BGP

实验11 边界网关协议BGP 一、实验目的 本次实验旨在验证边界网关协议&#xff08;BGP&#xff09;的实际作用&#xff0c;并深入学习在路由器上配置和使用BGP协议的方法。通过实验&#xff0c;我将探索BGP在不同自治系统之间的路由选择和信息交换的功能&#xff0c;理解其在互…...

leetcode 1853 转换日期格式(postgresql)

需求 表: Days ----------------- | Column Name | Type | ----------------- | day | date | ----------------- day 是这个表的主键。 给定一个Days表&#xff0c;请你编写SQL查询语句&#xff0c;将Days表中的每一个日期转化为"day_name, month_name day, year"…...

掌握时间,从`datetime`开始

文章目录 掌握时间&#xff0c;从datetime开始第一部分&#xff1a;背景介绍第二部分&#xff1a;datetime库是什么&#xff1f;第三部分&#xff1a;如何安装这个库&#xff1f;第四部分&#xff1a;简单库函数使用方法1. 获取当前日期和时间2. 创建特定的日期3. 计算两个日期…...

剖析千益畅行,共享旅游-卡,合规运营与技术赋能双驱下的旅游新篇

在数字化浪潮席卷各行各业的当下&#xff0c;旅游产业与共享经济模式深度融合&#xff0c;催生出旅游卡这类新兴产品。然而&#xff0c;市场乱象丛生&#xff0c;诸多打着 “共享” 幌子的旅游卡弊病百出&#xff0c;让从业者与消费者都深陷困扰。今天&#xff0c;咱们聚焦技术…...

集合框架(2)List

Collection的子接口&#xff1a;List、Set 1、List接口 鉴于Java中数组用来存储数据的局限性&#xff0c;我们通常使用java.util.List替代数组List集合类中元素有序、且可重复&#xff0c;集合中的每个元素都有其对应的顺序索引。JDK API中List接口的实现类常用的有&#xff…...

【子查询】.NET开源 ORM 框架 SqlSugar 系列

.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…...

西安理工大学丨ChatGPT助力学术论文写作训练营-助力发表SCI一区、二区

在当今学术研究中&#xff0c;科研人员在撰写论文时面临诸多挑战。首先是信息量的剧增&#xff0c;科研人员需要快速消化新知识&#xff0c;筛选相关信息并清晰表达。但论文写作不仅是信息的罗列&#xff0c;还需要条理清晰、逻辑严密、语言精准&#xff0c;特别是在竞争激烈的…...

go get依赖包失败,502 Bad gateway

问题描述 go get 依赖包失败&#xff0c;502 Bad gateway 解决办法 # 临时 export GOPROXY"https://goproxy.cn" go get -u xxxx # 或者直接永久生效 go env -w GOPROXY"https://goproxy.cn"...

71、docker镜像制作上传/下载到阿里云

基本思想:简单学习一下如何制作镜像和上传下载到私有阿里云,然后构建一个gpu的训练/推理环境,以备后续使用 一、配置环境 ubuntu@ubuntu:~$ sudo apt-get install docker.ioubuntu@ubuntu:~$ sudo docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS P…...

ZLMediaKit+wvp (ffmpeg+obs)推拉流测试

这里使用了两种方式: ffmpeg命令和 OBS OBS推流在网上找了些基本没有说明白的, 在ZLMediaKit的issues中看到了一个好大哥的提问在此记录一下 使用OBS推流&#xff0c;rtmp&#xff0c;报鉴权失败 推流 1. ffmpeg命令推流 官方说明文档地址: 推流规则 rtsp://192.168.1.4:10554…...

POSTGRESQL跟ORACLE语法区别和相同之处

跟ORACLE语法区别之处 1. Update和delete语法区别 Pg 和MySQL Update和delete的时候表名不能加别名 2. 插入数字类型不一样 ORACLE 对number类型的数据可以用’’ 字符串标记插入&#xff0c;但是PG不行&#xff0c;必须要进行正确的数据类型 3. SEQ使用不同 ORACEL的SEQ…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

Golang——6、指针和结构体

指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

LabVIEW双光子成像系统技术

双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制&#xff0c;展现出显著的技术优势&#xff1a; 深层组织穿透能力&#xff1a;适用于活体组织深度成像 高分辨率观测性能&#xff1a;满足微观结构的精细研究需求 低光毒性特点&#xff1a;减少对样本的损伤…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

Python实现简单音频数据压缩与解压算法

Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中&#xff0c;压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言&#xff0c;提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...

高防服务器价格高原因分析

高防服务器的价格较高&#xff0c;主要是由于其特殊的防御机制、硬件配置、运营维护等多方面的综合成本。以下从技术、资源和服务三个维度详细解析高防服务器昂贵的原因&#xff1a; 一、硬件与技术投入 大带宽需求 DDoS攻击通过占用大量带宽资源瘫痪目标服务器&#xff0c;因此…...

AD学习(3)

1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分&#xff1a; &#xff08;1&#xff09;PCB焊盘&#xff1a;表层的铜 &#xff0c;top层的铜 &#xff08;2&#xff09;管脚序号&#xff1a;用来关联原理图中的管脚的序号&#xff0c;原理图的序号需要和PCB封装一一…...

用递归算法解锁「子集」问题 —— LeetCode 78题解析

文章目录 一、题目介绍二、递归思路详解&#xff1a;从决策树开始理解三、解法一&#xff1a;二叉决策树 DFS四、解法二&#xff1a;组合式回溯写法&#xff08;推荐&#xff09;五、解法对比 递归算法是编程中一种非常强大且常见的思想&#xff0c;它能够优雅地解决很多复杂的…...

TJCTF 2025

还以为是天津的。这个比较容易&#xff0c;虽然绕了点弯&#xff0c;可还是把CP AK了&#xff0c;不过我会的别人也会&#xff0c;还是没啥名次。记录一下吧。 Crypto bacon-bits with open(flag.txt) as f: flag f.read().strip() with open(text.txt) as t: text t.read…...