java发送邮件354_基于SMTP的JAVA邮件发送程序

这个程序没有使用JavaMail API,而是根据SMTP协议的要求直接处理协议的细节发送邮件,虽然比较麻烦了一些,但是对了解邮件协议的细节很有帮助的。

本文分两部分,第一部分是SMTP命令介绍(这个从别的地方抄的,嘿嘿);第二部分通过一个实例真正理解一下发送邮件的过程。

一: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 结束会话

连接到 Postfix 使用 SMTP 命令发送邮件

例如:安装 Postfix 的邮件服务器IP是192.168.0.1 (蓝色字体内容由客户端输入,红色字体内容是服务返回的)

telnet 192.168.0.1 25------------------------------------------------- 使用 telnet 命令连接服务器 25 端口

helo test.com -----------------------------------------------------------向服务器标识用户身份发送 mail from 命令

ehlo test.com ----------------------------------------------------------- ESMTP 命令,发信需要认证。

auth login ----------------------------------------------------------------进行用户身份认证

334 VXNlcm5hbWU6

Y29zdGFAYW1heGl0Lm5ldA==----------------------------------- BASE64 加密后的用户名

334 UGFzc3dvcmQ6

MTk4MjIxNA== -------------------------------------------------------- BASE64 加密后的密码

235 authentication successfully-------------------------------- 身份认证成功

(535 authentication failed--------------------------------- ------身份认证失败)

发到本系统中域名下的账户可跳过身份认证。

test1@domain.com

250 ok----------------------------------------------------- ----------命令执行成功

test2@domain.com

250 ok----------------------------------------------------- ----------命令执行成功

data ------------------------------------------------------- -----------数据传输初始化

354 End data with .----------------------------------------- -----开始传输数据

From: test1@domain.com

To: test2@domain.com

Date: Mon, 25 Oct 2004 14:24:27 +0800

Subject: test mail

Hi, test2

This is a test mail, you don't reply it.

.------------------------------------------------------------ 数据内容,包括BASE64加密后的邮件内容, 以 CRLF.CRLF 结束数据传输

250 OK: queued as 2F6DE3929--------------------------------- 命令执行成功

quit ------------------------------------------------------- 结束会话

221 Bye

Connection closed by foreign host .------------------------- 断开连接

以上就是一个邮件发送的基本的命令。

再说一下邮件发送的基本过程:

如果你的邮件地址是a@host.com,而你要用这个邮箱发送一封邮件到to@tohost.com,你需要连接到服务器host.com上,当然这个连接可能需要认证,现在基本上都要验证,然后是发送邮件到服务器host.com上,关闭连接。在host.com上,你所发送的邮件进入发送队列中,轮到你要发送的邮件时,host.com主机再联系tohost.com,将邮件传输到服务器tohost.com上。

二:实例应用

-----------------------------------------------------------------------------------------------------------------------

MailMessage.java

----------------------------------------

//这个类其实就是一个基本的JavaBean,用于完成一些基本信息的设置,也可以不要这个东西,直接在程序中写明就可以,不过这样条理较清楚一些,而且修改也方便一些.

package mail;

public class MailMessage {

private String from;

private String to;

private String datafrom;

private String datato;

private String subject;

private String content;

private String date;

private String user;

private String password;

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

public String getUser() {

return user;

}

public void setUser(String user) {

this.user = user;

}

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 getSubject() {

return subject;

}

public void setSubject(String subject) {

this.subject = subject;

}

public String getTo() {

return to;

}

public void setTo(String to) {

this.to = to;

}

}

---------------------------------------------

SMTPClient .java

------------------------------

//主要的功能就在这里面完成了

package mail;

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;

public class SMTPClient {

private boolean debug=true;

BASE64Encoder encode=new BASE64Encoder();//用于加密后发送用户名和密码

public static void main(String[] args) throws UnknownHostException, IOException {

// TODO Auto-generated method stub

MailMessage message=new MailMessage();

message.setFrom("mailto:wasingmon@163.com%22);//发件人

message.setTo("mailto:wasingmon@eyou.com%22);//收件人

String server="smtp.163.com";//邮件服务器

message.setSubject("test");//邮件主题

message.setContent("test");//邮件内容

message.setDatafrom("mailto:wangxingmou@eyou.com%22);//发件人,在邮件的发件人栏目中显示

message.setDatato("mailto:wasingmon@163.com%22);//收件人,在邮件的收件人栏目中显示

message.setUser("wasingmon");//登陆邮箱的用户名

message.setPassword("");//登陆邮箱的密码

SMTPClient smtp=new SMTPClient(server,25);

boolean flag;

flag=smtp.sendMail(message,server);

if(flag){

System.out.println("邮件发送成功!");

}

else{

System.out.println("邮件发送失败!");

}

}

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:",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.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服务器都需要SMTP验证,所以本例子中也加入了这个验证,要不然邮件时发不出去的(刚开始我就这样)。

END!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/497533.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

看到记忆的印迹:神经科学家们如何定位、唤醒甚至偷换记忆

来源:澎湃新闻概要:借助新兴的脑部成像技术,神经科学家们得以“看到”与特定记忆相关的特定神经细胞,了解记忆形成和唤起的规律,并成功地重新激活记忆通路。《神探夏洛克》中福尔摩斯在停尸间的初次登场,给…

卓有成效的管理者--总结

思维导图:https://www.processon.com/view/link/60d6f723e401fd50b99628ad

oci连接mysql_OCILIB 连接Oracle数据库——插入数据

二、进阶教程参看官方文档实例,有详细的说明,包括:查询获取数据、绑定向量、数据库连接池、12c隐式结果集、使用Oracle对象和数据库通知等例子。这里只做一个最简单的插入数据演示。1、简单的封装void COciUtil::Init(){CString strAppPath …

人工合成生命的最新进展比AI还快

合成酵母的科学杂志当期封面来源:通信和互联网的扫地僧2016年以来,以AlphaGo为标志的人工智能技术进入了发展的快车道,成为了民众热议的话题。2017年12月27日,华大基因董事长汪建在深商大会上表示,未来的5-10年&#x…

加利福尼亚大学提出从「因果革命」的七大成就中为「机器学习」寻求良好的模型指导

原文来源:arxiv作者:Judea Pearl「雷克世界」编译:嗯~是阿童木呀可以这样说,目前的机器学习系统几乎完全是以统计模式或无模型模式运行的,这对于其功率和性能来说存在着严格的理论限制。这样的系统不能引发干预和反思&…

被讨厌的勇气--总结

思维导图:https://www.processon.com/view/link/60d6fc2c7d9c087f54753b90

创建一个动物类 java_使用java面向对象创建动物类并输出动物信息

题目:使用java面向对象创建动物类并输出动物信息gitup下载地址:https://github.com/benxiaohai8888/Javase/blob/master/Animal.java代码:import java.util.Scanner;public class Animal{private double weight;//体重private int leg;//腿的…

java执行字节码的语句_Java字节码指令

Java虚拟机的指令由一个字节长度的、代表着某种特定操作含义的数字(操作码,Opcode)以及跟随其后的零至多个代表此操作所需的参数(操作数,Operands)构成。即:Java指令 操作码 操作数。由于Java虚拟机采用面向操作数栈而不是寄存器的架构&…

3分钟了解今日头条推荐算法原理(附视频+PPT)

来源:大数据文摘概要:2018年1月,今日头条资深算法架构师曹欢欢博士,终于首次公开今日头条的算法原理,以期推动整个行业问诊算法、建言算法,希望消除各界对算法的误解。今日头条的内容分发算法一直颇神秘低调…

高效休息法--总结

思维导图:https://www.processon.com/view/link/60d6fcaf1e08532a43bea653

java 停止kettle转换_通过java运行Kettle转换

我创建了一个Java应用程序(试点)来运行水壶转换。这很简单,我只有主要的方法,得到一个.ktr文件并执行它。public static void main( String[] args ){try {KettleEnvironment.init();TransMeta transMeta new TransMeta("C:\\user\\car.ktr")…

执行-技术人的管理之路--总结

思维导图:https://www.processon.com/view/link/5f0a6983e401fd0c8fffa75b

java进度条动画_Android自定义控件之圆形进度条动画

本文实例为大家分享了Android实现圆形进度条动画的具体代码,供大家参考,具体内容如下首先贴上图片:额,感觉还行吧,就是进度条的颜色丑了点,不过咱是程序员,不是美工,配色这种问题当然…

人脸识别必读的N篇文章

来源:机器视觉概要:人脸检测/跟踪的目的是在图像/视频中找到各个人脸所在的位置和大小;对于跟踪而言,还需要确定帧间不同人脸间的对应关系。一 、人脸检测/跟踪人脸检测/跟踪的目的是在图像/视频中找到各个人脸所在的位置和大小&a…

所谓高情商就是会说话--总结

思维导图:https://www.processon.com/view/link/60d6fe741e08532a43bea811

美国12大科技公司如何参与自动驾驶?

来源:腾讯科技概要:无人驾驶汽车的潜力已经逐步显现,这一点,从本周在拉斯维加斯举行的国际消费电子展(CES)就可以看出端倪。无人驾驶汽车的潜力已经逐步显现,这一点,从本周在拉斯维加…

java web响应式框架_Web开发的十佳HTML5响应式框架

HTML5框架是一类有助于快速轻松创建响应式网站的程序包。这些HTML5框架有着能减轻编程任务和重复代码负担的神奇功能。关于HTML5的框架种类繁多,并且很瘦欢迎,因为它能允许开发人员花费更少的时间和精力去创建一个令人惊艳的网站。在本文中,我…

开放-封闭原则(OCP)

开放-封闭原则(The Open-Close Principle) 软件实体(类、模块、函数等)应该是可以扩展的,但是不可以修改的。 两个特征 1、对于扩展是开放的(Open for extension); 2、对于更改是…

风向2018 | AI 突围

来源:36氪概要:回到战场,考验各家公司CEO和谋士的时刻,已经到来。问:2017年AI行业最大的进展是什么?答:创业公司的估值。高估值,曾将AI初创公司带上高光的创投舞台,也正将…

php return 值_php return的用法是什么

php return的用法:1、通过“return expression”语法返回一个表达式结果;2、使用“return(expr)”语法返回函数表达式;3、直接使用return返回值即可。本文操作环境:Windows7系统、PHP7.1、Dell G3电脑。基本用法:a)、r…