JavaMail发送邮件详解

2,058 阅读8分钟

JavaMail介绍

          JavaMail 是sun公司(现以被甲骨文收购)为方便Java开发人员在应用程序中实现邮件发送和接收功能而提供的一套标准开发包,它支持一些常用的邮件协议,如前面所讲的SMTP,POP3,IMAP,还有MIME等。我们在使用JavaMail API 编写邮件时,无须考虑邮件的底层实现细节,只要调用JavaMail 开发包中相应的API类就可以了。
         JavaMail 下载地址: https://github.com/javaee/javamail/releases
       下载这个版本的JavaMail,包含了SMTP, IMAP, 和 POP3 协议的实现


JavaMail API

          JavaMail API 按照功能可以划分为如下三大类:

             ①、创建和解析邮件的API
             ②、发送邮件的API
             ③、接收邮件的API
  以上三种类型的API在JavaMail 中由多个类组成,但是主要有四个核心类,我们在编写程序时,记住这四个核心类,就很容易编写出Java邮件处理程序


 ①、Message 类:javax.mail.Message 类是创建和解析邮件的核心 API,这是一个抽象类,通常使用它的子类javax.mail.internet.MimeMessage 类。它的实例对象表示一份电子邮件。客户端程序发送邮件时,首先使用创建邮件的 JavaMail API 创建出封装了邮件数据的 Message 对象,然后把这个对象传递给邮件发送API(Transport 类) 发送。客户端程序接收邮件时,邮件接收API把接收到的邮件数据封装在Message 类的实例中,客户端程序在使用邮件解析API从这个对象中解析收到的邮件数据。


②、Transport 类:javax.mail.Transport 类是发送邮件的核心API 类,它的实例对象代表实现了某个邮件发送协议的邮件发送对象,例如 SMTP 协议,客户端程序创建好 Message 对象后,只需要使用邮件发送API 得到 Transport 对象,然后把 Message 对象传递给 Transport 对象,并调用它的发送方法,就可以把邮件发送给指定的 SMTP 服务器。

  ③、Store 类:javax.mail.Store 类是接收邮件的核心 API 类,它的实例对象代表实现了某个邮件接收协议的邮件接收对象,例如 POP3 协议,客户端程序接收邮件时,只需要使用邮件接收 API 得到 Store 对象,然后调用 Store 对象的接收方法,就可以从指定的 POP3 服务器获得邮件数据,并把这些邮件数据封装到表示邮件的 Message 对象中。

  ④、Session 类:javax.mail.Session 类用于定义整个应用程序所需的环境信息,以及收集客户端与邮件服务器建立网络连接的会话信息,例如邮件服务器的主机名、端口号、采用的邮件发送和接收协议等。Session 对象根据这些信息构建用于邮件收发的 Transport 和 Store 对象,以及为客户端创建 Message 对象时提供信息支持

使用JavaMail发送简单的纯文本右键

import javax.mail.*;import javax.mail.internet.InternetAddress;import javax.mail.internet.MimeMessage;import com.sun.mail.util.MailSSLSocketFactory;import java.security.GeneralSecurityException;import java.util.Properties;public class MailUtil {	 /**     * 发送邮件     * @param to 给谁发     * @param text 发送内容     */    public static void send_mail(String to,String text) throws MessagingException {        //创建连接对象 连接到邮件服务器        Properties properties = new Properties();        //设置发送邮件的基本参数        //发送邮件服务器        properties.put("mail.smtp.host", "smtp.qq.com");//      properties.put("mail.smtp.host", "smtp.exmail.qq.com");        //发送端口        properties.put("mail.smtp.port", "25");        properties.put("mail.smtp.auth", "true");        properties.put("mail.smtp.starttls.enable","true");//使用 STARTTLS安全连接  //        properties.put("mail.transport.protocol", "smtp");        //设置发送邮件的账号和密码        Session session = Session.getInstance(properties, new Authenticator() {            @Override            protected PasswordAuthentication getPasswordAuthentication() {                //两个参数分别是发送邮件的账户和密码//              return new PasswordAuthentication("admin@huic188.com","这里写你的账号的密码");                return new PasswordAuthentication("2664547804@qq.com","jszvqlebcplyeaih");            }        });        //创建邮件对象        Message message = new MimeMessage(session);        //设置发件人//      message.setFrom(new InternetAddress("admin@huic188.com"));        message.setFrom(new InternetAddress("2664547804@qq.com"));        //设置收件人        message.setRecipient(Message.RecipientType.TO,new InternetAddress(to));        //设置主题        message.setSubject("这是一份测试邮件");        //设置邮件正文  第二个参数是邮件发送的类型        message.setContent(text,"text/html;charset=UTF-8");        //发送一封邮件        Transport.send(message);    }}import javax.mail.MessagingException;public class Text {	public static void main(String[] args) {		 try {	            MailUtil.send_mail("1733860899@qq.com", "测试");	            System.out.println("邮件发送成功!");	        } catch (MessagingException e) {	            e.printStackTrace();	        }	}}

邮件发送问题

  • 发件人的邮箱账户名和密码:有的邮箱设置了独立密码,还有的必须用授权码登录(qq邮箱)blog.csdn.net/caiqirui/ar…(可以参考这篇博文)
  • 发件人的SMTP服务器地址:一般是 smtp.xxx.com,比如163邮箱是smtp.163.com,qq邮箱是smtp.qq.com
  • 有可能你收件人地址,发件人地址等信息都正确了,控制台也打印了正确的信息,但是在收件箱就是收不到信息。这是因为可能收件箱服务器拒收了你发的邮件(比如认为你的邮件是广告),这时候可能在垃圾箱里能找到,可能找不到。解决办法是重复的邮件内容不要多次发送,或者更换收件箱试试


使用JavaMail接收邮件

    接受邮件的用处不多,这里简单给出一个实例

import java.util.Properties;import javax.mail.Address;import javax.mail.Folder;import javax.mail.Message;import javax.mail.Session;import javax.mail.Store; public class RecipientMail {    //收件人地址    public static String recipientAddress = "xxx@163.com";    //收件人账户名    public static String recipientAccount = "xxx";    //收件人账户密码    public static String recipientPassword = "xxx";         public static void main(String[] args) throws Exception {        //1、连接邮件服务器的参数配置        Properties props = new Properties();        //设置传输协议        props.setProperty("mail.store.protocol", "pop3");        //设置收件人的POP3服务器        props.setProperty("mail.pop3.host", "pop3.163.com");        //2、创建定义整个应用程序所需的环境信息的 Session 对象        Session session = Session.getInstance(props);        //设置调试信息在控制台打印出来        //session.setDebug(true);                 Store store = session.getStore("pop3");        //连接收件人POP3服务器        store.connect("pop3.163.com", recipientAccount, recipientPassword);        //获得用户的邮件账户,注意通过pop3协议获取某个邮件夹的名称只能为inbox        Folder folder = store.getFolder("inbox");        //设置对邮件账户的访问权限        folder.open(Folder.READ_WRITE);                 //得到邮件账户的所有邮件信息        Message [] messages = folder.getMessages();        for(int i = 0 ; i < messages.length ; i++){            //获得邮件主题            String subject = messages[i].getSubject();            //获得邮件发件人            Address[] from = messages[i].getFrom();            //获取邮件内容(包含邮件内容的html代码)            String content = (String) messages[i].getContent();        }                 //关闭邮件夹对象        folder.close();        //关闭连接对象        store.close();    }}


使用JavaMail发送带图片、附件的邮件


import java.util.Date;import java.util.Properties; 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.AddressException;import javax.mail.internet.InternetAddress;import javax.mail.internet.MimeBodyPart;import javax.mail.internet.MimeMessage;import javax.mail.internet.MimeMultipart;import javax.mail.internet.MimeUtility; public class SendMailText_Picture_Enclosure {    //发件人地址    public static String senderAddress = "xxx@163.com";    //收件人地址    public static String recipientAddress = "xxx@qq.com";    //发件人账户名    public static String senderAccount = "xxx";    //发件人账户密码    public static String senderPassword = "xxx";         public static void main(String[] args) throws Exception {        //1、连接邮件服务器的参数配置        Properties props = new Properties();        //设置用户的认证方式        props.setProperty("mail.smtp.auth", "true");        //设置传输协议        props.setProperty("mail.transport.protocol", "smtp");        //设置发件人的SMTP服务器地址        props.setProperty("mail.smtp.host", "smtp.163.com");        //2、创建定义整个应用程序所需的环境信息的 Session 对象        Session session = Session.getInstance(props);        //设置调试信息在控制台打印出来        session.setDebug(true);        //3、创建邮件的实例对象        Message msg = getMimeMessage(session);        //4、根据session对象获取邮件传输对象Transport        Transport transport = session.getTransport();        //设置发件人的账户名和密码        transport.connect(senderAccount, senderPassword);        //发送邮件,并发送到所有收件人地址,message.getAllRecipients() 获取到的是在创建邮件对象时添加的所有收件人, 抄送人, 密送人        transport.sendMessage(msg,msg.getAllRecipients());                 //5、关闭邮件连接        transport.close();    }         /**     * 获得创建一封邮件的实例对象     * @param session     * @return     * @throws MessagingException     * @throws AddressException     */    public static MimeMessage getMimeMessage(Session session) throws Exception{        //1.创建一封邮件的实例对象        MimeMessage msg = new MimeMessage(session);        //2.设置发件人地址        msg.setFrom(new InternetAddress(senderAddress));        /**         * 3.设置收件人地址(可以增加多个收件人、抄送、密送),即下面这一行代码书写多行         * MimeMessage.RecipientType.TO:发送         * MimeMessage.RecipientType.CC:抄送         * MimeMessage.RecipientType.BCC:密送         */        msg.setRecipient(MimeMessage.RecipientType.TO,new InternetAddress(recipientAddress));        //4.设置邮件主题        msg.setSubject("邮件主题(包含图片和附件)","UTF-8");                 //下面是设置邮件正文        //msg.setContent("简单的纯文本邮件!", "text/html;charset=UTF-8");                 // 5. 创建图片"节点"        MimeBodyPart image = new MimeBodyPart();        // 读取本地文件        DataHandler dh = new DataHandler(new FileDataSource("src\\mailTestPic.png"));        // 将图片数据添加到"节点"        image.setDataHandler(dh);        // 为"节点"设置一个唯一编号(在文本"节点"将引用该ID)        image.setContentID("mailTestPic");                     // 6. 创建文本"节点"        MimeBodyPart text = new MimeBodyPart();        // 这里添加图片的方式是将整个图片包含到邮件内容中, 实际上也可以以 http 链接的形式添加网络图片        text.setContent("这是一张图片<br/><a href='http://www.cnblogs.com/ysocean/p/7666061.html'><img src='cid:mailTestPic'/></a>", "text/html;charset=UTF-8");                 // 7. (文本+图片)设置 文本 和 图片"节点"的关系(将 文本 和 图片"节点"合成一个混合"节点")        MimeMultipart mm_text_image = new MimeMultipart();        mm_text_image.addBodyPart(text);        mm_text_image.addBodyPart(image);        mm_text_image.setSubType("related");    // 关联关系                 // 8. 将 文本+图片 的混合"节点"封装成一个普通"节点"        // 最终添加到邮件的 Content 是由多个 BodyPart 组成的 Multipart, 所以我们需要的是 BodyPart,        // 上面的 mailTestPic 并非 BodyPart, 所有要把 mm_text_image 封装成一个 BodyPart        MimeBodyPart text_image = new MimeBodyPart();        text_image.setContent(mm_text_image);                 // 9. 创建附件"节点"        MimeBodyPart attachment = new MimeBodyPart();        // 读取本地文件        DataHandler dh2 = new DataHandler(new FileDataSource("src\\mailTestDoc.docx"));        // 将附件数据添加到"节点"        attachment.setDataHandler(dh2);        // 设置附件的文件名(需要编码)        attachment.setFileName(MimeUtility.encodeText(dh2.getName()));                        // 10. 设置(文本+图片)和 附件 的关系(合成一个大的混合"节点" / Multipart )        MimeMultipart mm = new MimeMultipart();        mm.addBodyPart(text_image);        mm.addBodyPart(attachment);     // 如果有多个附件,可以创建多个多次添加        mm.setSubType("mixed");         // 混合关系         // 11. 设置整个邮件的关系(将最终的混合"节点"作为邮件的内容添加到邮件对象)        msg.setContent(mm);        //设置邮件的发送时间,默认立即发送        msg.setSentDate(new Date());                 return msg;    } }


常用邮件协议介绍

SMTP协议(Simple Mail Tranfer Protocol)
  • 端口号:25,定义邮件客户端(UA,User Agent)与SMTP服务器之间,以及两天SMTP服务器之间通信规则
POP3协议(Post Office Protocol)
  • 端口号:110邮局协议,定义了客户端软件与POP3服务器的通信规则
IMAP协议(Internet Message Access Protocol)
  • Internet消息访问协议,它是POP3协议的一种扩展,也是定义邮件客户端软件与邮件服务器通信规则