首先,你需要准备2个jar包:mail.jar以及activation.jar 可以去网上下载。
发送邮件部分
MailTest.java
package com.lrb.java.mail.test;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
public class MailTest {
private MimeMessage mimMsg;//MIME邮件对象
private Session session;//邮件会话属性
private Properties prop;//系统属性
private String username = "";//smtp认证用户名密码
private String password = "";
private Multipart mp;//Multipart对象,邮件内容,标题,附件等内容均添加到其中后再生成MIME对象
public MailTest(String smtp){
setSmtpHost(smtp);
createMimeMessage();
}
/**
* 设置SMTP主机
* @param hostName String 主机名
*/
public void setSmtpHost(String hostName){
if(prop == null) prop = System.getProperties();//获得系统属性对象
prop.put("mail.smtp.host", hostName);//设置SMTP主机
}
/**
* 获得会话,并创建邮件对象
* @return boolean
*/
public boolean createMimeMessage(){
try {
session = Session.getDefaultInstance(prop,new SmtpAuth(this.username,this.password));//获得邮件会话对象
mimMsg = new MimeMessage(session);//创建MIME邮件对象
mp = new MimeMultipart();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 设置是否需要验证
* @param need boolean
*/
public void setNeedAuth(boolean need){
if(this.prop == null) this.prop = System.getProperties();
if(need){
this.prop.put("mail.smtp.auth", "true");
}else{
this.prop.put("mail.smtp.auth", "false");
}
}
/**
* 设置用户名、密码
* @param name String
* @param pass String
*/
public void setNamePass(String name,String pass){
username = name;
password = pass;
}
/**
* 设置标题
* @param mailSubject String
* @return boolean
*/
public boolean setSubject(String mailSubject){
try {
mimMsg.setSubject(mailSubject);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 设置邮件正文
* @param mailBody String
* @return boolean
*/
public boolean setBody(String mailBody){
try {
BodyPart bp = new MimeBodyPart();
bp.setContent("<meta http-equiv=Content-Type content=text/html; charset=gb2312>"+mailBody, "text/html;charset=GB2312");
mp.addBodyPart(bp);
return true;
} catch (Exception e) {
System.err.println("设置邮件正文时错误:"+e);
return false;
}
}
/**
* 添加附件
* @param fileName String
* @return boolean
*/
public boolean addFileAffix(String fileName){
try {
BodyPart bp = new MimeBodyPart();
FileDataSource fds = new FileDataSource(fileName);
bp.setDataHandler(new DataHandler(fds));
bp.setFileName(fds.getName());
mp.addBodyPart(bp);
return true;
} catch (Exception e) {
System.err.println("增加邮件附件:"+fileName+"发生错误"+e);
return false;
}
}
/**
* 设置发件人
* @param from String
* @return boolean
*/
public boolean setFrom(String from){
try {
mimMsg.setFrom(new InternetAddress(from));
return true;
} catch (Exception e) {
System.err.println("设置发件人:"+from+"时出错"+e);
return false;
}
}
/**
* 设置收件人(one)
* @param to String
* @return boolean
*/
public boolean setTo(String to){
try {
mimMsg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
return true;
} catch (Exception e) {
System.err.println("设置收件人:"+to+"时出错"+e);
return false;
}
}
/**
* 设置收件人(one or many)
* @param to InternetAddress[]
* @return boolean
*/
public boolean setTo(InternetAddress[] to){
if(to == null) return false;
try {
mimMsg.setRecipients(Message.RecipientType.TO, to);
return true;
} catch (Exception e) {
System.err.println("设置收件人:"+to+"时出错"+e);
return false;
}
}
/**
* 设置抄送人
* @param copyTo String
* @return boolean
*/
public boolean setCopyTo(String copyTo){
if(copyTo == null) return false;
try {
mimMsg.setRecipients(Message.RecipientType.CC, (Address[])InternetAddress.parse(copyTo));
return true;
} catch (Exception e) {
return false;
}
}
/**
* 发送操作
* @return boolean
*/
public boolean send(){
try {
mimMsg.setContent(mp);
mimMsg.saveChanges();
Transport transport = session.getTransport("smtp");
System.out.println(prop.getProperty("mail.smtp.host"));
System.out.println(prop.getProperty("mail.smtp.auth"));
transport.connect((String)prop.getProperty("mail.smtp.host"), username, password);
transport.sendMessage(mimMsg, mimMsg.getAllRecipients());
transport.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 开始测试,主程序
* @author lrb
* @param args
*/
public static void main(String[] args) {
String mailBody = "<meta http-equiv=Content-Type content=text/html; charset=gb2312>"
+"<div align=center> 使用程序自动发送邮件测试,请勿回复 </div>";
InternetAddress[] to = new InternetAddress[2];
try {
to[0] = new InternetAddress("lrbyantai@163.com");
to[1] = new InternetAddress("383405808@qq.com");
} catch (Exception e) {
e.printStackTrace();
}
MailTest mt = new MailTest("smtp.qq.com");
mt.setNeedAuth(true);
if(mt.setSubject("密码保护的注册资料(请不要回复)") == false) return;
if(mt.setBody(mailBody) == false) return;
if(mt.setTo(to) == false) return;
if(mt.setFrom("383405808@qq.com") == false) return;
if(mt.addFileAffix("c://test.xls") == false) return;
mt.setNamePass("你的邮箱地址(此处使用QQ邮箱为例,需要登录邮箱将相应服务开启)", "你的邮箱密码");
if(mt.send() == false) return;
}
}
SmtpAuth.java
package com.lrb.java.mail.test;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
public class SmtpAuth extends Authenticator {
private String uname,pwd;
public SmtpAuth(String username,String password){
this.uname = username;
this.pwd = password;
}
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(uname,pwd);
}
}
=================================================================================================
以下为接收邮件部分操作
MailReceiveTest.java
package com.lrb.java.mail.test;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import javax.mail.BodyPart;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.URLName;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
public class MailReceiveTest {
private MimeMessage mimMsg;
private String saveAttatchPath = "";//附件下载后的保存目录
private StringBuffer contentTxt = new StringBuffer();//存放邮件内容
private String dataFormat = "yyyy-MM-dd HH:mm:ss";//日期显示格式
/**
* 构造函数
* @param msg MimeMessage
*/
public MailReceiveTest(MimeMessage msg){
this.mimMsg = msg;
}
/**
* 设置MimeMessage对象
* @param mimeMessage MimeMessages
*/
public void setMimeMessage(MimeMessage mimeMessage){
this.mimMsg = mimeMessage;
}
/**
* 获得发件人的姓名和地址
* @return String
*/
public String getFrom(){
String fromAddr = "";
try {
InternetAddress[] addr = (InternetAddress[]) mimMsg.getFrom();
String from = addr[0].getAddress();
String personal = addr[0].getPersonal();
from = from == null?"":from;
personal = personal == null?"":personal;
fromAddr = personal + "<" + from+ ">";
} catch (Exception e) {
e.printStackTrace();
}
return fromAddr;
}
/**
* 获得邮件的收件人,抄送和密送的地址和姓名,根据所传递的参数的不同
* @param type String ("to"--收件人地址;"cc"--抄送人地址;"bcc"--密送人地址)
* @return String
*/
public String getOtherAddr(String type){
String mailAddr = "";
String addType = type.toUpperCase();
InternetAddress[] addr = null;
try {
if("TO".equals(addType) || "CC".equals(addType) || "BCC".equals(addType)){
if("TO".equals(addType))
addr = (InternetAddress[]) mimMsg.getRecipients(Message.RecipientType.TO);
else if("CC".equals(addType))
addr = (InternetAddress[]) mimMsg.getRecipients(Message.RecipientType.CC);
else
addr = (InternetAddress[]) mimMsg.getRecipients(Message.RecipientType.BCC);
if(addr != null
&& addr.length>0){
for(int i=0;i<addr.length;i++){
String mAddr = addr[i].getAddress();
String personal = addr[i].getPersonal();
mAddr = mAddr == null?"":new String(mAddr.getBytes("iso8859-1"),"gb2312");
personal = personal == null?"":new String(personal.getBytes("iso8859-1"),"gb2312");
String each = personal + "<" + mAddr +">";
mailAddr += "," + each; //拼接所有地址字符串
}
mailAddr = mailAddr.substring(1);//截取第一个逗号分隔符
}else{
return "";
}
}else{
throw new Exception("错误邮件地址类型");
}
} catch (Exception e) {
e.printStackTrace();
}
return mailAddr;
}
/**
* 获得邮件主题
* @return String
* @throws UnsupportedEncodingException
* @throws MessagingException
*/
public String getSubject() throws UnsupportedEncodingException, MessagingException{
String subject = "";
System.err.println(MimeUtility.encodeText(this.mimMsg.getSubject()));
try {
subject = mimMsg.getSubject();
subject = subject == null ? "" : MimeUtility.decodeText(subject);
} catch (Exception e) {
e.printStackTrace();
}
return subject;
}
/**
* 获得发送日期
* @return String
*/
public String getSendDate(){
String dateStr = "";
try {
Date date = mimMsg.getSentDate();
dateStr = new SimpleDateFormat(dataFormat).format(date);
} catch (Exception e) {
e.printStackTrace();
}
return dateStr;
}
/**
* 获得邮件正文内容
* @return String
* @throws UnsupportedEncodingException
*/
public String getContent() throws UnsupportedEncodingException{
return this.contentTxt.toString();
}
/**
* 根据MimeType类型的不同解析邮件,将邮件内容保存到StringBuffer中
* @param part Part
*/
public void getMailContent(Part part){
try {
String contentType = part.getContentType();
int nameIndex = contentType.indexOf("name");
boolean conName = false;
if(nameIndex != -1){
conName = true;
}
System.err.println("contentType:"+contentType);
if(part.isMimeType("text/plain") && !conName){
contentTxt.append(part.getContent());
//客户程序从javamail取得的正文内容字符集为iso-8859-1,所以还要将字符集转换一下
if(contentType.toLowerCase().indexOf("charset") == -1){
this.contentTxt = new StringBuffer(new String(this.contentTxt.toString().getBytes("iso-8859-1"),"gb2312"));
}
}else if(part.isMimeType("text/html") && !conName){
contentTxt.append(part.getContent());
//客户程序从javamail取得的正文内容字符集为iso-8859-1,所以还要将字符集转换一下
if(contentType.toLowerCase().indexOf("charset") == -1){
this.contentTxt = new StringBuffer(new String(this.contentTxt.toString().getBytes("iso-8859-1"),"gb2312"));
}
}else if(part.isMimeType("multipart/*")){
Multipart multipart = (Multipart) part.getContent();
int count = multipart.getCount();
for(int i=0;i<count;i++){
getMailContent(multipart.getBodyPart(i));
}
}else if(part.isMimeType("message/rfc822")){
getMailContent((Part) part.getContent());
}else{}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 判断是否需要回执,需要返回true,不需要返回false
* @return boolean
*/
public boolean getRelySign(){
try {
String needReply[] = mimMsg.getHeader("Disposition-Notification-To");
if(needReply != null) return true;
else return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 获得此邮件的Message-ID
* @return String
* @throws MessagingException
*/
public String getMsgId() throws MessagingException{
return this.mimMsg.getMessageID();
}
/**
* 判断邮件是否已读,如果已读返回true,未读返回false
* @return boolean
*/
public boolean isRead(){
try {
Flags flags = this.mimMsg.getFlags();
Flags.Flag[] flag = flags.getSystemFlags();
System.out.println("Flags' length:"+flag.length);
for(int i=0;i<flag.length;i++){
if(flag[i] == Flags.Flag.SEEN){
System.out.println("Message is Read!");
return true;
}
}
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 判断邮件是否包含附件
* @param part Part
* @return boolean
*/
public boolean isContainAttach(Part part){
boolean flag = false;
try {
String contenType = part.getContentType();
if(part.isMimeType("multipart/*")){
Multipart mp = (Multipart) part.getContent();
for(int i=0;i<mp.getCount();i++){
BodyPart bp = mp.getBodyPart(i);
String disposition = bp.getDisposition();
if(disposition != null
&& (disposition.equalsIgnoreCase(Part.ATTACHMENT) || disposition.equalsIgnoreCase(Part.INLINE))){
flag = true;
}else if(bp.isMimeType("multipart/*")){
flag = isContainAttach(bp);
}else{
String conType = bp.getContentType();
if(conType.toLowerCase().indexOf("application") != -1){
flag = true;
}else if(conType.toLowerCase().indexOf("name") != -1){
flag = true;
}
}
}
}else if(part.isMimeType("message/rfc822")){
flag = isContainAttach((Part) part.getContent());
}
} catch (Exception e) {
e.printStackTrace();
flag = false;
}
return flag;
}
/**
* 保存附件(可与isContainAttach方法合并为同一个):获取文件名后,调用保存文件方法进行保存
* @param part Part
*/
public void saveAttachment(Part part){
try {
String fileName = "";
if(part.isMimeType("multipart/*")){
Multipart mp = (Multipart) part.getContent();
for(int i=0;i<mp.getCount();i++){
BodyPart bp = mp.getBodyPart(i);
String disposition = bp.getDisposition();
if(disposition != null
&& (disposition.equalsIgnoreCase(Part.ATTACHMENT) || disposition.equalsIgnoreCase(Part.INLINE))){
fileName = bp.getFileName();
if(fileName != null && !"".equals(fileName)){
if(fileName.toLowerCase().indexOf("gb2312")!= -1
|| fileName.toLowerCase().indexOf("gbk")!= -1){
fileName = MimeUtility.decodeText(fileName);
}
saveFile(fileName, bp.getInputStream());
}
}else if(bp.isMimeType("multipart/*")){
saveAttachment(bp);
}else{
fileName = bp.getFileName();
if(fileName != null && !"".equals(fileName)){
if(fileName.toLowerCase().indexOf("gb2312")!= -1
|| fileName.toLowerCase().indexOf("gbk")!= -1){
fileName = MimeUtility.decodeText(fileName);
}
saveFile(fileName, bp.getInputStream());
}
}
}
}else if(part.isMimeType("message/rfc822")){
saveAttachment((Part) part.getContent());
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 在指定目录下保存附件文件
* @param fileName String
* @param in InputStream
*/
public void saveFile(String fileName, InputStream in){
BufferedOutputStream bos = null;
BufferedInputStream bis = null;
try {
String osName = System.getProperty("os.name");
String storeDir = this.saveAttatchPath;
String separator = System.getProperty("file.separator");
osName = osName == null ? "" : osName;
if(osName.toUpperCase().indexOf("WIN") != -1){
if(storeDir == null || storeDir.equals("")){
storeDir = "C:\\tmp";
}
}else{
storeDir = "/tmp";
}
File storeFile = new File(storeDir+separator+fileName);
System.out.println("storeFile's path:"+storeFile.toString());
bos = new BufferedOutputStream(new FileOutputStream(storeFile));
bis = new BufferedInputStream(in);
int m;
while((m = bis.read()) != -1){
bos.write(m);
bos.flush();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
bos.close();
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 设置附件保存路径
* @param path String
*/
public void setAttachPaht(String path){
this.saveAttatchPath = path;
}
/**
* 设置日期格式
* @param format String
*/
public void setDateFormat(String format){
this.dataFormat = format;
}
/**
* 开始测试 ---------------
* @throws MessagingException
* @throws UnsupportedEncodingException
*/
public static void main(String[] args) throws MessagingException, UnsupportedEncodingException {
Properties props = System.getProperties();
props.put("mail.smtp.host", "smtp.163.com");
props.put("mail.smtp.auth", "true");
Session session = Session.getDefaultInstance(props,null);
//URLName参数 pop3--协议,pop3.163.com--主机,110--pop3端口号,null--file,用户名,密码
URLName urlName = new URLName("pop3","pop3.163.com",110,null,"你的邮箱地址(此处使用163邮箱为例)","你的邮箱密码");
//使用SSL加密传输协议,gmail可以使用ssl协议来保证邮件传输的安全,使用SSL的POP3S的默认端口为995。
//URLName url=new URLName("pop3s","pop.gmail.com",995,null,"用户名","密码");
Store store = session.getStore(urlName);
store.connect();
//从邮件服务器中返回邮箱内的信息
Folder folder = store.getFolder("INBOX");
//打开Folder
folder.open(Folder.READ_ONLY);
Message msg[] = folder.getMessages();
System.out.println("Message's length:"+msg.length);
System.out.println("您的邮箱中共有"+folder.getMessageCount()+"封邮件。其中有"
+folder.getUnreadMessageCount()+"封已读邮件,"+folder.getNewMessageCount()
+"封未读邮件");
for(int i=0;i<msg.length;i++){
System.out.println("=====================");
MailReceiveTest mrt = new MailReceiveTest((MimeMessage) msg[i]);
System.out.println("contentType:"+mrt.mimMsg.getContentType());
//主题
System.out.println("Message "+(i+1)+" subject:"+mrt.getSubject());
//发送日期
System.out.println("Message "+(i+1)+" sendDate:"+mrt.getSendDate());
//是否回执
System.out.println("Message "+(i+1)+" replySign:"+mrt.getRelySign());
//是否已读
System.out.println("Message "+(i+1)+" hasRead:"+mrt.isRead());
//是否包含附件
System.out.println("Message "+(i+1)+" hasAttachment:"+mrt.isContainAttach(msg[i]));
//发件人
System.out.println("Message "+(i+1)+" from:"+mrt.getFrom());
//收信人地址
System.out.println("Message "+(i+1)+" to:"+mrt.getOtherAddr("to"));
//抄送地址
System.out.println("Message "+(i+1)+" cc:"+mrt.getOtherAddr("cc"));
//密送地址
System.out.println("Message "+(i+1)+" bcc:"+mrt.getOtherAddr("bcc"));
//设置日期格式
mrt.setDateFormat("yy年MM月dd日 HH:mm:ss");
//发送日期(第二次打印输出)
System.out.println("Message "+(i+1)+" sendDate2:"+mrt.getSendDate());
//Message-ID
System.out.println("Message "+(i+1)+" Message-ID:"+mrt.getMsgId());
//获得邮件内容
mrt.getMailContent(msg[i]);
System.out.println("Message "+(i+1)+" mailContent:"+mrt.getContent());
//设置附件保存路径
mrt.setAttachPaht("D:\\");
//保存附件
mrt.saveAttachment(msg[i]);
if(i>=4) break; //由于邮箱邮件太多,只取前5封邮件
}
folder.close(true);
store.close();
}
}
因涉及邮箱隐私,控制台输出部分暂且忽略,各位同学可以用自己的邮箱做试验。
在接收邮件时考虑了中文乱码的问题,以及附件下载的问题。
做过实验的细心的同学可能会发现,使用POP3协议无法获取邮件的已读和未读状态。虽然使用了javamail的相关方法,但是得不到相应的数据。在这里就用到了IMAP协议。后面我会做一个使用IMAP接收邮件的例子。