Java Mail是利用已存在的邮箱账号,不必登录如网易邮箱,qq邮箱等官方邮箱网站而使用程序发送邮件。这在web中很常见,比如直接在招聘网站给hr发邮件就是一个典型运用。
利用Java Mail发送邮件的大致步骤:
1.首先,构建一个用于登录校验的类,确保你对此邮箱账户有发送邮件的权限。(相当于登录邮箱的过程)
public class MailAuthenticator extends Authenticator {
private String username;
private String password;
//带参数的构造器,初始化邮箱登录的用户名和密码
public MailAuthenticator(String username, String password) {
// super();
this.username = username;
this.password = password;
}
//重写该方法,获得 PasswordAuthentication 对象
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
2.简单邮件类,包括主题(subject)和内容(content)。
public class SimpleMail {
private String subject;
private Object content;
public SimpleMail(String subject, Object content) {
super();
this.subject = subject;
this.content = content;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public Object getContent() {
return content;
}
public void setContent(Object content) {
this.content = content;
}
}
3.发送邮件的工具类
3.1)一些必备属性 vs 邮件发送初始化(构造器)
//发送邮件的props文件
private Properties props = System.getProperties();
//邮件服务器的登录验证
private MailAuthenticator authenticator;
//邮箱发送会话
private Session session;
public MailSender(String username, String password) {
//根据发送邮箱的账号解析出smtp服务器
String smtpHostName = "smtp." + username.split("@")[1];
//初始化props
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.host", smtpHostName);
//发送验证
authenticator = new MailAuthenticator(username,password);
//创建邮箱收发会话的session
session = Session.getInstance(props, authenticator);
}
3.2)发送邮件的方法
情形一:简单邮件(不含附件)发送
//向一个人发送邮件
public void send(String recipient, SimpleMail mail) throws AddressException, MessagingException {
//根据session创建MimeMessage
MimeMessage message = new MimeMessage(session);
//发件人
message.setFrom(new InternetAddress(authenticator.getUsername()));
//收件人
message.setRecipient(RecipientType.TO, new InternetAddress(recipient));
//主题
message.setSubject(mail.getSubject());
//内容
message.setContent(mail.getContent().toString(), "text/html;charset=utf-8");
//发送
Transport.send(message);
}
情形二:简单邮件群发
只需把收件人改成一个集合,但传入message的recipient应为数组
public void send(List<String> recipients, SimpleMail mail) throws MessagingException {
//.............................
//收件人们
InternetAddress[] addresses = new InternetAddress[recipients.size()];
for(int i=0; i< addresses.length; i++) {
addresses[i] = new InternetAddress(recipients.get(i));
}
message.setRecipients(RecipientType.TO, addresses);
//..............................
}
情形三:带多个附件发送
//向一个人发送邮件(带多个附件)
public void send(String recipient, SimpleMail mail, List<File> attachments) throws AddressException, MessagingException, UnsupportedEncodingException {
//根据session创建MimeMessage
MimeMessage message = new MimeMessage(session);
//发件人
message.setFrom(new InternetAddress(authenticator.getUsername()));
//收件人
message.setRecipient(RecipientType.TO, new InternetAddress(recipient));
//主题
message.setSubject(mail.getSubject());
Multipart multipart = new MimeMultipart();
//邮件正文
BodyPart contentPart = new MimeBodyPart();
contentPart.setContent(mail.getContent(), "text/html;charset=utf-8");
multipart.addBodyPart(contentPart);
//邮件附件
if(attachments != null) {
for(File attachment : attachments) {
BodyPart attachmentPart = new MimeBodyPart();
DataSource source = new FileDataSource(attachment);
attachmentPart.setDataHandler(new DataHandler(source));
//避免中文乱码的处理
attachmentPart.setFileName(MimeUtility.encodeWord(attachment.getName()));
multipart.addBodyPart(attachmentPart);
}
}
message.setContent(multipart);
//保存邮件
message.saveChanges();
Transport.send(message);
}
注:带一个附件的写法很简单,就是把方法的形参变为File attachment,而邮件附件里不用for循环即可。同理,带多个附件和一个附件的群发原理大致,此处省略……
方法小结:
注意带附件和不带附件的写法上的区别——不带附件的简单邮件只需用MimeMessage 对象包装即可,加上设置其subject(主题),content(内容)即可发送;而带附件的邮件对象的正文需用Multipart 包装,其中Multipart 又包括邮件内容(content)和邮件附件,这两个字部分都是用BodyPart 包装的。
4.遇到的问题
1)java.lang.NoClassDefFoundError: com/sun/mail/util/LineInputStream
造成这个错误是由于mail.jar包里的javax.mail和javax.activation和java ee包里的javax.mail和javax.activation冲突了,只需到达myeclipse安装目录下找到java ee包里的javax.mail和javax.activation,把这两个目录删除即可——千万不要删除整个javaee.jar包!
2)javax.mail.AuthenticationFailedException: 454 Authentication failed, please open smtp flag first!
确保收发邮箱的SMTP/POP3功能已经开启!
5.测试类(以带多个附件的邮件发送为例)
public static void main(String[] args) {
SimpleMailSender sender = new SimpleMailSender("xxxxx@126.com", "xxxxx");
String subject = "这是一份测试邮件4";
Object content = "今天天气真好啊!<br/>注:附件为一封日志文件和图片";
SimpleMail mail = new SimpleMail(subject, content);
try {
// List<String> recipients = new ArrayList<String>();
// recipients.add("xxxx@sohu.com");
// recipients.add("xxxx@yean.net");
// sender.send(recipients, mail);
List<File> attaches = new ArrayList<File>();
File attach1 = new File("C:\\Users\\xxxx\\Desktop\\log.txt");
File attach2 = new File("C:\\Users\\xxx\\Desktop\\彩虹.jpg");
attaches.add(attach1);
attaches.add(attach2);
sender.send("yyyyy@sohu.com", mail, attaches);
System.out.println("发送成功!");
} catch (AddressException e) {
System.out.println("未找到接收邮箱");
e.printStackTrace();
} catch (MessagingException e) {
System.out.println("发送失败");
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
打开接收邮箱,可看到邮件:
主题:
内容:
附件: