8.郵件發送功能

来源:https://www.cnblogs.com/zhang-3/archive/2023/09/30/17738032.html
-Advertisement-
Play Games

這裡想補充下上個文章,感覺有點不太行。因為每次設計新的表結構就要去更新一下,所以,乾脆隨著我要做的功能去展示我的表結構設計,最終再把所有的表結構包括sql語句統計出來,感覺這樣更新會方便很多~ 這個文章主要是發送郵件的功能。之前提過,我不是一下子把後端全部完成,然後再一下子搞定後端。所以我前後端是要 ...


這裡想補充下上個文章,感覺有點不太行。因為每次設計新的表結構就要去更新一下,所以,乾脆隨著我要做的功能去展示我的表結構設計,最終再把所有的表結構包括sql語句統計出來,感覺這樣更新會方便很多~

這個文章主要是發送郵件的功能。之前提過,我不是一下子把後端全部完成,然後再一下子搞定後端。所以我前後端是要一起做,然後去完善介面功能。

登錄註冊這個功能,90%網站都需要。可以不用,但是不能沒有。本篇文章主要是實現註冊的驗證碼發放功能(郵件or手機號)。

因為發簡訊得收費,咳咳,所以這裡先做的郵件發送驗證碼。這個在網路衝浪的時候要註冊某些網站賬號的時候一般都會遇上把?之前看有的朋友是後臺返回一張驗證碼的圖片,這個我後面應該也會做一下,但我覺得意義不是特別大。就跟死驗證一樣,這樣我怎麼判定你輸入的郵箱是否是正確真實可用的呢?我不想給資料庫搞一堆臟數據,麻煩

之前微軟是自帶一個郵箱發送的庫的,現在好像棄用了,雖然還可以用。但是微軟推薦了一個新的開源的第三方庫MailKit。使用起來相對來說,代碼減少了不少,感覺挺好用的,官網也有案例,所以不會細說,官網的很詳細,我也不想寫博客都是搬運官網的。我的代碼會加上自己的註釋。哪怕你不看官網,跟著我這個流程走就100%沒問題。

正文開始~ 

先展示下,驗證碼表的資料庫結構:註釋說明都有應該無需細說了

 建表SQL

create table  dbo.AutoCode
(
       Id                INT identity(1, 1) not null  /*編號*/,
       Code              VARCHAR(20) not null  /*驗證碼*/,
       Phone             VARCHAR(20) null  /*手機號*/,
       Email             VARCHAR(100) null  /*郵箱*/,
       ExpDate           FLOAT not null  /*過期時間*/,
       CreateDate        DATETIME default getdate() null  /*創建日期*/,
       UpdateDate        DATETIME default getdate() null  /*修改日期*/
);
alter  table dbo.AutoCode
       add constraint PK_AutoCode_Id primary key (Id);
EXEC sp_addextendedproperty 'MS_Description', '驗證碼表', 'user', dbo, 'table', AutoCode, NULL, NULL;
EXEC sp_addextendedproperty 'MS_Description', '編號', 'user', dbo, 'table', AutoCode, 'column', Id;
EXEC sp_addextendedproperty 'MS_Description', '驗證碼', 'user', dbo, 'table', AutoCode, 'column', Code;
EXEC sp_addextendedproperty 'MS_Description', '手機號', 'user', dbo, 'table', AutoCode, 'column', Phone;
EXEC sp_addextendedproperty 'MS_Description', '郵箱', 'user', dbo, 'table', AutoCode, 'column', Email;
EXEC sp_addextendedproperty 'MS_Description', '過期時間 (當前時間+過期時間)的時間戳', 'user', dbo, 'table', AutoCode, 'column', ExpDate;
EXEC sp_addextendedproperty 'MS_Description', '創建日期 預設為當前時間', 'user', dbo, 'table', AutoCode, 'column', CreateDate;
EXEC sp_addextendedproperty 'MS_Description', '修改日期 預設為當前時間', 'user', dbo, 'table', AutoCode, 'column', UpdateDate;
View Code

 使用SQLsugar生成實體到FastEasy.Model類庫中。

這裡插一句吧,前面不是用T4模板搞了個生成倉儲模式4個類的代碼生成嗎,我可能目前對於T4還是不是很會,在T4模板使用第三方庫的時候會報一個找不到netstand程式集的問題,我目前很疑惑。然後看了下別人的代碼生成器,好像通過後臺管理系統就可以,那目前可能我弄的這個還不是很好,但是也極大的減少了一些工作量,以後我會再學習下這塊兒,也搞個更方便的代碼生成器。T4模板確實有一些局限性……

那我是又在base基類添加了一個方法,CreateModels。我這個資料庫空空如也,所以選擇了全部生成,當然也可以根據條件去篩選生成,甚至重命名,修改欄位名,諸如此類的。這是sqlsugar提供的,真的很強大,可以去學習一下。中秋的時候阿妮亞又更新了一個功能,可以把增刪改寫成一個方法,但我目前還是沒看,只是看到了介紹,這個以後再去看一下,nb~

代碼只有一句:第一個參數是生成的目錄路徑,第二個是命名空間
    public void CreateModels()
    {
        db.DbFirst.IsCreateAttribute().CreateClassFile(@"D:\FastEasy\API\FastEasy.Model\Models\", "FastEasy.Model.Models");
    }

 如何使用呢。因為是要繼承base基類,所以得有個實體,所以我就手動創建了一個空的base類。然後用T4代碼生成器分別生成了倉儲層和服務層的介面和實現類。主要是避免沒有泛型傳入,註入的時候報錯。然後直接調用這個方法就好了,base類在這裡沒有作用!只是避免註入解析的時候不報錯!

其實應該稍微感覺的出來這樣好像有點麻煩……無奈現在手裡活不夠多,經驗欠缺,暫時沒有想到別的思路,但我們有代碼生成器,終歸也麻煩不到哪去,一分鐘就搞定了

 到這裡,我們生成了實體,然後通過T4代碼生成器,同樣根據資料庫生成了各自的倉儲層和服務層。這裡就不得不提一個弊端了。但是這隻能說目前的,就是要先生成實體,因為T4模板不需要運行就可以生成,所以沒實體的話,依賴註入會找不到實體而報錯,這樣就沒法運行程式生成實體了。除非就是說,咱們搞個控制台程式單獨運行下?反正上邊也提到了,這個T4我弄的確實不到位,只是最基礎的一些功能,還需繼續完善呀~~~


 

言歸正傳,這篇文章主要說的是發送郵件!

上面簡單提到了,我們使用的是微軟推薦的一個第三方庫:MailKit+MimeKit。NuGet管理器自行下載。

MailKit是用於向郵箱服務端發送消息的。

MimeKit則是創建郵件實例的(包括並不局限:發送人接收人郵件內容等……)。

再簡單點理解就是,通過MailKIt把MimeKit創建的郵件實例發送給郵箱服務端,然後根據你的郵件實例解析發送相應的郵件。似乎我這麼說有點繞嘴,但我是這麼理解的。甚至一開始我都很好奇,為什麼要分成兩個包安裝呀,或者你內置進去唄?不過他這些個庫不僅僅支持你發送郵件,好像還能下載郵件,刪除郵件,挺多功能的,確實np,但這些我好像也用不上,有興趣的同學就自行學習吧~

實現註冊發送郵件驗證碼的功能。其實很簡單。首先搞清楚,我們需要的情景是如何的:

  1. 用戶填寫郵箱
  2. 發送驗證碼到郵箱
  3. 正則匹配輸入的是否正確格式
  4. 生成隨機驗證碼
  5. 新增到資料庫
  6. 返回結果給前端成功還是失敗

正則也沒啥可說的,因為你百度郵箱正則就找到了匹配規則拿過來用就好了。隨機驗證碼這個更沒什麼可說的Random……當然你可以搞更複雜的,但我覺得我這樣應該足夠了。

我把這兩個方法寫在了Common類庫中。因為他們不涉及業務邏輯,是可公用的。因此做成靜態類方法直接調用就好。

        /// <summary>
        /// 檢驗是否手機號
        /// </summary>
        /// <param name="number">號碼</param>
        /// <returns></returns>
        public static bool IsPhone(string number)
        {
            string phoneRegex = @"^1\d{10}$";
            return Regex.IsMatch(number, phoneRegex);
        }

        /// <summary>
        /// 檢驗是否郵箱
        /// </summary>
        /// <param name="number">號碼</param>
        /// <returns></returns>
        public static bool IsEmail(string number)
        {
            string emailRegex = @"^\S+@\S+\.\S+$";
            return Regex.IsMatch(number, emailRegex);
        }
        /// <summary>
        /// 創建一個4位隨機驗證碼
        /// </summary>
        /// <returns></returns>
        public static string CreateRandomCode()
        {
            int num = 4;
            const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; // 根據需要修改字元集合
            Random random = new();
            char[] code = new char[num];

            for (int i = 0; i < num; i++)
            {
                code[i] = chars[random.Next(chars.Length)];
            }
            return new string(code);
        }

 

包括發送郵件的功能,也理所應當的放在Common類庫中。目前因為針對發送郵件的功能,可能封裝的方法自由度不高,我貼的代碼只做參考,可以根據自己需求完善 郵件實例是用MimeKit中的MimeMessage創建的。裡面包含了發送人,接收人,郵件內容等。原本我想傳遞這個類型的參數,但是官方的這個實例中,發送人和接收人是不能直接賦值的,要Add添加進去。這對我們來說還是有點麻煩的 ,主要是傳參太麻煩了。所以自己創建了一個新的實體類型Mime,主要用來傳遞參數。
using MimeKit;

namespace FastEasy.Common.Extension.Mail
{
    public class Mime
    {
        /// <summary>
        /// 主題
        /// </summary>
        public string Subject { get; set; }

        /// <summary>
        /// 消息內容
        /// </summary>
        public TextPart Body { get; set; }

        /// <summary>
        /// 發送人,預設為“官方”
        /// </summary>
        public MailboxAddress From { get; set; } = new MailboxAddress("神里凌華", "[email protected]");

        /// <summary>
        /// 郵箱SMTP授權碼
        /// </summary>
        public string Code { get; set; } = "XXXXX";

        /// <summary>
        /// 接收人
        /// </summary>
        public MailboxAddress To { get; set; }

        /// <summary>
        /// 465加密25不加密
        /// </summary>
        public  int Port { get; set; } = 465;
    }
}

 發送郵件方法:通過上面的註釋應該都可以看懂,所以不過多解釋廢話了

        /// <summary>
        /// 發送郵件
        /// </summary>
        /// <param name="mime">郵件消息體</param>
        /// <returns></returns>
        public static async Task<bool> SendMail(Mime mime)
        {
            //郵件實例
            MimeMessage message = new()
            {                
                Subject = mime.Subject,
                Body = mime.Body,
            };
            message.To.Add(mime.To);
            message.From.Add(mime.From);
            try
            {
                using var client = new SmtpClient();
                client.Connect("smtp.163.com", mime.Port, mime.Port == 465);
                client.Authenticate(mime.From.Address, mime.Code);
                await client.SendAsync(message);
                client.Disconnect(true);
            }
            catch
            {
                return false;
            }
            return true;
        }

 

由此看來,該功能並未涉及程式本身的業務邏輯,因此只要在API程式層調用相應的公共方法,然後調用基類的新增方法即可完成。 API程式層代碼:  
        /// <summary>
        /// 發送驗證碼
        /// </summary>
        /// <param name="user">郵箱或者手機號</param>
        /// <returns></returns>
        [HttpPost]
        [SwaagerRoute(SwaggerVersion.FastEasy, "CreateCode")]
        public async Task<ResultDto> CreateCode(string user)
        {
            var result = new ResultDto();
            var code = RandomCode.CreateRandomCode();

            if (RegexMatch.IsPhone(user))
            {
                result.State = false;
                result.Message = "暫不支持手機號註冊";
            }
            else if (RegexMatch.IsEmail(user))
            {
                var mime = new Mime
                {
                    Body = new MimeKit.TextPart()
                    {
                        Text = code
                    },
                    Subject = "驗證碼",
                    To = new MimeKit.MailboxAddress(user, user),
                };
                var autocode = new AutoCode
                {
                    Code = code,
                    CreateDate = DateTime.Now,
                    Email = user,
                    ExpDate = DateTimeOffset.Now.AddMinutes(10).ToUnixTimeSeconds(),
                    UpdateDate = DateTime.Now
                };
                if (await EmailKit.SendMail(mime) && await service.CreateEntityAsync(autocode))
                {
                    result.State = true;
                    result.Message = "發送成功請查收";
                }
                else
                {
                    result.State = false;
                    result.Message = "發送失敗";
                }
            }
            else
            {
                result.State = false;
                result.Message = "請輸入正確的註冊號碼";
            };
            return result;
        }

我承認我廢話太多了,我本意想講的詳細點……看效果:

 掰掰,中秋國慶快樂……我還沒買到票……

     

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 魅族雲服務的相冊功能,沒有一鍵選擇所有的圖片,就挺噁心的。魅族不一直提供雲相冊的服務了,就需要將圖片全部下載。之前有大神寫過油潑猴的腳本。 今天拿來用,發現用不了。 又在網上查一下了,有npm的開源下載工具。附上碼雲地址,沒用過。https://gitee.com/moreant/mpcb 但是部署 ...
  • 我們在使用SpringMVC從前端接受傳遞過來的日期數據時,預設傳遞過來的數據是String類型,如果我們從前端傳遞過來的數據格式是yyyy/MM/dd,SpringMVC有內置類型轉化器會將String類型自動轉化成Date類型。但如果我們從前端傳遞過來的數據格式是yyyy-MM-dd,Sprin... ...
  • Feign 簡介 Spring Cloud Feign 是一個 HTTP 請求調用的輕量級框架,可以以 Java 介面註解的方式調用 HTTP 請求,而不用通過封裝 HTTP 請求報文的方式直接調用 Feign 通過處理註解,將請求模板化,當實際調用的時候傳入參數,根據參數再應用到請求上,進而轉化成 ...
  • Get請求和Post請求都是HTTP協議中的兩種常見請求方法,底層都是TCP/IP協議,用於客戶端與伺服器之間的數據傳輸。 ...
  • 目錄題目翻譯題目描述輸入格式輸出格式樣例 #1樣例輸入 #1樣例輸出 #1樣例 #2樣例輸入 #2樣例輸出 #2樣例 #3樣例輸入 #3樣例輸出 #3題目簡化題目思路AC代碼 題目翻譯 【題目描述】 你決定用素數定理來做一個調查. 眾所周知, 素數又被稱為質數,其含義就是除了數字一和本身之外不能被其 ...
  • 布爾值表示兩個值之一:True(真)或False(假)。 布爾值 在編程中,您經常需要知道一個表達式是否為True或False。 您可以在Python中評估任何表達式,並獲得兩個答案之一:True或False。 當您比較兩個值時,表達式會被評估,Python會返回布爾答案: 示例 print(10 ...
  • 面積圖,或稱區域圖,是一種隨有序變數的變化,反映數值變化的統計圖表。 面積圖也可用於多個系列數據的比較。這時,面積圖的外觀看上去類似層疊的山脈,在錯落有致的外形下表達數據的總量和趨勢。面積圖不僅可以清晰地反映出數據的趨勢變化,也能夠強調不同類別的數據間的差距對比。 面積圖的特點在於,折線與自變數坐標 ...
  • 用Rust手把手編寫一個wmproxy(代理,內網穿透等), 通訊協議源碼解讀篇 項目 ++wmproxy++ gite: https://gitee.com/tickbh/wmproxy github: https://github.com/tickbh/wmproxy 事件模型的選取 OS線程, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...