https://docs.abp.io/en/abp/latest/Emailing
使用郵件
第一步:在項目中已入如下包:
<PackageReference Include="Volo.Abp.Emailing" Version="6.0.1" />
<PackageReference Include="Volo.Abp.MailKit" Version="6.0.1" />
添加模塊依賴
namespace AbpManaul
{
[DependsOn(
...
typeof(AbpEmailingModule),
typeof(AbpMailKitModule)
)]
public class AbpManualApplicationModule : AbpModule
{
}
}
第二步:使用 appsettings.json 存儲配置項,如下所示
代碼清單:AbpManual.Web/appsettings.json
{
...
"Settings": {
"Abp.Mailing.Smtp.Host": "smtp.126.com",
"Abp.Mailing.Smtp.Port": "25",
"Abp.Mailing.Smtp.UserName": "abpdev",
"Abp.Mailing.Smtp.Password": "rHGKfmXnrF7p8uZovp2I6A==", // 原值:123, 是郵箱smtp服務的授權碼
"Abp.Mailing.Smtp.Domain": "",
"Abp.Mailing.Smtp.EnableSsl": "false",
"Abp.Mailing.Smtp.UseDefaultCredentials": "false",
"Abp.Mailing.DefaultFromAddress": "[email protected]",
"Abp.Mailing.DefaultFromDisplayName": "Abp 手冊"
},
"StringEncryption": {
"DefaultPassPhrase": "DOKIDhw8UbBTB82G" //加密鹽
}
}
特別注意:
Abp.Mailing.Smtp.Password 必須是一個加密值, 不能使用原值,否則拋如下異常,
The input data is not a complete block.
System.Security.Cryptography.CryptographicException: The input data is not a complete block.
at Internal.Cryptography.UniversalCryptoDecryptor.UncheckedTransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
at Internal.Cryptography.UniversalCryptoTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
at System.Security.Cryptography.CryptoStream.ReadAsyncCore(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken, Boolean useAsync)
如何根據密碼的原值得到加密值,見下一節:加密 SMTP 密碼
Tips:如何郵箱申請開通smtp服務
先去郵箱平臺申請一個郵箱,然後申請開通smtp服務,
這我使用的是126郵箱,Abp.Mailing.Smtp.Password 的原值不是郵箱的登錄密碼,
而是申請開通smtp服務成功後,得到的一個授權碼
第三步:發送郵件
using Microsoft.Extensions.Logging;
using Volo.Abp;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Emailing;
namespace AbpManual.BackgroundJobs
{
/// <summary>
/// https://docs.abp.io/zh-Hans/abp/latest/Background-Jobs
/// 後臺作業是一個實現IBackgroundJob<TArgs>接口或繼承自BackgroundJob<TArgs>類的類
/// </summary>
public class EmailSendingJob : AsyncBackgroundJob<EmailSendingArgs>, ITransientDependency
{
private readonly IEmailSender _emailSender;
private readonly ILogger<EmailSendingJob> _logger;
public EmailSendingJob(
IEmailSender emailSender,
ILogger<EmailSendingJob> logger)
{
_emailSender = emailSender;
_logger = logger;
}
public override async Task ExecuteAsync(EmailSendingArgs args)
{
// 模擬隨機產生異常,看看後臺作業是否因失敗再次執行
if (RandomHelper.GetRandom(0, 10) < 5)
{
throw new ApplicationException("A sample exception from the EmailSendingJob!");
}
_logger.LogInformation($"############### EmailSendingJob: 郵件已成功發送至郵箱:{args.EmailAddress} ###############");
//lock (Console.Out)
//{
// var oldColor = Console.ForegroundColor;
// Console.ForegroundColor = ConsoleColor.Green;
// Console.WriteLine();
// Console.WriteLine($"############### EmailSendingJob: 郵件已成功發送至郵箱:{args.EmailAddress} ###############");
// Console.WriteLine();
// Console.ForegroundColor = oldColor;
//}
// 發送郵件
await _emailSender.SendAsync(
args.EmailAddress,
args.Subject,
args.Body
);
}
}
}
第四步:測試
編輯測試服務
代碼清單:AbpManual.Application/BackgroundJobs/BackgroundJobService.cs
using AbpManual.BackgroundJobs;
using Volo.Abp.Application.Services;
using Volo.Abp.BackgroundJobs;
namespace AbpManaul.BackgroundJobs
{
public class BackgroundJobService : ApplicationService, IBackgroundJobService
{
/// <summary>
/// 默認後臺作業管理器
/// https://docs.abp.io/zh-Hans/abp/latest/Background-Jobs
/// ABP framework 包含一個簡單的 IBackgroundJobManager 實現;
/// </summary>
private readonly IBackgroundJobManager _backgroundJobManager;
public BackgroundJobService(IBackgroundJobManager backgroundJobManager)
{
_backgroundJobManager = backgroundJobManager;
}
public async Task RegisterAsync(RegisterInput input)
{
//TODO: 創建一個新用戶到數據庫中...
await _backgroundJobManager.EnqueueAsync(
new EmailSendingArgs
{
EmailAddress = input.EmailAddress,
Subject = "You've successfully registered!",
Body = "恭喜你註冊成功!"
}
);
}
}
public class RegisterInput
{
public string Name { get; set; }
public string EmailAddress { get; set; }
public string Password { get; set; }
}
}
點擊執行按鈕,郵件發送成功,如下圖所示:
郵件內容也正確:
加密 SMTP 密碼
Abp.Mailing.Smtp.Password 必須是一個加密值。如果你使用 ISettingManager 設置密碼,你不必擔心。它在內部加密 set 上的值並在 get 上解密。
如果使用 appsettings.json 存儲密碼,則應手動注入 ISettingEncryptionService 並使用其 Encrypt 方法獲取加密值。這可以通過在你的應用程序中創建一個簡單的代碼來完成。然後你可以刪除代碼。
更好的做法是,你可以在應用程序中創建一個 UI 來配置電子郵件設置。在這種情況下,你可以直接使用 ISettingManager 而不用擔心加密。
定義一個函數,獲取加密後的密碼,如下所示:
using Volo.Abp.Emailing;
using Volo.Abp.Settings;
namespace AbpManaul.Application.Settings;
public class SettingService
{
private readonly ISettingEncryptionService _settingEncryptionService;
private readonly ISettingDefinitionManager _settingDefinitionManager;
public SettingService(
ISettingEncryptionService settingEncryptionService,
ISettingDefinitionManager settingDefinitionManager)
{
_settingEncryptionService = settingEncryptionService;
_settingDefinitionManager = settingDefinitionManager;
}
public string EncryptMailingSmtpPassword(string passsword)
{
var setting = _settingDefinitionManager.Get(EmailSettingNames.Smtp.Password);
var encryptPassword = _settingEncryptionService.Encrypt(setting, passsword);
return encryptPassword;
}
}
然後調用函數EncryptMailingSmtpPassword()
,獲取加密後的密碼,比如:
調用函數EncryptMailingSmtpPassword(123)
返回 "3zil2vJ325s+uboMEiKCDA=="
然後在使用該值在配置文件 appsettings.json
對 Abp.Mailing.Smtp.Password
進行設置,如下所示:
...
"Settings": {
...
"Abp.Mailing.Smtp.Password": "3zil2vJ325s+uboMEiKCDA==",
...
},
...