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; } }
郵件以下