问题
Hi guys i'm trying to configure a password reset email sender but when I run the web app (i'm using .net core 2.1) it doesn't give any error it just redirect to page(as it should) but no email is sent.The email sender is actually working (it sends a email with a verification code). Please check the code below and help me find the error i have no clue.
ForgetPassword.cshtml.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using ProjectiWebFinal.Areas.Identity.Services;
using ProjectiWebFinal.Data;
namespace ProjectiWebFinal.Areas.Identity.Pages.Account
{
[AllowAnonymous]
public class ForgotPasswordModel : PageModel
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly IEmailSender _emailSender;
public ForgotPasswordModel(UserManager<ApplicationUser> userManager, IEmailSender emailSender)
{
_userManager = userManager;
_emailSender = emailSender;
}
[BindProperty]
public InputModel Input { get; set; }
public class InputModel
{
[Required]
[EmailAddress]
public string Email { get; set; }
[Required]
public string UserName { get; set; }
}
public async Task<IActionResult> OnPostAsync()
{
if (ModelState.IsValid)
{
var user = await _userManager.FindByEmailAsync(Input.UserName);
if (user == null || !(await _userManager.IsEmailConfirmedAsync(user)))
{
// Don't reveal that the user does not exist or is not confirmed
return RedirectToPage("./ForgotPasswordConfirmation");
}
// For more information on how to enable account confirmation and password reset please
// visit https://go.microsoft.com/fwlink/?LinkID=532713
var code = await _userManager.GeneratePasswordResetTokenAsync(user);
var callbackUrl = Url.Page(
"/Account/ResetPassword",
pageHandler: null,
values: new { userId = user.Id, code = code },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(
user.Email,
"Reset Password For"+user.UserName,
$"Please reset your password by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>." +
$"You will be redirected to another page to Create your new password!");
return RedirectToPage("./ForgotPasswordConfirmation");
}
return Page();
}
}
}
ForgotPassword.cshtml
@page
@model ForgotPasswordModel
@{
ViewData["Title"] = "Forgot your password?";
}
<h2>@ViewData["Title"]</h2>
<h4>Enter your email.</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Input.UserName"></label>
<input asp-for="Input.UserName" class="form-control" />
<span asp-validation-for="Input.UserName" class="text-danger"></span>
<label asp-for="Input.Email"></label>
<input asp-for="Input.Email" class="form-control" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
ResetPassword.cshtml
@page
@model ResetPasswordModel
@{
ViewData["Title"] = "Reset password";
}
<h2>@ViewData["Title"]</h2>
<h4>Reset your password.</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<input asp-for="Input.Code" type="hidden" />
<div class="form-group">
<label asp-for="Input.Username"></label>
<input asp-for="Input.Username" class="form-control" />
<span asp-validation-for="Input.Username" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Email"></label>
<input asp-for="Input.Email" class="form-control" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Password"></label>
<input asp-for="Input.Password" class="form-control" />
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.ConfirmPassword"></label>
<input asp-for="Input.ConfirmPassword" class="form-control" />
<span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-default">Reset</button>
</form>
</div>
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
ResetPassword.cshtml.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using ProjectiWebFinal.Data;
namespace ProjectiWebFinal.Areas.Identity.Pages.Account
{
[AllowAnonymous]
public class ResetPasswordModel : PageModel
{
private readonly UserManager<ApplicationUser> _userManager;
public ResetPasswordModel(UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
}
[BindProperty]
public InputModel Input { get; set; }
public class InputModel
{
[Required]
public string Username { get; set; }
[Required]
[EmailAddress]
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)]
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 string Code { get; set; }
}
public IActionResult OnGet(string code = null)
{
if (code == null)
{
return BadRequest("A code must be supplied for password reset.");
}
else
{
Input = new InputModel
{
Code = code
};
return Page();
}
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
var user = await _userManager.FindByEmailAsync(Input.Email);
if (user == null)
{
// Don't reveal that the user does not exist
return RedirectToPage("./ResetPasswordConfirmation");
}
var result = await _userManager.ResetPasswordAsync(user, Input.Code, Input.Password);
if (result.Succeeded)
{
return RedirectToPage("./ResetPasswordConfirmation");
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
return Page();
}
}
}
Here it is Myemailsender.cs that i use for emali confirmation and it's working(it sends the email to the user.
using Microsoft.AspNetCore.Identity.UI.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Threading.Tasks;
namespace ProjectiWebFinal.Areas.Identity.Services
{
public class MyEmailSender : IEmailSender
{
private string host;
private int port;
private bool enableSSL;
private string Email;
private string password;
// Get our parameterized configuration
public MyEmailSender(string host, int port, bool enableSSL, string email, string password)
{
this.host = host;
this.port = port;
this.enableSSL = enableSSL;
this.Email = email;
this.password = password;
}
// Use our configuration to send the email by using SmtpClient
public Task SendEmailAsync(string email, string subject, string htmlMessage)
{
var client = new SmtpClient(host, port)
{
Credentials = new NetworkCredential(Email, password),
EnableSsl = enableSSL
};
return client.SendMailAsync(
new MailMessage(Email, email, subject, htmlMessage) { IsBodyHtml = true }
);
}
}
}
来源:https://stackoverflow.com/questions/59774404/reset-password-email-not-sent-email-sender-works-for-email-confirmation-but-n