MailSender.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. using MailKit;
  2. using MailKit.Net.Smtp;
  3. using MailKit.Security;
  4. using Microsoft.Extensions.Logging;
  5. using Microsoft.Extensions.Options;
  6. using MimeKit;
  7. using MTWorkHR.Core.Email;
  8. using MTWorkHR.Core.Entities;
  9. using MTWorkHR.Core.Global;
  10. //using SendGrid;
  11. //using SendGrid.Helpers.Mail;
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Linq;
  15. using System.Net;
  16. using System.Text;
  17. using System.Threading.Tasks;
  18. namespace MTWorkHR.Infrastructure.EmailService
  19. {
  20. public class MailSender : IMailSender
  21. {
  22. public AppSettingsConfiguration _configuration { get; }
  23. private readonly ILogger<MailSender> _logger;
  24. public MailSender(AppSettingsConfiguration configuration,ILogger<MailSender> logger)
  25. {
  26. _configuration = configuration;
  27. _logger = logger;
  28. }
  29. //public async Task<bool> SendEmailGrid(EmailMessage email)
  30. //{
  31. // var client = new SendGridClient(_configuration.MailSettings.ApiKey);
  32. // var to = new EmailAddress(email.To);
  33. // var from = new EmailAddress
  34. // {
  35. // Email = _configuration.MailSettings.FromAddress,
  36. // Name = _configuration.MailSettings.FromName
  37. // };
  38. // email.Body = email.Body + " /n" + email.url;
  39. // var message = MailHelper.CreateSingleEmail(from, to, email.Subject, email.Body, email.Body);
  40. // var response = await client.SendEmailAsync(message);
  41. // return response.IsSuccessStatusCode;
  42. //}
  43. public async Task<bool> SendEmail(EmailMessage email)
  44. {
  45. var mailTo = email.To;
  46. var settings = _configuration.MailSettings;
  47. // Validate configuration settings
  48. if (string.IsNullOrEmpty(settings.SmtpUsername) ||
  49. string.IsNullOrEmpty(settings.Password) ||
  50. string.IsNullOrEmpty(settings.FromAddress) ||
  51. string.IsNullOrEmpty(settings.Host) ||
  52. settings.Port == 0 ||
  53. string.IsNullOrEmpty(mailTo))
  54. {
  55. Console.WriteLine("Invalid mail settings or recipient address.");
  56. return false;
  57. }
  58. // Create the email message
  59. var emailObj = new MimeMessage();
  60. emailObj.From.Add(new MailboxAddress("MTWork", settings.FromAddress)); // Display name + verified sender address
  61. emailObj.Sender = MailboxAddress.Parse(settings.FromAddress);
  62. emailObj.To.Add(MailboxAddress.Parse(mailTo));
  63. emailObj.Subject = email.Subject;
  64. // Build the email body with HTML content
  65. var builder = new BodyBuilder();
  66. var emailBody = email.Body;
  67. if (!string.IsNullOrEmpty(email.url))
  68. {
  69. // Use string interpolation with proper HTML escaping
  70. emailBody += $"Please click on <a href=\"{email.url}\">this link</a> or copy the following URL and open it: '{WebUtility.HtmlEncode(email.url)}'";
  71. }
  72. builder.HtmlBody = emailBody;
  73. emailObj.Body = builder.ToMessageBody();
  74. // Initialize SMTP client with logging
  75. //using var logger = new ProtocolLogger("smtp.log", append: false);
  76. using var smtp = new SmtpClient();
  77. try
  78. {
  79. _logger.LogInformation("Connecting to SMTP server {Host}:{Port} with username :[{SmtpUsername}]",
  80. settings.Host, settings.Port, settings.SmtpUsername);
  81. // Connect to Azure Communication Services SMTP server
  82. await smtp.ConnectAsync(settings.Host, settings.Port, SecureSocketOptions.StartTls);
  83. _logger.LogInformation("Authenticating with username {SmtpUsername}:[{pass}]", settings.SmtpUsername, settings.Password);
  84. // Authenticate using SMTP Username and Entra app client secret
  85. await smtp.AuthenticateAsync(settings.SmtpUsername, settings.Password);
  86. _logger.LogInformation("Sending email to {To} with subject {Subject}", mailTo, email.Subject);
  87. // Send the email
  88. await smtp.SendAsync(emailObj);
  89. _logger.LogInformation("Email sent successfully to {To}", mailTo);
  90. }
  91. catch (AuthenticationException ex)
  92. {
  93. _logger.LogError(ex, "Authentication failed for username {SmtpUsername}: {Message}",
  94. settings.SmtpUsername, ex.Message);
  95. throw ex;
  96. Console.WriteLine($"Authentication failed: {ex.Message}, Inner Exception: {ex.InnerException?.Message}");
  97. return false;
  98. }
  99. catch (SmtpCommandException ex)
  100. {
  101. _logger.LogError(ex, "SMTP error: {Message}, Status: {StatusCode}", ex.Message, ex.StatusCode);
  102. throw ex;
  103. Console.WriteLine($"SMTP error: {ex.Message}, Status: {ex.StatusCode}, Inner Exception: {ex.InnerException?.Message}");
  104. return false;
  105. }
  106. catch (Exception ex)
  107. {
  108. _logger.LogError(ex, "Error sending email to {To}: {Message}", mailTo, ex.Message);
  109. throw ex;
  110. Console.WriteLine($"Error sending email: {ex.Message}, Inner Exception: {ex.InnerException?.Message}");
  111. return false;
  112. }
  113. finally
  114. {
  115. // Ensure disconnection
  116. if (smtp.IsConnected)
  117. {
  118. await smtp.DisconnectAsync(true);
  119. _logger.LogInformation("Disconnected from SMTP server");
  120. }
  121. }
  122. return true;
  123. }
  124. public async Task<bool> SendEmailSMTP(EmailMessage email)
  125. {
  126. var mailTo = email.To;
  127. var settings = _configuration.MailSettings;
  128. if (settings.FromAddress == null || settings.FromAddress== "" || settings.Password == null || settings.TemplatePath == null || settings.Host == null || settings.Port == 0 || mailTo == null)
  129. return false;
  130. //string FilePath = _configuration.MailSettings.TemplatePath;
  131. //StreamReader str = new StreamReader(FilePath);
  132. //string MailText = str.ReadToEnd();
  133. //str.Close();
  134. //MailText = MailText.Replace("[NotificationType]", email.Subject).Replace("[Info]", email.Body).Replace("[Link]", email.url );
  135. var emailObj = new MimeMessage();
  136. emailObj.From.Add(new MailboxAddress("MTWork", _configuration.MailSettings.FromAddress)); // Ensure From matches authenticated email
  137. emailObj.Sender = MailboxAddress.Parse(_configuration.MailSettings.FromAddress);
  138. emailObj.To.Add(MailboxAddress.Parse(mailTo));
  139. emailObj.Subject = email.Subject;
  140. var builder = new BodyBuilder();
  141. email.Body = email.Body +
  142. ( string.IsNullOrEmpty( email.url ) ?"": "Please click on <a href =\"" + email.url + "\">this link</a> or copy the following url and open it : \' " + email.url+"\'");
  143. builder.HtmlBody = email.Body;
  144. emailObj.Body = builder.ToMessageBody();
  145. using var logger = new ProtocolLogger("smtp.log", append: false);
  146. using var smtp = new SmtpClient(logger);
  147. try
  148. {
  149. smtp.Connect(_configuration.MailSettings.Host, _configuration.MailSettings.Port, MailKit.Security.SecureSocketOptions.StartTls);
  150. smtp.Authenticate(_configuration.MailSettings.FromAddress, _configuration.MailSettings.Password);
  151. await smtp.SendAsync(emailObj);
  152. //smtp.Disconnect(true);
  153. }
  154. catch (MailKit.Security.AuthenticationException ex)
  155. {
  156. Console.WriteLine($"Authentication failed: {ex.Message}");
  157. throw;
  158. }
  159. catch (Exception ex)
  160. {
  161. Console.WriteLine($"Error sending email: {ex.Message}");
  162. throw;
  163. }
  164. finally
  165. {
  166. await smtp.DisconnectAsync(true);
  167. }
  168. return true;
  169. }
  170. }
  171. }