MailService.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. using Application.Abstractions.Cache;
  2. using Application.Abstractions.Messaging.Email;
  3. using Application.Features.Config.Get;
  4. using Infrastructure.Persistence;
  5. using SharedKernel;
  6. using MailKit.Net.Smtp;
  7. using MailKit.Security;
  8. using MimeKit;
  9. using Microsoft.EntityFrameworkCore;
  10. using Microsoft.Extensions.Logging;
  11. using Microsoft.Extensions.Options;
  12. namespace Infrastructure.Messaging.Email
  13. {
  14. public class MailService : IMailService
  15. {
  16. private readonly ILogger<MailService> _logger;
  17. private readonly ICacheService _cache;
  18. private readonly AppSettings.SmtpSection _smtp;
  19. private readonly AppDbContext _db;
  20. // SMTP 정보
  21. public string Host { get; set; } = default!;
  22. public int Port { get; set; } = 587;
  23. public string? User { get; set; }
  24. public string? Password { get; set; }
  25. public bool UseStartTls { get; set; } = true;
  26. public string FromEmail { get; set; } = default!;
  27. public string FromName { get; set; } = "no-reply";
  28. public MailService(ILogger<MailService> logger, ICacheService cache, IOptions<AppSettings> options, AppDbContext db)
  29. {
  30. _logger = logger;
  31. _cache = cache;
  32. _smtp = options.Value.SMTP;
  33. _db = db;
  34. }
  35. public async Task SendAsync(SendData data, CancellationToken ct = default)
  36. {
  37. _logger.LogInformation("Sending email to {ToAddress} with subject {Subject}", data.ToAddress, data.Subject);
  38. // 1. Redis 캐시에서 Config 조회
  39. var config = await _cache.GetAsync<Response>(CacheKeys.Config, ct);
  40. if (config is null)
  41. {
  42. var entity = await _db.Config.AsNoTracking().OrderByDescending(x => x.ID).FirstOrDefaultAsync();
  43. if (entity is null)
  44. {
  45. Host = _smtp.Host;
  46. Port = _smtp.Port;
  47. User = _smtp.User;
  48. Password = _smtp.Password;
  49. UseStartTls = _smtp.UseStartTls;
  50. FromEmail = _smtp.FromEmail;
  51. FromName = _smtp.FromName;
  52. }
  53. else
  54. {
  55. Host = entity.Basic.SmtpServer ?? "";
  56. Port = entity.Basic.SmtpPort ?? 587;
  57. UseStartTls = entity.Basic.SmtpEnableSSL;
  58. User = entity.Basic.SmtpUsername;
  59. Password = entity.Basic.SmtpPassword;
  60. FromEmail = entity.Basic.FromEmail ?? "";
  61. FromName = entity.Basic.FromName ?? "";
  62. }
  63. }
  64. else
  65. {
  66. Host = config.Basic.SmtpServer!;
  67. Port = config.Basic.SmtpPort! ?? 587;
  68. UseStartTls = config.Basic.SmtpEnableSSL;
  69. User = config.Basic.SmtpUsername;
  70. Password = config.Basic.SmtpPassword;
  71. FromEmail = config.Basic.FromEmail!;
  72. FromName = config.Basic.FromName!;
  73. }
  74. var message = new MimeMessage();
  75. message.From.Add(new MailboxAddress(FromName, FromEmail));
  76. message.To.Add(MailboxAddress.Parse(data.ToAddress));
  77. message.Subject = data.Subject;
  78. var body = new BodyBuilder
  79. {
  80. HtmlBody = data.MessageHtml,
  81. TextBody = data.MessageText
  82. };
  83. message.Body = body.ToMessageBody();
  84. using var client = new SmtpClient();
  85. var secure = UseStartTls ? SecureSocketOptions.StartTls : SecureSocketOptions.Auto;
  86. await client.ConnectAsync(Host, Port, secure, ct);
  87. if (!string.IsNullOrWhiteSpace(User))
  88. {
  89. await client.AuthenticateAsync(User, Password, ct);
  90. }
  91. await client.SendAsync(message, ct);
  92. await client.DisconnectAsync(true, ct);
  93. _logger.LogInformation("Email sent to {ToAddress} with subject {Subject}", data.ToAddress, data.Subject);
  94. }
  95. }
  96. }