ASP.NET Core 3.1 创建发送邮件确认服务

ASP.NET Core 3.1 create a service to send email confirmation

我在几个页面上调用了方法 EmailConfirmation,所以我决定为此创建一个服务。

但我对 GetEmailConfirmCallback 有疑问:Url 为空。

我也想更改身份区域页面并使用此服务,而不是在注册和外部登录等某些页面中,...每次都执行相同的任务。

这是我的 class:

public class ApplicationServices : ControllerBase
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly IEmailSender _emailSender;
    private readonly IWebHostEnvironment _webHostEnvironment;

    public ApplicationServices(IEmailSender emailSender, UserManager<ApplicationUser> userManager, IWebHostEnvironment webHostEnvironment)
    {
        _emailSender = emailSender;
        _userManager = userManager;
        _webHostEnvironment = webHostEnvironment;
    }

    public async Task<ResultModel> EmailConfirmation(ApplicationUser user, string returnUrl = "/Identity/Account/Login")
    {
        ResultModel resultModel = new ResultModel();

        try
        {
            var pathToEmailTemplate = _webHostEnvironment.WebRootPath
            + Path.DirectorySeparatorChar.ToString()
            + "templates"
            + Path.DirectorySeparatorChar.ToString()
            + "email_templates"
            + Path.DirectorySeparatorChar.ToString()
            + "confirm-email-reset-password.html";

            string emailTemplateString = string.Empty;

            using (StreamReader SourceReader = System.IO.File.OpenText(pathToEmailTemplate))
            {
                emailTemplateString = SourceReader.ReadToEnd();
            }

            string messageSubject = "Confirm your email";
            string messageBody = $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(await GetEmailConfirmCallback(user, returnUrl))}'>clicking here</a>.";

            string messageSenderName = "Support team.";

            string emailMessage = string.Format(emailTemplateString, messageSubject, string.IsNullOrEmpty(user.FullName) ? user.FullName : "User", messageBody, messageSenderName);

            await _emailSender.SendEmailAsync(user.Email, messageSubject, emailMessage);

            resultModel.IsSucceed = true;
            return resultModel;
        }
        catch (Exception e)
        {
            resultModel.IsSucceed = false;
            resultModel.Message = e.Message;
            return resultModel;
        }
    }
    
    private async Task<string> GetEmailConfirmCallback(ApplicationUser user, string returnUrl)
    {
        var codeEmail = await _userManager.GenerateEmailConfirmationTokenAsync(user);
        codeEmail = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(codeEmail));
        var callbackUrlEmail = Url.Page(
        "/Account/ConfirmEmail",
        pageHandler: null,
        values: new { area = "Identity", userId = user.Id, code = codeEmail, returnUrl },
        protocol: Request.Scheme);

        return callbackUrlEmail;
    }
}

如有任何建议或帮助,我们将不胜感激。

您是否尝试过使用 Url.Action 而不是 Url.PageUrl.Action 用于 MVC,Url.Page 用于 Razor。您没有指定您使用的是 Razor 还是 MVC。

好的,这是过去的一些细节link

他们使用了 URL.Action 就像这个例子:

在您的代码中,您使用的是 Url.Page。

这是另一个使用 Url.Action 的例子:

  1. 在Startup.cs
  2. 中注册HttpContextAccessor
services.AddHttpContextAccessor();
  1. 在服务中添加 IHttpContextAccessorLinkGenerator 作为依赖项注入 class
private readonly UserManager<ApplicationUser> _userManager;
private readonly IEmailSender _emailSender;
private readonly IWebHostEnvironment _webHostEnvironment;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly LinkGenerator _generator;

public ApplicationServices(UserManager<ApplicationUser> userManager, 
                            IEmailSender emailSender, 
                            IWebHostEnvironment webHostEnvironment, 
                            IHttpContextAccessor httpContextAccessor, 
                            LinkGenerator generator)
{
    _userManager = userManager;
    _emailSender = emailSender;
    _webHostEnvironment = webHostEnvironment;
    _httpContextAccessor = httpContextAccessor;
    _generator = generator;
}
  1. 改变方法GetEmailConfirmCallback
private async Task<string> GetEmailConfirmCallback(ApplicationUser user, HttpContext context, string returnUrl)
{
    var codeEmail = await _userManager.GenerateEmailConfirmationTokenAsync(user);
    codeEmail = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(codeEmail));


    var callbackUrlEmail = _generator.GetUriByPage(_httpContextAccessor.HttpContext,
    page:"/Account/ConfirmEmail",
    handler: null,
    values: new { area = "Identity", userId = user.Id, code = codeEmail, returnUrl });


    return callbackUrlEmail;
}