- 论坛徽章:
- 0
|
JAVA平台事实上已经为我们提供了MAIL实现(JAVAMAIL API),但是,JAVAMAIL的实现实在不值一提,无论其易用性还是性能,都差强人意.SUN的开发小组成员他们只能是JAVA精英,但他们不是MAIL的行家,对我而言,JAVAMAIL最多只能算是一个标准,一种接口,而SUN根本不应该自己去实现.
一种技术,在任何平台上实现都是同样的技术,语言本身只是一种工具,而不应该让技术服从于语言.但JAVAMAIL就把MAIL技术服从JAVA语言的层次,所以它已经不具有MAIL自己本来的性能优势.那么,本文就把MAIL技术还它本来面目,它不是JAVA的API,而是MAIL技术在JAVA平台上的实现.
当然,本文不会教你如何从最底层来实现MAIL技术的各种协议,也不会自己实现SMTP和POP,IMAP等服务程序----和JAVAMAIL在同一起跑线上,基于已有的服务程序来应用.纵观整个JAVA网络编程,90%是对应用层编程,很少要我们自己用JAVA写服务的,那不是一两个人做的事.
什么是 SMTP ?
SMTP (Simple Mail Transfer Protocol) : 电子邮件从客户机传输到服务器或从某一个服务器传输到另一个服务器使用的传输协议。 SMTP 是请求/响应协议,命令和响应都是基于 ASCII 文本,并以 CR 和 LF 符结束。响应包括一个表示返回状态的三位数字代码。SMTP 在 TCP 协议 25 端口监听连接请求。
什么是 ESMTP ?
ESMTP (Extended SMTP),顾名思义,扩展 SMTP 就是对标准 SMTP 协议进行的扩展。它与 SMTP 服务的区别仅仅是,使用 SMTP 发信不需要验证用户帐户,而用 ESMTP 发信时, 服务器会要求用户提供用户名和密码以便验证身份。验证之后的邮件发送过程与 SMTP 方式没有两样。
SMTP 命令包括:
HELO 向服务器标识用户身份。发送者能欺骗,说谎,但一般情况下服务器都能检测到。
EHLO 向服务器标识用户身份。发送者能欺骗,说谎,但一般情况下服务器都能检测到。
MAIL FROM 命令中指定的地址是发件人地址
RCPT TO 标识单个的邮件接收人;可有多个 RCPT TO;常在 MAIL 命令后面。
DATA 在单个或多个 RCPT 命令后,表示所有的邮件接收人已标识,并初始化数据传输,以 CRLF.CRLF 结束
VRFY 用于验证指定的用户/邮箱是否存在;由于安全方面的原因,服务器常禁止此命令
EXPN 验证给定的邮箱列表是否存在,扩充邮箱列表,也常被禁用
HELP 查询服务器支持什么命令
NOOP 无操作,服务器应响应 OK
RSET 重置会话,当前传输被取消
QUIT 结束会话
POP3简介:
在POP3协议中有三种状态,认可状态,处理状态,和更新状态。当客户机与服务器建立联系时,一旦客户机提供了自己身份并成功确认,即由认可状态转入处理状态,在完成相应的操作后客户机发出quit命令,则进入更新状态,更新之后最后重返认可状态。
POP3基本命令集:
USER username
PASS password
STAT 请求服务器发回关于邮箱的统计资料,如邮件总数和总字节数
LIST 返回邮件数量和每个邮件的大小
RETR [Msg#] 返回由参数标识的邮件的全部文本
DELE [Msg#] 服务器将由参数标识的邮件标记为删除,由quit命令执行
RSET 服务器将重置所有标记为删除的邮件,用于撤消DELE命令
NOOP 服务器返回一个肯定的响应
QUIT 更新
//----------------------------MailMessage.java-------------------------
public class MailMessage {
private String from, to, datafrom, datato, subject, content, date, user, password;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getDatafrom() {
return datafrom;
}
public void setDatafrom(String datafrom) {
this.datafrom = datafrom;
}
public String getDatato() {
return datato;
}
public void setDatato(String datato) {
this.datato = datato;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
}
//----------------------------MailMessage.END-------------------------
//----------------------------SMTPClient.java-------------------------
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.StringTokenizer;
import sun.misc.BASE64Encoder;
public class SMTPClient {
private boolean debug = true;
private Socket socket;
BASE64Encoder base64Encode = new BASE64Encoder();// 用于加密后发送用户名和密码
public SMTPClient(String server, int port){
boolean smtpAndPortIsOK = true;
try {
socket = new Socket(server, 25);
} catch (UnknownHostException e) {
smtpAndPortIsOK = false;
System.out.println(e.getMessage());
} catch (IOException e) {
smtpAndPortIsOK = false;
e.printStackTrace();
} finally {
if(smtpAndPortIsOK) {
System.out.println("已经建立SMTP连接!");
}else {
System.out.println("SMTP:" + server + " & PORT:" + port + " 连接失败!");
}
}
}
// 注册到邮件服务器
public void helo(String server, BufferedReader in, BufferedWriter out) throws IOException {
int result;
result = getResult(in);
// 连接上邮件服务后,服务器给出220应答
if (result != 220) {
throw new IOException("连接服务器失败");
}
result = sendServer("HELO " + server, in, out);
// HELO命令成功后返回250
if (result != 250) {
throw new IOException("注册邮件服务器失败!");
}
}
private int sendServer(String str, BufferedReader in, BufferedWriter out) throws IOException {
out.write(str);
out.newLine();
out.flush();
if (debug) {
System.out.println("已发送命令:" + str);
}
return getResult(in);
}
public int getResult(BufferedReader in) {
String line = "";
try {
line = in.readLine();
if (debug) {
System.out.println("服务器返回状态:" + line);
}
} catch (Exception e) {
e.printStackTrace();
}
// 从服务器返回消息中读出状态码,将其转换成整数返回
StringTokenizer st = new StringTokenizer(line, " ");
return Integer.parseInt(st.nextToken());
}
public void authLogin(MailMessage message, BufferedReader in, BufferedWriter out) throws IOException {
int result;
result = sendServer("AUTH LOGIN", in, out);
if (result != 334) {
if(result == 502) {
System.out.println("此SMTP无需验证!");
return;
}else {
throw new IOException("用户验证失败!");
}
}
result = sendServer(base64Encode.encode(message.getUser().getBytes()), in, out);
if (result != 334) {
throw new IOException("用户名错误!");
}
result = sendServer(base64Encode.encode(message.getPassword().getBytes()),
in, out);
if (result != 235) {
throw new IOException("验证失败!");
}
}
// 开始发送消息,邮件源地址
public void mailfrom(String source, BufferedReader in, BufferedWriter out) throws IOException {
int result;
result = sendServer("MAIL FROM:", in, out);
if (result != 250) {
throw new IOException("指定源地址错误");
}
}
// 设置邮件收件人
public void rcpt(String touchman, BufferedReader in, BufferedWriter out) throws IOException {
int result;
result = sendServer("RCPT TO:", in, out);
if (result != 250) {
throw new IOException("指定目的地址错误!");
}
}
// 邮件体
public void data(String from, String to, String subject, String content, BufferedReader in, BufferedWriter out) throws IOException {
int result;
result = sendServer("DATA", in, out);
// 输入DATA回车后,若收到354应答后,继续输入邮件内容
if (result != 354) {
throw new IOException("不能发送数据");
}
out.write("From: " + from);
out.newLine();
out.write("To: " + to);
out.newLine();
out.write("Subject: " + subject);
out.newLine();
out.write(content);
out.newLine();
// 句号加回车结束邮件内容输入
result = sendServer(".", in, out);
if (result != 250) {
throw new IOException("发送数据错误");
}
}
// 退出
public void quit(BufferedReader in, BufferedWriter out) throws IOException {
int result;
result = sendServer("QUIT", in, out);
if (result != 221) {
throw new IOException("未能正确退出");
}
}
// 发送邮件主程序
public boolean sendMail(MailMessage message, String server) {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
helo(server, in, out);// HELO命令
authLogin(message, in, out);// AUTH LOGIN命令
mailfrom(message.getFrom(), in, out);// MAIL FROM
rcpt(message.getTo(), in, out);// RCPT
data(message.getDatafrom(), message.getDatato(), message.getSubject(), message.getContent(), in, out);// DATA
quit(in, out);// QUIT
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public static void main(String[] args){
int port = 25;
String server = "smtp.xxx.xxx";// 邮件服务器
boolean flag = false;
MailMessage message = new MailMessage();
message.setFrom("
[email=from@xxx.xxx");//]from@xxx.xxx");//[/email]
发件人
message.setTo("
[email=toAddress@xxx.xxx");//]toAddress@xxx.xxx");//[/email]
收件人
message.setSubject("test");// 邮件主题
message.setContent("你好");// 邮件内容
message.setDatafrom("miracle");// 发件人,在邮件的发件人栏目中显示
message.setDatato("longlongago");// 收件人,在邮件的收件人栏目中显示
message.setUser("user");// 登陆邮箱的用户名
message.setPassword("passwd");// 登陆邮箱的密码
SMTPClient smtp = new SMTPClient(server, port);
if(smtp != null) {
flag = smtp.sendMail(message, server);
}
if (flag) {
System.out.println("邮件发送成功!");
} else {
System.out.println("邮件发送失败!");
}
}
}
//----------------------------SMTPClient.END-------------------------
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/56194/showart_442288.html |
|