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
apiKeyResolverISendGridApiKeyResolverService for resolving SendGrid API key from various sources.
optionsIOptions<SendGridOptions>SendGrid configuration options including template IDs and sender information.
loggerILogger<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
apiKeyResolverISendGridApiKeyResolverService for resolving SendGrid API key from various sources.
optionsIOptions<SendGridOptions>SendGrid configuration options including template IDs and sender information.
loggerILogger<SendGridEmailSender>Logger for recording email operations and errors.
clientFactoryFunc<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
toEmailstringRecipient email address. Must be a valid email format.
toNamestringRecipient name (from profile FullName or email local-part if profile name is unavailable).
htmlContentstringRaw HTML content for the email body. Must not be empty or whitespace.
ctCancellationTokenCancellation 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 namecurrent_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
recipientUserThe user who should receive the notification.
projectProjectThe project containing the forum topic.
topicProjectForumTopicThe forum topic where the message was posted.
messageProjectForumMessageThe newly posted forum message.
unsubscribeAllUrlstringURL for unsubscribing from all forum notifications.
unsubscribeTopicUrlstringURL for unsubscribing from notifications for this specific topic.
ctCancellationTokenCancellation 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
recipientUserThe user who should receive the notification.
projectProjectThe project where the topic was created.
topicProjectForumTopicThe newly created forum topic.
firstMessageProjectForumMessageThe first message in the topic (typically the topic creator's initial post).
unsubscribeAllUrlstringURL for unsubscribing from all forum notifications.
unsubscribeTopicUrlstringURL for unsubscribing from notifications for this specific topic.
ctCancellationTokenCancellation 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
toEmailstringThe recipient email address. Must be a valid email format.
cancellationTokenCancellationTokenCancellation 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
toEmailstringThe recipient email address.
invitationCodestringThe invitation code to include in the email.
invitationLinkstringThe full invitation link URL.
expiresAtstringOptional expiration date of the invitation, formatted as a string.
labelstringOptional label for the invitation.
senderNamestringOptional name of the admin sending the invitation.
supportEmailstringOptional support email address to include in the email.
cancellationTokenCancellationTokenCancellation 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
applicantEmailstringThe email address of the applicant.
applicantNamestringThe full name of the applicant.
roleTitlestringThe title of the volunteer role they applied for.
cancellationTokenCancellationTokenCancellation 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
applicantEmailstringThe email address of the applicant.
applicantNamestringThe full name of the applicant.
roleTitlestringThe title of the volunteer role they applied for.
cancellationTokenCancellationTokenCancellation 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
applicantEmailstringThe email address of the applicant.
applicantNamestringThe full name of the applicant.
roleTitlestringThe title of the volunteer role they applied for.
cancellationTokenCancellationTokenCancellation 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.