Files
ColaFlow/colaflow-api/src/Modules/Identity/ColaFlow.Modules.Identity.Infrastructure/Services/SmtpEmailService.cs
Yaojia Wang 921990a043 feat(backend): Implement email service infrastructure for Day 7
Add complete email service infrastructure with Mock and SMTP implementations.

Changes:
- Created EmailMessage domain model for email data
- Added IEmailService interface for email sending
- Implemented MockEmailService for development/testing (logs emails)
- Implemented SmtpEmailService for production SMTP sending
- Added IEmailTemplateService interface for email templates
- Implemented EmailTemplateService with HTML templates for verification, password reset, and invitation emails
- Registered email services in DependencyInjection with provider selection
- Added email configuration to appsettings.Development.json (Mock provider by default)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 21:16:11 +01:00

88 lines
2.9 KiB
C#

using System.Net;
using System.Net.Mail;
using ColaFlow.Modules.Identity.Application.Services;
using ColaFlow.Modules.Identity.Domain.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace ColaFlow.Modules.Identity.Infrastructure.Services;
/// <summary>
/// SMTP-based email service for production use
/// </summary>
public sealed class SmtpEmailService : IEmailService
{
private readonly ILogger<SmtpEmailService> _logger;
private readonly IConfiguration _configuration;
public SmtpEmailService(
ILogger<SmtpEmailService> logger,
IConfiguration configuration)
{
_logger = logger;
_configuration = configuration;
}
public async Task<bool> SendEmailAsync(EmailMessage message, CancellationToken cancellationToken = default)
{
try
{
var smtpHost = _configuration["Email:Smtp:Host"];
var smtpPort = int.Parse(_configuration["Email:Smtp:Port"] ?? "587");
var smtpUsername = _configuration["Email:Smtp:Username"];
var smtpPassword = _configuration["Email:Smtp:Password"];
var enableSsl = bool.Parse(_configuration["Email:Smtp:EnableSsl"] ?? "true");
var defaultFromEmail = _configuration["Email:From"] ?? "noreply@colaflow.local";
var defaultFromName = _configuration["Email:FromName"] ?? "ColaFlow";
using var smtpClient = new SmtpClient(smtpHost, smtpPort)
{
Credentials = new NetworkCredential(smtpUsername, smtpPassword),
EnableSsl = enableSsl
};
using var mailMessage = new MailMessage
{
From = new MailAddress(
message.FromEmail ?? defaultFromEmail,
message.FromName ?? defaultFromName),
Subject = message.Subject,
Body = message.HtmlBody,
IsBodyHtml = true
};
mailMessage.To.Add(message.To);
// Add plain text alternative if provided
if (!string.IsNullOrEmpty(message.PlainTextBody))
{
var plainView = AlternateView.CreateAlternateViewFromString(
message.PlainTextBody,
null,
"text/plain");
mailMessage.AlternateViews.Add(plainView);
}
await smtpClient.SendMailAsync(mailMessage, cancellationToken);
_logger.LogInformation(
"Email sent successfully to {To} with subject: {Subject}",
message.To,
message.Subject);
return true;
}
catch (Exception ex)
{
_logger.LogError(
ex,
"Failed to send email to {To} with subject: {Subject}",
message.To,
message.Subject);
return false;
}
}
}