From 92f030887b45604744d488131a506abbda14b4b5 Mon Sep 17 00:00:00 2001
From: zlyx <1242874891@qq.com>
Date: 星期一, 02 五月 2022 21:21:14 +0800
Subject: [PATCH] [add]: 1. (common) pom.xml - 增加邮件依赖 ; 2. (admin) application-dev.yml - 增加邮件配置 ; 3. (framework) MailProperties, MailConfig - 增加邮件属性配置 ; 4. (common) MailUtils - 重写 Hutool MailUtil方法 ; 5. (demo) MailController - 邮件发送测试方法 ;

---
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/MailConfig.java                |   39 +++
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/MailProperties.java |   65 +++++
 pom.xml                                                                                 |    1 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/email/MailUtils.java                  |  468 +++++++++++++++++++++++++++++++++++++++
 ruoyi-common/pom.xml                                                                    |    6 
 ruoyi-demo/src/main/java/com/ruoyi/demo/controller/MailController.java                  |   54 ++++
 ruoyi-admin/src/main/resources/application-dev.yml                                      |   28 ++
 7 files changed, 661 insertions(+), 0 deletions(-)

diff --git a/pom.xml b/pom.xml
index 4fc098f..71963f2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -38,6 +38,7 @@
         <dynamic-ds.version>3.5.1</dynamic-ds.version>
         <tlog.version>1.3.6</tlog.version>
         <xxl-job.version>2.3.0</xxl-job.version>
+        <mail.version>1.6.2</mail.version>
 
         <!-- jdk11 缂哄け渚濊禆 jaxb-->
         <jaxb.version>3.0.1</jaxb.version>
diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml
index 45eb5be..50e060b 100644
--- a/ruoyi-admin/src/main/resources/application-dev.yml
+++ b/ruoyi-admin/src/main/resources/application-dev.yml
@@ -137,6 +137,34 @@
     # 鏄惁寮�鍚痵sl
     ssl: false
 
+  # 閭欢
+  mail:
+    enabled: false
+    # 閭欢鏈嶅姟鍦板潃 (enabled = true 鏃舵墦寮�璇ラ厤缃�)
+#    host: smtp.qq.com
+    # 鐢ㄦ埛鍚�
+    username: xxx@qq.com
+    # 鎺堟潈鐮� (璁剧疆 - 璐︽埛 - POP3/SMTP鏈嶅姟)
+    password: xxx
+    # QQ閭鍔犲瘑绔彛锛屼笉鍚岄偖绠辩殑绔彛涓嶄竴鏍�
+    port: 465
+    properties:
+      mail:
+        smtp:
+          socketFactory:
+            class: javax.net.ssl.SSLSocketFactory
+          ssl:
+            trust: smtp.qq.com
+          # 鏄惁闇�瑕佺敤鎴疯璇�
+          auth: true
+          starttls:
+            # 鍚敤TLS鍔犲瘑
+            enable: true
+            required: true
+    # 浼犺緭鍗忚 starttls.enable = true 鏃朵负 smtps
+    protocol: smtps
+    debug: true
+
 redisson:
   # 绾跨▼姹犳暟閲�
   threads: 4
diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml
index bb476cb..fd6a999 100644
--- a/ruoyi-common/pom.xml
+++ b/ruoyi-common/pom.xml
@@ -159,6 +159,12 @@
             <artifactId>lock4j-redisson-spring-boot-starter</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>com.sun.mail</groupId>
+            <artifactId>javax.mail</artifactId>
+            <version>${mail.version}</version>
+        </dependency>
+
     </dependencies>
 
 </project>
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/email/MailUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/email/MailUtils.java
new file mode 100644
index 0000000..92fa89a
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/email/MailUtils.java
@@ -0,0 +1,468 @@
+package com.ruoyi.common.utils.email;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.CharUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.mail.*;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import javax.mail.Authenticator;
+import javax.mail.Session;
+import java.io.File;
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * 閭欢宸ュ叿绫�
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class MailUtils {
+
+    private static final MailAccount ACCOUNT = SpringUtils.getBean(MailAccount.class);
+
+    /**
+     * 鑾峰彇閭欢鍙戦�佸疄渚�
+     */
+    public static MailAccount getMailAccount() {
+        return ACCOUNT;
+    }
+
+    /**
+     * 鑾峰彇閭欢鍙戦�佸疄渚� (鑷畾涔夊彂閫佷汉浠ュ強鎺堟潈鐮�)
+     *
+     * @param username 鍙戦�佷汉
+     * @param password 鎺堟潈鐮�
+     */
+    public static MailAccount getMailAccount(String username, String password) {
+        ACCOUNT.setFrom(StringUtils.blankToDefault(username, ACCOUNT.getUser()));
+        ACCOUNT.setUser(StringUtils.blankToDefault(username, ACCOUNT.getUser()));
+        ACCOUNT.setPass(StringUtils.blankToDefault(password, ACCOUNT.getPass()));
+        return ACCOUNT;
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�佹枃鏈偖浠讹紝鍙戦�佺粰鍗曚釜鎴栧涓敹浠朵汉<br>
+     * 澶氫釜鏀朵欢浜哄彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     *
+     * @param to      鏀朵欢浜�
+     * @param subject 鏍囬
+     * @param content 姝f枃
+     * @param files   闄勪欢鍒楄〃
+     * @return message-id
+     * @since 3.2.0
+     */
+    public static String sendText(String to, String subject, String content, File... files) {
+        return send(to, subject, content, false, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�丠TML閭欢锛屽彂閫佺粰鍗曚釜鎴栧涓敹浠朵汉<br>
+     * 澶氫釜鏀朵欢浜哄彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     *
+     * @param to      鏀朵欢浜�
+     * @param subject 鏍囬
+     * @param content 姝f枃
+     * @param files   闄勪欢鍒楄〃
+     * @return message-id
+     * @since 3.2.0
+     */
+    public static String sendHtml(String to, String subject, String content, File... files) {
+        return send(to, subject, content, true, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佸崟涓垨澶氫釜鏀朵欢浜�<br>
+     * 澶氫釜鏀朵欢浜哄彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     *
+     * @param to      鏀朵欢浜�
+     * @param subject 鏍囬
+     * @param content 姝f枃
+     * @param isHtml  鏄惁涓篐TML
+     * @param files   闄勪欢鍒楄〃
+     * @return message-id
+     */
+    public static String send(String to, String subject, String content, boolean isHtml, File... files) {
+        return send(splitAddress(to), subject, content, isHtml, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佸崟涓垨澶氫釜鏀朵欢浜�<br>
+     * 澶氫釜鏀朵欢浜恒�佹妱閫佷汉銆佸瘑閫佷汉鍙互浣跨敤閫楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     *
+     * @param to      鏀朵欢浜猴紝鍙互浣跨敤閫楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     * @param cc      鎶勯�佷汉锛屽彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     * @param bcc     瀵嗛�佷汉锛屽彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     * @param subject 鏍囬
+     * @param content 姝f枃
+     * @param isHtml  鏄惁涓篐TML
+     * @param files   闄勪欢鍒楄〃
+     * @return message-id
+     * @since 4.0.3
+     */
+    public static String send(String to, String cc, String bcc, String subject, String content, boolean isHtml, File... files) {
+        return send(splitAddress(to), splitAddress(cc), splitAddress(bcc), subject, content, isHtml, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�佹枃鏈偖浠讹紝鍙戦�佺粰澶氫汉
+     *
+     * @param tos     鏀朵欢浜哄垪琛�
+     * @param subject 鏍囬
+     * @param content 姝f枃
+     * @param files   闄勪欢鍒楄〃
+     * @return message-id
+     */
+    public static String sendText(Collection<String> tos, String subject, String content, File... files) {
+        return send(tos, subject, content, false, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�丠TML閭欢锛屽彂閫佺粰澶氫汉
+     *
+     * @param tos     鏀朵欢浜哄垪琛�
+     * @param subject 鏍囬
+     * @param content 姝f枃
+     * @param files   闄勪欢鍒楄〃
+     * @return message-id
+     * @since 3.2.0
+     */
+    public static String sendHtml(Collection<String> tos, String subject, String content, File... files) {
+        return send(tos, subject, content, true, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佺粰澶氫汉
+     *
+     * @param tos     鏀朵欢浜哄垪琛�
+     * @param subject 鏍囬
+     * @param content 姝f枃
+     * @param isHtml  鏄惁涓篐TML
+     * @param files   闄勪欢鍒楄〃
+     * @return message-id
+     */
+    public static String send(Collection<String> tos, String subject, String content, boolean isHtml, File... files) {
+        return send(tos, null, null, subject, content, isHtml, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佺粰澶氫汉
+     *
+     * @param tos     鏀朵欢浜哄垪琛�
+     * @param ccs     鎶勯�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param bccs    瀵嗛�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param subject 鏍囬
+     * @param content 姝f枃
+     * @param isHtml  鏄惁涓篐TML
+     * @param files   闄勪欢鍒楄〃
+     * @return message-id
+     * @since 4.0.3
+     */
+    public static String send(Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, boolean isHtml, File... files) {
+        return send(getMailAccount(), true, tos, ccs, bccs, subject, content, null, isHtml, files);
+    }
+
+    // ------------------------------------------------------------------------------------------------------------------------------- Custom MailAccount
+
+    /**
+     * 鍙戦�侀偖浠剁粰澶氫汉
+     *
+     * @param mailAccount 閭欢璁よ瘉瀵硅薄
+     * @param to          鏀朵欢浜猴紝澶氫釜鏀朵欢浜洪�楀彿鎴栬�呭垎鍙烽殧寮�
+     * @param subject     鏍囬
+     * @param content     姝f枃
+     * @param isHtml      鏄惁涓篐TML鏍煎紡
+     * @param files       闄勪欢鍒楄〃
+     * @return message-id
+     * @since 3.2.0
+     */
+    public static String send(MailAccount mailAccount, String to, String subject, String content, boolean isHtml, File... files) {
+        return send(mailAccount, splitAddress(to), subject, content, isHtml, files);
+    }
+
+    /**
+     * 鍙戦�侀偖浠剁粰澶氫汉
+     *
+     * @param mailAccount 閭欢甯愭埛淇℃伅
+     * @param tos         鏀朵欢浜哄垪琛�
+     * @param subject     鏍囬
+     * @param content     姝f枃
+     * @param isHtml      鏄惁涓篐TML鏍煎紡
+     * @param files       闄勪欢鍒楄〃
+     * @return message-id
+     */
+    public static String send(MailAccount mailAccount, Collection<String> tos, String subject, String content, boolean isHtml, File... files) {
+        return send(mailAccount, tos, null, null, subject, content, isHtml, files);
+    }
+
+    /**
+     * 鍙戦�侀偖浠剁粰澶氫汉
+     *
+     * @param mailAccount 閭欢甯愭埛淇℃伅
+     * @param tos         鏀朵欢浜哄垪琛�
+     * @param ccs         鎶勯�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param bccs        瀵嗛�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param subject     鏍囬
+     * @param content     姝f枃
+     * @param isHtml      鏄惁涓篐TML鏍煎紡
+     * @param files       闄勪欢鍒楄〃
+     * @return message-id
+     * @since 4.0.3
+     */
+    public static String send(MailAccount mailAccount, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, boolean isHtml, File... files) {
+        return send(mailAccount, false, tos, ccs, bccs, subject, content, null, isHtml, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�丠TML閭欢锛屽彂閫佺粰鍗曚釜鎴栧涓敹浠朵汉<br>
+     * 澶氫釜鏀朵欢浜哄彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     *
+     * @param to       鏀朵欢浜�
+     * @param subject  鏍囬
+     * @param content  姝f枃
+     * @param imageMap 鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
+     * @param files    闄勪欢鍒楄〃
+     * @return message-id
+     * @since 3.2.0
+     */
+    public static String sendHtml(String to, String subject, String content, Map<String, InputStream> imageMap, File... files) {
+        return send(to, subject, content, imageMap, true, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佸崟涓垨澶氫釜鏀朵欢浜�<br>
+     * 澶氫釜鏀朵欢浜哄彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     *
+     * @param to       鏀朵欢浜�
+     * @param subject  鏍囬
+     * @param content  姝f枃
+     * @param imageMap 鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
+     * @param isHtml   鏄惁涓篐TML
+     * @param files    闄勪欢鍒楄〃
+     * @return message-id
+     */
+    public static String send(String to, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
+        return send(splitAddress(to), subject, content, imageMap, isHtml, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佸崟涓垨澶氫釜鏀朵欢浜�<br>
+     * 澶氫釜鏀朵欢浜恒�佹妱閫佷汉銆佸瘑閫佷汉鍙互浣跨敤閫楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     *
+     * @param to       鏀朵欢浜猴紝鍙互浣跨敤閫楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     * @param cc       鎶勯�佷汉锛屽彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     * @param bcc      瀵嗛�佷汉锛屽彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     * @param subject  鏍囬
+     * @param content  姝f枃
+     * @param imageMap 鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
+     * @param isHtml   鏄惁涓篐TML
+     * @param files    闄勪欢鍒楄〃
+     * @return message-id
+     * @since 4.0.3
+     */
+    public static String send(String to, String cc, String bcc, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
+        return send(splitAddress(to), splitAddress(cc), splitAddress(bcc), subject, content, imageMap, isHtml, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�丠TML閭欢锛屽彂閫佺粰澶氫汉
+     *
+     * @param tos      鏀朵欢浜哄垪琛�
+     * @param subject  鏍囬
+     * @param content  姝f枃
+     * @param imageMap 鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
+     * @param files    闄勪欢鍒楄〃
+     * @return message-id
+     * @since 3.2.0
+     */
+    public static String sendHtml(Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, File... files) {
+        return send(tos, subject, content, imageMap, true, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佺粰澶氫汉
+     *
+     * @param tos      鏀朵欢浜哄垪琛�
+     * @param subject  鏍囬
+     * @param content  姝f枃
+     * @param imageMap 鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
+     * @param isHtml   鏄惁涓篐TML
+     * @param files    闄勪欢鍒楄〃
+     * @return message-id
+     */
+    public static String send(Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
+        return send(tos, null, null, subject, content, imageMap, isHtml, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佺粰澶氫汉
+     *
+     * @param tos      鏀朵欢浜哄垪琛�
+     * @param ccs      鎶勯�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param bccs     瀵嗛�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param subject  鏍囬
+     * @param content  姝f枃
+     * @param imageMap 鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
+     * @param isHtml   鏄惁涓篐TML
+     * @param files    闄勪欢鍒楄〃
+     * @return message-id
+     * @since 4.0.3
+     */
+    public static String send(Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
+        return send(getMailAccount(), true, tos, ccs, bccs, subject, content, imageMap, isHtml, files);
+    }
+
+    // ------------------------------------------------------------------------------------------------------------------------------- Custom MailAccount
+
+    /**
+     * 鍙戦�侀偖浠剁粰澶氫汉
+     *
+     * @param mailAccount 閭欢璁よ瘉瀵硅薄
+     * @param to          鏀朵欢浜猴紝澶氫釜鏀朵欢浜洪�楀彿鎴栬�呭垎鍙烽殧寮�
+     * @param subject     鏍囬
+     * @param content     姝f枃
+     * @param imageMap    鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
+     * @param isHtml      鏄惁涓篐TML鏍煎紡
+     * @param files       闄勪欢鍒楄〃
+     * @return message-id
+     * @since 3.2.0
+     */
+    public static String send(MailAccount mailAccount, String to, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
+        return send(mailAccount, splitAddress(to), subject, content, imageMap, isHtml, files);
+    }
+
+    /**
+     * 鍙戦�侀偖浠剁粰澶氫汉
+     *
+     * @param mailAccount 閭欢甯愭埛淇℃伅
+     * @param tos         鏀朵欢浜哄垪琛�
+     * @param subject     鏍囬
+     * @param content     姝f枃
+     * @param imageMap    鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
+     * @param isHtml      鏄惁涓篐TML鏍煎紡
+     * @param files       闄勪欢鍒楄〃
+     * @return message-id
+     * @since 4.6.3
+     */
+    public static String send(MailAccount mailAccount, Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
+        return send(mailAccount, tos, null, null, subject, content, imageMap, isHtml, files);
+    }
+
+    /**
+     * 鍙戦�侀偖浠剁粰澶氫汉
+     *
+     * @param mailAccount 閭欢甯愭埛淇℃伅
+     * @param tos         鏀朵欢浜哄垪琛�
+     * @param ccs         鎶勯�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param bccs        瀵嗛�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param subject     鏍囬
+     * @param content     姝f枃
+     * @param imageMap    鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
+     * @param isHtml      鏄惁涓篐TML鏍煎紡
+     * @param files       闄勪欢鍒楄〃
+     * @return message-id
+     * @since 4.6.3
+     */
+    public static String send(MailAccount mailAccount, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, Map<String, InputStream> imageMap,
+                              boolean isHtml, File... files) {
+        return send(mailAccount, false, tos, ccs, bccs, subject, content, imageMap, isHtml, files);
+    }
+
+    /**
+     * 鏍规嵁閰嶇疆鏂囦欢锛岃幏鍙栭偖浠跺鎴风浼氳瘽
+     *
+     * @param mailAccount 閭欢璐︽埛閰嶇疆
+     * @param isSingleton 鏄惁鍗曚緥锛堝叏灞�鍏变韩浼氳瘽锛�
+     * @return {@link Session}
+     * @since 5.5.7
+     */
+    public static Session getSession(MailAccount mailAccount, boolean isSingleton) {
+        Authenticator authenticator = null;
+        if (mailAccount.isAuth()) {
+            authenticator = new UserPassAuthenticator(mailAccount.getUser(), mailAccount.getPass());
+        }
+
+        return isSingleton ? Session.getDefaultInstance(mailAccount.getSmtpProps(), authenticator) //
+            : Session.getInstance(mailAccount.getSmtpProps(), authenticator);
+    }
+
+    // ------------------------------------------------------------------------------------------------------------------------ Private method start
+
+    /**
+     * 鍙戦�侀偖浠剁粰澶氫汉
+     *
+     * @param mailAccount      閭欢甯愭埛淇℃伅
+     * @param useGlobalSession 鏄惁鍏ㄥ眬鍏变韩Session
+     * @param tos              鏀朵欢浜哄垪琛�
+     * @param ccs              鎶勯�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param bccs             瀵嗛�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param subject          鏍囬
+     * @param content          姝f枃
+     * @param imageMap         鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:${cid}
+     * @param isHtml           鏄惁涓篐TML鏍煎紡
+     * @param files            闄勪欢鍒楄〃
+     * @return message-id
+     * @since 4.6.3
+     */
+    private static String send(MailAccount mailAccount, boolean useGlobalSession, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content,
+                               Map<String, InputStream> imageMap, boolean isHtml, File... files) {
+        final Mail mail = Mail.create(mailAccount).setUseGlobalSession(useGlobalSession);
+
+        // 鍙�夋妱閫佷汉
+        if (CollUtil.isNotEmpty(ccs)) {
+            mail.setCcs(ccs.toArray(new String[0]));
+        }
+        // 鍙�夊瘑閫佷汉
+        if (CollUtil.isNotEmpty(bccs)) {
+            mail.setBccs(bccs.toArray(new String[0]));
+        }
+
+        mail.setTos(tos.toArray(new String[0]));
+        mail.setTitle(subject);
+        mail.setContent(content);
+        mail.setHtml(isHtml);
+        mail.setFiles(files);
+
+        // 鍥剧墖
+        if (MapUtil.isNotEmpty(imageMap)) {
+            for (Map.Entry<String, InputStream> entry : imageMap.entrySet()) {
+                mail.addImage(entry.getKey(), entry.getValue());
+                // 鍏抽棴娴�
+                IoUtil.close(entry.getValue());
+            }
+        }
+
+        return mail.send();
+    }
+
+    /**
+     * 灏嗗涓仈绯讳汉杞负鍒楄〃锛屽垎闅旂涓洪�楀彿鎴栬�呭垎鍙�
+     *
+     * @param addresses 澶氫釜鑱旂郴浜猴紝濡傛灉涓虹┖杩斿洖null
+     * @return 鑱旂郴浜哄垪琛�
+     */
+    private static List<String> splitAddress(String addresses) {
+        if (StrUtil.isBlank(addresses)) {
+            return null;
+        }
+
+        List<String> result;
+        if (StrUtil.contains(addresses, CharUtil.COMMA)) {
+            result = StrUtil.splitTrim(addresses, CharUtil.COMMA);
+        } else if (StrUtil.contains(addresses, ';')) {
+            result = StrUtil.splitTrim(addresses, ';');
+        } else {
+            result = CollUtil.newArrayList(addresses);
+        }
+        return result;
+    }
+    // ------------------------------------------------------------------------------------------------------------------------ Private method end
+
+}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/MailController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/MailController.java
new file mode 100644
index 0000000..53f130f
--- /dev/null
+++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/MailController.java
@@ -0,0 +1,54 @@
+package com.ruoyi.demo.controller;
+
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.utils.email.MailUtils;
+import io.swagger.annotations.Api;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.io.File;
+
+
+/**
+ * 娴嬭瘯閭欢鍙戦�� Controller
+ *
+ * @author Michelle.Chung
+ */
+@Validated
+@Api(value = "閭欢鎺у埗鍣�", tags = {"娴嬭瘯閭欢鍙戦��"})
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+@RequestMapping("/demo/mail")
+@RestController
+public class MailController {
+
+    /**
+     * 鍙戦�侀偖浠�
+     *
+     * @param to      鎺ユ敹浜�
+     * @param subject 鏍囬
+     * @param text    鍐呭
+     */
+    @GetMapping("/sendSimpleMessage")
+    public R<Void> sendSimpleMessage(String to, String subject, String text) {
+        MailUtils.send(to, subject, text, false);
+        return R.ok("鎿嶄綔鎴愬姛");
+    }
+
+    /**
+     * 鍙戦�侀偖浠讹紙甯﹂檮浠讹級
+     *
+     * @param to      鎺ユ敹浜�
+     * @param subject 鏍囬
+     * @param text    鍐呭
+     */
+    @GetMapping("/sendMessageWithAttachment")
+    public R<Void> sendMessageWithAttachment(String to, String subject, String text, String filePath) {
+        MailUtils.send(to, subject, text, false, new File(filePath));
+        return R.ok("鎿嶄綔鎴愬姛");
+    }
+
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MailConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MailConfig.java
new file mode 100644
index 0000000..d4ff8a7
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MailConfig.java
@@ -0,0 +1,39 @@
+package com.ruoyi.framework.config;
+
+import cn.hutool.extra.mail.MailAccount;
+import com.ruoyi.framework.config.properties.MailProperties;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.Resource;
+
+/**
+ * JavaMail 閰嶇疆
+ *
+ * @author Michelle.Chung
+ */
+@Configuration
+public class MailConfig {
+
+    @Resource
+    private MailProperties mailProperties;
+
+    /**
+     * 鍒濆鍖� JavaMailSender
+     */
+    @Bean
+    @ConditionalOnProperty(value = "spring.mail.enabled", havingValue = "true")
+    public MailAccount mailAccount() {
+        MailAccount account = new MailAccount();
+        account.setFrom(mailProperties.getUsername());
+        account.setUser(mailProperties.getUsername());
+        account.setPass(mailProperties.getPassword());
+        account.setPort(mailProperties.getPort());
+        account.setAuth(mailProperties.getAuth());
+        account.setDebug(mailProperties.getDebug());
+        account.setStarttlsEnable(mailProperties.getStarttlsEnable());
+        return account;
+    }
+
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/MailProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/MailProperties.java
new file mode 100644
index 0000000..ce2103f
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/MailProperties.java
@@ -0,0 +1,65 @@
+package com.ruoyi.framework.config.properties;
+
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * JavaMail 閰嶇疆灞炴��
+ *
+ * @author Michelle.Chung
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "spring.mail")
+public class MailProperties {
+
+    /**
+     * 杩囨护寮�鍏�
+     */
+    private String enabled;
+
+    /**
+     * 閭欢鏈嶅姟鍦板潃
+     */
+    private String host;
+
+    /**
+     * 鐢ㄦ埛鍚�
+     */
+    private String username;
+
+    /**
+     * 鎺堟潈鐮� (璁剧疆 - 璐︽埛 - POP3/SMTP鏈嶅姟)
+     */
+    private String password;
+
+    /**
+     * 閭鍔犲瘑绔彛锛屼笉鍚岄偖绠辩殑绔彛涓嶄竴鏍�
+     */
+    private Integer port;
+
+    /**
+     * 鏄惁闇�瑕佺敤鎴疯璇�
+     */
+    @Value("${spring.mail.properties.mail.smtp.auth}")
+    private Boolean auth;
+
+    /**
+     * 鏄惁鍚敤TLS鍔犲瘑
+     */
+    @Value("${spring.mail.properties.mail.smtp.starttls.enable}")
+    private Boolean starttlsEnable;
+
+    @Value("${spring.mail.properties.mail.smtp.ssl.trust}")
+    private String sslTrust;
+
+    private Boolean debug;
+
+    /**
+     * 浼犺緭鍗忚 starttls.enable = true 鏃朵负 smtps
+     */
+    private String protocol;
+
+}

--
Gitblit v1.9.3