通過spring實現javamail發送郵件功能


以前很早的時候大家都用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來發送郵件,異步操作優於同步操作。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM