JNDI(二)编写具有SMTP服务器功能的邮件发送程序

参考书籍《张孝详 java邮件开发详解》

(1)按例程6-6编写一个名为SMTPSender.java的程序,这个程序向属于多个不同域的收件人发送邮件,它直接连接到每个收件人所在域的SMTP服务器进行邮件发送。

例程6-6 SMTPSender.java


import javax.naming.Context;

import javax.naming.NamingException;

import javax.naming.directory.Attribute;

import javax.naming.directory.Attributes;

import javax.naming.directory.DirContext;

import javax.naming.directory.InitialDirContext;


import java.util.Properties;

import java.util.Date;

import javax.mail.Session;

import javax.mail.Transport;

import javax.mail.internet.InternetAddress;

import javax.mail.Message;

import javax.mail.internet.MimeMessage;



public class SMTPSender

{

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

    {

        //下面是邮件要群发给的多个收件人地址

        String [] to = {"it315_test@sohu.com","it315_test@sina.com",

                            "it315_test@163.com","it315_test@126.com"};


        //创建Session对象

        Properties props = new Properties();

        /*mail.smtp.localhost属性用于设置SMTP协议的EHLO命令中的

 主机名,其他SMTP服务器可能需要使用这个主机名确定发件SMTP

 服务器的身份,这个信息可以从JavaMail的javadocs文档中的

        com.sun.mail.smtp包的帮助页面内查看到。

        */

        props.setProperty("mail.smtp.localhost","mail.itcast.cn");

        Session session = Session.getInstance(props);

        session.setDebug(true);


        Message msg = createMessage(session);

        for(int i=0; i<to.length; i++)

        {

            try

{

                sendMessage(session,msg,to[i]);

            }

catch(Exception e)

            {

                e.printStackTrace();

            }

        }

    }


    public static Message createMessage(Session session)

                throws Exception

    {


        String from = "it315_test@sina.com ";//发件人地址

        String subject = "SMTPSender demo";//邮件主题

        String body = "SMTPSender demo";//邮件内容


        //创建代表邮件的MimeMessage对象,不包含收件人地址

        MimeMessage msg = new MimeMessage(session);

        msg.setFrom(new InternetAddress(from));

        msg.setSentDate(new Date());

        msg.setSubject(subject);

        msg.setText(body);

        return msg;    

    }


    public static void sendMessage(Session session,Message msg,String to)

            throws Exception

    {

        //设置邮件内容的收件人并生成邮件消息内容

        msg.setRecipients(Message.RecipientType.TO,

                            InternetAddress.parse(to));

        msg.saveChanges();


        //连接收件人地址所在的SMTP服务器并发送邮件

        Transport transport = session.getTransport("smtp");

        String domain = to.substring(to.indexOf("@")+1);

        String smtpServer = getSmtpServer(domain,null);

        transport.connect(smtpServer,null,null);

        transport.sendMessage(msg,

                          msg.getRecipients(Message.RecipientType.TO));

        transport.close();     

    }


    public static String getSmtpServer(String domain,String dnsServer)

                        throws Exception

    {

        DirContext ctx = new InitialDirContext();

        Attributes attrsMx = null;

        if(dnsServer != null)

        {

            attrsMx = ctx.getAttributes("dns:" + "//" + dnsServer +

                                    "/" + domain, new String[]{"MX"});

        }

        else

        {

            attrsMx = ctx.getAttributes("dns:" + "/" + domain, new String[]{"MX"});        

        }          


        String recordMx = (String)attrsMx.get("MX").get();

        String smtpServer = recordMx.substring(

                            recordMx.indexOf(" ") + 1);

        return smtpServer;

    }

}

实际的SMTP服务器程序要比上面的程序复杂得多,它们每天要向大量的其他SMTP服务器发送大量的邮件,当它们连接上一台其他的SMTP服务器并发送一封邮件后,是否要立即与这个服务器断开连接呢?这就是一个比较难以处理的问题了,如果不断开连接,而随后一段时间内又没有要发送给该SMTP服务器的邮件了,这样就造成网络连接资源浪费;如果发送一封邮件后立即断开与该SMTP服务器的连接,而随后的邮件又是要发送到的该SMTP服务器,又要重新与该SMTP服务器建立连接,这样明显是一种低效率的方法。关于这个问题,有兴趣的读者可以去看一些开源的SMTP服务器程序的源代码,我们就不再这里讨论如何解决这些问题了。

(2)在Windows命令行窗口中编译并运行这个java程序,通常情况下,这个程序发送邮件的过程都会以失败告终,如图6.15所示。

图6.15

出现图6.15中的错误是因为现在的大多数SMTP服务器都增加了一些防垃圾邮件的措施,如果邮件发送程序以SMTP服务器的身份向它们发送邮件,它们要求运行该邮件发送程序的计算机必须在Internet上注册了主机名(也就是A记录),并且这台计算机的IP地址没有被列入进它们的黑名单,而我和读者们使用的计算机往往都无法满足这些条件。

对于sina这样的大型网站,它们提供了完全独立的SMTP服务器来分别与普通邮件客户端程序和其他SMTP服务器进行通信。邮件客户端程序连接的SMTP服务器是smtp.sina.com.cn,smtp.sina.com.cn服务器总是要求对方进行用户身份验证。其他smtp服务器连接的sina的SMTP服务器是sina.com域中MX记录所对应的计算机,例如,sinamx.sina.com.cn,这些注册成了MX记录的计算机不要求对方进行用户身份验证,但也采取各种方式来防止对方发送垃圾邮件。显然,smtp.sina.com.cn是不能被注册为MX记录的,因为它需要对方传递用户身份信息,其他SMTP无法根本无法与之正常通信。

对于小型网站,它们用同一台SMTP服务器来与普通邮件客户端程序和其他SMTP服务器进行通信,它们通常根据对方在ehlo命令中提供的主机名是否与该计算机的ip地址反向解析到的主机名一致来判断对方是普通的邮件客户端程序,还是其他SMTP服务器。如果对方在ehlo命令中指定的主机名与对方的IP地址不匹配,小型网站的SMTP服务器程序则认为对方是普通的邮件客户端程序,需要对方传递用户认证信息;如果对方在ehlo命令中指定的主机名与对方的IP地址匹配,小型网站的SMTP服务器程序则认为对方也是一台SMTP服务器,不需要对方提供用户认证信息即可直接发送邮件。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,875评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,569评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,475评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,459评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,537评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,563评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,580评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,326评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,773评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,086评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,252评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,921评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,566评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,190评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,435评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,129评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,125评论 2 352

推荐阅读更多精彩内容