sequenceDiagram actor User participant API as API Controller participant Mediator as MediatR pipeline
(ValidationBehavior) box Handler Layer participant ResendHandler as ResendConfirmationEmailHandler participant UserMgr as UserManager(ApplicationUser) participant TokenSvc as TokenService end box Infrastructure Layer participant SMTP as Email Provider participant Template as Template Provider end box Repository / Cross-slice participant UserStore as DapperUserStore
(IUserStore/IUserPasswordStore/IUserEmailStore) participant EmailDispatcher as EmailDispatcher
(Features.Emails) end participant DB as SQL Server User->>API: POST /api/auth/confirm/resend?userId={id} (requires Bearer access token) activate API API->>Mediator: Send(ResendConfirmationEmailCommand(userId)) activate Mediator Mediator->>ResendHandler: Handle(command) activate ResendHandler ResendHandler->>UserMgr: FindByIdAsync(userId) activate UserMgr UserMgr->>UserStore: FindByIdAsync(userId) activate UserStore UserStore->>DB: SELECT ... FROM UserAccount WHERE UserAccountID = @Id activate DB DB-->>UserStore: row or null deactivate DB UserStore-->>UserMgr: ApplicationUser or null deactivate UserStore UserMgr-->>ResendHandler: ApplicationUser or null deactivate UserMgr alt User not found ResendHandler->>ResendHandler: return silently (prevents user enumeration) else User found ResendHandler->>UserMgr: IsEmailConfirmedAsync(user) UserMgr-->>ResendHandler: bool alt Already confirmed ResendHandler->>ResendHandler: return silently (no-op) else Not yet confirmed ResendHandler->>TokenSvc: GenerateConfirmationToken(user) activate TokenSvc TokenSvc-->>ResendHandler: confirmation token deactivate TokenSvc ResendHandler->>Mediator: Publish(ConfirmationEmailResendRequestedNotification) activate Mediator Note right of Mediator: Features.Emails has a direct ProjectReference on Features.Users and handles the notification via ConfirmationEmailResendRequestedNotificationHandler Mediator->>EmailDispatcher: SendResendConfirmationEmailAsync(firstName, email, confirmationToken) activate EmailDispatcher EmailDispatcher->>Template: Render email (same Razor pipeline as registration) EmailDispatcher->>SMTP: SendAsync(email, subject, body) deactivate EmailDispatcher alt Email sent successfully Note right of Mediator: ConfirmationEmailResendRequestedNotificationHandler completes normally else EmailDispatcher throws Note right of Mediator: ConfirmationEmailResendRequestedNotificationHandler catches and logs the exception — the resend request is unaffected end deactivate Mediator end end ResendHandler-->>Mediator: (void) deactivate ResendHandler Mediator-->>API: (void) deactivate Mediator API->>User: 200 OK {message: "confirmation email has been resent"} Note right of API: Always 200 OK regardless of outcome above — same user-enumeration precaution as a not-found user or an already-confirmed account deactivate API