Not really major push as I start the year. Development wise I'm able to piece parts of my project which are Registration, Forgot and Reset password.
They are actually basic features of any web applications so one should set it up as soon as you start the development process.
For local email I managed to use my existing localhost setup of Mailhog in my Docker component. Here's how it works for high level flow for reset password.- Allow user to post forgot password using their email
- Generate password token and generate reset link
- Send reset password email to user
- Allow user to submit new password
- Added Email Service class
- Add EmailConfigOptions class
- Inject to Program.cs
- Add email config to appsettings.json which will be loaded
- Load the SMTP config to Program.cs
public class EmailService{private readonly EmailServiceOptions _options;public EmailService(EmailServiceOptions options){_options = options;}public async Task SendEmailAsync(string recipient, string subject, string body){using (var client = new SmtpClient(_options.SmtpServer, _options.SmtpPort)){client.UseDefaultCredentials = false;client.Credentials = new NetworkCredential(_options.SmtpUsername,_options.SmtpPassword);using (var message = new MailMessage()){message.From = new MailAddress(_options.From);message.To.Add(recipient);message.Subject = subject;message.Body = body;await client.SendMailAsync(message);}}}}
public class EmailServiceOptions{public string SmtpServer { get; set; } = string.Empty;public int SmtpPort { get; set; } = 1025;public string SmtpUsername { get; set; } = string.Empty;public string SmtpPassword { get; set; } = string.Empty;public string From{ get; set; } = string.Empty;}
var emailOptions = builder.Configuration.GetSection("EmailService").Get<EmailServiceOptions>();builder.Services.AddSingleton(emailOptions);builder.Services.AddTransient<EmailService>();
[HttpPost("forgot-password")]public async Task<IActionResult> ForgotPassword(ForgotPasswordVM request){// Validate request parametersif (!ModelState.IsValid){return BadRequest(ModelState);}// Check if the provided email is registeredvar user = await _userManager.FindByEmailAsync(request.EmailAddress);if (user == null){return BadRequest(new { message = "The provided email is not registered." });}// Generate a password reset tokenvar token = await _userManager.GeneratePasswordResetTokenAsync(user);// Send the password reset emailvar resetUrl = $"{request.ResetUrl}?token={HttpUtility.UrlEncode(token)}&email={HttpUtility.UrlEncode(request.EmailAddress)}";await _emailService.SendEmailAsync(request.EmailAddress, "Password reset request", $"Please reset your password by following this link: {resetUrl}");return Ok();}