zoukankan      html  css  js  c++  java
  • javamail 详细实现(转发)

    本文档分三个部分,第一部分简要简单介绍了JavaMail,第二部分用一个完整的JavaMail的实例(API)详解javamail,
    最后写测试javamail API的例子和两个使用javamail中的重要技术,一个是介绍如何用velocity构建javamail的模板,
    一个是如何读取properties文件。


    javamail 简介:
       JavaMail是Sun发布的用来处理email的API。它可以方便地执行一些常用的邮件传输。

      虽然JavaMail是Sun的API之一,但它目前还没有被加在标准的java开发工具包中
    (Java Development Kit),这就意味着你在使用前必须另外下载JavaMail文件。除此以外,
    你还需要有Sun的JavaBeans Activation Framework (JAF)。JavaBeans Activation Framework
    的运行很复杂,在这里简单的说就是JavaMail的运行必须得依赖于它的支持。在Windows 2000下
    使用需要指定这些文件的路径,在其它的操作系统上也类似。


    Java Mail API是Java对电子邮件处理的延伸,它提供和通讯协定无关的 Java解决方案,
    可以处理各种email格式,包括IMAP、POP、SMTP,以及MI ME,和其他和Internet相关的讯息通讯协
    点击在新窗口中浏览此图片

    javamail API实例:
        在写实例前  我们需要载两个jar包,一个是javamail.jar和activation.jar,这里有个要说明下,
    如果你用的是jdk1.6的版本,那么可以不用activation.jar,如果是jdk1.6一下的版本要用activation.jar,
    因为jdk1.6集成了activation.jar。 你可以到  http://java.sun.com/products/javamail/downloads/index.html 去下载
        说了那么多  下面就是我们的具体javamail的代码了  SendMail.java

    import org.apache.velocity.Template;
    import org.apache.velocity.VelocityContext;
    import org.apache.velocity.app.VelocityEngine;
    import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;

    import javax.activation.DataHandler;
    import javax.activation.FileDataSource;
    import javax.mail.*;
    import javax.mail.internet.InternetAddress;
    import javax.mail.internet.MimeBodyPart;
    import javax.mail.internet.MimeMessage;
    import javax.mail.internet.MimeMultipart;
    import java.io.StringWriter;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Properties;


    class SendMail {

        private MimeMessage mimeMsg;     //MIME邮件对象
        private Session session;         //邮件会话对象
        private Properties props;        //系统属性
        private boolean needAuth = false;   //smtp是否需要认证
        private String username = "";       //smtp认证用户名和密码
        private String password = "";
        private String agentIp = "";
        private String agentPort = "";
        private Multipart mp;
        private static final String CHAR_SET = "UTF-8";     //Multipart对象,邮件内容,标题,附件等内容均添加到其中后再生成MimeMessage对象

        
        public SendMail() {
        }

        /**
         * this construct has no agent
         *
         * @param smtp
         */
        public SendMail(String smtp) {
            setSmtpHost(smtp);
            createMimeMessage();
        }

        /**
         * this construct has agent
         *
         * @param smtp
         * @param agentIp
         * @param agentPort
         */
        public SendMail(String smtp, String agentIp, String agentPort) {
            this.agentIp = agentIp;
            this.agentPort = agentPort;
            setSmtpHost(smtp);
            createMimeMessage();
        }

        /**
         * it is set the hostName
         *
         * @param hostName String
         */
        public void setSmtpHost(String hostName) {
            if (props == null)
                props = System.getProperties();                //获得系统属性对象
            props.put("mail.smtp.host", hostName);               //设置SMTP主机

            if (null != this.agentIp && this.agentIp.length() != 0 && !this.agentIp.equals("0")) {
                props.put("http.proxyHost", this.agentIp);
            }

            if (null != this.agentPort && this.agentPort.length() != 0 && !this.agentPort.equals("0")) {
                props.put("http.proxyPort", this.agentPort);
            }
        }

        /**
         * creete MIME mail object
         *
         * @return boolean
         */
        public boolean createMimeMessage() {
            try {
                session = Session.getDefaultInstance(props, null);        //获得邮件会话对象
            }
            catch (Exception e) {
                return false;
            }

            try {
                mimeMsg = new MimeMessage(session);                       //创建MIME邮件对象
                mp = new MimeMultipart();
                return true;
            }
            catch (Exception e) {
                System.err.println("create MIME mail object failure" + e);
                return false;
            }
        }


        /**
         * set identity of tsmtp validation
         *
         * @param needAuth boolean
         */
        public void setNeedAuth(boolean needAuth) {
            if (props == null) props = System.getProperties();

            if (needAuth) {
                props.put("mail.smtp.auth", "true");
            } else {
                props.put("mail.smtp.auth", "false");
            }
        }


        /**
         * set user name and password
         *
         * @param name boolean
         * @param pass boolean
         */
        public void setNamePass(String name, String pass) {
            username = name;
            password = pass;
        }


        /**
         * set subject of mail
         *
         * @param subject
         * @return boolean
         */
        public boolean setSubject(String subject) {
            try {
                mimeMsg.setSubject(subject);
                return true;
            }
            catch (Exception e) {
                System.err.println("set mail subject is error " + e);
                return false;
            }
        }


        /**
         * set the content of mail,the charset of content shoule be UTF-8
         *
         * @param body
         * @return boolean
         */
        public boolean setBody(String body) {
            try {
                BodyPart bp = new MimeBodyPart();
                bp.setContent("" + body, "text/html;charset=" + CHAR_SET);
                mp.addBodyPart(bp);
                return true;
            }
            catch (Exception e) {
                System.err.println("set mail body is error" + e);
                return false;
            }
        }


        /**
         * add the attachments, "filePath" should be real local path of a file
         *
         * @param filePath
         * @return boolean
         */
        public boolean addFileAffix(String filePath) {
            try {
                BodyPart bp = new MimeBodyPart();
                FileDataSource fileds = new FileDataSource(filePath);
                bp.setDataHandler(new DataHandler(fileds));
                bp.setFileName(fileds.getName());
                mp.addBodyPart(bp);
                return true;
            }
            catch (Exception e) {
                System.err.println("Affix" + filePath + "accour error" + e);
                return false;
            }
        }


        /**
         * set the from of mail
         *
         * @param from
         * @return boolean
         */
        public boolean setFrom(String from) {
            try {
                mimeMsg.setFrom(new InternetAddress(from));
                return true;
            }
            catch (Exception e) {
                System.out.println("set sender is error" + e);
                return false;
            }
        }


        /**
         * set the send to of mail
         *
         * @param to
         * @return boolean
         */
        public boolean setTo(String to) {
            if (to == null) return false;
            try {
                mimeMsg.setRecipients(Message.RecipientType.TO, (Address[]) InternetAddress.parse(to));
                return true;
            }
            catch (Exception e) {
                System.out.println("reciever's address is error" + e);
                return false;
            }

        }

        /**
         * set the copy to of mail
         *
         * @param copyto
         * @return boolean
         */
        public boolean setCopyTo(String copyto) {
            if (copyto == null) return false;
            try {
                mimeMsg.setRecipients(Message.RecipientType.CC, (Address[]) InternetAddress.parse(copyto));
                return true;
            }
            catch (Exception e) {
                return false;
            }
        }

        /**
         * set the bcc of mail
         *
         * @param bccto
         * @return boolean
         */
        public boolean setBccTo(String bccto) {
            if (bccto == null) return false;
            try {
                mimeMsg.setRecipients(Message.RecipientType.BCC, (Address[]) InternetAddress.parse(bccto));
                return true;
            }
            catch (Exception e) {
                return false;
            }
        }


        /**
         * put the mail send out
         *
         * @return boolean
         */
        public boolean sendout() {
            try {
                mimeMsg.setContent(mp);
                mimeMsg.saveChanges();
                Session mailSession = Session.getInstance(props, null);
                Transport transport = mailSession.getTransport("smtp");
                transport.connect((String) props.get("mail.smtp.host"), username, password);
                transport.sendMessage(mimeMsg, mimeMsg.getAllRecipients());
                transport.close();
                return true;
            }
            catch (Exception e) {
                System.err.println("send fail ");
                System.err.println(e + " ");
                return false;
            }
        }

    那么我们的API就写完了,下面是几点要重要说明的
    1.一定是创建Session。

    如果,你是发送邮件那么 接下来你需要创建你要发送的邮件,也就是一个 message对象。

    现在的message对象好像一张白纸,现在就需要我们来添加内容啦message.setContent()可以帮你搞定。

    然后我们需要写“信封” message.setFrom(); message.addRecipient();...


    哈哈,都搞定了,然后就可以寄出去了
    Transport transport = session.getTransport("smtp");
    transport.sendMessage(message, message.getAllRecipients());
    transport.close();

    好了,邮件发送完成了:),嘻嘻当然,这里有些过于乐观了,在发送的过程中我们还有遇到其它一些问题,
    比如,认证,地址等。下面就JavaMail几个重要的类进行一下介绍

    首先是session类:

    Session 定义了一个基本的邮件会话,任何工作都是基于这个Session的。Session 对象需要一个
    java.util.Properties 对象来得到类似 邮件服务器,用户名,密码这样的信息。

    Session 的构造函数是私有的,你可以通过 getDefaultInstance() 方法来取得一个单一的可以被共享的默认session 如:

      Properties props = new Properties();
      // 填写一些信息
      Session session = Session.getDefaultInstance(props,null);

    或者,你可以使用 getInstance() 方法来创建一个唯一的 session如:

      Properties props = new Properties();
      // 填写一些信息
      Session session = Session.getInstance(props,null);

    在这两种方法中 其中的 null 参数是一个 Authenticator 对象,在这里没有被使用的,所以就是null

    在大多数案例中,使用一个共享session 已经做够了。

    Message类

    一 旦你创建了Session对象,那么下面要做的就是创建 message 来发送。Message 是一个抽象类,在大部分应用中你可以使用它的子类 javax.mail.internet.MimeMessage 。MimeMessage 是一个理解在不同RFCs中定义的MIME类型以及headers的e-mail message 。 Message headers 必须使用 US-ASCII 字符集。

    可以用如下的方法创建一个 Message
      MimeMessage message = new MimeMessage(session);
    我们注意到,这里需要用session对象作为构造函数的参数。当然,还有其它的构造函数,比如从用RFC822格式化过的输入流来创建message。

    一旦你得到了 message ,你就可以来设置它的各个部分(parts)。设置内容(content)的基本的机制是使用setContent() 方法。

      message.setContent("Email Content. ","text/plain");

    如果,你能够明确你的使用MimeMessage来创建message 并且只是使用普通的文本(plain text) 那么你也可以使用 setText() 方法,setTest()方法只需要设置具体的内容,它默认的MIME类型是 text/plain
      
      message.setText("Email Content. ");

    对于普通文本类型的邮件,有一种机制是首选( message.setText("Email Content. "))的设置内容的方法。如果要创建其它类型的message ,比如 HTML类型的message  那么还是需要使用前者 ( message.setContent("Email Content. ","text/html"); )

    设置主题(subject ),使用setSubject() 方法
      
      message.setSubject(" Subject ");


    Address 类

    当 你已经创建了Session 以及 Message,并且已经为message 填充了内容,那么接下来要做的就是给你的邮件添加一个地址(Address)。 就像Message一样,Address也是一个抽象类,我们可以使用它 的一个子类javax.mail.internet.InternetAddress 。

    创建一个地址非常简单

      Address address = new InternetAddress("suixin@asiainfo.com");

    如果,你希望在出现邮件地址的地方出现一个名称,那么你只需要再多传递一个参数。

      Address address = new InternetAddress("suixin@asiainfo.com","Steve");


    你需要为 message 的from以及 to 字段创建address对象。为了识别发送者,你需要使用setFrom() 和 setReplyTo() 方法。
      
      messge.setFrom(address);

    如果你的message 需要显示多个 from 地址,可以使用 addFrom() 方法

      Address address[] = {....};
      message.addFrom(address);

    为了辨识message 的收件人,你需要使用 setRecipient() 方法。这个方法除了address参数之外,还需要一个Message.RecipientType 。

      message.addRecipient(type,address);

    Message.RecipientType有几个预先定义好的类型

    Message.RecipientType.TO  收件人
    Message.RecipientType.CC  抄送
    Message.RecipientType.BCC  暗送

    如果你的一封邮件,需要发送给你的老师,并还要给你的几个同学,那么你可以这样

    Address toAddress = new InternetAddress("teacher@17288.com");
    Address[] ccAddress = {new InternetAddress("schoolmate1@17288.com"),new InternetAddress("schoolmate2@17288.com")};

    message.addRecipient(Message.RecipientType.To, toAddress);
    message.addRecipient(Message.RecipientType.CC, ccAddress);

    JavaMail 没有提供电子邮件地址有效性的检测。这些超越了JavaMail API的范围。


    Authenticator 类


    通过Authenticator设置用户名、密码,来访问受保护的资源,这里的资源一般指的是邮件服务器。

    Authenticator也是一个抽象类,你需要自己编写子类已备应用。你需要实现getPasswordAuthentication()方法,并返 回一个PasswordAuthentication实例。你必须在 session被创建时, 注册你的 Authenticator。这样,当需要进行认证是,你的Authenticator就可以被得到。

      Properties props = new Properties();
      //设置属性
      Authenticator auth = new YourAuthenticator();
      Session session = Session.getDefaultInstance(props, auth);

    Transport 类:

    发送消息最后的一步就是使用Transport类,你可以通过两种方法来进行发送。
    Transport 是一个抽象类,你可以调用它静态的send() 方法来发送

      Transport.send(message);

    或者,你可以为你使用的协议从session中取得一个指定的实例,

      Transport transport = session.getTransport("smtp");
      transport.sendMessage(message, message.getAllRecipients());
      transport.close();

    下面我们写一个测试类,来测试我们上面的方法

    TestSendMail.java

    import java.util.Properties;
    import java.io.InputStream;

    /**
    *
    *To test send mail with tamplate
    */
    public class TestSendMail {
         public static void main(String[] args) throws Exception {

            Properties pro = new Properties();
            InputStream is = TestSendMail.class.getClassLoader().getResourceAsStream("mail.properties");
            pro.load(is);

            SendMail themail = new SendMail(pro.getProperty("mail.smtp"), pro.getProperty("mail.agentIp"), pro.getProperty("mail.agentPort"));
            themail.setNeedAuth(true);
            themail.setNamePass(pro.getProperty("mail.name"), pro.getProperty("mail.password"));
            
            if(null != pro.getProperty("mail.subject").toString() && pro.getProperty("mail.subject").toString() != ""){
                themail.setSubject(pro.getProperty("mail.subject").toString());
            }

            if(null != pro.getProperty("mail.content").toString() && pro.getProperty("mail.content").toString() != ""){
               themail.setBody(pro.getProperty("mail.content"));
            }

            if(null != pro.getProperty("mail.from").toString() && pro.getProperty("mail.from").toString() != ""){
               themail.setFrom(pro.getProperty("mail.from"));
            }

            if(null != pro.getProperty("mail.to").toString() && pro.getProperty("mail.to").toString() != ""){
               themail.setTo(pro.getProperty("mail.to"));
            }

            if(null != pro.getProperty("mail.cc").toString() && pro.getProperty("mail.cc").toString() != ""){
               themail.setCopyTo(pro.getProperty("mail.cc").toString());
            }

            if(null != pro.getProperty("mail.bcc").toString() && pro.getProperty("mail.bcc").toString() != ""){
               themail.setBccTo(pro.getProperty("mail.bcc").toString());
            }

            if(null != pro.getProperty("mail.affixFile")){
               themail.addFileAffix(pro.getProperty("mail.affixFile"));
            }
            
            themail.sendout();
      }
    }

    注意为了方便我们把数据都放在一个perproties文件里的,mail.properties这个文件你可以放在任意编译路径下,都可以读到

    下面是perproties的内容


    mail.smtp = mail.google.com  //mail的服务
    mail.name = servicetest      //邮件的用户名
    mail.password = testservice  //邮件的密码
    mail.agentIp = 10.0.1.8      //代理服务器的Ip
    mail.agentPort = 8080        //代理服务器的端口号
    mail.from = timoth.wang@dextrys.com     // 邮件发送者
    mail.to = timoth.wang@dextrys.com        // 邮件接收者
    mail.cc = andy.zhao@dextrys.com ,lexy.chen@dextrys.com , wg1191@163.com  //抄送
    mail.bcc = steven.lv@dextrys.com                    //暗送
    mail.subject = this is the subject                  //主题
    mail.affixFile = D:\wg\test.css                    //附件的路径和文件名
    mail.content = <a href=http://www.google.com>google</a>       //邮件内容

    下面将介绍怎样用邮件模板发邮件
    我们用velocity这个优秀的框架来实现我们的mail模板
    下面我们对velocity 做个简单的认识

    Velocity是一个基于java的模板引擎(template engine)。它允许任何人仅仅简单的使用模板语言
    (template language)来引用由java代码定义的对象。
    当Velocity应用于web开发时,界面设计人员可以和java程序开发人员同步开发一个遵循MVC架构的web站点,
    也就是说,页面设计人员可以只关注页面的显示效果,而由java程序开发人员关注业务逻辑编码。
    Velocity将java代码从web页面中分离出来,这样为web站点的长期维护提供了便利,同时也为我们在JSP和PHP之
    外又提供了一种可选的方案。

    想了解更多,建议去googl一下,因为我们的主要目的是javamail
    那好,我们就开始我们的javamail模板之旅吧
    首先我们要下载一个velocity的Jar包才能支持velocity框架  大家可以到这里下 http://velocity.apache.org/download.cgi
    建议下1.5版本的

    OK ,那么既然是模板我们就先设计一下我们的邮件模板吧,velocity所以的模板是一.vm作为后缀名的  所以我们的mailTemplate.vm
    就是我们的模板文件吧  下面是内容:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <title>vehicle ceo</title>


      </head>
        <body  >
        
         Hi  $to


           Welcome to  $site  


           $content          


           $test              




          from $from        



                    
                    
    <body >
    </html>

    你可以在里面任意设计   如果是变量 那么用$+变量名  这个可以通过后台传进来实现动态交互。
    摸版我们已经设计好了  那么下面我们来写一个用摸版的方法吧

    其实就一个方法而已 , 你可以把这个方法加在前面的SendMial.java类里

    /**
         * get mail content with template.  the keys in the map should relative to the variable that define in the
         * body of vm file
         *
         * @param templateName this is a vm file , the template style in it
         * @param map          the map you can set the variable in it according you need
         *                     return StringWriter   the mail body in it
         */
        public String getMailContentWithTemplate(String templateName, Map map) throws Exception {

            VelocityEngine ve = new VelocityEngine();
            ve.setProperty("file.resource.loader.class", ClasspathResourceLoader.class.getName());
            ve.init();
            /* next, get the Template */
            Template t = ve.getTemplate(templateName, "utf-8");
            /* create a context and add data */
            VelocityContext context = new VelocityContext();
            Iterator keys = map.keySet().iterator();
            while (keys.hasNext()) {
                String key = keys.next().toString();
                context.put(key, map.get(key));
            }
            StringWriter writer = new StringWriter();
            t.merge(context, writer);
            return writer.toString();
        }

    这个方法的两个参数比较重要 templateName 是.vm文件的名字,map这是用户可以自定义的,要注意map里的key要和.vm文件里的变量相对应
    具体看下面的测试类

    那么下面就是一个对发邮件模板的测试啦  TestTamplate.java

    import java.util.Properties;
    import java.util.Map;
    import java.util.HashMap;
    import java.io.InputStream;
    import java.io.StringWriter;

    /**
    * To test send mail with tamplate
    */
    public class TestTamplate {

        public static void main(String args[]) throws Exception {

            Properties pro = new Properties();
            InputStream is = TestTamplate.class.getClassLoader().getResourceAsStream("mail.properties");
            pro.load(is);
            SendMail themail = new SendMail(pro.getProperty("mail.smtp"), pro.getProperty("mail.agentIp"), pro.getProperty("mail.agentPort"));

            Map map = new HashMap();
            map.put("to", "andy.zhao@suzsoft.com");
            map.put("site", "vehicle  CEO");
            map.put("test", "this is a test,中文");
            map.put("content", "<a href="http://www.google.cn">aaa</a>");
            map.put("from", "eric");

            String writer = themail.getMailContentWithTemplate(("mailTemplate.vm"), map);
            themail.setNeedAuth(true);
            themail.setNamePass(pro.getProperty("mail.name"), pro.getProperty("mail.password"));
            themail.setTo(pro.getProperty("mail.to").toString());

            if (null != pro.getProperty("mail.cc").toString() && pro.getProperty("mail.cc").toString() != "") {
                themail.setCopyTo(pro.getProperty("mail.cc").toString());
            }

            if (null != pro.getProperty("mail.bcc").toString() && pro.getProperty("mail.bcc").toString() != "") {
                themail.setBccTo(pro.getProperty("mail.bcc").toString());
            }

            if (null != pro.getProperty("mail.subject").toString() && pro.getProperty("mail.subject").toString() != "") {
                themail.setSubject(pro.getProperty("mail.subject").toString());
            }

            themail.setBody(writer);

            if (null != pro.getProperty("mail.from") && pro.getProperty("mail.from") != "") {
                themail.setFrom(pro.getProperty("mail.from"));
            }

            if (null != pro.getProperty("mail.affixFile")) {
                themail.addFileAffix(pro.getProperty("mail.affixFile"));
            }
            themail.sendout();


        }
    }


  • 相关阅读:
    第一个ADO.NET连接SQl server数据库
    Mysql编码
    SNMP协议报文分析
    物理层计算
    随机产生数组
    c#排序
    c#计算一段代码的时间复杂度
    jwt认证
    drf三大组件之频率认证组件
    drf三大组件之认证组件与权限组件
  • 原文地址:https://www.cnblogs.com/zghull/p/3365155.html
Copyright © 2011-2022 走看看