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);
// }
//}
}
}