什么情况需要邮件发送?
1、注册后,账户激活功能 (获得有效真实邮箱地址)
2、商城广告邮件
3、节日祝福
4、系统对用户功能通知,可以通过邮件
今天学习目标:通过java程序发送邮件
邮件服务器? 网络中一台电脑,在电脑安装邮件服务器端软件,需要对服务器进行配置
电子邮箱? 邮件服务器上账户,可以通过电子邮箱登陆 邮件服务器
* 服务器会为每个邮箱账户,分配一定空间,用来保存邮箱相关电子邮件
邮件收发协议? SMTP、POP3、IMAP
SMTP 发送邮件协议,默认端口25
POP3 收取邮件协议,默认端口110
* 协议是用来规定通信格式的
IMAP 收取邮件协议,默认端口143,允许用户在线操作邮件,而不需要将邮件下载 ------- GMAIL开发IMAP权限
收发邮件过程是怎么样?
1、[email protected] 通过新浪客户端 连接新浪smtp服务器,发送邮件
2、新浪是smtp 需要将信件转投 给搜狐的 smtp服务器
3、搜狐smtp 获得邮件后,会将邮件保存 [email protected] 对应邮箱空间里
4、[email protected] 通过搜狐客户端,连接搜狐pop3服务器,pop3会读取bbb对应邮箱空间,获得aaa发送的邮件,返回客户端显示邮件内容
手动收发邮件实验
1、在sina和sohu 分别注册两个邮箱账户
sina: [email protected] / 1qaz2wsx
sohu: [email protected] /1qaz2wsx
2、用sina向sohu发送一封邮件,通过telnet(socket程序) 手动根据协议发送邮件
3、安装telnet
抄送:A 发给B ,选择抄送给C , B可以看见邮件抄送给 C (邮件是给B的,需要让C知道B已经收到邮件)
暗送:A 发给B,选择暗送给C ,B可以看见邮件,但是不能看到邮件发给C (邮件给B,也想给C一份,但不想让B知道)
4、使用SMTP发送邮件 连接新浪smtp : telnet stmp.sina.com 25
ehlo xxx ----- SMTP2代 helo
auth login ----- 发邮件时,发给服务器用户名和密码必须使用base64编码
eXV5YW5nOTQ4OTU=
MXFhejJ3c3g=
mail from:<[email protected]> ----- 发件人
rcpt to:<[email protected]> ----- 收件人
data ------ 邮件内容
from:<[email protected]>
to:<[email protected]>
subject:第一封0713测试邮件
这是一封测试邮件,哈哈~~~~
.
quit ----- 退出客户端
5、安装易邮
工具 --- 服务器设置 ---- 修改单域名 estore.com -------------------- [email protected]
账户 --- 新建账户 aaa/111 bbb/111
用[email protected] 向 [email protected] 发送一封邮件
6、smtp连接易邮发件
连接易邮smtp服务器 telnet localhost 25
ehlo xxx ----- SMTP2代 helo
auth login ----- 发邮件时,发给服务器用户名和密码必须使用base64编码
YWFh
MTEx
mail from:<[email protected]> ----- 发件人
rcpt to:<[email protected]> ----- 收件人
data ------ 邮件内容
from:<[email protected]>
to:<[email protected]>
subject:第一封0713测试邮件
这是一封测试邮件,哈哈~~~~
.
quit ----- 退出客户端
7、pop3连接易邮收取邮件
连接易邮pop3服务器 telnet localhost 110
user bbb
pass 111
stat ----- 返回邮箱的统计信息
list 邮件号 ------ 邮件信息
retr 邮件号 ------ 收取邮件内容
quit
-----------------------------------------------------------------------------------------------------------------------------------------------
telnet win7 输入中文 ? 问题 ---- 客户端本身问题
putty 小工具 模拟客户端,采用多种连接协议 连接服务器 ------ 企业使用远程连接操作linux
对putty设置
window --- Translation (Use font encoding 就是系统默认编码集gbk) ------------------- 可以将字符集设为utf-8 , window不需要
window --- appearance ---- change 字体显示中文字体(新宋体) 字符集 gb2312
Session中对ip port 和协议进行配置
两种客户端收发邮件软件使用:foxmail、outlook
* 定时收发邮件,提醒用户有新的邮件
1、foxmail 安装配置
邮箱 --- 新建邮箱账户
输入邮箱 密码点击下一步
* 在foxmail安装目录/mail目录/ 每配置一个邮箱 出现一个文件夹
配置pop3 ---- 需要写真实服务器地址 ---- 易邮localhost
配置smtp
2、outlook 安装配置
工具 --- 电子邮箱账户 ---- 添加新电子邮件账户
其它设置 --- 发送服务器 --- 勾选我的发送服务器要求验证
其它设置 --- 高级 ---- 勾选在服务器上保留邮件副本
* win7 无法连通本地易邮
cmd> ping localhost ---- ::1 ---- 解决在hosts文件 添加127.0.0.1 localhost
RFC822文档 规定邮件内容格式 区分和smtp ?
SMTP 通信协议,规定发送邮件时,客户端与服务器通信数据格式
RFC822文档 对邮件中文规定
邮件内容 包括邮件头和邮件体
邮件头 from(发件人) to(收件人) subject(标题) cc(抄送) bcc(暗送)
邮件体 : 邮件正文内容,需要和邮件头以一个空行分隔
RFC822文档 规定一封简单邮件如何编写,本身存在漏洞
* 发邮件过程中 mail from字段 和 RFC822文档 from字段 不同会出现什么问题? 冒名邮件问题
* 对方收取邮件时,只能看到from字段内容,无法得知mail from 地址
ehlo xxx
auth login
YWFh
MTEx
mail from:<[email protected]>
rcpt to:<[email protected]>
data
from: <[email protected]>
to:<[email protected]>
subject:面试通知
尊敬的李先生,我们已经看过您的简历,发觉您的简历,非常符合我公司搜索研发部,Android开发技术经理职位,请于2012年4月1日到中关村科贸大厦12层B座1205室参加面试。
google人力资源部
2012.1.1
.
--------------------------------------------------------------------------------------------------------------------------
JavaMail 是一套sun 提供开发邮件收发程序API,JavaMail编写程序就是邮件客户端程序(和outlook、foxmail功能类似)
* JavaMail开发需要类库 javamail API ,还需要下载 Java Activation Framework (jaf) ---- javamail API 依赖 jaf
导入jar包
mail.jar activation.jar(JDK6.0以后官方API自带)
* JDK6.0 以后开发 只需要导入 mail.jar ----- rt.jar 提供javax.activation 开发包
* JDK5.0(包括) 之前开发,需要导入mail.jar 和 activation.jar
javax.mail.Message 类 ----- 代表邮件本身
* 在javamailAPI中 一个邮件 就是一个Message对象
* 开发中使用javax.mail.internet.MimeMessage 代表邮件
javax.mail.Session 类 ----- 代表与服务器连接会话(简单理解连接)
***** java.lang.NoClassDefFoundError: com/sun/mail/util/LineInputStream 异常
MyEclipse 中javaee.jar 提供javamai API 与 JavaMail 引入jar包发生冲突
解决 :删除javaee.jar里面的mail目录和activation目录
window --- preferences --- 搜索lib ----- Library sets
JAVAMAIL 邮件收发四个核心类
1、Message 邮件
2、Session 连接会话
3、Transport 发送邮件
4、Store 收取邮件
发送邮件编程
1、创建与邮件发送服务器连接Session
2、编写邮件内容 Message
* 符合邮件内容格式RFC822文档 setFrom setRecipients setSubject setText
3、使用Transport工具类 发送邮件
@Test
public void demo2() throws MessagingException {
Properties properties = new Properties();
// 设置properties 属性
properties.put("mail.transport.protocol", "smtp");
properties.put("mail.smtp.host", "smtp.exmail.qq.com");
properties.put("mail.smtp.auth", "true");// 连接认证
properties.put("mail.debug", "true");// 在控制台显示连接日志信息
Session session = Session.getInstance(properties);
// 步骤二 编写Message
MimeMessage message = new MimeMessage(session);// 代表一封邮件
// from字段
message.setFrom(new InternetAddress("[email protected]"));
// to 字段
message.setRecipients(Message.RecipientType.TO, "[email protected]");
// subject字段
message.setSubject("javamail发送简单邮件");
// 邮件正文内容
message.setText("使用javamail 可以发送简单邮件 ...");
// 步骤三 使用Transport发送邮件
Transport transport = session.getTransport();
// 发邮件前进行身份校验
transport.connect("[email protected]", "123");
transport.sendMessage(message, message.getAllRecipients());
}
-------------------------------------------------------------------------------------------
RFC822 只定义简单邮件格式,没有定义复杂邮件如何编写
MIME 协议 是 RFC822文档的升级补充,完全支持RFC822文档
MIME 将邮件体分成多个部分,每个部分使用分隔线进行分隔,为每个部分提供Content-Type 类型属性
MIME描述邮件多个部分之间关系
1、multipart/mixed 用于携带附件
2、multipart/related 内嵌图片,音乐
3、multipart/alternative 防止兼容问题
* 发送简历时,将简历文件与邮件正文关系设置为alternative,当邮件客户端如果支持简历格式,简历会显示在正文中,如果不支持简历格式,简历会以附件携带
如果发送复杂邮件时,需要携带附件,需要为附件部分,设置Content-Disposition属性,值attachment
* 语法 Content-Dispostion : attachment;filenam=文件名
内嵌图片或者其他资源是,内嵌资源需要提供Content-ID属性,作为该资源唯一标识
* 在邮件正文中通过 <img src="cid:唯一标识" /> 引用内嵌图片和资源
JavaMail怎样描述一封复杂邮件
MimeMessage ----- 整封邮件
MimeBodyPart ---- 邮件每个部分
MimeMultiPart ---- 将BodyPart进行整合
1、判断邮件由几个部分组成,每个部分设计BodyPart
2、将BodyPart组合起来 ---- MultiPart(只有BodyPart之间可以组合,MultiPart不可以和其它BodyPart直接组合,需要组合将MultiPart转换BodyPart)
3、将最后合成MultiPart 交给MimeMessage 对象
总结一下:
1、发送内嵌图片 :图片设置ContentID,在邮件正文中cid:设置id引用目标图片,实现内嵌效果 ---- 图片关系related
2、发送携带附件 :附件中文名,setFileName设置,通过MimeUtility 对中文附件名进行编码 ---- 自动生成Content-Disposition字段 ---- 附件关系mixed
@Test
// 内嵌图片邮件
public void demo3() throws Exception {
// 发送邮件需要三个步骤
// 步骤一:创建Session
Properties properties = new Properties();
properties.put("mail.transport.protocol", "smtp");
properties.put("mail.smtp.host", "localhost");
properties.put("mail.smtp.auth", "true");// 连接认证
properties.put("mail.debug", "true");// 在控制台显示连接日志信息
Session session = Session.getInstance(properties);// 与邮件服务器连接会话
// 步骤二:创建Message
MimeMessage message = new MimeMessage(session);
// 设置邮件头(简单邮件和复杂邮件相同
message.setFrom(new InternetAddress("[email protected]"));
message.setRecipients(Message.RecipientType.TO, "[email protected]");
message.setSubject("javamail发送内嵌图片邮件");
// 设置邮件体(简单邮件和复杂邮件区别 就在于邮件体)
MimeBodyPart pic = new MimeBodyPart();// 图片
// 链接数据文件
pic.setDataHandler(new DataHandler(new FileDataSource("beauty.jpg")));
// DataSource dataSource = new FileDataSource("beauty.jpg");
// DataHandler dataHandler = new DataHandler(dataSource);
// pic.setDataHandler(dataHandler);
// 设置一个唯一标识(用于在正文中引入)
pic.setContentID("mypic");
MimeBodyPart content = new MimeBodyPart(); // 邮件正文
content.setContent("<h1>美女图片</h1><img src='cid:mypic' />",
"text/html;charset=utf-8");
// 将两个BodyPart整合
MimeMultipart mimeMultipart = new MimeMultipart();
mimeMultipart.addBodyPart(pic);
mimeMultipart.addBodyPart(content);
// 设置关系
mimeMultipart.setSubType("related");
message.setContent(mimeMultipart);
// message.writeTo(System.out);
// 步骤三:Transport发送邮件
Transport transport = session.getTransport();
transport.connect("aaa", "111");
transport.sendMessage(message, message.getAllRecipients());
}
@Test
//发送附件
public void demo3() throws MessagingException, UnsupportedEncodingException {
Properties properties = new Properties();
// 设置properties 属性
properties.put("mail.transport.protocol", "smtp");
properties.put("mail.smtp.host", "smtp.exmail.qq.com");
properties.put("mail.smtp.auth", "true");// 连接认证
// properties.put("mail.debug", "true");// 在控制台显示连接日志信息
Session session = Session.getInstance(properties);
// 步骤二 编写Message
MimeMessage message = new MimeMessage(session);// 代表一封邮件
// from字段
message.setFrom(new InternetAddress("[email protected]"));
// to 字段
message.setRecipients(Message.RecipientType.TO, "[email protected]");
// subject字段
message.setSubject("javamail发送携带附件邮件");
// 邮件正文内容
MimeBodyPart attache = new MimeBodyPart();
attache.setDataHandler(new DataHandler(new FileDataSource(
"大嘴巴 - maybe的机率.mp3")));
// 中文附件名的编码
attache.setFileName(MimeUtility.encodeText("大嘴巴 - maybe的机率.mp3"));// 自动生成mime
MimeBodyPart text = new MimeBodyPart();
text.setContent("<h1>附件是歌曲</h1>", "text/html;charset=utf-8");
MimeMultipart mm = new MimeMultipart();
mm.addBodyPart(attache);
mm.addBodyPart(text);
mm.setSubType("mixed");
message.setContent(mm);
// 步骤三 使用Transport发送邮件
Transport transport = session.getTransport();
// 发邮件前进行身份校验
transport.connect("[email protected]", "xxx");
transport.sendMessage(message, message.getAllRecipients());
}
--------------------------------------------------------------------------------------------------------------------
邮件发送综合案例:注册账户,发送激活邮件,去邮箱激活,进行登陆
* 如果账户未激活情况下,不允许用户登陆
1、功能一:用户注册(用户名、密码、邮箱)--- 在注册服务器端,发送一封激活邮件
2、功能二:去邮件,进行邮件激活
3、功能三:用户登陆(判断用户账户是否激活)
create table user(
id int primary key auto_increment,
username varchar(40) unique,
password varchar(40),
email varchar(100) unique ,
state int ,
activecode varchar(100),
updatetime timestamp
);
state为1 账户已经激活 state为0 账户未激活
activecode 激活码,在服务器端生成,当用户注册后,将激活码发到对方邮箱,并且将激活码保存数据库
账户激活有时间要求,在数据表保存updatetime,控制用户按时进行激活
***** 编写定时器 每隔6小时 运行一次,判断哪个账户已经24小时未激活,未激活,删除用户(发送通知邮件)
Tomcat对JavaMail的支持(JNDI访问) ----- 之前学习tomcat数据库连接池
1、在tomcat启动时,准备javamail 的session对象
2、在Servlet、JSP 通过JNDI方式 访问容器中Session对象
3、获得Session对象,发送邮件
配置javamail/Session
<Context>
<Resource name="mail/Session" auth="Container"
type="javax.mail.Session"
mail.smtp.host="localhost"
mail.transport.protocol="smtp"
mail.smtp.auth="true"
/>
</Context>
***** java.lang.ClassCastException: javax.mail.Session cannot be cast to javax.mail.Session
错误位置:Session session = (Session) envCtx.lookup("mail/Session");
错误原因:Java中类加载器顺序 (tomcat创建Session使用common加载器,加载tomcat/lib , Servlet中Session使用当前应用类加载器,加载WEB-INF/lib)
.java ---- 编译 ---- .class ----- 需要被JVM的类加载器程序进行加载 ---- java.lang.Class类对象
解决:将当前工程WEB-INF/lib/mail.jar删除
----------------------------------------------------------------------------------------------
MX与A记录(配置邮件服务器相关的信息)
MX记录:在DNS中进行注册,目的让其它服务器找到服务器地址
* 通过nslookup
set type=mx
sina.com
freemx.sinamail.sina.com.cn DNS查询MX记录 (发信不需要登陆)
smtp.sina.com 从网站上获得地址 (发信需要先登陆)
***** 如果连接MX记录中新浪服务器地址,发信,是不是也不需要登陆? A记录校验
*如果你用搜狐身份连接 新浪mx记录服务器,新浪服务器中会通过A记录 校验你的身份?
set type=a
sohu.com
Non-authoritative answer:
Name: sohu.com
Addresses: 61.135.181.175, 61.135.181.176
当你冒充搜狐去新浪发信时,新浪从DNS上获得sohu的A记录,比较来访者ip 与A记录ip是否相同,相同不是冒充的,不同证明冒充
A 记录:当别人以邮箱服务器身份连接不要认证mx记录时候,需要从DNS中获得对方A记录,与来访者IP进行笔记,进行身份验证
***** 自己搭建一个邮件服务器,千万不要忘记去DNS上注册MX记录和A记录