Table of Contents

Class SendGridEmailSender

Namespace
Builvero.Infrastructure.Services
Assembly
Builvero.Infrastructure.dll

Implementation of IEmailSender using SendGrid's dynamic templates for email delivery.

public class SendGridEmailSender : IEmailSender
Inheritance
SendGridEmailSender
Implements
Inherited Members

Remarks

This service handles all email sending operations using SendGrid's API:

  • Test emails (Hello template)
  • Forum notifications (new topic, new message)
  • Admin updates (bulk emails to users by role)
  • Project invitations and join requests

All emails use SendGrid dynamic templates configured via SendGridOptions. The API key is resolved using ISendGridApiKeyResolver which supports environment variables, AWS SSM Parameter Store, or direct configuration.

Email addresses are validated using a regex pattern: ^[^@\s]+@[^@\s]+\.[^@\s]+$ SendGrid API keys must start with "SG." to be considered valid.

Constructors

SendGridEmailSender(ISendGridApiKeyResolver, IOptions<SendGridOptions>, ILogger<SendGridEmailSender>)

Initializes a new instance of the SendGridEmailSender class.

public SendGridEmailSender(ISendGridApiKeyResolver apiKeyResolver, IOptions<SendGridOptions> options, ILogger<SendGridEmailSender> logger)

Parameters

apiKeyResolver ISendGridApiKeyResolver

Service for resolving SendGrid API key from various sources.

options IOptions<SendGridOptions>

SendGrid configuration options including template IDs and sender information.

logger ILogger<SendGridEmailSender>

Logger for recording email operations and errors.

SendGridEmailSender(ISendGridApiKeyResolver, IOptions<SendGridOptions>, ILogger<SendGridEmailSender>, Func<string, ISendGridClientWrapper>)

Initializes a new instance of the SendGridEmailSender class with a custom client factory (for testing).

public SendGridEmailSender(ISendGridApiKeyResolver apiKeyResolver, IOptions<SendGridOptions> options, ILogger<SendGridEmailSender> logger, Func<string, ISendGridClientWrapper> clientFactory)

Parameters

apiKeyResolver ISendGridApiKeyResolver

Service for resolving SendGrid API key from various sources.

options IOptions<SendGridOptions>

SendGrid configuration options including template IDs and sender information.

logger ILogger<SendGridEmailSender>

Logger for recording email operations and errors.

clientFactory Func<string, ISendGridClientWrapper>

Factory function for creating SendGrid client instances (allows mocking in tests).

Methods

SendAdminUpdateEmailAsync(string, string, string, CancellationToken)

Sends an admin update email to a user using the AdminUpdates SendGrid template.

public Task SendAdminUpdateEmailAsync(string toEmail, string toName, string htmlContent, CancellationToken ct = default)

Parameters

toEmail string

Recipient email address. Must be a valid email format.

toName string

Recipient name (from profile FullName or email local-part if profile name is unavailable).

htmlContent string

Raw HTML content for the email body. Must not be empty or whitespace.

ct CancellationToken

Cancellation token to cancel the operation.

Returns

Task
Implementation of using SendGrid's dynamic templates for email delivery.

Remarks

Uses the "AdminUpdates" SendGrid dynamic template (configured via AdminUpdatesTemplateId). The email subject is defined in the SendGrid template and cannot be overridden.

The template receives the following dynamic data:

  • content_html: The raw HTML content (triple-braced in template for unescaped rendering)
  • recipient_name: The recipient's name
  • current_year: The current year (for copyright/footer)
  • unsubscribe_url: URL for unsubscribing from admin updates

The HTML content is sent as-is without escaping, allowing rich formatting. The template must use triple braces ({{{content_html}}}) to render the HTML without escaping.

Exceptions

ArgumentException

Thrown when:

  • Email is empty, null, or does not match the email regex pattern
  • HTML content is empty or whitespace
InvalidOperationException

Thrown when:

  • SendGrid API key cannot be resolved
  • API key format is invalid (does not start with "SG.")
  • SendGrid API returns a non-success status code

SendForumNewMessageAsync(User, Project, ProjectForumTopic, ProjectForumMessage, string, string, CancellationToken)

Sends a notification email when a new message is posted in a forum topic.

public Task SendForumNewMessageAsync(User recipient, Project project, ProjectForumTopic topic, ProjectForumMessage message, string unsubscribeAllUrl, string unsubscribeTopicUrl, CancellationToken ct = default)

Parameters

recipient User

The user who should receive the notification.

project Project

The project containing the forum topic.

topic ProjectForumTopic

The forum topic where the message was posted.

message ProjectForumMessage

The newly posted forum message.

unsubscribeAllUrl string

URL for unsubscribing from all forum notifications.

unsubscribeTopicUrl string

URL for unsubscribing from notifications for this specific topic.

ct CancellationToken

Cancellation token to cancel the operation.

Returns

Task
Implementation of using SendGrid's dynamic templates for email delivery.

Remarks

Uses a SendGrid dynamic template for forum message notifications. The email includes project information, topic title, and the new message content.

SendForumNewTopicAsync(User, Project, ProjectForumTopic, ProjectForumMessage, string, string, CancellationToken)

Sends a notification email when a new forum topic is created in a project.

public Task SendForumNewTopicAsync(User recipient, Project project, ProjectForumTopic topic, ProjectForumMessage firstMessage, string unsubscribeAllUrl, string unsubscribeTopicUrl, CancellationToken ct = default)

Parameters

recipient User

The user who should receive the notification.

project Project

The project where the topic was created.

topic ProjectForumTopic

The newly created forum topic.

firstMessage ProjectForumMessage

The first message in the topic (typically the topic creator's initial post).

unsubscribeAllUrl string

URL for unsubscribing from all forum notifications.

unsubscribeTopicUrl string

URL for unsubscribing from notifications for this specific topic.

ct CancellationToken

Cancellation token to cancel the operation.

Returns

Task
Implementation of using SendGrid's dynamic templates for email delivery.

Remarks

Uses a SendGrid dynamic template for forum topic notifications. The email includes project information, topic title, and the first message content.

SendHelloEmailAsync(string, CancellationToken)

Sends a "Hello" test email to verify SendGrid configuration.

public Task SendHelloEmailAsync(string toEmail, CancellationToken cancellationToken = default)

Parameters

toEmail string

The recipient email address. Must be a valid email format.

cancellationToken CancellationToken

Cancellation token to cancel the operation.

Returns

Task
Implementation of using SendGrid's dynamic templates for email delivery.

Remarks

Uses the "Hello" SendGrid dynamic template (configured via HelloTemplateId). This method is primarily used for testing email service configuration via the admin test email endpoint.

The email is sent with minimal dynamic template data. Error responses from SendGrid are logged with status codes and error bodies for debugging, but sensitive information is not exposed.

Exceptions

ArgumentException

Thrown when email is empty, null, or does not match the email regex pattern.

InvalidOperationException

Thrown when:

  • SendGrid API key cannot be resolved
  • API key format is invalid (does not start with "SG.")
  • SendGrid API returns a non-success status code

SendInvitationEmailAsync(string, string, string, string?, string?, string?, string?, CancellationToken)

Sends an invitation email to a recipient containing an invitation code and link.

public Task SendInvitationEmailAsync(string toEmail, string invitationCode, string invitationLink, string? expiresAt, string? label, string? senderName, string? supportEmail, CancellationToken cancellationToken = default)

Parameters

toEmail string

The recipient email address.

invitationCode string

The invitation code to include in the email.

invitationLink string

The full invitation link URL.

expiresAt string

Optional expiration date of the invitation, formatted as a string.

label string

Optional label for the invitation.

senderName string

Optional name of the admin sending the invitation.

supportEmail string

Optional support email address to include in the email.

cancellationToken CancellationToken

Cancellation token to cancel the operation.

Returns

Task
Implementation of using SendGrid's dynamic templates for email delivery.

Remarks

Uses the "Invitation" SendGrid dynamic template (configured via SendGrid:InvitationTemplateId). The template receives dynamic data: invitation_code, invitation_link, expires_at, label, sender_name, support_email, current_year.

Exceptions

ArgumentException

Thrown when email format is invalid.

InvalidOperationException

Thrown when SendGrid API key cannot be resolved, template ID is not configured, or SendGrid API returns errors.

SendVolunteerApplicationAcceptedEmailAsync(string, string, string, CancellationToken)

Sends an email notification when a volunteer application status is changed to "Accepted".

public Task SendVolunteerApplicationAcceptedEmailAsync(string applicantEmail, string applicantName, string roleTitle, CancellationToken cancellationToken = default)

Parameters

applicantEmail string

The email address of the applicant.

applicantName string

The full name of the applicant.

roleTitle string

The title of the volunteer role they applied for.

cancellationToken CancellationToken

Cancellation token to cancel the operation.

Returns

Task
Implementation of using SendGrid's dynamic templates for email delivery.

Remarks

Uses the "VolunteerApplicationAccepted" SendGrid dynamic template (configured via SendGrid:VolunteerApplicationAcceptedTemplateId).

Exceptions

ArgumentException

Thrown when email format is invalid.

InvalidOperationException

Thrown when SendGrid API key cannot be resolved, template ID is not configured, or SendGrid API returns errors.

SendVolunteerApplicationDeclinedEmailAsync(string, string, string, CancellationToken)

Sends an email notification when a volunteer application is declined/discarded.

public Task SendVolunteerApplicationDeclinedEmailAsync(string applicantEmail, string applicantName, string roleTitle, CancellationToken cancellationToken = default)

Parameters

applicantEmail string

The email address of the applicant.

applicantName string

The full name of the applicant.

roleTitle string

The title of the volunteer role they applied for.

cancellationToken CancellationToken

Cancellation token to cancel the operation.

Returns

Task
Implementation of using SendGrid's dynamic templates for email delivery.

Remarks

Uses the "VolunteerApplicationDeclined" SendGrid dynamic template (configured via SendGrid:VolunteerApplicationDeclinedTemplateId).

Exceptions

ArgumentException

Thrown when email format is invalid.

InvalidOperationException

Thrown when SendGrid API key cannot be resolved, template ID is not configured, or SendGrid API returns errors.

SendVolunteerApplicationWaitlistEmailAsync(string, string, string, CancellationToken)

Sends an email notification when a volunteer application status is changed to "Reviewed" (waitlist).

public Task SendVolunteerApplicationWaitlistEmailAsync(string applicantEmail, string applicantName, string roleTitle, CancellationToken cancellationToken = default)

Parameters

applicantEmail string

The email address of the applicant.

applicantName string

The full name of the applicant.

roleTitle string

The title of the volunteer role they applied for.

cancellationToken CancellationToken

Cancellation token to cancel the operation.

Returns

Task
Implementation of using SendGrid's dynamic templates for email delivery.

Remarks

Uses the "VolunteerApplicationWaitlist" SendGrid dynamic template (configured via SendGrid:VolunteerApplicationWaitlistTemplateId).

Exceptions

ArgumentException

Thrown when email format is invalid.

InvalidOperationException

Thrown when SendGrid API key cannot be resolved, template ID is not configured, or SendGrid API returns errors.