#225 fixed the registration verification email by having InitiatePreRegistrationCommandHandler publish SendEmailCommand : IRemoteCommand to the Notifications worker instead of resolving the API-edge NoOpEmailService (which drops outbound SMTP). The other in-process IEmailService callers listed in the NoOpEmailService XML doc still hit the stub, so their emails are silently dropped in Production too.
Remaining callers to migrate
Caller
Email method
Migration
RegisterUserCommandHandler
SendUserConfirmationEmailAsync
new SendUserConfirmationEmailCommand (template stays worker-side)
CreateOrganizationCommandHandler
SendOrganizationConfirmationEmailAsync
new SendOrganizationConfirmationEmailCommand (template stays worker-side)
Add SendUserConfirmationEmailCommand and SendOrganizationConfirmationEmailCommand (IRemoteCommand, notifications exchange) to SpikerSoft.Contracts.Workers. These carry only data (recipient, name, confirmation URL); the HTML templates remain in the worker's EmailService (no template duplication on the API edge).
Add matching worker handlers in SpikerSoft.Workers.Notifications that call the existing EmailService.SendUserConfirmationEmailAsync / SendOrganizationConfirmationEmailAsync.
Register both fire-and-forget routes in NotificationsRpcConsumerHostedService.
Refactor the four callers to publish the appropriate command via MediatR and drop their direct IEmailService dependency.
Update affected unit tests.
Acceptance criteria
User email confirmation, organization confirmation, pre-registration code resend, and parental approval emails are all delivered by the Notifications worker.
No NoOpEmailService "Skipping outbound SMTP" warnings remain on these paths.
Existing tests pass; new coverage for the added worker handlers.
## Background
#225 fixed the registration verification email by having `InitiatePreRegistrationCommandHandler` publish `SendEmailCommand : IRemoteCommand` to the Notifications worker instead of resolving the API-edge `NoOpEmailService` (which drops outbound SMTP). The other in-process `IEmailService` callers listed in the `NoOpEmailService` XML doc still hit the stub, so their emails are silently dropped in Production too.
## Remaining callers to migrate
| Caller | Email method | Migration |
|---|---|---|
| `RegisterUserCommandHandler` | `SendUserConfirmationEmailAsync` | new `SendUserConfirmationEmailCommand` (template stays worker-side) |
| `CreateOrganizationCommandHandler` | `SendOrganizationConfirmationEmailAsync` | new `SendOrganizationConfirmationEmailCommand` (template stays worker-side) |
| `ResendPreRegistrationCodesCommandHandler` | `SendEmailAsync` (body built in caller) | reuse `SendEmailCommand` |
| `ParentalEmailService` (behind `IParentalEmailService`) | `SendEmailAsync` (body built in caller) | reuse `SendEmailCommand` |
## Plan
1. Add `SendUserConfirmationEmailCommand` and `SendOrganizationConfirmationEmailCommand` (`IRemoteCommand`, `notifications` exchange) to `SpikerSoft.Contracts.Workers`. These carry only data (recipient, name, confirmation URL); the HTML templates remain in the worker's `EmailService` (no template duplication on the API edge).
2. Add matching worker handlers in `SpikerSoft.Workers.Notifications` that call the existing `EmailService.SendUserConfirmationEmailAsync` / `SendOrganizationConfirmationEmailAsync`.
3. Register both fire-and-forget routes in `NotificationsRpcConsumerHostedService`.
4. Refactor the four callers to publish the appropriate command via MediatR and drop their direct `IEmailService` dependency.
5. Update affected unit tests.
## Acceptance criteria
- [ ] User email confirmation, organization confirmation, pre-registration code resend, and parental approval emails are all delivered by the Notifications worker.
- [ ] No `NoOpEmailService` "Skipping outbound SMTP" warnings remain on these paths.
- [ ] Existing tests pass; new coverage for the added worker handlers.
Follow-up to #225.
Resolved in spikersoft-backend PR #9 (merged to master at 2026-06-15T23:15:02Z).
The remaining in-process IEmailService callers that still hit the NoOpEmailService stub now publish remote commands handled by SpikerSoft.EventHandlers.Notifications:
RegisterUserCommandHandler -> new SendUserConfirmationEmailCommand
CreateOrganizationCommandHandler -> new SendOrganizationConfirmationEmailCommand
The two new confirmation commands carry only template data; the HTML templates stay in the worker's EmailService (no MailKit/markup on the API edge). NoOpEmailService remains registered defensively as a DI fallback that warns if any future caller bypasses the worker. New worker-handler unit tests added; existing tests updated.
Closing.
Resolved in spikersoft-backend PR #9 (merged to `master` at 2026-06-15T23:15:02Z).
The remaining in-process `IEmailService` callers that still hit the `NoOpEmailService` stub now publish remote commands handled by `SpikerSoft.EventHandlers.Notifications`:
- `RegisterUserCommandHandler` -> new `SendUserConfirmationEmailCommand`
- `CreateOrganizationCommandHandler` -> new `SendOrganizationConfirmationEmailCommand`
- `ResendPreRegistrationCodesCommandHandler` -> `SendEmailCommand`
- `ParentalEmailService` -> `SendEmailCommand`
The two new confirmation commands carry only template data; the HTML templates stay in the worker's `EmailService` (no MailKit/markup on the API edge). `NoOpEmailService` remains registered defensively as a DI fallback that warns if any future caller bypasses the worker. New worker-handler unit tests added; existing tests updated.
Closing.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Background
#225 fixed the registration verification email by having
InitiatePreRegistrationCommandHandlerpublishSendEmailCommand : IRemoteCommandto the Notifications worker instead of resolving the API-edgeNoOpEmailService(which drops outbound SMTP). The other in-processIEmailServicecallers listed in theNoOpEmailServiceXML doc still hit the stub, so their emails are silently dropped in Production too.Remaining callers to migrate
RegisterUserCommandHandlerSendUserConfirmationEmailAsyncSendUserConfirmationEmailCommand(template stays worker-side)CreateOrganizationCommandHandlerSendOrganizationConfirmationEmailAsyncSendOrganizationConfirmationEmailCommand(template stays worker-side)ResendPreRegistrationCodesCommandHandlerSendEmailAsync(body built in caller)SendEmailCommandParentalEmailService(behindIParentalEmailService)SendEmailAsync(body built in caller)SendEmailCommandPlan
SendUserConfirmationEmailCommandandSendOrganizationConfirmationEmailCommand(IRemoteCommand,notificationsexchange) toSpikerSoft.Contracts.Workers. These carry only data (recipient, name, confirmation URL); the HTML templates remain in the worker'sEmailService(no template duplication on the API edge).SpikerSoft.Workers.Notificationsthat call the existingEmailService.SendUserConfirmationEmailAsync/SendOrganizationConfirmationEmailAsync.NotificationsRpcConsumerHostedService.IEmailServicedependency.Acceptance criteria
NoOpEmailService"Skipping outbound SMTP" warnings remain on these paths.Follow-up to #225.
Resolved in spikersoft-backend PR #9 (merged to
masterat 2026-06-15T23:15:02Z).The remaining in-process
IEmailServicecallers that still hit theNoOpEmailServicestub now publish remote commands handled bySpikerSoft.EventHandlers.Notifications:RegisterUserCommandHandler-> newSendUserConfirmationEmailCommandCreateOrganizationCommandHandler-> newSendOrganizationConfirmationEmailCommandResendPreRegistrationCodesCommandHandler->SendEmailCommandParentalEmailService->SendEmailCommandThe two new confirmation commands carry only template data; the HTML templates stay in the worker's
EmailService(no MailKit/markup on the API edge).NoOpEmailServiceremains registered defensively as a DI fallback that warns if any future caller bypasses the worker. New worker-handler unit tests added; existing tests updated.Closing.