using System.Net.Mail; using System.Net; namespace Diligent.WebAPI.Business.Services { /// /// Provieds an API for sending emails in both sync & async fashion, as well as sending emails with delays. /// public class Emailer : IEmailer { private readonly MailSettings _settings; private readonly ILogger _logger; public Emailer(IOptions mailSettings, ILogger logger) { _settings = mailSettings.Value; _logger = logger; } /// /// Sends an email asynchronously and inserts a new record to the underlying database. /// /// /// /// /// /// /// /// /// /// /// public async Task SendEmailAndWriteToDbAsync(List to, string subject, string body, bool isHtml = false, List cc = null) { _logger.LogInformation($"Start sending email to {to}"); var emailResult = await SendEmailAsync(to, subject, body, isHtml, cc); //_logger.LogInformation("Create email entity for save in db"); var email = CreateEmail(to, subject, body, isHtml); if (emailResult) { email.SentTime = DateTime.Now; } //_logger.LogInformation("Save email in db"); //var dbResult = await WriteEmailToDbAsync(email); //_logger.LogInformation("Email is saved in db."); return emailResult; // && dbResult > 0; } public async Task SendEmailAndWriteToDbAsync(string to, string subject, string body, bool isHtml = false, List cc = null) { return await SendEmailAndWriteToDbAsync(new List { to }, subject, body, isHtml, cc); } /// /// Sends an email synchronously and inserts a new record to the underlying database. /// /// /// /// /// /// /// /// /// /// /// public bool SendEmailAndWriteToDb(List to, string subject, string body, bool isHtml = false, List cc = null) { var emailResult = SendEmail(to, subject, body, isHtml, cc); var email = CreateEmail(to, subject, body, isHtml); if (emailResult) { email.SentTime = DateTime.Now; } //var dbResult = WriteEmailToDb(email); return emailResult; // && dbResult > 0; } public bool SendEmailAndWriteToDb(string to, string subject, string body, bool isHtml = false, List cc = null) { return SendEmailAndWriteToDb(new List { to }, subject, body, isHtml, cc); } /// /// Sends an email synchronously. /// /// /// /// /// /// /// /// /// /// /// public bool SendEmail(List to, string subject, string body, bool isHtml = false, List cc = null) { try { using (var smtp = GetSmtpClient()) { var message = GetMailMessage(to, subject, body, isHtml, cc); smtp.Send(message); return true; } } catch (ArgumentException) { throw; } catch (Exception e) { throw new Exception("Failed to send email message.", e); } } /// /// Sends an email asynchronously. /// /// /// /// /// /// /// /// /// /// /// public async Task SendEmailAsync(List to, string subject, string body, bool isHtml = false, List cc = null) { try { _logger.LogInformation("Getting SMTP client settings from appsettings file"); using (var smtp = GetSmtpClient()) { _logger.LogInformation("Create mail message"); var message = GetMailMessage(to, subject, body, isHtml, cc); _logger.LogInformation("Message created."); _logger.LogInformation("Sending message to client"); await smtp.SendMailAsync(message); _logger.LogInformation("Email message sent."); return true; } } catch (ArgumentException ex) { _logger.LogInformation($"Error in arguments {ex}"); throw; } catch (Exception e) { _logger.LogInformation($"Error {e}"); throw new Exception("Failed to send email message.", e); } } /// /// Creates a object and configures it. /// /// public SmtpClient GetSmtpClient() { var smtp = new SmtpClient(_settings.SmtpServer) { Timeout = 1000000 }; if (!string.IsNullOrWhiteSpace(_settings.SmtpUsername)) { smtp.UseDefaultCredentials = false; smtp.Credentials = new NetworkCredential( _settings.SmtpUsername, _settings.SmtpPassword); smtp.EnableSsl = _settings.SmtpUseSSL; smtp.Port = _settings.SmtpPort; } return smtp; } /// /// Creates a new from the specified arguments. /// /// /// /// /// /// /// /// /// public MailMessage GetMailMessage(List to, string subject, string body, bool isHtml = false, List cc = null) { var message = new MailMessage { Sender = new MailAddress(_settings.SmtpFrom, _settings.SmtpFromName), From = new MailAddress(_settings.SmtpFrom), Subject = subject, Body = body, IsBodyHtml = isHtml }; if (to.Any()) { message.To.Add(string.Join(",", to.Where(email => !string.IsNullOrWhiteSpace(email)))); } else { throw new ArgumentException("The list of recipient emails can not be empty"); } if (cc != null && cc.Any()) { message.CC.Add(string.Join(",", cc.Where(email => !string.IsNullOrWhiteSpace(email)))); } return message; } /// /// Sends an email aysnchronously. If the "dont send before" argument is specified, then the email will be sent with a delay - after the specified time. /// /// /// /// /// /// /// /// /// /// public async Task SendEmailWithDelayAsync(List to, string subject, string body, bool isHtml = false, DateTime? dontSendBefore = null) { try { var email = CreateEmail(to, subject, body, isHtml, dontSendBefore); //var result = await WriteEmailToDbAsync(email); return true; } catch (ArgumentException) { throw; } catch (Exception e) { throw new Exception("Error while attempting to send an email with delay.", e); } } /// /// Creates a object with specified arguments. /// /// /// /// /// /// /// /// /// public DiligEmail CreateEmail(List to, string subject, string body, bool isHtml = false, DateTime? dontSendBefore = null) { if (!to.Any()) { throw new ArgumentException("The list of recipient emails can not be empty"); } var email = new DiligEmail { To = to.Aggregate((previous, next) => previous + ";" + next), Subject = subject, Body = body, IsHtml = isHtml, DontSendBefore = dontSendBefore, CreateTime = DateTime.Now }; return email; } /// /// Fills the specified object with the specified list. /// /// /// /// /// //public DiligEmail FillEmailAttachments(DiligEmail email) //{ // if (email == null) // { // throw new ArgumentNullException(nameof(email), "Email can not be null"); // } // if (attachments != null && attachments.Any()) // { // attachments.ForEach(attachment => // { // email.DiligEmailAttachments.Add(new DiligEmailAttachment // { // FileName = attachment.FileName, // SourceFileName = attachment.SourceFileName, // Type = attachment.Type, // Disposition = attachment.Disposition // }); // }); // } // return email; //} /// /// Writes the specified object to the underlying database. /// /// /// /// /// //public async Task WriteEmailToDbAsync(DiligEmail email) //{ // try // { // if (email == null) // { // throw new ArgumentNullException(nameof(email), "Email can not be null"); // } // _entities.DiligEmails.Add(email); // var result = await _entities.SaveChangesAsync(); // return result; // } // catch (Exception e) // { // throw new Exception("Failed to write entry into the database", e); // } //} /// /// Writes the specified object to the underlying database. /// /// /// /// /// //public int WriteEmailToDb(DiligEmail email) //{ // try // { // if (email == null) // { // throw new ArgumentNullException(nameof(email), "Email can not be null"); // } // _entities.DiligEmails.Add(email); // var result = _entities.SaveChanges(); // return result; // } // catch (ArgumentException) // { // throw; // } // catch (Exception e) // { // throw new Exception("Failed to write entry into the database", e); // } //} } }