华南理工大学无线电爱好者协会软件小组Java学习笔记JavaEE 学习专题

Java Web 之 JavaMail

2017-01-18  本文已影响1318人  廖少少

本文包括:

1、名词解释

2、邮件收发过程

3、JavaMail 知识概要

4、发送一封符合 MIME 协议的 JavaMail

5、总结

6、MX记录与A记录

1、名词解释

> IMAP是什么?
> 
> IMAP,即Internet Message Access Protocol(互联网邮件访问协议),您可以通过这种协议从邮件服务器上获取邮件的信息、下载邮件等。IMAP与POP类似,都是一种邮件获取协议。


> IMAP和POP有什么区别?
>
> POP允许电子邮件客户端下载服务器上的邮件,但是您在电子邮件客户端的操作(如:移动邮件、标记已读等),这是不会反馈到服务器上的,比如:您通过电子邮件客户端收取了QQ邮箱中的3封邮件并移动到了其他文件夹,这些移动动作是不会反馈到服务器上的,也就是说,QQ邮箱服务器上的这些邮件是没有同时被移动的 。但是IMAP就不同了,电子邮件客户端的操作都会反馈到服务器上,您对邮件进行的操作(如:移动邮件、标记已读等),服务器上的邮件也会做相应的动作。也就是说,IMAP是“双向”的。
> 
> 同时,IMAP可以只下载邮件的主题,只有当您真正需要的时候,才会下载邮件的所有内容。

2、邮件收发过程

3、JavaMail 知识概要

  1. JavaMail 是一套邮件收发程序 API,编写 JavaMail 程序就是编写邮件客户端程序(类似于 outlook、foxmail 等邮件客户端)。

  2. JavaMail 开发需要类库 javamail 的API,还需要 Java Activation Framework (jaf) ,JavaMail 依赖于 jaf ,但在 MyEclipse 10 的环境下,不需要弄 jaf ,详情见下一点。

  3. 导入 jar 包

    mail.jar ( JDK6.0 以后官方 API 自带)

    • JDK6.0 以后开发,不需要导入 mail.jar 。
    • JDK5.0(包括) 之前开发,需要导入 mail.jar ,如果出现了问题,解决措施见下方。

    如果出现了如下问题:

    java.lang.NoClassDefFoundError:

    com/sun/mail/util/LineInputStream 异常

    原因: MyEclipse 新建工程自带的 javaee.jar 提供的 javaMail API 与 JavaMail的 jar 包发生冲突

    解决 :删除 javaee.jar 里面的 mail 目录和 activation 目录(如果想一劳永逸,去 javaee.jar 所在的硬盘位置把这两个目录删掉。

  4. JavaMail 邮件收发四个核心类

    1. Message 邮件

    2. Session 连接会话

    3. Transport 发送邮件

    4. Store 收取邮件

  5. 发送邮件编程

    1. 创建与邮件发送服务器连接Session

    2. 编写邮件内容 Message

      符合邮件内容格式RFC822文档 setFrom , setRecipients , setSubject , setText

    3. 使用 Transport 工具类 发送邮件

    4. demo :

       public void demo2() throws AddressException, MessagingException {
           // 步骤一 创建与邮件服务器连接会话
           Properties properties = new Properties();// 配置与服务器连接参数
           // 设置properties 属性
           properties.put("mail.transport.protocol", "smtp");
           properties.put("mail.smtp.host", "localhost"); // localhost是易邮邮件服务器的本地主机
           properties.put("mail.smtp.auth", "true");// 连接认证
           properties.put("mail.debug", "true");// 在控制台显示连接日志信息
           Session session = Session.getInstance(properties);// 与邮件服务器连接会话
      
           // 步骤二 编写Message
           MimeMessage message = new MimeMessage(session);// 代表一封邮件
           // from字段
           message.setFrom(new InternetAddress("aaa@estore.com"));
           // to 字段
           message.setRecipients(Message.RecipientType.TO, "bbb@estore.com");
           // subject字段
           message.setSubject("javamail发送简单邮件");
           // 邮件正文内容
           message.setText("使用javamail 可以发送简单邮件 ...");
      
           // 步骤三 使用Transport发送邮件
           Transport transport = session.getTransport();
           // 发邮件前进行身份校验
           transport.connect("aaa", "111");
           transport.sendMessage(message, message.getAllRecipients());
       }
      

4、发送一封符合 MIME 协议的 JavaMail

  1. MIME协议的引入:

    RFC822 文档只定义简单邮件格式,没有定义复杂邮件如何编写(前文的demo中邮件只包含简单的文本信息)。而 MIME 协议是 RFC822 文档的升级补充,完全支持 RFC822 文档。

  2. MIME协议的用法:

    对于一封复杂邮件,如果包含了多个不同的数据(例如图片、附件等等),MIME 协议规定:要将邮件体分成多个部分,每个部分使用分隔线进行分隔,并使用 Content-Type 头字段对数据的类型以及多个数据之间的关系进行描述。

  3. Content-Type 头字段(每段数据都需要)

    • 数据类型:

      • 格式:主类型/子类型。

      • 主类型包括:text、image、audio、video、application、message等。

      • 每个主类型下面又有多个子类型,例如text主类型包含plain、html、css、xml等子类型。

    • 数据的关系:

      1. multipart/mixed 用于携带附件

      2. multipart/related 内嵌图片,音乐

      3. multipart/alternative 防止兼容问题

        发送简历时,将简历文件与邮件正文关系设置为alternative,当邮件客户端如果支持简历格式,简历会显示在正文中,如果不支持简历格式,简历会以附件携带

  4. Content-Disposition 头字段(附件才需要)

    该头字段用于指定邮件阅读程序处理数据内容的方式。如果发送复杂邮件时需要携带附件,必须在附件部分,设置 Content-Disposition 头字段,它的值应该为 attachment 。

     Content-Dispostion : attachment;filename="1.bmp"
    
  5. Content-ID 头字段(内嵌图片、音乐才需要)

    该头字段为 "multipart/related" 组合消息中的内嵌资源指定一个唯一标识号。在邮件正文中通过

     ![](cid:唯一标识)
    

    引用内嵌图片和资源。

  6. 图解:

  7. JavaMail API中与MIME协议相关的类:

    • MimeMessage 类 ----- 代表整封邮件,包括MIME对象的消息头与MimeMultipart对象

    • MimeBodyPart 类 ---- 代表邮件中一个MIME消息

    • MimeMultiPart 类 ---- 代表一个或多个MIME消息组合而成的组合MIME消息

  8. JavaMail 怎样描述一封复杂邮件?

    • 判断邮件由几个部分组成,为每个部分设计 BodyPart ( MIME 消息)。

    • 将所有 BodyPart 组合起来变为 Multipart (注意:只有 BodyPart 与 BodyPart 之间才可以组合,MultiPart 不可以直接和 BodyPart 组合,需要将 MultiPart 转换为 BodyPart 后,再与 BodyPart 组合)。

    • 将最后合成的 MultiPart 交给 MimeMessage 对象。

  9. 内嵌图片的邮件 demo :

     // 内嵌图片邮件
     public void demo3() throws Exception {
         // 发送邮件需要三个步骤
         // 步骤一:创建Session
         Properties properties = new Properties();
         properties.put("mail.transport.protocol", "smtp");
         properties.put("mail.smtp.host", "localhost");
         properties.put("mail.smtp.auth", "true");// 连接认证
         properties.put("mail.debug", "true");// 在控制台显示连接日志信息
         Session session = Session.getInstance(properties);// 与邮件服务器连接会话
         // 步骤二:创建Message
         MimeMessage message = new MimeMessage(session);
         // 设置邮件头(简单邮件和复杂邮件相同
         message.setFrom(new InternetAddress("aaa@estore.com"));
         message.setRecipients(Message.RecipientType.TO, "bbb@estore.com");
         message.setSubject("javamail发送内嵌图片邮件");
         // 设置邮件体(简单邮件和复杂邮件区别 就在于邮件体)
         MimeBodyPart pic = new MimeBodyPart();// 图片
         // 链接数据文件
         pic.setDataHandler(new DataHandler(new FileDataSource("beauty.jpg")));
    
         // 也可以用下面三行代码代替“链接数据文件”的操作,但明显更繁琐
         // DataSource dataSource = new FileDataSource("beauty.jpg");
         // DataHandler dataHandler = new DataHandler(dataSource);
         // pic.setDataHandler(dataHandler);
    
         // 设置一个唯一标识(用于在正文中引入)
         pic.setContentID("mypic");
    
         MimeBodyPart content = new MimeBodyPart(); // 邮件正文
         content.setContent("<h1>美女图片</h1>![](cid:mypic)",
                 "text/html;charset=utf-8");
    
         // 将两个BodyPart整合
         MimeMultipart mimeMultipart = new MimeMultipart();
         mimeMultipart.addBodyPart(pic);
         mimeMultipart.addBodyPart(content);
    
         // 设置关系
         mimeMultipart.setSubType("related");
         
         // 将MimeMultiPart发给MimeMessage
         message.setContent(mimeMultipart);
         // message.writeTo(System.out); // 将该邮件所包含的信息打印到控制台
    
         // 步骤三:Transport发送邮件
         Transport transport = session.getTransport();
         transport.connect("aaa", "111");
         transport.sendMessage(message, message.getAllRecipients());
     }
    
  10. 包含附件的邮件 demo :

    // 携带附件邮件
    public void demo4() throws Exception {
        // 步骤一:创建Session
        Properties properties = new Properties();
        properties.put("mail.transport.protocol", "smtp");
        properties.put("mail.smtp.host", "localhost");
        properties.put("mail.smtp.auth", "true");// 连接认证
        properties.put("mail.debug", "true");// 在控制台显示连接日志信息
        Session session = Session.getInstance(properties);// 与邮件服务器连接会话
    
        // 步骤二:创建Message
        MimeMessage message = new MimeMessage(session);
        // 设置邮件头(简单邮件和复杂邮件相同
        message.setFrom(new InternetAddress("aaa@estore.com"));
        message.setRecipients(Message.RecipientType.TO, "bbb@estore.com");
        message.setSubject("javamail发送携带附件邮件");
        // 设置邮件体
        MimeBodyPart attachment = new MimeBodyPart();
        // 链接数据文件
        attachment.setDataHandler(new DataHandler(new FileDataSource(
                "大嘴巴 - maybe的机率.mp3")));
    
        // 因中文附件名编码的问题,会产生乱码,必须使用 JavaMail 提供的工具类 MimeUtility 来包装中文字符
        // 设置 filename 可自动生成: Content-Disposition:attachment;filename=xxx 
        attachment.setFileName(MimeUtility.encodeText("大嘴巴 - maybe的机率.mp3")); 
    
        MimeBodyPart content = new MimeBodyPart();
        content.setContent("<h1>附件是首好听的歌曲!</h1>", "text/html;charset=utf-8");
    
        MimeMultipart mimeMultipart = new MimeMultipart();
        mimeMultipart.addBodyPart(attachment);
        mimeMultipart.addBodyPart(content);
        mimeMultipart.setSubType("mixed");
    
        message.setContent(mimeMultipart);
    
        // 步骤三:Transport发送邮件
        Transport transport = session.getTransport();
        transport.connect("aaa", "111");
        transport.sendMessage(message, message.getAllRecipients());
    }
    
  11. 既内嵌图片又包含附件的邮件 demo (工具类 MailUtils.java 见 第12 点):

    // 编写最复杂一封邮件,既要内嵌图片,也要携带附件
    public void demo5() throws Exception {
        // 步骤一 创建Session
        Session session = MailUtils.createSession();
    
        // 步骤二 编写邮件Message
        MimeMessage message = new MimeMessage(session);
        // 设置邮件头(简单邮件和复杂邮件相同
        message.setFrom(new InternetAddress("aaa@estore.com"));
        message.setRecipients(Message.RecipientType.TO, "bbb@estore.com");
        message.setSubject("javamail发送最复杂邮件");
    
        // 设置邮件体
        MimeBodyPart pic = new MimeBodyPart();
        pic.setDataHandler(new DataHandler(new FileDataSource("beauty.jpg")));
        pic.setContentID("myimg");// 内嵌图片唯一标识
    
        MimeBodyPart attachment = new MimeBodyPart();
        attachment.setDataHandler(new DataHandler(new FileDataSource(
                "大嘴巴 - maybe的机率.mp3")));
        attachment.setFileName(MimeUtility.encodeText("大嘴巴 - maybe的机率.mp3"));// 附件解决中文路乱码
    
        MimeBodyPart content = new MimeBodyPart();
        content.setContent("<h1>最复杂邮件,有图片,有附件</h1>![](cid:myimg)",
                "text/html;charset=utf-8");
    
        // 整合
        MimeMultipart mp1 = new MimeMultipart();
        mp1.addBodyPart(pic);
        mp1.addBodyPart(content);
        mp1.setSubType("related");
    
        MimeBodyPart temp = new MimeBodyPart();// 将multipart转换bodypart可以和其它bodypart一起合并
        temp.setContent(mp1);
    
        MimeMultipart mp2 = new MimeMultipart();
        mp2.addBodyPart(attachment);
        mp2.addBodyPart(temp);
        mp2.setSubType("mixed");
    
        message.setContent(mp2);
    
        // 步骤三 发送邮件 Transport
        MailUtils.sendMail(session, message);
    }
    
  12. MailUtils.java (抽出公共代码,编写成为一个工具类,很实用的思想):

    public class MailUtils {
        private static String targetSMTP = "localhost";// SMTP服务器地址
        private static String user = "aaa"; // 发件账户
        private static String pass = "111"; // 发件密码
    
        // 创建邮件服务器链接会话
        public static Session createSession() {
            Properties properties = new Properties();
            properties.put("mail.transport.protocol", "smtp");
            properties.put("mail.smtp.host", targetSMTP);
            properties.put("mail.smtp.auth", "true");// 连接认证
            properties.put("mail.debug", "true");// 在控制台显示连接日志信息
            Session session = Session.getInstance(properties);// 与邮件服务器连接会话
    
            return session;
        }
    
        // 发送邮件
        public static void sendMail(Session session, Message message)
                throws Exception {
            Transport transport = session.getTransport();
            transport.connect(user, pass);
            transport.sendMessage(message, message.getAllRecipients());
        }
    }
    

5、总结

6、MX 记录与 A 记录

上一篇下一篇

猜你喜欢

热点阅读