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("[email protected]", "xxxxx"); String subject = "这是一份测试邮件4"; Object content = "今天天气真好啊!<br/>注:附件为一封日志文件和图片"; SimpleMail mail = new SimpleMail(subject, content); try { // List<String> recipients = new ArrayList<String>(); // recipients.add("[email protected]"); // recipients.add("[email protected]"); // 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("[email protected]", 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(); } }
打开接收邮箱,可看到邮件:
主题:
附件: