Java使用JavaMail收发Email电子邮件
使用JavaMail收发送电子邮件,包括带有附件和内嵌图片的邮件!
Email就是电子邮件。发邮件是从客户端把邮件发送到邮件服务器,收邮件是把邮件服务器的邮件下载到客户端,Java同样提供了收发邮件的API。
163、126、QQ、sohu、sina等网站都提供了邮件服务,这些网站都有自己的邮件服务器,我们自己的Email用户页面实际上就相当于客户端。
文章目录
- 1 邮件协议
- 1.1 邮件协议
- 1.2 理解电子邮件收发过程
- 1.3 邮件服务器名称
- 2 JavaMail
- 2.1 JavaMail概述
- 2.2 maven依赖
- 2.3 JavaMail发送邮件
- 2.3.1 简单邮件
- 2.3.2 发送HTML文本
- 2.3.3 发送附件
- 2.3.4 发送内嵌图片HTML
- 2.4 JavaMail收取邮件
- 2.5 相关异常
- 3 总结
1 邮件协议
1.1 邮件协议
与HTTP协议相同,收发邮件也是需要有传输协议的:
- SMTP:(Simple Mail Transfer Protocol,简单邮件传输协议)发邮件协议;
- POP3:(Post Office Protocol Version 3,邮局协议第3版)收邮件协议;
- IMAP:(Internet Message Access Protocol,因特网消息访问协议)收发邮件协议。
这些协议都属于应用层协议。
1.2 理解电子邮件收发过程
其实你可以把邮件服务器理解为邮局!如果你需要给朋友寄一封信,那么你需要把信放到邮筒中,这样你的信会“自动”到达邮局,邮局会把信邮到另一个省市的邮局中。然后这封信会被送到收信人的邮箱中。最终收信人需要自己经常查看邮箱是否有新的信件。
其实每个邮件服务器都由SMTP服务器和POP3服务器构成,其中SMTP服务器负责发邮件的请求,而POP3负责收邮件的请求。
当然,有时我们也会使用163的账号,向126的账号发送邮件。这时邮件是发送到126的邮件服务器,而对于163的邮件服务器是不会存储这封邮件的。
1.3 邮件服务器名称
smtp服务器的端口号为25,服务器名称为smtp.xxx.xxx。
pop3服务器的端口号为110,服务器名称为pop3.xxx.xxx。
例如:
- 163: smtp.163.com和pop3.163.com;
- 126: smtp.126.com和pop3.126.com;
- qq: smtp.qq.com和pop3.qq.com;
- sohu: smtp.sohu.com和pop3.sohu.com;
- sina: smtp.sina.com和pop3.sina.com。
2 JavaMail
2.1 JavaMail概述
JavaMail是由SUN公司提供的专门用于Java收发邮件的API,使用Java程序发送邮件时,我们无需关心SMTP协议的底层原理,只需要使用JavaMail这个标准API就可以直接发送邮件。
JavaMail中主要类有javax.mail.Session、javax.mail.internet.MimeMessage、javax.mail.Transport
。
- Session: 表示会话,即客户端与邮件服务器之间的会话!想获得会话需要给出账户和密码,当然还要给出服务器名称。在邮件服务中的Session对象,就相当于连接数据库时的Connection对象。
- MimeMessage: 表示邮件类,它是Message的子类。它包含邮件的主题(标题)、内容,收件人地址、发件人地址,还可以设置抄送和暗送,甚至还可以设置附件。
- Transport: 用来发送邮件。它是发送器!
2.2 maven依赖
使用JavaMail的API我们需要引入对应的jar包或者maven依赖:
<!-- https://mvnrepository.com/artifact/com.sun.mail/javax.mail -->
<dependency><groupId>com.sun.mail</groupId><artifactId>javax.mail</artifactId><version>1.6.2</version>
</dependency>
jar包下载地址为:https://mvnrepository.com/artifact/com.sun.mail/javax.mail/1.6.2。
2.3 JavaMail发送邮件
我们使用smtp协议发送邮件!
2.3.1 简单邮件
发送一个简单的邮件需要三步:
- 根据服务器参数和认证器信息来获取Session实例;
- 根据Session创建MimeMessage对象,MimeMessage中包含了各种可以设置的邮件属性
- 通过Transport发送邮件
简单的案例如下:
/*** @author lx*/
public class SimpleSendEmail {public static void main(String[] args) throws MessagingException {/** 1 获取Session*//*设置服务器参数*/Properties props = new Properties();//设置服务器主机名props.put("mail.smtp.host", "smtp.163.com");//设置需要认证props.put("mail.smtp.auth", "true");// 启用TLS加密props.put("mail.smtp.starttls.enable", "true");/** 根据服务器参数集合和认证器来获取Session实例** Authenticator是一个接口表示认证器,即校验客户端的身份。* 我们需要自己来实现这个接口,实现这个接口需要使用账户和密码。*/Session session = Session.getInstance(props, new Authenticator() {@Overrideprotected PasswordAuthentication getPasswordAuthentication() {//使用自己的账户和密码,有些邮件服务器可能需要的是申请的授权码return new PasswordAuthentication("xxxx@163.com", "xxxx");}});// 设置debug模式,将会输出日志信息session.setDebug(true);/** 2 根据Session创建MimeMessage对象** MimeMessage中包含了各种可以设置的邮件属性*/MimeMessage msg = new MimeMessage(session);//设置发信人msg.setFrom(new InternetAddress("xxx@163.com"));//设置收信人,可以设置多个,采用参数数组或者","分隔msg.addRecipients(TO, "xxx@qq.com");//设置抄送人,可以设置多个,采用参数数组或者","分隔msg.addRecipients(CC, "xxx@yeah.net");//设置暗送人,可以设置多个,采用参数数组或者","分隔msg.addRecipients(BCC, "xxx@xx.com");//设置邮件主题(标题)msg.setSubject("第一封邮件");//设置邮件内容(正文)和类型msg.setContent("说点啥呢?", "text/plain;charset=utf-8");/** 3 发送邮件*/Transport.send(msg);}
}
2.3.2 发送HTML文本
有时候我们的邮件正文可能是一个HTML页面,发送方式和上面的案例完全一致,只需要注意编码格式为“text/html;charset=utf-8”,后面的字符集要与html文本的字符集一致。
当然,也可以发送图片资源等等。
/*** @author lx*/
public class SendHtmlEmail {public static void main(String[] args) throws MessagingException {/** 1 获取Session*//*设置服务器参数*/Properties props = new Properties();//设置服务器主机名props.put("mail.smtp.host", "smtp.163.com");//设置需要认证props.put("mail.smtp.auth", "true");// 启用TLS加密props.put("mail.smtp.starttls.enable", "true");/** 根据服务器参数集合和认证器来获取Session实例** Authenticator是一个接口表示认证器,即校验客户端的身份。* 我们需要自己来实现这个接口,实现这个接口需要使用账户和密码。*/Session session = Session.getInstance(props, new Authenticator() {@Overrideprotected PasswordAuthentication getPasswordAuthentication() {//使用自己的账户和密码,有些邮件服务器可能需要的是授权码return new PasswordAuthentication("xx@163.com", "xxx");}});// 设置debug模式,将会输出日志信息session.setDebug(true);/** 2 根据Session创建MimeMessage对象** MimeMessage中包含了各种可以设置的邮件属性*/MimeMessage msg = new MimeMessage(session);//设置发信人msg.setFrom(new InternetAddress("x@163.com"));//设置收信人,可以设置多个,采用参数数组或者","分隔msg.addRecipients(TO, "xx@qq.com");//设置抄送人,可以设置多个,采用参数数组或者","分隔msg.addRecipients(CC, "xxx@yeah.net");//设置暗送人,可以设置多个,采用参数数组或者","分隔msg.addRecipients(BCC, "xxx@ikang.com");//设置邮件主题(标题)msg.setSubject("HTML邮件");//设置邮件内容(正文)和类型msg.setContent("<h2><font color=red>2021加油哦!</font></h2>", "text/html;charset =utf-8");/** 3 发送邮件*/Transport.send(msg);}
}
结果:
2.3.3 发送附件
如果想发送带有附件邮件,那么需要设置邮件的内容为MimeMultiPart,而不仅仅是一段文本。
多部件对象MimeMultiPart,可以理解为是部件的集合。一个Multipart对象可以添加若干个BodyPart,其中第一个BodyPart是文本,即邮件正文,后面的BodyPart是附件,最后将MimeMultiPart设置到msg的content中。
案例如下:
/*** @author lx*/
public class SendMultipartEmail {public static void main(String[] args) throws MessagingException, IOException {/** 1 获取Session*//*设置服务器参数*/Properties props = new Properties();//设置服务器主机名props.put("mail.smtp.host", "smtp.163.com");//设置需要认证props.put("mail.smtp.auth", "true");// 启用TLS加密props.put("mail.smtp.starttls.enable", "true");/** 根据服务器参数集合和认证器来获取Session实例** Authenticator是一个接口表示认证器,即校验客户端的身份。* 我们需要自己来实现这个接口,实现这个接口需要使用账户和密码。*/Session session = Session.getInstance(props, new Authenticator() {@Overrideprotected PasswordAuthentication getPasswordAuthentication() {//使用自己的账户和密码,有些邮件服务器可能需要的是申请的授权码return new PasswordAuthentication("ccc@163.com", "ccc");}});// 设置debug模式,将会输出日志信息session.setDebug(true);/** 2 根据Session创建MimeMessage对象** MimeMessage中包含了各种可以设置的邮件属性*/MimeMessage msg = new MimeMessage(session);//设置发信人msg.setFrom(new InternetAddress("ccc@163.com"));//设置收信人,可以设置多个,采用参数数组或者","分隔msg.addRecipients(TO, "ccc@qq.com");//设置抄送人,可以设置多个,采用参数数组或者","分隔msg.addRecipients(CC, "cc@yeah.net");//设置暗送人,可以设置多个,采用参数数组或者","分隔msg.addRecipients(BCC, "c@ikang.com");//设置邮件主题(标题)msg.setSubject("附件");//设置邮件内容(正文)和类型//msg.setContent("<h2><font color=red>2021加油哦!</font></h2>", "text/html;charset =utf-8");/** 创建一个多部件对象Multipart,可以理解为是部件的集合。* 一个Multipart对象可以添加若干个BodyPart,其中第一个BodyPart是文本,即邮件正文,后面的BodyPart是附件*/Multipart parts = new MimeMultipart();/** 设置邮件的内容为多部件内容。*/msg.setContent(parts);/** 创建第一个部件,为邮件正文*/BodyPart contentPart = new MimeBodyPart();//给部件设置正文内容contentPart.setContent("<h2><font color=red>附件来了!</font></h2>", "text/html;charset=utf-8");//把部件添加到部件集中parts.addBodyPart(contentPart);/** 创建第二个附件部件,一张图片*/MimeBodyPart imagepart = new MimeBodyPart();//设置附件名称imagepart.setFileName("people.jpg");//注意,如果在设置文件名称时,文件名称中包含了中文的话,那么需要使用MimeUitlity类来给中文编码://imagepart.setFileName(MimeUtility.encodeText("中文.jpg"));//设置附件,二进制文件可以用application/octet-stream,Word文档则是application/msword。FileInputStream fileInputStream = new FileInputStream("email\\src\\main\\resources\\people.jpg");imagepart.setDataHandler(new DataHandler(new ByteArrayDataSource(fileInputStream, "application/octet-stream")));//把附件添加到部件集中parts.addBodyPart(imagepart);/** 3 发送邮件*/Transport.send(msg);}
}
结果:
2.3.4 发送内嵌图片HTML
发送的HTML文本的内嵌图片可以采用网络链接,也可以使用本地图片。本地内嵌图片实际上也是一个附件,即邮件本身也是Multipart,但需要做一点额外的处理。
在HTML邮件中引用图片时,需要设定一个ID,用类似<img src=“cid:img1”>引用,然后,在添加图片作为BodyPart时,除了要正确设置MIME类型(根据图片类型使用image/jpeg或image/png),还需要设置ContentID为img1与HTML的中的img 标签的img1关联。
/*** @author lx*/
public class SendPicEmail {public static void main(String[] args) throws MessagingException, IOException {/** 1 获取Session*//*设置服务器参数*/Properties props = new Properties();//设置服务器主机名props.put("mail.smtp.host", "smtp.163.com");//设置需要认证props.put("mail.smtp.auth", "true");// 启用TLS加密props.put("mail.smtp.starttls.enable", "true");/** 根据服务器参数集合和认证器来获取Session实例** Authenticator是一个接口表示认证器,即校验客户端的身份。* 我们需要自己来实现这个接口,实现这个接口需要使用账户和密码。*/Session session = Session.getInstance(props, new Authenticator() {@Overrideprotected PasswordAuthentication getPasswordAuthentication() {//使用自己的账户和密码,有些邮件服务器可能需要的是申请的授权码return new PasswordAuthentication("xxx@163.com", "xx");}});// 设置debug模式,将会输出日志信息session.setDebug(true);/** 2 根据Session创建MimeMessage对象** MimeMessage中包含了各种可以设置的邮件属性*/MimeMessage msg = new MimeMessage(session);//设置发信人msg.setFrom(new InternetAddress("cc@163.com"));//设置收信人,可以设置多个,采用参数数组或者","分隔msg.addRecipients(TO, "dd@ikang.com");//设置抄送人,可以设置多个,采用参数数组或者","分隔msg.addRecipients(CC, "cc@yeah.net");//设置暗送人,可以设置多个,采用参数数组或者","分隔msg.addRecipients(BCC, "xx@qq.com");//设置邮件主题(标题)msg.setSubject("这是一封图片HTML邮件");//设置邮件内容(正文)和类型//msg.setContent("<h2><font color=red>2021加油哦!</font></h2>", "text/html;charset =utf-8");/** 创建一个多部件对象Multipart,可以理解为是部件的集合。* 一个Multipart对象可以添加若干个BodyPart,其中第一个BodyPart是文本,即邮件正文,后面的BodyPart是附件*/Multipart parts = new MimeMultipart();/** 设置邮件的内容为多部件内容。*/msg.setContent(parts);/** 创建第一个部件,为邮件正文*/BodyPart contentPart = new MimeBodyPart();//给部件设置正文内容contentPart.setContent("<h1>Hello图片来了!</h1><p><img src='cid:img1'></p>", "text/html;charset=utf-8");//把部件添加到部件集中parts.addBodyPart(contentPart);/** 创建第二个部件,一张图片,html中的图片也算作附件*/MimeBodyPart imagepart = new MimeBodyPart();//设置附件名称imagepart.setFileName("people.jpg");//注意,如果在设置文件名称时,文件名称中包含了中文的话,那么需要使用MimeUitlity类来给中文编码://imagepart.setFileName(MimeUtility.encodeText("中文.jpg"));//设置附件,二进制文件可以用application/octet-stream,Word文档则是application/msword。FileInputStream fileInputStream = new FileInputStream("email\\src\\main\\resources\\people.jpg");imagepart.setDataHandler(new DataHandler(new ByteArrayDataSource(fileInputStream, "image/jpeg")));//设置ContentID与HTML的中的<img src="cid:img01">关联imagepart.setContentID("img1");//把附件添加到部件集中parts.addBodyPart(imagepart);/** 3 发送邮件*/Transport.send(msg);}
}
2.4 JavaMail收取邮件
我们使用pop3协议收取邮件!
public class ReceiveEmail {public static void main(String[] args) throws MessagingException {//POP3主机名String host = "pop3.163.com";//设置传输协议String protocol = "pop3";//用户账号String username = "15732631416@163.com";//密码或者授权码String password = "NPYRDKGYNSZIRZYO";/** 获取Session*/Properties props = new Properties();//协议props.setProperty("mail.store.protocol", protocol);//POP3主机名props.setProperty("mail.pop3.host", host);props.setProperty("mail.smtp.auth", "true");Session session = Session.getInstance(props);session.setDebug(true);/** 获取Store,一个Store对象表示整个邮箱的存储**/URLName urlName = new URLName(protocol, host, 110, null, username, password);Store store = session.getStore(urlName);//连接邮件服务器store.connect();//要收取邮件,我们需要通过Store访问指定的Folder(文件夹),通常是INBOX表示收件箱//获取邮箱的邮件夹,通过pop3协议获取某个邮件夹的名称只能为inbox,不区分大小写Folder folder = store.getFolder("INBOX");//打开邮箱方式(邮件访问权限),这里的只读权限folder.open(Folder.READ_ONLY);//打印邮件总数/新邮件数量/未读数量/已删除数量:System.out.println("Total messages: " + folder.getMessageCount());System.out.println("New messages: " + folder.getNewMessageCount());System.out.println("Unread messages: " + folder.getUnreadMessageCount());System.out.println("Deleted messages: " + folder.getDeletedMessageCount());// 获得邮件夹Folder内的所有邮件Message对象,一个Message代表一个邮件Message[] messages = folder.getMessages();for (Message message : messages) {/*解析邮件*///获取主题String subject = message.getSubject();System.out.println(subject);//解析其他内容//………………}//传入true表示删除操作会同步到服务器上(即删除服务器收件箱的邮件),无参方法默认传递truefolder.close();store.close();}
}
2.5 相关异常
- Exception in thread “main” com.sun.mail.smtp.SMTPSendFailedException: 554 DT:SPM
- 一般是被邮件服务器识别为垃圾邮件,可以换个复杂点的主题和内容,或者换台主机发送。这很麻烦,比如在运行上面的案例时就有可能抛出这样的异常!
- Exception in thread “main” javax.mail.AuthenticationFailedException: 535 Error: authentication failed
- PasswordAuthentication中的用户登陆信息错误,可能是密码或者授权码错误。
- Exception in thread “main” com.sun.mail.smtp.SMTPSendFailedException: 553 Mail from must equal authorized user
- 如果用户信息和发件人信息不一致
3 总结
本次我们学习了使用JavaMail的API简单的收发邮件的过程,电子邮件的收发需要使用道SMTP和POP3协议。在实际开发中,这样的底层API我们用的比较少,因为代码编写很麻烦,因此本文了解就行了。
在实际项目开发中,常常使用Spring框架为我们提供的更高级的发送邮件的API。
如有需要交流,或者文章有误,请直接留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!
Java使用JavaMail收发Email电子邮件相关推荐
- java中javamail收发邮件实现方法
概述 1.邮件相关的标准 厂商所提供的 JavaMail 服务程序可以有选择地实现某些邮件协议,常见的邮件协议包括: SMTP(Simple Mail Transfer Protocol) :即简单邮 ...
- [新星计划] Python smtplib模块 | 轻松学会收发E-mail(电子邮件)
文章目录 ● 理论知识 ■ smtplib模块作用 ■ 邮件协议 ● 实操步骤 ■ QQ邮箱获取授权码 ■ 代码部分 □ 示例1 □ 示例2 □ 示例3 ■ Foxmail登录 □ 使用POP3协议登 ...
- java 邮件收发_java中javamail收发邮件实现方法
概述 1.邮件相关的标准 厂商所提供的 JavaMail 服务程序可以有选择地实现某些邮件协议,常见的邮件协议包括: SMTP(Simple Mail Transfer Protocol) :即简单邮 ...
- Java 使用JavaMail通过Gmail发送电子邮件
JavaMail提供给开发者处理电子邮件相关的编程接口.它是Sun发布的用来处理email的API可以方便地执行一些常用的邮件传输.可以基于JavaMail开发出类似于Microsoft Outloo ...
- java mail 收 附件_使用 JavaMail 收发邮件,解决中文附件问题
几天来一直在开发一个项目,其中一部分需要用 JavaMail 收发邮件,于是就在网上找了一些相关的源代码,最后经过整理和修改,终于好使了,希望能够给使用 JavaMail 收发邮件的朋友提供一个参考 ...
- java applet 在线demo_编写可在线收发E-mail的Java Applet
编写可在线收发E-mail的Java Applet 作者:未知 文章来源:www.jspcn.net 发布日期:2005年01月19日 说起Java,有些人可能会想到一些用于修饰主页的Apple ...
- Android Java使用JavaMail API发送和接收邮件的代码示例
JavaMail是Oracle甲骨文开发的Java邮件类API,支持多种邮件协议,这里我们就来看一下Java使用JavaMail API发送和接收邮件的代码示例 使用Javamail发送邮件,必需的j ...
- python模块之email: 电子邮件编码解码 (一、解码邮件)
https://yq.aliyun.com/articles/54621 python模块之email: 电子邮件编码解码 (一.解码邮件) python自带的email模块是个很有意思的东西,它可以 ...
- Java基于JavaMail实现向QQ邮箱发送邮件遇到的问题
最近使用Java基于JavaMail实现向QQ邮箱发送邮件老是发送失败,在网上搜了下,终于找到原因,记录下. 参考:http://www.jb51.net/article/78405.htm 网上还有 ...
- java 使用 Amazon SES 发送电子邮件
java 使用 Amazon SES发送电子邮件,有三种方式,具体哪三种请移步这里. 这里只介绍一种:利用Amazon SES 的 SMTP 服务,javax.mail发送邮件.此方法也可以直接用于1 ...
最新文章
- pandas写excel报错ModuleNotFoundError: No module named ‘xlwt‘
- HUAWEI视讯技术学习笔记(转载)
- 柱状图中最大的矩形—leetcode84
- leetcode713. 乘积小于K的子数组(双指针)
- php重度写如何优化,win10玩游戏掉帧严重怎么处理
- 洛克人html5,《洛克人Zero/Zx合集》:跳票冷饭,与预期有差但依旧很香
- 利用XMLHTTP无刷新添加数据之Post篇(转)
- 【Python】学习笔记2-数据类型:数组、数组循环切片
- 百度高德谷歌地图与大地坐标系相互转换
- Maya2018安装报错:visual c++ 2010 sp1 错误代码1612
- 学科分类号 计算机技术,学科分类号 0806.DOC
- PHPExcel出现 Formula Error的解决方案
- 跳槽进阿里了,面试阿里P6也没那么难。
- 爬取某视频网站电影,仅参考学习
- 现代密码学导论-10-EAV安全
- 【Linux进程间通信】二、pipe管道
- cqp VS bitrate VS crf [学习笔记]
- CSP2020考试感悟
- TypeScript(ts)笔记总结01
- 【论文解读】Optimizing FPGA-based Accelerator Design for Deep Convolutional Neural Networks