Author:Rockay(劉其超,劉濤)Page:http://www.cnblogs.com/RockayEmail:rockay_liu@126.com
註:有部分是參考網上資料。
由於最近幫朋友做一個JAVA郵件群發功能。因為最近一年都在搞.NET,JAVA幾乎忘記完了,於是上網查了些資料。與大家分享一下:
SMTP 命令
什麼是 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 結束會話
Title
///////////////////////////////////////////MailMessage實體類///////////////////////////////////////
package gxa.sf.rockay;
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.SocketException;
import java.net.UnknownHostException;
import java.util.StringTokenizer;
import sun.misc.BASE64Encoder;
/**
* SMTP用戶端調用類
* @author Rockay(劉其超,劉濤)
* http://www.cnblogs.com/Rockay
*/
public class SMTPClient {
public SMTPClient()
{
}
private boolean debug=true;
BASE64Encoder encode=new BASE64Encoder();//用於加密後發送使用者名稱和密碼
public boolean Send(String server,String from,String[] to,String[] cc,String[] bc,
String subject,String content,String user,String pwd) throws UnknownHostException, IOException
{
MailMessage message=new MailMessage();
message.setFrom(from);//寄件者
for(int i=0;i<to.length;i++)
{
message.setTo(to[i]);//收件者
message.setDatato(to[i]);//收件者,在郵件的收件者欄目中顯示
}
for(int i=0;i<cc.length;i++)
{
message.setCc(cc[i]);//收件者
}
for(int i=0;i<bc.length;i++)
{
message.setBc(bc[i]);//收件者
}
message.setDatafrom(from);//寄件者,在郵件的寄件者欄目中顯示
message.setSubject(subject);//郵件主題
message.setContent(content);//郵件內容
message.setUser(user);//登陸郵箱的使用者名稱
message.setPassword(pwd);//登陸郵箱的密碼
SMTPClient smtp=new SMTPClient(server,25);
boolean flag;
flag=smtp.sendMail(message,server);
if(flag){
System.out.println("郵件發送成功!");
}
else{
System.out.println("郵件發送失敗!");
}
return flag;
}
private Socket socket;
public SMTPClient(String server,int port) throws UnknownHostException, IOException{
try{
socket=new Socket(server,25);
}catch(SocketException e){
System.out.println(e.getMessage());
}catch(Exception e){
e.printStackTrace();
}finally{
System.out.println("已經建立串連!");
}
}
//註冊到郵件伺服器
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){
throw new IOException("使用者驗證失敗!");
}
result=sendServer(encode.encode(message.getUser().getBytes()),in,out);
if(result!=334){
throw new IOException("使用者名稱錯誤!");
}
result=sendServer(encode.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:<"+source+">",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:<"+touchman+">",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.newLine();
out.write(content);
out.newLine();
//句號加斷行符號結束郵件內容輸入
result=sendServer(".",in,out);
System.out.println(result);
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;
}
}
///////////////////////////////////////////SMTP用戶端調用類///////////////////////////////////////
package gxa.sf.rockay;
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.SocketException;
import java.net.UnknownHostException;
import java.util.StringTokenizer;
import sun.misc.BASE64Encoder;
/**
* SMTP用戶端調用類
* @author Rockay(劉其超,劉濤)
* http://www.cnblogs.com/Rockay
*/
public class SMTPClient {
public SMTPClient()
{
}
private boolean debug=true;
BASE64Encoder encode=new BASE64Encoder();//用於加密後發送使用者名稱和密碼
public boolean Send(String server,String from,String[] to,String[] cc,String[] bc,
String subject,String content,String user,String pwd) throws UnknownHostException, IOException
{
MailMessage message=new MailMessage();
message.setFrom(from);//寄件者
for(int i=0;i<to.length;i++)
{
message.setTo(to[i]);//收件者
message.setDatato(to[i]);//收件者,在郵件的收件者欄目中顯示
}
for(int i=0;i<cc.length;i++)
{
message.setCc(cc[i]);//收件者
}
for(int i=0;i<bc.length;i++)
{
message.setBc(bc[i]);//收件者
}
message.setDatafrom(from);//寄件者,在郵件的寄件者欄目中顯示
message.setSubject(subject);//郵件主題
message.setContent(content);//郵件內容
message.setUser(user);//登陸郵箱的使用者名稱
message.setPassword(pwd);//登陸郵箱的密碼
SMTPClient smtp=new SMTPClient(server,25);
boolean flag;
flag=smtp.sendMail(message,server);
if(flag){
System.out.println("郵件發送成功!");
}
else{
System.out.println("郵件發送失敗!");
}
return flag;
}
private Socket socket;
public SMTPClient(String server,int port) throws UnknownHostException, IOException{
try{
socket=new Socket(server,25);
}catch(SocketException e){
System.out.println(e.getMessage());
}catch(Exception e){
e.printStackTrace();
}finally{
System.out.println("已經建立串連!");
}
}
//註冊到郵件伺服器
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){
throw new IOException("使用者驗證失敗!");
}
result=sendServer(encode.encode(message.getUser().getBytes()),in,out);
if(result!=334){
throw new IOException("使用者名稱錯誤!");
}
result=sendServer(encode.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:<"+source+">",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:<"+touchman+">",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.newLine();
out.write(content);
out.newLine();
//句號加斷行符號結束郵件內容輸入
result=sendServer(".",in,out);
System.out.println(result);
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);
authLogin(message,in,out);
mailfrom(message.getFrom(),in,out)
rcpt(message.getTo(),in,out);
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;
}
}