以前很早的時候大家都用javamail實現發送郵件的功能,而且我們也一直沿用至今,代碼拷過來用用就行了,現在我們改為用spring來實現,這樣一來減少代碼的復雜度,也能更好的契合spring理念
首先spring的相關jar包都是要引入的,其次要引入mail.jar
<!-- https://mvnrepository.com/artifact/com.sun.mail/javax.mail --> <dependency> <groupId>com.sun.mail</groupId> <artifactId>javax.mail</artifactId> <version>${javax.mail.version}</version> </dependency>
然后需要配置一個spring-mail.xml這樣的文件,如果不新建,也可以在service中加入就行,但是為了做更好的分層,還是分開較好
配置spring的javamail發送器,這邊配置了qq郵箱和qq企業郵箱的配置,需要注意的是host是不同的,另外如果是個人qq郵箱,需要使用授權碼,授權碼在qq郵箱中查看即可,而企業郵箱就是企業管理員分配的登錄密碼即可
<!-- 使用qq郵箱 --> <bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <!-- <property name="host" value="smtp.qq.com"/> --> <property name="host" value="smtp.exmail.qq.com"/> <property name="port" value="587"/> <!-- <property name="username" value="xxxxx@qq.com"/> --> <property name="username" value="xxxx@xxxxx.com"/> <!-- qq郵箱的授權碼,如果是企業郵箱,則使用登錄密碼 --> <!-- <property name="password" value="xxxxxxxxxxxxxxx"/> --> <property name="password" value="xxxxxxxxxxxxxxx"/> <property name="javaMailProperties"> <props > <prop key="mail.smtp.auth">true</prop> </props> </property> </bean>
附帶一提網易郵箱是多么的坑爹:
<!-- 使用163郵箱 --> <!-- <bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> --> <!-- <property name="host" value="smtp.163.com"/> --> <!-- <property name="port" value="25"/> --> <!-- <property name="username" value="xxxxxxxxx@163.com"/> --> <!-- 163郵箱的授權碼,而不是登錄密碼 --> <!-- <property name="password" value="xxxxxxxxxxxx"/> --> <!-- <property name="javaMailProperties"> --> <!-- <props > --> <!-- <prop key="mail.smtp.auth">true</prop> --> <!-- </props> --> <!-- </property> --> <!-- </bean> -->
使用網易郵箱會莫名報554的錯誤,也是就是說認定你的郵件是垃圾郵件,重復發送同一份郵件,內容一致,或者帶有相關關鍵字,都會被列為垃圾郵件,然后會禁止30分鍾左右,非常不人性化,所以不建議使用163作為發送器
配置郵箱的發送者以及標題,這個不寫也可以,可以在發送的時候直接配置都行
<bean id="simpleMailMessage" class="org.springframework.mail.SimpleMailMessage"> <property name="from" value="xxxxx@xxxx.com" /> <!-- <property name="from" value="xxxxx@qq.com" /> --> <property name="subject" value="xxxx" /> </bean>
最后的配置是freemarker模板,為何要模板,因為我們平時發送郵件會有很多不同的分類,分類配置在枚舉中,根據不同的分類去選擇不同的模板,一般來說注冊碼,密碼重置,活動頁面等等都需要作為一個單獨的HTML來發送,而一個HTML我們不可能會以servlet的形式把標簽都寫在java代碼中,所以采用模板來實現,是最好的方式:
<!--FreeMarker模板--> <bean id="freeMarkerConfigurer" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> <property name="templateLoaderPath" value="classpath:freemarker" /> <property name="freemarkerSettings"> <props> <prop key="locale">zh_CN</prop> <prop key="default_encoding">UTF-8</prop> </props> </property> </bean>
配置模板路徑
填充模板內容
<h2><font color="green">${nickName},您好!</font></h2> <p>注意:30分鍾后鏈接將失效!</p> <p>請點擊以下鏈接完成密碼重置操作:</p> <p><a href="www.abc.com" target="_blank">www.abc.com/user/reset?userId=test10011</a></p> <p>${content}</p>
編寫郵件發送器,一方面從freemarker中構建郵件內容,一方面再執行mail發送操作
@Component public class PwdMailSender { @Autowired private JavaMailSender javaMailSender; @Autowired private SimpleMailMessage simpleMailMessage; @Autowired private FreeMarkerConfigurer freeMarkerConfigurer; /** * * @Description: 從模板中構建郵件內容 * @param nickName 用戶昵稱 * @param content 郵件內容 * @param email 接受郵件 * * @author leechenxiang * @date 2017年2月5日 下午1:22:00 */ public void send(String nickName, String content, String email) { String to = email; String text = ""; Map<String, String> map = new HashMap<String, String>(1); map.put("nickName", nickName); map.put("content", content); try { // 根據模板內容,動態把map中的數據填充進去,生成HTML Template template = freeMarkerConfigurer.getConfiguration().getTemplate("mail.ftl"); // map中的key,對應模板中的${key}表達式 text = FreeMarkerTemplateUtils.processTemplateIntoString(template, map); } catch (IOException e) { e.printStackTrace(); } catch (TemplateException e) { e.printStackTrace(); } sendMail(to, null, text); } /** * * @Description: 執行發送郵件 * @param to 收件人郵箱 * @param subject 郵件主題 * @param content 郵件內容 * * @author leechenxiang * @date 2017年2月5日 下午1:22:34 */ public void sendMail(String to, String subject, String content) { try { MimeMessage message = javaMailSender.createMimeMessage(); MimeMessageHelper messageHelper = new MimeMessageHelper(message, true, "UTF-8"); messageHelper.setFrom(simpleMailMessage.getFrom()); if (subject != null) { messageHelper.setSubject(subject); } else { messageHelper.setSubject(simpleMailMessage.getSubject()); } messageHelper.setTo(to); messageHelper.setText(content, true); javaMailSender.send(message); } catch (MessagingException e) { e.printStackTrace(); } } }
最后在需要調用的地方執行就行
@Autowired private PwdMailSender pwdMailSender; @RequestMapping("/mail") @ResponseBody public Object mail(){ pwdMailSender.send("lee", "在這里填寫你所需要的內容", "leechenxiang@163.com"); return "success"; }
然后收到的郵件內容就如下
需要注意的是,這么做發送郵件由於單線程操作是不可取的,可以參考之前的多線程,執行多線程操作,或者引入消息隊列RMQ或者AMQ來發送郵件,異步操作優於同步操作。