发送邮件使用的是smtp协议,该协议位于tcp层上, 从最基础的理论上讲使用的就是底层socket。
而smtp使用的就是socket 25端口,
利用socket读写功能向smtp服务器写入执行命令,
从最根本上讲就是向邮件smtp服务器发送指令,而smtp 协议就是一问一答的过程。这和我们在linux服务器上敲入命令是一个过程
smtp协议几个常用指令如下:
HELO
客户端为标识自己的身份而发送的命令(通常带域名)
MAIL FROM
标识邮件的发件人;以 MAIL FROM: 的形式使用。
RCPT TO
标识邮件的收件人;以 RCPT TO: 的形式使用。
DATA
客户端发送的、用于启动邮件内容传输的命令。
QUIT
终止会话。
废话少说 将如下代码执行即可,由于代码简单,并加入了一些注释,改实例使用了base64包,
import it.sauronsoftware.base64.Base64;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SMTPDemo {
public static void main(String[] args) throws IOException, UnknownHostException{
//发送邮箱
String userMail = "[email protected]";
//邮箱密码
String password = "*******";
//smtp服务器
String mailHost = "smtp.163.com";
//检查邮箱的有效性
checkEmailAddress(userMail);
SMTP mail = new SMTP(mailHost, userMail, password);
MailInfo mailInfo = new MailInfo();
//构造邮件信息
//发件人,
mailInfo.setFromAddress(userMail);
//收件人
mailInfo.setToAddress("[email protected]");
mailInfo.setSubject("欢迎你,这是邮件标题");
mailInfo.setContentType("text/html;charset=\"utf-8\"");
mailInfo.setContent("这是邮件内容");
if (mail != null){
if (mail.send(mailInfo)){
System.out.println("mail sent.");
}else {
System.out.println("Connect to SMTP server failed!");
}
}
System.out.println("Done.");
}
static void checkEmailAddress(String address){
if (address.indexOf('@') == -1)
{
System.out.println("Invalid e-mail address '" + address + "'");
System.exit(10);
}
}
}
class SMTP{
private final static int SMTP_PORT = 25;
private InetAddress mailHost;
private InetAddress ourselves;
private String userMail;
private String password;
public SMTP(String host, String userMail, String password) throws UnknownHostException{
//smtp服务器
mailHost = InetAddress.getByName(host);
ourselves = InetAddress.getLocalHost();
this.userMail = userMail;
this.password = password;
System.out.println("smtp host : " + mailHost);
}
public boolean send(MailInfo mailInfo) throws IOException{
Socket smtpPipe;
InputStream inn;
OutputStream outt;
//构建socket端口为25为smtp端口
smtpPipe = new Socket(mailHost, SMTP_PORT);
inn = smtpPipe.getInputStream();
outt = smtpPipe.getOutputStream();
//输入流,读取服务器返回信息
BufferedReader inBR = new BufferedReader(new InputStreamReader(inn));
//输出流,发送给服务器信息
PrintWriter outPrinter = new PrintWriter(new OutputStreamWriter(outt), true);
if (inn == null || outt == null){
System.out.println("Failed to open stream to socket");
return false;
}
//读取服务器初始化信息
String initiaID = inBR.readLine();
System.out.println(initiaID);
String receiveMsg = "";
//发送stmp协议命令,所有smtp都是从 helo命令开始的,向服务器问好
outPrinter.println("HELO " + ourselves.getHostName());
outPrinter.flush();
System.out.println("HELO " + ourselves.getHostName());
//服务器返回helo命令的信息
String welcome = inBR.readLine();
System.out.println(welcome);
//发送smtp服务器用户验证
outPrinter.println("AUTH LOGIN");
outPrinter.flush();
receiveMsg = inBR.readLine();
System.out.println("login :"+receiveMsg);
if (!receiveMsg.startsWith("334")){
return false;
}
//发送用户邮件名
outPrinter.println(Base64.encode(userMail));
outPrinter.flush();
receiveMsg = inBR.readLine();
System.out.println("user :"+receiveMsg);
if (!receiveMsg.startsWith("334")){
return false;
}
//发送用户密码
outPrinter.println(Base64.encode(password));
outPrinter.flush();
//验证通过
receiveMsg = inBR.readLine();
System.out.println("password :"+receiveMsg);
if (!receiveMsg.startsWith("235")){
return false;
}
//mail from 命令 发送发件人信箱
System.out.println("MAIL FROM :<" + mailInfo.fromAddress +">");
outPrinter.println("MAIL FROM :<" + mailInfo.fromAddress +">");
outPrinter.flush();
//服务器返回接收发件人信箱信息
receiveMsg = inBR.readLine();
System.out.println("MAIL FROM sendOK " +receiveMsg);
if (!receiveMsg.startsWith("250")){
return false;
}
//收件人rcpt to命令
System.out.println("RCPT TO: <" + mailInfo.toAddress + ">");
outPrinter.println("RCPT TO: <" + mailInfo.toAddress + ">");
outPrinter.flush();
//返回服务器处理rcpt结果
receiveMsg = inBR.readLine();
System.out.println("rcpt receive:"+receiveMsg);
if (!receiveMsg.startsWith("250")){
return false;
}
//邮件主体开始,data命令之后跟的就是邮件内容
outPrinter.println("DATA");
outPrinter.flush();
receiveMsg = inBR.readLine();
System.out.println("DATA receive:"+receiveMsg);
if (!receiveMsg.startsWith("354")){
return false;
}
//邮件格式:from: 发送人, to:收件人,
//content-type:text/html;charset="utf-8",为邮件内容编码格式,
//subject: 邮件标题
//date: 邮件日期
StringBuilder msgBody = new StringBuilder();
msgBody.append("From: <"+ mailInfo.fromAddress+ ">" + "\r\n");
msgBody.append("To: <"+ mailInfo.toAddress + ">" + "\r\n");
msgBody.append("Content-Type: "+ mailInfo.contentType + "\r\n");
msgBody.append("Subject: "+ mailInfo.subject +" \r\n");
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = format.format(new Date());
msgBody.append("Date: "+date+" \r\n");
outPrinter.println(msgBody);
outPrinter.flush();
//邮件内容
outPrinter.println(mailInfo.content+ "\r\n");
outPrinter.flush();
//.点号是邮件的结束符,必须要发送
outPrinter.println("\r\n.\r\n");
outPrinter.flush();
String acceptOK = inBR.readLine();
System.out.println("send mail endmsg:"+acceptOK);
//quit命令,退出邮件链接,即端口socket链接
outPrinter.println("QUIT");
return true;
}
}
class MailInfo{
String subject;
String fromAddress;
String toAddress;
String contentType;
String content;
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getFromAddress() {
return fromAddress;
}
public void setFromAddress(String fromAddress) {
this.fromAddress = fromAddress;
}
public String getToAddress() {
return toAddress;
}
public void setToAddress(String toAddress) {
this.toAddress = toAddress;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}