Harden password reset and email send flows
This commit is contained in:
@@ -18,14 +18,16 @@ public sealed class AuthController : ControllerBase
|
||||
private readonly ITokenService _tokens;
|
||||
private readonly IAppEmailSender _email;
|
||||
private readonly IGoogleTokenValidator _googleTokens;
|
||||
private readonly ILogger<AuthController> _logger;
|
||||
|
||||
public AuthController(IConfiguration cfg, UserManager<ApplicationUser> users, ITokenService tokens, IAppEmailSender email, IGoogleTokenValidator googleTokens)
|
||||
public AuthController(IConfiguration cfg, UserManager<ApplicationUser> users, ITokenService tokens, IAppEmailSender email, IGoogleTokenValidator googleTokens, ILogger<AuthController> logger)
|
||||
{
|
||||
_cfg = cfg;
|
||||
_users = users;
|
||||
_tokens = tokens;
|
||||
_email = email;
|
||||
_googleTokens = googleTokens;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpGet("config")]
|
||||
@@ -395,12 +397,20 @@ public sealed class AuthController : ControllerBase
|
||||
|
||||
var link = $"{baseUrl}/reset-password?email={Uri.EscapeDataString(user.Email)}&token={Uri.EscapeDataString(token)}";
|
||||
|
||||
await _email.SendAsync(
|
||||
user.Email,
|
||||
"Password reset",
|
||||
$"You requested a password reset for Jobbjakt.\n\nReset link:\n{link}\n\nIf you did not request this, you can ignore this email.",
|
||||
cancellationToken
|
||||
);
|
||||
try
|
||||
{
|
||||
await _email.SendAsync(
|
||||
user.Email,
|
||||
"Password reset",
|
||||
$"You requested a password reset for Jobbjakt.\n\nReset link:\n{link}\n\nIf you did not request this, you can ignore this email.",
|
||||
cancellationToken
|
||||
);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to send password reset email to {Email}", user.Email);
|
||||
return Problem(statusCode: StatusCodes.Status503ServiceUnavailable, title: "Email delivery unavailable", detail: "Password reset email could not be sent right now. Please try again later.");
|
||||
}
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
@@ -429,6 +439,11 @@ public sealed class AuthController : ControllerBase
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
private IActionResult EmailDeliveryUnavailable(string detail)
|
||||
{
|
||||
return Problem(statusCode: StatusCodes.Status503ServiceUnavailable, title: "Email delivery unavailable", detail: detail);
|
||||
}
|
||||
|
||||
private static string? TrimOrNull(string? value)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(value) ? null : value.Trim();
|
||||
|
||||
@@ -19,13 +19,15 @@ namespace JobTrackerApi.Controllers
|
||||
private readonly ISummarizerService _summarizer;
|
||||
private readonly IAppEmailSender _email;
|
||||
private readonly UserManager<ApplicationUser> _users;
|
||||
private readonly ILogger<JobApplicationsController> _logger;
|
||||
|
||||
public JobApplicationsController(JobTrackerContext db, ISummarizerService summarizer, IAppEmailSender email, UserManager<ApplicationUser> users)
|
||||
public JobApplicationsController(JobTrackerContext db, ISummarizerService summarizer, IAppEmailSender email, UserManager<ApplicationUser> users, ILogger<JobApplicationsController> logger)
|
||||
{
|
||||
_db = db;
|
||||
_summarizer = summarizer;
|
||||
_email = email;
|
||||
_users = users;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
private string? CurrentUserId =>
|
||||
@@ -2492,7 +2494,15 @@ Job description:
|
||||
var toEmail = (request.ToEmail ?? job.Company?.RecruiterEmail ?? string.Empty).Trim();
|
||||
if (string.IsNullOrWhiteSpace(toEmail)) return BadRequest("Recipient email is required.");
|
||||
|
||||
await _email.SendAsync(toEmail, request.Subject.Trim(), request.Body.Trim(), cancellationToken);
|
||||
try
|
||||
{
|
||||
await _email.SendAsync(toEmail, request.Subject.Trim(), request.Body.Trim(), cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to send follow-up email for job {JobId} to {Email}", id, toEmail);
|
||||
return Problem(statusCode: StatusCodes.Status503ServiceUnavailable, title: "Email delivery unavailable", detail: "Follow-up email could not be sent right now. Please try again later.");
|
||||
}
|
||||
|
||||
_db.Correspondences.Add(new Correspondence
|
||||
{
|
||||
|
||||
@@ -17,12 +17,14 @@ public sealed class UsersController : ControllerBase
|
||||
private readonly RoleManager<IdentityRole> _roles;
|
||||
private readonly IAppEmailSender _email;
|
||||
private readonly IConfiguration _cfg;
|
||||
public UsersController(UserManager<ApplicationUser> users, RoleManager<IdentityRole> roles, IAppEmailSender email, IConfiguration cfg)
|
||||
private readonly ILogger<UsersController> _logger;
|
||||
public UsersController(UserManager<ApplicationUser> users, RoleManager<IdentityRole> roles, IAppEmailSender email, IConfiguration cfg, ILogger<UsersController> logger)
|
||||
{
|
||||
_users = users;
|
||||
_roles = roles;
|
||||
_email = email;
|
||||
_cfg = cfg;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public sealed record UserDto(
|
||||
@@ -150,12 +152,20 @@ public sealed class UsersController : ControllerBase
|
||||
|
||||
var link = $"{baseUrl}/reset-password?email={Uri.EscapeDataString(u.Email)}&token={Uri.EscapeDataString(token)}";
|
||||
|
||||
await _email.SendAsync(
|
||||
u.Email,
|
||||
"Password reset",
|
||||
$"An admin initiated a password reset for your Jobbjakt account.\n\nReset link:\n{link}\n",
|
||||
cancellationToken
|
||||
);
|
||||
try
|
||||
{
|
||||
await _email.SendAsync(
|
||||
u.Email,
|
||||
"Password reset",
|
||||
$"An admin initiated a password reset for your Jobbjakt account.\n\nReset link:\n{link}\n",
|
||||
cancellationToken
|
||||
);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to send admin-initiated password reset email to {Email}", u.Email);
|
||||
return Problem(statusCode: StatusCodes.Status503ServiceUnavailable, title: "Email delivery unavailable", detail: "Password reset email could not be sent right now. Please try again later.");
|
||||
}
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
@@ -176,12 +186,20 @@ public sealed class UsersController : ControllerBase
|
||||
? "This is a test email from the Jobbjakt admin panel.\n\nIf you received this, the SMTP configuration is working."
|
||||
: request!.Message!.Trim();
|
||||
|
||||
await _email.SendAsync(
|
||||
toEmail,
|
||||
subject,
|
||||
$"{message}\n\nSent at: {DateTimeOffset.UtcNow:u}",
|
||||
cancellationToken
|
||||
);
|
||||
try
|
||||
{
|
||||
await _email.SendAsync(
|
||||
toEmail,
|
||||
subject,
|
||||
$"{message}\n\nSent at: {DateTimeOffset.UtcNow:u}",
|
||||
cancellationToken
|
||||
);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to send test email to {Email}", toEmail);
|
||||
return Problem(statusCode: StatusCodes.Status503ServiceUnavailable, title: "Email delivery unavailable", detail: "Test email could not be sent right now. Please try again later.");
|
||||
}
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user