Asp.net Core 电子邮件发件人在注册页面中不起作用
Posted
技术标签:
【中文标题】Asp.net Core 电子邮件发件人在注册页面中不起作用【英文标题】:Asp.net Core Email Sender is not working in Registration page 【发布时间】:2022-01-04 20:27:00 【问题描述】:我正在尝试使用 asp.net 身份设置一个 asp.net core razor 页面应用程序。
我已经完成了所有设置,我正在尝试生成用于注册的电子邮件,但代码如下:
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email", $"Please confirm your account by <a href='htmlEncoder.Default.Encode(value: callbackUrl)'>clicking here</a>.").ConfigureAwait(false);
没有被击中。就像它甚至不会调试到它一样,因此我的注册电子邮件没有被发送或生成。这些值保存在我的 SQL Server 数据库中,没有任何问题。
这是我要进行的设置:
appsetting.js
程序.cs
public class Program
/// <summary>
/// Defines the entry point of the application.
/// </summary>
/// <param name="args">The arguments.</param>
public static void Main(string[] args)
CreateHostBuilder(args).Build().Run();
var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
try
logger.Debug("init main");
CreateHostBuilder(args).Build().Run();
catch (Exception exception)
// NLog: catch setup errors
logger.Error(exception, "Stopped program because of exception");
throw;
finally
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
NLog.LogManager.Shutdown();
/// <summary>
/// Creates the host builder.
/// </summary>
/// <param name="args">The arguments.</param>
/// <returns></returns>
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
webBuilder.UseStartup<Startup>();
)
.ConfigureLogging(logging =>
logging.ClearProviders();
logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
)
.UseNLog(); // NLog: Setup NLog for Dependency injection
Starup.cs
/// <summary>
/// Startup
/// </summary>
public class Startup
/// <summary>
/// Initializes a new instance of the <see cref="Startup"/> class.
/// </summary>
/// <param name="configuration">The configuration.</param>
public Startup(IConfiguration configuration)
Configuration = configuration;
/// <summary>
/// Gets the configuration.
/// </summary>
/// <value>
/// The configuration.
/// </value>
public IConfiguration Configuration get;
/// <summary>
/// Configures the services.
/// // This method gets called by the runtime. Use this method to add services to the container.
/// </summary>
/// <param name="services">The services.</param>
public void ConfigureServices(IServiceCollection services)
// Add framework services.
services
.AddControllersWithViews()
.AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
// Added for identity set up - core27
services.AddRazorPages();
services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
services.Configure<EmailSettings>(Configuration.GetSection("EmailSettings"));
services.Configure<SessionTimeoutSettings>(Configuration.GetSection("SessionTimeoutSettings"));
services.AddSingleton<IEmailSender, EmailSender>();
// not sure what this is for?
//services.AddDevExpressControls();
// Auto Mapper Configurations
var mappingConfig = new MapperConfiguration(cfg =>
cfg.AddMaps(Assembly.GetExecutingAssembly());
cfg.SourceMemberNamingConvention = new LowerUnderscoreNamingConvention();
cfg.DestinationMemberNamingConvention = new PascalCaseNamingConvention();
);
var sessionTimeout = Convert.ToDouble(Configuration.GetSection("SessionTimeoutSettings").GetSection("SessionTimeout").Value);
services.AddSession(options =>
options.IdleTimeout = TimeSpan.FromMinutes(sessionTimeout);
);
/// <summary>
/// Configures the specified application.
/// </summary>
/// <param name="app">The application.</param>
/// <param name="env">The env.</param>
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
else
app.UseExceptionHandler("/Error");
app.UseStaticFiles();
app.UseRouting();
// Added for identity set up - core27
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
endpoints.MapControllers();
endpoints.MapDefaultControllerRoute();
endpoints.MapRazorPages();
);
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions
FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "node_modules")),
RequestPath = "/node_modules",
);
EmailSender.cs
#pragma warning disable SA1649 // File name should match first type name
public interface IEmailSender
#pragma warning restore SA1649 // File name should match first type name
/// <summary>
/// Sends the email asynchronous.
/// </summary>
/// <param name="email">The email.</param>
/// <param name="subject">The subject.</param>
/// <param name="message">The message.</param>
/// <returns>Task</returns>
Task SendEmailAsync(string email, string subject, string message);
/// <summary>
/// EmailSender
/// </summary>
/// <seealso cref="MORE.Website.Service.IEmailSender" />
public class EmailSender : IEmailSender
/// <summary>
/// The email settings
/// </summary>
private readonly EmailSettings emailSettings;
/// <summary>
/// The env
/// </summary>
private readonly IWebHostEnvironment env;
/// <summary>
/// Initializes a new instance of the <see cref="EmailSender"/> class.
/// </summary>
/// <param name="emailSettings">The email settings.</param>
/// <param name="env">The env.</param>
public EmailSender(
IOptions<EmailSettings> emailSettings,
IWebHostEnvironment env)
this.emailSettings = emailSettings.Value;
this.env = env;
/// <summary>
/// Sends the email asynchronous.
/// </summary>
/// <param name="email">The email.</param>
/// <param name="subject">The subject.</param>
/// <param name="message">The message.</param>
/// <exception cref="InvalidOperationException">InvalidOperationException</exception>
/// <returns>Task</returns>
public async Task SendEmailAsync(string email, string subject, string message)
try
var mimeMessage = new MimeMessage();
mimeMessage.From.Add(new MailboxAddress(emailSettings.SenderName, emailSettings.SenderFromAddress));
mimeMessage.To.Add(new MailboxAddress(email));
mimeMessage.Subject = subject;
mimeMessage.Body = new TextPart("html")
Text = message,
;
using (var client = new SmtpClient())
// For demo-purposes, accept all SSL certificates (in case the server supports STARTTLS)
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
if (env.IsDevelopment())
// The third parameter is useSSL (true if the client should make an SSL-wrapped
// connection to the server; otherwise, false).
// set to false for testing.
await client.ConnectAsync(emailSettings.MailServer, emailSettings.MailPort, false);
else
await client.ConnectAsync(emailSettings.MailServer);
// Note: only needed if the SMTP server requires authentication
await client.AuthenticateAsync(emailSettings.Sender, emailSettings.Password);
await client.SendAsync(mimeMessage);
await client.DisconnectAsync(true);
catch (Exception ex)
// TODO: handle exception
throw new InvalidOperationException(ex.Message);
Registration.cshtml
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Logging;
using Svc27M.Areas.Identity.Data;
using Svc27M.Services;
[AllowAnonymous]
public class RegisterModel : PageModel
private readonly SignInManager<Svc27MUser> _signInManager;
private readonly UserManager<Svc27MUser> _userManager;
private readonly ILogger<RegisterModel> _logger;
private readonly IEmailSender _emailSender;
public RegisterModel(
UserManager<Svc27MUser> userManager,
SignInManager<Svc27MUser> signInManager,
ILogger<RegisterModel> logger,
IEmailSender emailSender)
_userManager = userManager;
_signInManager = signInManager;
_logger = logger;
_emailSender = emailSender;
[BindProperty]
public InputModel Input get; set;
public string ReturnUrl get; set;
public IList<AuthenticationScheme> ExternalLogins get; set;
public class InputModel
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email get; set;
[Required]
[StringLength(100, ErrorMessage = "The 0 must be at least 2 and at max 1 characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password get; set;
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword get; set;
public async Task OnGetAsync(string returnUrl = null)
ReturnUrl = returnUrl;
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
returnUrl = returnUrl ?? Url.Content("~/");
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
if (ModelState.IsValid)
var user = new Svc27MUser UserName = Input.Email, Email = Input.Email ;
var result = await _userManager.CreateAsync(user, Input.Password);
if (result.Succeeded)
_logger.LogInformation("User created a new account with password.");
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new area = "Identity", userId = user.Id, code = code, returnUrl = returnUrl ,
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email", $"Please confirm your account by <a href='HtmlEncoder.Default.Encode(value: callbackUrl)'>clicking here</a>.").ConfigureAwait(false);
if (_userManager.Options.SignIn.RequireConfirmedAccount)
return RedirectToPage("RegisterConfirmation", new email = Input.Email, returnUrl = returnUrl );
else
await _signInManager.SignInAsync(user, isPersistent: false);
return LocalRedirect(returnUrl);
foreach (var error in result.Errors)
ModelState.AddModelError(string.Empty, error.Description);
// If we got this far, something failed, redisplay form
return Page();
【问题讨论】:
【参考方案1】:我想通了:
内部有一个IEmailSender
接口:
using Microsoft.AspNetCore.Identity.UI.Services;
我的IEmailSender
并没有指向我创建的本地地址。
以下是更改和修复。
现在正在正确发送电子邮件以进行注册。
这是我的代码更改:
【讨论】:
以上是关于Asp.net Core 电子邮件发件人在注册页面中不起作用的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 ASP.NET Core Identity 将登录/注册系统添加到现有数据库?
ASP.NET MVC 用户管理器 SendEmailAsync:如何更改发件人电子邮件
ASP.NET Core 2.1 Razor 页面返回带有模型的页面