Java 实现邮件的发送,使用 JavaMail 和 Spring 实现html
JavaMail 是 Java 处理电子邮件相关的编程接口,可是没有被加在标准的Java开发工具包中(Java Development Kit),因此咱们使用 JavaMail 须要另外下载依赖包
javax.mail.jar
包实现了 SMTP、IMAP 和 POP3 协议java
<dependency> <groupId>com.sun.mail</groupId> <artifactId>javax.mail</artifactId> <version>1.6.2</version> </dependency>
下面是用 qq 邮箱发送一个简单的纯文本邮件的例子web
public class SentSimpleMail { private static final String MAIL_HOST = "smtp.qq.com"; // 发送邮件的主机 private static final String FROM = "827952316@qq.com"; // 发件人邮箱地址 /** * 用qq邮箱发送一个简单邮件 * * @param subject * @param text * @param toRecipients 接收邮件,逗号分隔 * @throws AddressException * @throws MessagingException */ public void sentSimpleMail(String subject, String text, String toRecipients) throws AddressException, MessagingException { /* * 初始化JavaMail会话 */ Properties props = System.getProperties(); // 得到系统属性配置,用于链接邮件服务器的参数配置 props.setProperty("mail.smtp.host", MAIL_HOST); // 发送邮件的主机 props.setProperty("mail.smtp.auth", "true"); Session session = Session.getInstance(props, null);// 得到Session对象 session.setDebug(true); // 设置是否显示debug信息,true 会在控制台显示相关信息 /* * 建立邮件消息,发送邮件 */ Message message = new MimeMessage(session); message.setFrom(new InternetAddress(FROM)); // To: 收件人 // message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(toRecipient)); message.setRecipients(MimeMessage.RecipientType.TO, InternetAddress.parse(toRecipients, false)); // To: 增长收件人(可选) // message.addRecipient(MimeMessage.RecipientType.TO, new InternetAddress(toRecipient); // Cc: 抄送(可选) // message.setRecipient(MimeMessage.RecipientType.CC, new InternetAddress(ccRecipient)); // Bcc: 密送(可选) // message.setRecipient(MimeMessage.RecipientType.BCC, new InternetAddress(bccRecipient)); message.setSubject(subject); // 邮件标题 message.setText(text); // 邮件内容 // 简单发送邮件的方式 Transport.send(message, FROM, "xxxxxxxxxxx"); // 受权码 } public static void main(String[] args) throws AddressException, MessagingException { new SentSimpleMail().sentSimpleMail("标题", "邮件内容", "827952316@qq.com"); } }
受权spring
若是须要提供用户名和密码给e-mail服务器来达到用户认证的目的,须要另外添加受权信息编程
props.setProperty("mail.smtp.auth", "true"); props.setProperty("mail.user", "${user}"); props.setProperty("mail.password", "${password}");
或者在发送的时候加上用户和受权码,如服务器
Transport.send(message, FROM, "xxxxxxxxxxx"); // 受权码
如在使用 qq 邮箱发送邮件须要获取受权码,在邮箱的“设置-帐户”中设置 session
发送邮件的内容为 HTML 时,须要把 Mimemessage 的 ContentType 设为 "text/html"框架
message.setDataHandler(new DataHandler( new ByteArrayDataSource("<h1>This is html message</h1>", "text/html")));
或者ide
message.setContent("<h1>This is html message</h1>", "text/html" );
MimeMessage 继承Message,表示整封邮件
MimeBodyPart 表示邮件的一个MIME消息
MimeMultipart 表示一个由多个MIME消息组合成的组合MIME消息工具
public class SendMail { public void sendMail(String subject, String text, String toRecipients) throws AddressException, MessagingException, IOException { String host = "smtp.qq.com"; // 发送邮件的主机 String from = "827952316@qq.com"; // 发件人邮箱地址 /* * 初始化JavaMail会话 */ Properties props = System.getProperties(); // 得到系统属性配置,用于链接邮件服务器的参数配置 props.setProperty("mail.smtp.host", host); // 发送邮件的主机 props.setProperty("mail.smtp.auth", "true"); props.setProperty("mail.user", from); props.setProperty("mail.password", "xxxxxxxxxxxxxx"); //密码或者受权码 Session session = Session.getInstance(props, null);// 得到Session对象 session.setDebug(true); // 设置是否显示debug信息,true 会在控制台显示相关信息 /* * 建立邮件消息,发送邮件 */ Message message = new MimeMessage(session); message.setFrom(new InternetAddress(from)); message.setRecipients(MimeMessage.RecipientType.TO, InternetAddress.parse(toRecipients, false)); message.setSubject(subject); // 邮件标题 //建立多重消息 MimeMultipart mp = new MimeMultipart(); // 文本部分 MimeBodyPart textPart = new MimeBodyPart(); textPart.setText(text); // 附件部分 MimeBodyPart filePart = new MimeBodyPart(); filePart.attachFile("D:/0.jpeg"); filePart.setFileName("0.jpeg"); mp.addBodyPart(textPart); mp.addBodyPart(filePart); message.setContent(mp); Transport.send(message); } public static void main(String[] args) throws AddressException, MessagingException, IOException { new SendMail().sendMail("标题", "邮件内容", "827952316@qq.com"); } }
在 spring 中,关于邮件(JavaMail)的集成 API 是在 spring-context-supprot 中的 org.springframework.mail
包中,须要 JavaMail 的类库支持。
在项目中,邮件功能多是一个横切关注点,极可能为 AOP 的一个切面
MailSender 是发送电子邮件的核心接口。SimpleMailMessage 类封装了简单的邮件属性(例如from和to)的简单值
使用 MailSender 和 SimpleMailMessage 来发送邮件
@Component public class SendMailManagerImpl implements SendMailManager { @Autowired private MailSender mailSender; @Autowired private SimpleMailMessage templateMessage; @Override public void sendMail(String[] to) { // SimpleMailMessage SimpleMailMessage msg = new SimpleMailMessage(this.templateMessage); msg.setTo(to);//接收人 msg.setText("邮件内容"); //这里的邮件内容是 文本类型 // msg.setCc(cc);// 抄送 // msg.setBcc(bcc);// 密送 // msg.setReplyTo(replyTo);// 回复 // msg.setSentDate(new Date());// 发送时间 // msg.setSubject(subject);// 主题 // msg.setFrom(from);// 发送人 try{ this.mailSender.send(msg); } catch (MailException ex) { System.out.println(ex.getMessage()); } } }
咱们在 xml 中配置 MailSender 和 模板消息
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host" value="smtp.qq.com" /> <!-- 若是须要帐号密码受权 --> <property name="username" value="827952316@qq.com"/> <property name="password" value="xxxxxxxxxxxxxxxx"/> </bean> <!-- 能够作一个模板,把邮件的通用内容放到这里 --> <bean id="templateMessage" class="org.springframework.mail.SimpleMailMessage"> <property name="from" value="827952316@qq.com" /> <property name="subject" value="统一标题" /> </bean>
上面的例子是利用了 spring 所封装的 SimpleMailMessage 类。不过 Spring 框架的邮件支持也附带了标准 JavaMail 实现,JavaMailSender 类可使用 JavaMail 的 MimeMessage 类
@Component public class SendMailManagerImpl2 implements SendMailManager { @Autowired private JavaMailSender mailSender; public void sendMail(String[] to) { MimeMessagePreparator preparator = (MimeMessage mimeMessage) -> { Arrays.asList(to).stream().forEach(x -> { try { mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(x)); } catch (MessagingException e) { System.err.println(e.getMessage()); } }); mimeMessage.setFrom(new InternetAddress("827952316@qq.com")); mimeMessage.setText("邮件内容"); }; try { this.mailSender.send(preparator); } catch (MailException ex) { System.err.println(ex.getMessage()); } } }
使用 MimeMessageHelper 能够很方便的建立处理 JavaMail 的 MimeMessage 对象
JavaMailSenderImpl sender = new JavaMailSenderImpl(); sender.setHost("smtp.qq.com"); MimeMessage message = sender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(message); helper.setTo("test@qq.com"); helper.setText("邮件内容"); sender.send(message);
当咱们想要邮件有附件和内联资源的时候,使用 MimeMessageHelper 就很方便了
咱们发送邮件一般会须要有附件或者是内联资源(好比,内嵌的图片),在建立这些至关复杂的邮件,SimpleMailMessage 就很差用了,使用 MimeMessageHelper 帮咱们建立 MimeMessage 对象
@Component public class SendMailManagerImpl3 implements SendMailManager { @Autowired private JavaMailSender mailSender; public void sendMail(String[] to) { MimeMessage message = mailSender.createMimeMessage(); try { // 使用 true 表示要建立一个有多部分的邮件 MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8"); helper.setFrom("827952316@qq.com"); helper.setTo(to); // 使用 true 表示邮件内容为 HTML,在这里引用内联资源 图片 helper.setText("<html><body><h1>邮件内容</h1><img src='cid:inlineImg'/></body></html>", true); // 添加附件 FileSystemResource file = new FileSystemResource(new File("D:/0.jpeg")); helper.addAttachment("CoolImage.jpeg", file); // 添加内联资源(在html中引用) FileSystemResource res = new FileSystemResource(new File("D:/0.jpeg")); helper.addInline("inlineImg", res); this.mailSender.send(message); } catch (MailException | MessagingException ex) { System.err.println(ex.getMessage()); } } }
使用内联资源的时候要指定 Content-ID,MimeMessage在邮件内容中添加。添加文本和资源的顺序很是重要。要先添加文本,而后再添加资源
一般咱们在使用代码建立邮件是都不会是简单的纯文本邮件,在使用Java代码建立基于HTML的电子邮件内容很是繁琐且容易出错,并且更改电子邮件内容的显示结构须要编写Java代码,从新编译,从新部署
使用模板是能够解决这些问题的,使用模板库(例如FreeMarker、Velocity、Thymeleaf)来定义电子邮件内容的显示结构。从 Spring 4.3 以后,Velocity支持已被弃用。这里咱们使用 FreeMaker 模板发送邮件作个例子
首先咱们添加依赖
<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.28</version> </dependency>
FreeMarker 配置
<!-- web项目中 --> <!-- <bean id="freeMarkerConfigurer" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> <property name="templateLoaderPath" value="/WEB-INF/config/template/" /> <property name="freemarkerSettings"> <props> <prop key="template_update_delay">1800</prop>模板更新延时 <prop key="default_encoding">UTF-8</prop> <prop key="locale">zh_CN</prop> </props> </property> </bean> --> <!-- 非web --> <bean id="freeMarkerConfiguration" class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean"> <property name="templateLoaderPath" value="classpath:template/ftl/" /> </bean>
FreeMarker 模板 user.ftl
<html> <body> <h3>username: ${user.username}</h3> <p>password : ${user.password}</p> <span>Sent using FreeMarker Template</span> </body> </html>
使用 FreeMarker 模板得到邮件内容
@Component public class TemplateManagerImpl implements SendMailManager { @Autowired private JavaMailSender mailSender; @Autowired private Configuration freeMarkerConfiguration; @Override public void sendMail(String[] to,User user) { MimeMessage message = mailSender.createMimeMessage(); try { // 使用 true 表示要建立一个有多部分的邮件 MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8"); helper.setFrom("827952316@qq.com"); helper.setTo(to); helper.setSubject("标题"); //获取模板 Map<String, Object> model = new HashMap<String, Object>(); model.put("user", user); String text = geFreeMarkerTemplateContent(model); // 使用 true 表示邮件内容为 HTML helper.setText(text, true); this.mailSender.send(message); } catch (MailException | MessagingException ex) { System.err.println(ex.getMessage()); } } /** * 得到模板内容 * @param model * @return */ private String geFreeMarkerTemplateContent(Map<String, Object> model) { String content = null; try { content = FreeMarkerTemplateUtils.processTemplateIntoString(freeMarkerConfiguration.getTemplate("user.ftl"), model); } catch (Exception e) { System.err.println(e.getMessage()); } return content; } }
邮件以下