123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- using MailKit;
- using MailKit.Net.Smtp;
- using MailKit.Security;
- using Microsoft.Extensions.Logging;
- using Microsoft.Extensions.Options;
- using MimeKit;
- using MTWorkHR.Core.Email;
- using MTWorkHR.Core.Entities;
- using MTWorkHR.Core.Global;
- //using SendGrid;
- //using SendGrid.Helpers.Mail;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net;
- using System.Text;
- using System.Threading.Tasks;
- namespace MTWorkHR.Infrastructure.EmailService
- {
- public class MailSender : IMailSender
- {
- public AppSettingsConfiguration _configuration { get; }
- private readonly ILogger<MailSender> _logger;
- public MailSender(AppSettingsConfiguration configuration,ILogger<MailSender> logger)
- {
- _configuration = configuration;
- _logger = logger;
- }
- //public async Task<bool> SendEmailGrid(EmailMessage email)
- //{
- // var client = new SendGridClient(_configuration.MailSettings.ApiKey);
- // var to = new EmailAddress(email.To);
- // var from = new EmailAddress
- // {
- // Email = _configuration.MailSettings.FromAddress,
- // Name = _configuration.MailSettings.FromName
- // };
- // email.Body = email.Body + " /n" + email.url;
- // var message = MailHelper.CreateSingleEmail(from, to, email.Subject, email.Body, email.Body);
- // var response = await client.SendEmailAsync(message);
- // return response.IsSuccessStatusCode;
- //}
- /// <summary>
- /// Send Email using an azure email address, smtpUserName and password
- /// </summary>
- /// <param name="email"></param>
- /// <returns></returns>
- public async Task<bool> SendEmailAzure(EmailMessage email)
- {
- var mailTo = email.To;
- var settings = _configuration.MailSettings;
- // Validate configuration settings
- if (string.IsNullOrEmpty(settings.SmtpUsername) ||
- string.IsNullOrEmpty(settings.Password) ||
- string.IsNullOrEmpty(settings.FromAddress) ||
- string.IsNullOrEmpty(settings.Host) ||
- settings.Port == 0 ||
- string.IsNullOrEmpty(mailTo))
- {
- Console.WriteLine("Invalid mail settings or recipient address.");
- return false;
- }
- // Create the email message
- var emailObj = new MimeMessage();
- emailObj.From.Add(new MailboxAddress("MTWork", settings.FromAddress)); // Display name + verified sender address
- emailObj.Sender = MailboxAddress.Parse(settings.FromAddress);
- emailObj.To.Add(MailboxAddress.Parse(mailTo));
- emailObj.Subject = email.Subject;
- // Build the email body with HTML content
- var builder = new BodyBuilder();
- var emailBody = email.Body;
- if (!string.IsNullOrEmpty(email.url))
- {
- // Use string interpolation with proper HTML escaping
- emailBody += $"Please click on <a href=\"{email.url}\">this link</a> or copy the following URL and open it: '{WebUtility.HtmlEncode(email.url)}'";
- }
- builder.HtmlBody = emailBody;
- emailObj.Body = builder.ToMessageBody();
- // Initialize SMTP client with logging
- //using var logger = new ProtocolLogger("smtp.log", append: false);
- using var smtp = new SmtpClient();
- try
- {
- _logger.LogInformation("Connecting to SMTP server {Host}:{Port} with username :[{SmtpUsername}]",
- settings.Host, settings.Port, settings.SmtpUsername);
- // Connect to Azure Communication Services SMTP server
- await smtp.ConnectAsync(settings.Host, settings.Port, SecureSocketOptions.StartTls);
- _logger.LogInformation("Authenticating with username {SmtpUsername}:[{pass}]", settings.SmtpUsername, settings.Password);
- // Authenticate using SMTP Username and Entra app client secret
- await smtp.AuthenticateAsync(settings.SmtpUsername, settings.Password);
- _logger.LogInformation("Sending email to {To} with subject {Subject}", mailTo, email.Subject);
- // Send the email
- await smtp.SendAsync(emailObj);
- _logger.LogInformation("Email sent successfully to {To}", mailTo);
- }
- catch (AuthenticationException ex)
- {
- _logger.LogError(ex, "Authentication failed for username {SmtpUsername}: {Message}",
- settings.SmtpUsername, ex.Message);
- throw ex;
- }
- catch (SmtpCommandException ex)
- {
- _logger.LogError(ex, "SMTP error: {Message}, Status: {StatusCode}", ex.Message, ex.StatusCode);
- throw ex;
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error sending email to {To}: {Message}", mailTo, ex.Message);
- throw ex;
- }
- finally
- {
- // Ensure disconnection
- if (smtp.IsConnected)
- {
- await smtp.DisconnectAsync(true);
- _logger.LogInformation("Disconnected from SMTP server");
- }
- }
- return true;
- }
- //Send Email using an email address and password
- public async Task<bool> SendEmail(EmailMessage email)
- {
- var mailTo = email.To;
- var settings = _configuration.MailSettings;
- if (settings.FromAddress == null || settings.FromAddress== "" || settings.Password == null || settings.TemplatePath == null || settings.Host == null || settings.Port == 0 || mailTo == null)
- return false;
- //string FilePath = _configuration.MailSettings.TemplatePath;
- //StreamReader str = new StreamReader(FilePath);
- //string MailText = str.ReadToEnd();
- //str.Close();
- //MailText = MailText.Replace("[NotificationType]", email.Subject).Replace("[Info]", email.Body).Replace("[Link]", email.url );
- var emailObj = new MimeMessage();
- emailObj.From.Add(new MailboxAddress("MTWork", _configuration.MailSettings.FromAddress)); // Ensure From matches authenticated email
- emailObj.Sender = MailboxAddress.Parse(_configuration.MailSettings.FromAddress);
- emailObj.To.Add(MailboxAddress.Parse(mailTo));
- emailObj.Subject = email.Subject;
- var builder = new BodyBuilder();
- email.Body = email.Body +
- ( string.IsNullOrEmpty( email.url ) ?"": "Please click on <a href =\"" + email.url + "\">this link</a> or copy the following url and open it : \' " + email.url+"\'");
- builder.HtmlBody = email.Body;
- emailObj.Body = builder.ToMessageBody();
- using var logger = new ProtocolLogger("smtp.log", append: false);
- using var smtp = new SmtpClient(logger);
- try
- {
- await smtp.ConnectAsync(_configuration.MailSettings.Host, _configuration.MailSettings.Port, MailKit.Security.SecureSocketOptions.StartTls);
- await smtp.AuthenticateAsync(_configuration.MailSettings.FromAddress, _configuration.MailSettings.Password);
- _logger.LogInformation("Sending email to {To} with subject {Subject}", mailTo, email.Subject);
- await smtp.SendAsync(emailObj);
- _logger.LogInformation("Email sent successfully to {To}", mailTo);
- }
- catch (AuthenticationException ex)
- {
- _logger.LogError(ex, "Authentication failed for username {SmtpUsername}: {Message}",
- settings.SmtpUsername, ex.Message);
- throw ex;
- }
- catch (SmtpCommandException ex)
- {
- _logger.LogError(ex, "SMTP error: {Message}, Status: {StatusCode}", ex.Message, ex.StatusCode);
- throw ex;
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error sending email to {To}: {Message}", mailTo, ex.Message);
- throw ex;
- }
- finally
- {
- _logger.LogInformation("Disconnected from SMTP server");
- await smtp.DisconnectAsync(true);
- }
- return true;
- }
- }
- }
|