Java发送邮件(一)之JavaMail

前言

本文将讲述如何利用原生JavaMail发送邮件,如果需要看如何利用Spring来实现邮件发送,请参考我的另外一篇博客《Java发送邮件(二)之Spring》,不过Spring其实也是基于JavaMail来做的,所以还是有必要先了解一下JavaMail的一些基本概念和操作。

一、什么是SMTP、POP3、IMAP?

学习Java发送邮件,必然会涉及到的一个术语就是SMTP,而且在邮箱中设置SMTP的时候我们还会看到另外两个术语:POP3和IMAP。那什么是SMTP、POP3、IMAP呢?

简单的说,这三个都是邮件收发相关的三种协议。

  • SMTP:全称是“Simple Mail Transfer Protocol”,简单邮件传输协议,它是一组用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式。SMTP 协议属于 TCP/IP 协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。用于发送电子邮件的传输协议
  • POP3:全称是"Post Office Protocol 3",是邮局协议的第3个版本,它规定怎样将个人计算机连接到Internet的邮件服务器和下载电子邮件的电子协议。用于接收电子邮件的标准协议
  • IMAP:全称是"Internet Mail Access Protocol",即交互式邮件存取协议,它是跟POP3类似邮件访问标准协议之一。不同的是,开启了IMAP后,您在电子邮件客户端收取的邮件仍然保留在服务器上,同时在客户端上的操作都会反馈到服务器上,如:删除邮件,标记已读等,服务器上的邮件也会做相应的动作,是POP3的替代协议

二、利用JavaMail发送邮件

JavaMail是Oracle官方提供的一组API库,并没有包含在标准的JDK中,使用时需要我们自己引入依赖,github地址:https://github.com/javaee/javamail。官方提供的这个库能实现对邮件的各种操作,如果感兴趣的可以参考官方提供的使用demo和指导手册详细研究,我们今天仅通过发送邮件这个动作来了解一下这个类库的基本使用。

2.1 引入依赖:
<dependency>
    <groupId>javax.mail</groupId>
    <artifactId>mail</artifactId>
    <version>1.4.7</version>
</dependency>

JavaMail最新版为1.6.2,这里使用1.4.7是为了方便测试,具体使用1.6.2的问题在后面会提到。

2.2 设置发件人邮件的SMTP服务

以QQ邮箱为例,我们进入邮箱后点击设置 -> 账户,开启SMTP的开关,以及按照操作提示获取SMTP认证的授权码即可。

2.3 API使用

首先,邮件有几个关键要素我们需要掌握,分别是:

  • 发件人
  • 收件人
  • 抄送人
  • 密送人
  • 邮件主题
  • 邮件附件
  • 邮件正文

在了解了这些因素之后,自然我们在使用API的时候也是针对设置这些因素来展开的,具体有以下步骤:

(1)设置邮件服务器的一些基本设置(包括邮件SMTP服务器地址,SMTP认证所需要的账号和授权码);

(2)设置发件人、收件人、抄(密)送人

(3)设置邮件主题和正文

(4)有附件的情况设置附件(可选)

接下来我们将按照这个步骤写示例代码:

public static void main(String[] args) throws MessagingException {
    // 1. 初始化配置
    Properties properties = initProps();
    // 2. 通过配置获取session
    Session session = Session.getInstance(properties);
    session.setDebug(true);//debug时控制台能展示更多的log
    // 3.创建邮件
    MimeMessage msg = new MimeMessage(session);
    // 设置发件人
    String from = "fajianren@qq.com";
    // QQ邮箱采用的是SMTP授权码认证
    String authorizedCode = "wmz******jf";
    msg.setFrom(new InternetAddress(from));
    // 设置收件人
    String recipient = "shoujianren@qq.com";
    InternetAddress[] toAddrs = {new InternetAddress(recipient)};
    msg.setRecipients(Message.RecipientType.TO, toAddrs);
    // 也可以使用下面这个方法这是收件人(1.6版本可以直接使用收件人的地址字符串)
    //msg.setRecipients(Message.RecipientType.TO, recipient);
    // 设置抄送人,如果是密送,类型使用Message.RecipientType.BCC,多人与上方同理
    msg.setRecipients(Message.RecipientType.CC, recipient);
    // 设置邮件主题,如果主题中存在中文,要使用支持的字符集
    msg.setSubject("JavaMail邮件测试","UTF-8");
    // 设置发送时间,这个时间可以随意设置,用于显示发送时间
    Calendar calendar = Calendar.getInstance();
    calendar.add(Calendar.DAY_OF_MONTH,-1);
    Date date = calendar.getTime();
    msg.setSentDate(date);
    // 设置发送正文,同样要指定字符集,除非全英文
    msg.setText("这是一个测试邮件;\n另一行<font style='color:blue;'>蓝色的字体</font>","UTF-8", "html");

    // 4. 邮件发送
    Transport transport = session.getTransport();
    // 连接SMTP认证
    transport.connect(from, authorizedCode);
    // 通过Transport对象发送邮件
    transport.sendMessage(msg,msg.getAllRecipients());

}

/**
 * 设置的基础属性有哪些?
 * 可以参考官方的Java Doc,地址:https://javaee.github.io/javamail/docs/api/
 * 分别在
 * com.sun.mail.smtp
 * com.sun.mail.imap
 * com.sun.mail.pop3
 * 3个包级的文档注释中的Description部分有列表展示了每个参数的含义
 */
private static Properties initProps() {
    Properties properties = new Properties();
    properties.put("mail.transport.protocol","smtp");
    // 发件人邮箱的smtp服务器地址
    properties.put("mail.smtp.host","smtp.qq.com");
    // smtp服务器端口
    properties.put("mail.smtp.port","25");
    properties.put("mail.debug", "true");
    properties.put("mail.smtp.auth","true");
    return properties;
}
2.4 API使用时的问题
2.4.1 如何设置多个收件人(抄送人)?
// 如果有多个收件人,可使用addRecipients方法添加
msg.addRecipients(Message.RecipientType.TO, recipient);
// 或者在setRecipients时全部设置进去.setRecipients方法接收的是一个Address[]数组
2.4.2 RecipientType的类型有哪些?分别代表什么?
RecipientType.TO  收件人
RecipientType.C   抄送人
RecipientType.BC  密送人 
2.4.3 如何发送带格式的邮件,比如html?
// MimeMessage的setText有3个重载方法
// setText(String text) 发送普通文本邮件
msg.setText("Hello JavaMail");
// setText(String text, String charset)发送普通文本邮件,指定字符集使得邮件内容不仅局限于英文
msg.setText("你好,JavaMail", "UTF-8");
// setText(String text, String charset, String subtype) 发送指定类型的邮件,类型根据subtype变化
msg.setText("<font style='color:red;'>你好</font>,JavaMail!", "UTF-8","html");
2.4.4 邮件发送时乱码怎么办?

见2.4.3设置好字符集。

2.4.5 发送邮件时报错java.lang.ClassNotFoundException: com.sun.mail.util.MailLogger

出现这个错误一般是因为使用了1.6及以上的版本,我们来看一下1.6版本的maven坐标

<dependency>
    <groupId>javax.mail</groupId>
    <artifactId>javax.mail-api</artifactId>
    <version>1.6.1</version>
</dependency>

MailLogger是JavaMail的一部分,包含在Java EE环境里面,但是不包含在Java SE环境里面,出现这个错误很大的原因是在SE环境里面测试邮件的发送;javax.mail-api只适合编译,但是如果你实在要运行代码,必须完全实现JavaMail, 这也是为什么前面提到用1.4.7版本做测试。

2.4.6 发送邮件时报错com.sun.mail.smtp.SMTPSenderFailedException: 503 Error: need EHLO and AUTH first

从字面意思很容易看出来是因为没有设置认证参数。那么解决问题的办法就是设置认证参数。设置认证参数除了上面demo中的通过transport.connect(username,password)方法认证以外,还可以通过以下设置Authenticator对象的方式进行认证。

// 创建一个密码认证
Authenticator authenticator = new Authenticator() {
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication("fajianren@qq.com","wm*******jf");
    }
};

// 在使用时可以设置进session中
Session session = Session.getInstance(props, authenticator);
// 省略部分代码.......
// 然后在发送邮件的时候就不需要通过transport.connect(username,password)来认证了
// 直接使用
Transport.send(msg,msg.getAllRecipients());
2.4.7 设置邮件的Properties属性 有哪些?分别代表什么意思?

具体含义参见官方Java Doc,地址:https://javaee.github.io/javamail/docs/api/

官方分别在以下三个包级文档的Description中有三张列表,展示了所有的设置参数的key以及含义

  • com.sun.mail.smtp
  • com.sun.mail.imap
  • com.sun.mail.pop3

在这里插入图片描述

Reference

http://help.163.com/09/1223/14/5R7P6CJ600753VB8.html

https://javaee.github.io/javamail/docs/api/

https://github.com/javaee/javamail

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值