带用户验证的SMTP邮件客户端java实现

  一、程序的实现

SMTP (Simple Mail Transfer Protocol) : 电子邮件从客户机传输到服务器或从某一个服务器传输到另一个服务器使用的传输协议。 SMTP 是请求/响应协议,命令和响应都是基于 ASCII 文本,并以 CR LF 符结束。响应包括一个表示返回状态的三位数字代码。SMTP TCP 协议 25 端口监听连接请求。首先,我们创建套接字,然后创建基于套接字输入输出流的过滤器流。可以方便的向服务器整行读取写入数据。相关代码如下:

              java.net.Socket s=new java.net.Socket(_smtp.getText(),25);  //创建套接字,SMTP默认25端口

              _out=new PrintWriter(s.getOutputStream());                 //实例化输入输出流

         _in=new BufferedReader(new InputStreamReader(s.getInputStream()));

Send()函数用来发送数据后读取服务器的响应。其异常抛出由调用者处理,send函数将发送的信息写入到服务器,同时在状态栏输出,整行读取数据后将响应状态也在侧边栏输出。

主要发送命令如下:

        send(null);

            send("HELO " + java.net.InetAddress.getLocalHost().getHostName()+"\r\n");//noly

            /*用户验证,发送base64加密的用户名密码*/

            send("AUTH LOGIN"+"\r\n");//only

            send((new   sun.misc.BASE64Encoder()).encode(_from.getText().getBytes())+"\r\n");//only

            send((new   sun.misc.BASE64Encoder()).encode( _pwd.getText().getBytes())+"\r\n");//only

            send("MAIL FROM: " + _from.getText()+"\r\n");//only

            send("RCPT TO: " + _to.getText()+"\r\n");

        send("DATA"+"\r\n");

其中用户验证采用普遍的Base64加密后的用户名,密码。

接着我们发送邮件正文。最先发送的是邮件的相关信息,注意相关信息一般可以造假,除非服务器进行检测。内容如下:

_out.print("cc:" + "这里是抄送内容"+"\r\n");

              _out.print("From:" + "来自邮箱"+"\r\n");

            _out.print("to:" + "发送的邮件地"+"\r\n");

            _out.print("date:" + "时间"+"\r\n");

            _out.print("Subject:" + _subject.getText()+"\r\n");

正文采用MIME(Multipurpose Internet Mail Extensions,多功能Internet 邮件扩充服务)来实现发送功能各异的文本。MIME信息由正常的Internet文本邮件组成,文本邮件拥有一些特别的符合RFC 822的信息头和格式化过的信息体(用ASCII 的子集来表示的附件)。这些MIME头给出了一种在邮件中表示附件的特别的方法。我们首先发送正文的相关信息头,然后通过不同的MIME段(每段前也缀以一个特别的头)来发送html、纯文本、加密的附件等。主要代码如下:

                _out.print("X-Mailer:Hector’s mail\r\n"      //先发送信息头   

                 +"MIMI-Version:1.0\r\n"+"Content-Type:multipart/mixed;boundary=\"#BOUNDARY#\"\r\n\r\n"

                +"Content-Transfer-Encoding:7bit\r\n\r\n"

                +"This is a multi-part message in MIME format\r\n\r\n"

                +"–#BOUNDARY#\r\n"   //一个分段标志而已,便于分段发送各种数据

                +&q
uot;Content-Type: text/html;charset=gb2312\r\n"

                +"Content-Transfer-Encoding:printable\r\n\r\n"

                +_body.getText()+"\r\n"     //html正文 

                );

正文发送完之后,我们以send("\r\n"+"."+"\r\n")作为结束,接着我们退出与服务器的链接send("quit"+"\r\n"),最后关闭套接字s.close()

其中的异常捕获后输出到状态栏。

 

二、结果分析

下图是运行后的界面和发送的内容,状态栏显示邮件正在发送列队中。

SMTPA发邮件,客户端

在邮箱中检测到了带HTML的邮件,其中的加粗,换行,斜体html标签都成功实现。

 SMTP带用户名验证

三、程序需要改进的地方

 测试在linux下发送失败,原因是Doswindows采用回车+换行CR/LF表示下一行, (具体参考[关于linux和windows的CR, LF, CR/LF 回车 换行问题])

UNIX/Linux采用换行符LF表示下一行。经过不断替换换行符,在linux发送成功,需要改换行符的地方:

            send("HELO " + java.net.InetAddress.getLocalHost().getHostName()+"\n");

            send("AUTH LOGIN"+"\n");

            send((new   sun.misc.BASE64Encoder()).encode(_from.getText().getBytes())+"\n");

            send((new   sun.misc.BASE64Encoder()).encode( _pwd.getText().getBytes())+"\n");

考虑我们可以通过System.getProperty("os.name")函数获取操作系统中的关键字如(windows)来自动选择换行符,实现多操作系统的兼容。

为了方便的编辑html文件,可以键入一个html编辑器,另外实现多收件人,以及多附件的发送。

此小程序只是为学习SMTP协议,精力有限,想丰富此程序的功能,请自行调试代码。

 

代码下载:201001261229413388.txt

 程序简陋,仅供学习之用,有问题请到http://www.ourys.com/post/SMTP-JAVA-AUTH_LOGIN.html这里讨论。

 

3 评论

  1. 发送附件的功能我还是不太明白。

    Hector 于 2010-1-28 10:14:47 回复

    附件是根据MIME服务的原理构成的,MIME把各种数据分段,每段定义相应的格式,附件应该是要读取数据流并用BASE64加密吧,具体的参考一下MIME,我也只是简单测试了一下,随意发了几个数据可以当附件发送出去,读取数据流加密等没有时间做~

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据