Spring-邮件发送出现bug出现Bug以及解决方案乐字节

32次阅读

共计 4447 个字符,预计需要花费 12 分钟才能阅读完成。

详细 Spring 如何进行邮件发送

本文由乐字节 Java 架构课程独家赞助播出

Spring 邮件发送

主要内容

JavaMail 概述

​ JavaMail,顾名思义,提供给开发者处理电子邮件相关的编程接口。JavaMail 是由 Sun 定义的一套收发电子邮件的 API,它可以方便地执行一些常用的邮件传输,不同的厂商可以提供自己的实现类。但它并没有包含在 JDK 中,而是作为 JavaEE 的一部分。

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

  • SMTP:简单邮件传输协议,用于发送电子邮件的传输协议;
  • POP3:用于接收电子邮件的标准协议;
  • IMAP:互联网消息协议,是 POP3 的替代协议。

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

协议介绍

​ 在研究 JavaMail API 的细则之前,首先需要对于 API 用到的协议有个认识。对于 java mail 来说用到的协议有常见的几种:SMTP、POP、IMAP、MIME

SMTP

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

POP

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

IMAP

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

MIME

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

JavaMail 的关键对象

​ JavaMail 对收发邮件进行了高级的抽象,形成了一些关键的的接口和类,它们构成了程序的基础,下面我们分别来了解一下这些最常见的对象。

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.host、mail.pop3.port 以及 IMAP 的 mail.imap.host、mail.imap.host 等。

Session 会话对象

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

​ Session 的主要作用,包括两个方面:

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

Transport 和 Store 传输和存储

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

Message 消息对象

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

Address 地址

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

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 对象返回给调用程序。

Java Mail 环境准备

设置邮箱服务

这里是以 163 邮箱为例

![]()

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

![]()

![]()

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

添加依赖

创建 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>

ependency>

<groupId>javax.mail</groupId>
<artifactId>javax.mail-api</artifactId>
<version>1.6.2</version>

</dependency>


### 后续待更新

正文完
 0