Java 发送邮件
方式:
方式1:只依赖 javax.mail
依赖:
1 <dependency> 2 <groupId>javax.mail</groupId> 3 <artifactId>mail</artifactId> 4 <version>1.4.7</version> 5 </dependency>
示例代码:
1 package cn.edu.buaa.act.mail; 2 3 import java.util.Date; 4 import java.util.Properties; 5 6 import javax.activation.DataHandler; 7 import javax.activation.DataSource; 8 import javax.activation.FileDataSource; 9 import javax.mail.Address; 10 import javax.mail.Authenticator; 11 import javax.mail.BodyPart; 12 import javax.mail.Message; 13 import javax.mail.Multipart; 14 import javax.mail.PasswordAuthentication; 15 import javax.mail.Session; 16 import javax.mail.Transport; 17 import javax.mail.internet.InternetAddress; 18 import javax.mail.internet.MimeBodyPart; 19 import javax.mail.internet.MimeMessage; 20 import javax.mail.internet.MimeMultipart; 21 22 public class SendEmail { 23 24 private boolean validate = true; 25 // 发送者邮箱名 26 private String username = "monitor_car"; 27 // 发件人邮箱 28 private String FROM = username + "@163.com"; 29 // 发送者邮箱密码 30 private String password = "xxxx123"; 31 // 邮件显示的发件人 32 private String FROM_NAME = "zhangyang"; 33 // 邮件服务器 34 private String Email_Host = "smtp.163.com"; 35 // 邮件标题 36 private String Email_Subject = "开会通知"; 37 // 邮件头 38 private String Email_Header = "This Is Email Header"; 39 // 邮件内容 40 private String Email_Body = "<a href=\"http://www.baidu.com\">This Is Email Body</a>"; 41 // 收件人邮箱 42 private String TO = "xxxx@163.com"; 43 44 public void doSendEmail(int mailType) { 45 46 // 获取系统环境 47 Properties prop = new Properties(); 48 Authenticator auth = null; 49 // 判断发送邮件是否需要验证 50 if (validate) { 51 // 邮件服务器认证 用户名和密码 52 auth = new Authenticator() { 53 protected PasswordAuthentication getPasswordAuthentication() { 54 return new PasswordAuthentication(username, password); 55 } 56 }; 57 } 58 // 添加必要的信息 59 prop.put("mail.smtp.host", Email_Host); 60 prop.put("mail.smtp.auth", validate); 61 62 // 设置对话和邮件服务器进行通讯 63 Session session = Session.getDefaultInstance(prop, auth); 64 // 在控制台显示Debug信息 65 session.setDebug(true); 66 // 设置邮件对象 67 Message message = new MimeMessage(session); 68 try { 69 // 设置邮件主题 70 message.setSubject(Email_Subject); 71 // 设置邮件标题 72 message.setHeader("Header", Email_Header); 73 // 设置发送时间 74 message.setSentDate(new Date()); 75 76 // 设置发信人地址 和 名字 77 Address address = new InternetAddress(FROM, FROM_NAME); 78 // 把发件人信息添加到信息中 79 message.setFrom(address); 80 81 // 设置发件人地址 82 Address toAddress = new InternetAddress(TO); 83 // 设置接收人地址 84 message.setRecipient(Message.RecipientType.TO, toAddress); 85 86 // 设置多个收件人地址 87 // message.addRecipient(Message.RecipientType.TO,new 88 // InternetAddress("xxx@xxx.com")); 89 90 // 设置邮件格式 91 switch (mailType) { 92 case 1:// 发送纯文本邮件 93 message.setContent(Email_Body, "text/plain; charset=utf-8"); 94 break; 95 case 2:// 发送html邮件 96 message.setContent(Email_Body, "text/html; charset=utf-8"); 97 break; 98 case 3:// 发送附件 99 message.setContent(Email_Body, "text/html; charset=utf-8"); 100 101 Multipart multipart = new MimeMultipart(); 102 // 邮件正文部分 103 BodyPart messageBodyPart = new MimeBodyPart(); 104 messageBodyPart.setText("bodypart"); 105 multipart.addBodyPart(messageBodyPart); 106 107 // 邮件附件部分 108 messageBodyPart = new MimeBodyPart(); 109 // 设置上传的资源 110 DataSource source = new FileDataSource("C:/Users/zsm/Desktop/省级行政图.jpg"); 111 // 添加到 112 messageBodyPart.setDataHandler(new DataHandler(source)); 113 // 设置文件名称,记得后缀名 114 messageBodyPart.setFileName("tmp.jpg"); 115 multipart.addBodyPart(messageBodyPart); 116 117 message.setContent(multipart); 118 break; 119 default: { 120 System.out.println("要发送的邮件类型错误"); 121 System.exit(1); 122 } 123 } 124 125 // 保存上面添加的信息 126 message.saveChanges(); 127 // 发送邮件 128 System.out.println("类型 " + mailType + "开始发送邮件……"); 129 Transport.send(message); 130 System.out.println("发送成功!"); 131 } catch (Exception e) { 132 System.out.println("出错"); 133 e.printStackTrace(); 134 } 135 } 136 137 /** 138 * @param args 139 */ 140 public static void main(String[] args) { 141 new SendEmail().doSendEmail(1); 142 } 143 }
方式2:Spring基于javax.mail的进一步封装(更易用的API、自动配置等)。个人感觉区别不是很大
依赖:spring-boot-starter-mail
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency>
示例代码:
import java.util.Set; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Component; import lombok.extern.slf4j.Slf4j; @Slf4j @Component public class SsMailSender { @Autowired JavaMailSender mailSender;// 注意需要在配置文件配置好邮件服务器的地址后 JavaMailSender Bean才会被自动创建,否则会报找不到Bean的错 @Value("${spring.mail.username}") private String mailFrom; /** * 发送邮件的方法。 * * @param mailSubject 邮件标题 * @param mailHtmlContent 邮件内容,支持html标签 * @param mailsTo 接收方邮件地址,可有多个 * @param mailsCc 邮件抄送地址,可有多个 * @param mailsBcc 邮件隐秘抄送地址,可有多个 * * @return 发送成功与否 */ public boolean send(String mailSubject, String mailHtmlContent, Set<String> mailsTo, Set<String> mailsCc, Set<String> mailsBcc) { try { MimeMessage mimeMessage = mailSender.createMimeMessage(); mimeMessage.setContentID(System.currentTimeMillis() + ""); MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); helper.setFrom(mailFrom); if (null != mailsTo) { helper.setTo(mailsTo.toArray(new String[0]));// 接收邮件者 } if (null != mailsCc) { helper.setCc(mailsCc.toArray(new String[0]));// 邮件抄送者 } if (null != mailsBcc) { helper.setBcc(mailsBcc.toArray(new String[0]));// 邮件隐秘抄送者,其他收件人收到邮件内容时不会看到隐秘抄送者 } helper.setSubject(mailSubject); helper.setText(mailHtmlContent, true); // helper.addAttachment("课程列表.xls", file);//附件 mailSender.send(mimeMessage); return true; } catch (MessagingException e) { log.error("error when sending email: " + e.getMessage(), e); return false; } } }
示例代码:(综合两种)
接口定义:
1 public interface EmailSender { 2 3 default void setHostPortToMailPropertiesIfEnableAuth(Properties javaxMailPropertises, String host, int port) { 4 Object authEnabled = javaxMailPropertises.get("mail.smtp.auth");// may be true or "true" 5 if ("true".equals(authEnabled + "")) { 6 javaxMailPropertises.put("mail.smtp.host", host); 7 javaxMailPropertises.put("mail.smtp.port", port); 8 } 9 } 10 11 default String generateDisplayNameFromEmail(String email) { 12 if (null == email) { 13 return null; 14 } 15 int index = email.indexOf("@"); 16 return -1 == index ? "[" + email + "]" : email.substring(0, index); 17 } 18 19 /** 20 * 21 * @param mailSubject 邮件标题 22 * @param mailContent 邮件正文内容,支持html标签 23 * @param mailAttachFileAbsPaths 邮件的附加文件的路径,文件系统的绝对路径 24 * @param mailsTo 接收方邮件地址,可有多个 25 * @param mailsCc 邮件抄送地址,可有多个、可无 26 * @param mailsBcc 邮件隐秘抄送地址,可有多个、可无。其他收件人收到邮件内容时不会看到隐秘抄送者 27 */ 28 public void doSendEmail(@NotEmpty String mailSubject, @NotEmpty String mailContent, @Nullable List<String> mailAttachFileAbsPaths, @NotEmpty Set<String> mailsTo, @Nullable Set<String> mailsCc, 29 @Nullable Set<String> mailsBcc) throws MessagingException, UnsupportedEncodingException; 30 }
方式1的实现:
1 import java.io.UnsupportedEncodingException; 2 import java.util.Collection; 3 import java.util.List; 4 import java.util.Properties; 5 import java.util.Set; 6 import java.util.stream.Collectors; 7 8 import javax.activation.DataHandler; 9 import javax.activation.FileDataSource; 10 import javax.mail.Address; 11 import javax.mail.Authenticator; 12 import javax.mail.BodyPart; 13 import javax.mail.Message; 14 import javax.mail.MessagingException; 15 import javax.mail.Multipart; 16 import javax.mail.PasswordAuthentication; 17 import javax.mail.Session; 18 import javax.mail.Transport; 19 import javax.mail.internet.AddressException; 20 import javax.mail.internet.InternetAddress; 21 import javax.mail.internet.MimeBodyPart; 22 import javax.mail.internet.MimeMessage; 23 import javax.mail.internet.MimeMultipart; 24 25 import org.springframework.lang.Nullable; 26 import org.springframework.util.StringUtils; 27 28 import lombok.extern.slf4j.Slf4j; 29 30 /** 借助javax.mail实现的邮件发送工具类 */ 31 @Slf4j 32 public class JavaxEmailSender implements EmailSender { 33 34 private boolean logDebugInfo = true; 35 36 private String mailFrom; 37 private Authenticator auth; 38 private Properties javaxMailPropertises; 39 40 /** 41 * 42 * @param host 43 * @param port 44 * @param username 45 * @param password 46 * @param javaxMailPropertises javax.mail所使用到的properties的设置,如"mail.smtp.host"。具有的配置项可参阅 47 * <a href= 48 * "https://javaee.github.io/javamail/docs/api/com/sun/mail/smtp/package-summary.html">https://javaee.github.io/javamail/docs/api/com/sun/mail/smtp/package-summary.html</a> 49 */ 50 public JavaxEmailSender(String host, int port, String username, String password, Properties javaxMailPropertises) { 51 setHostPortToMailPropertiesIfEnableAuth(javaxMailPropertises, host, port); 52 this.mailFrom = username; 53 this.auth = new Authenticator() { 54 @Override 55 protected PasswordAuthentication getPasswordAuthentication() { 56 return new PasswordAuthentication(username, password); 57 } 58 }; 59 this.javaxMailPropertises = javaxMailPropertises; 60 log.info("javaxMailPropertises={}", javaxMailPropertises); 61 } 62 63 @Override 64 public void doSendEmail(String mailSubject, String mailContent, List<String> mailAttachFileAbsPaths, Set<String> mailsTo, Set<String> mailsCc, Set<String> mailsBcc) 65 throws MessagingException, UnsupportedEncodingException { 66 Session session = Session.getDefaultInstance(javaxMailPropertises, auth); 67 // 是否在控制台显示Debug信息 68 session.setDebug(logDebugInfo); 69 // 设置邮件对象 70 Message message = new MimeMessage(session); 71 // 设置邮件主题(标题) 72 message.setSubject(mailSubject); 73 // 设置发信人地址 和 名字。未指定后者则默认会采用邮箱@前面的部分 74 message.setFrom(new InternetAddress(mailFrom, generateDisplayNameFromEmail(mailFrom))); 75 // 设置收件人地址 76 message.setRecipients(Message.RecipientType.TO, parseEmailAddress(mailsTo)); 77 message.setRecipients(Message.RecipientType.CC, parseEmailAddress(mailsCc)); 78 message.setRecipients(Message.RecipientType.BCC, parseEmailAddress(mailsBcc)); 79 // 设置邮件正文内容 80 Multipart multipart = new MimeMultipart(); 81 message.setContent(multipart); 82 { 83 String type = "text/html; charset=utf-8"; 84 BodyPart messageBodyPart = new MimeBodyPart(); 85 messageBodyPart.setContent(mailContent, type); 86 multipart.addBodyPart(messageBodyPart); 87 } 88 // 设置附件 89 if (null != mailAttachFileAbsPaths) { 90 for (String fileAbsPath : mailAttachFileAbsPaths) { 91 if (StringUtils.isEmpty(fileAbsPath)) { 92 continue; 93 } 94 String fileName = fileAbsPath.substring(fileAbsPath.lastIndexOf("/") + 1); 95 BodyPart messageBodyPart = new MimeBodyPart(); 96 messageBodyPart.setDataHandler(new DataHandler(new FileDataSource(fileAbsPath))); 97 messageBodyPart.setFileName(fileName);// 必须 98 multipart.addBodyPart(messageBodyPart); 99 } 100 } 101 102 // 发送邮件 103 Transport.send(message); 104 log.info("发送邮件,from={}, to={}, cc={}, bcc={}", mailFrom, mailsTo, mailsCc, mailsBcc); 105 106 } 107 108 private @Nullable Address[] parseEmailAddress(Collection<String> emailAddresses) { 109 if (null == emailAddresses) { 110 return null; 111 } 112 return emailAddresses.stream().map(e -> { 113 try { 114 return (new InternetAddress(e)); 115 } catch (AddressException e1) { 116 e1.printStackTrace(); 117 return null;// TODO email 118 } 119 }).collect(Collectors.toList()).toArray(new Address[0]); 120 } 121 }
方式2的实现:
1 import java.io.UnsupportedEncodingException; 2 import java.nio.charset.StandardCharsets; 3 import java.util.List; 4 import java.util.Properties; 5 import java.util.Set; 6 7 import javax.activation.FileDataSource; 8 import javax.mail.MessagingException; 9 import javax.mail.internet.MimeMessage; 10 11 import org.springframework.mail.javamail.JavaMailSender; 12 import org.springframework.mail.javamail.JavaMailSenderImpl; 13 import org.springframework.mail.javamail.MimeMessageHelper; 14 import org.springframework.util.StringUtils; 15 16 import lombok.extern.slf4j.Slf4j; 17 18 /** 19 * 借助Spring框架的JavaMailSender(其是对Javax mail的进一步封装,封装了连接复用管理等)来实现的邮件发送工具类。<br> 20 * JavaMailSender的默认实现是JavaMailSenderImpl。 21 */ 22 @Slf4j 23 public class SpringEmailSender implements EmailSender { 24 // 容器自动注入。 25 // 当在配置文件配置好邮件服务器的地址(spring.mail.host)后 JavaMailSender 26 // Bean才会被Spring容器自动创建,否则启动会报找不到Bean的错。 27 // 配置文件见org.springframework.boot.autoconfigure.mail.MailProperties 28 // 自动创建的逻辑见org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration#mailSender方法 29 // @Autowired 30 // JavaMailSender mailSender; 31 32 private String mailFrom; 33 private JavaMailSender mailSender; 34 35 /** 36 * 37 * @param host 38 * @param port 39 * @param username 40 * @param password 41 * @param javaxMailPropertises javax.mail所使用到的properties的设置,如"mail.smtp.host"。具有的配置项可参阅 42 * <a href= 43 * "https://javaee.github.io/javamail/docs/api/com/sun/mail/smtp/package-summary.html">https://javaee.github.io/javamail/docs/api/com/sun/mail/smtp/package-summary.html</a> 44 */ 45 public SpringEmailSender(String host, int port, String username, String password, Properties javaxMailPropertises) { 46 setHostPortToMailPropertiesIfEnableAuth(javaxMailPropertises, host, port); 47 48 // 对JavaMailSender手动初始化(不依赖Spring容器自动创建Bean) 49 // 参考Spring容器对自动创建JavaMailSender的过程:org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration#mailSender方法 50 JavaMailSenderImpl ms = new JavaMailSenderImpl(); 51 ms.setHost(host); 52 ms.setPort(port); 53 ms.setUsername(username); 54 ms.setPassword(password); 55 ms.setDefaultEncoding(StandardCharsets.UTF_8.name()); 56 ms.setJavaMailProperties(javaxMailPropertises); 57 58 this.mailFrom = username; 59 this.mailSender = ms; 60 log.info("javaxMailPropertises={}", javaxMailPropertises); 61 } 62 63 @Override 64 public void doSendEmail(String mailSubject, String mailContent, List<String> mailAttachFileAbsPaths, Set<String> mailsTo, Set<String> mailsCc, Set<String> mailsBcc) 65 throws MessagingException, UnsupportedEncodingException { 66 MimeMessage mimeMessage = mailSender.createMimeMessage(); 67 mimeMessage.setContentID(System.currentTimeMillis() + ""); 68 MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); 69 70 // 设置邮件主题(标题) 71 helper.setSubject(mailSubject); 72 // 设置发信人地址 和 名字。未指定后者则默认会采用邮箱@前面的部分 73 helper.setFrom(mailFrom, generateDisplayNameFromEmail(mailFrom)); 74 // 设置收件人地址 75 if (null != mailsTo) { 76 helper.setTo(mailsTo.toArray(new String[0])); 77 } 78 if (null != mailsCc) { 79 helper.setCc(mailsCc.toArray(new String[0])); 80 } 81 if (null != mailsBcc) { 82 helper.setBcc(mailsBcc.toArray(new String[0])); 83 } 84 // 设置邮件正文内容 85 helper.setText(mailContent, true); 86 // 设置附件 87 if (null != mailAttachFileAbsPaths) { 88 for (String fileAbsPath : mailAttachFileAbsPaths) { 89 if (StringUtils.isEmpty(fileAbsPath)) { 90 continue; 91 } 92 String fileName = fileAbsPath.substring(fileAbsPath.lastIndexOf("/") + 1); 93 helper.addAttachment(fileName, new FileDataSource(fileAbsPath)); 94 } 95 } 96 97 mailSender.send(mimeMessage); 98 log.info("发送邮件,from={}, to={}, cc={}, bcc={}", mailFrom, mailsTo, mailsCc, mailsBcc); 99 } 100 }
配置文件:(定义配置类,可借助SpringBoot将之对应到application.yml文件配置项)
1 public static class EmailConfig { 2 3 private String subject = " 潜渊教育-验证码-test"; 4 /** 邮件内容模板 */ 5 private final String template = "您好,您的验证码为:%s,本验证码%s秒内有效,如非本人操作,请忽略本邮件。"; 6 /** 验证码的字符个数 */ 7 private int charCount = 5; 8 9 // 以下为mail自身设置相关得到配置,同spring.mail的MailProperties类定义的属性 10 private String host = "smtp.partner.outlook.cn"; 11 private int port = 587; 12 private String username = "edu.noreply@xx.com"; 13 private String password = "xx@xxx"; 14 /** javax.mail定义并用到的配置 */ 15 private Properties javaxEmailProperties = new Properties(); 16 { 17 javaxEmailProperties.put("mail.transport.protocol", "smtp"); 18 javaxEmailProperties.put("mail.smtp.starttls.enable", true); 19 javaxEmailProperties.put("mail.smtp.starttls.required", true); 20 javaxEmailProperties.put("mail.smtp.auth", true); 21 // 如下两个字段必须,但在实现时自动采用上述host、port的值,故无须重复指定 22 // mailSessionProperties.put("mail.smtp.host", "smtp.partner.outlook.cn");// 必须 23 // mailSessionProperties.put("mail.smtp.port", 587);// 必须 24 25 } 26 }