using CarCareTracker.Models; using MimeKit; using MailKit.Net.Smtp; using MailKit.Security; namespace CarCareTracker.Helper { public interface IMailHelper { OperationResponse NotifyUserForRegistration(string emailAddress, string token); OperationResponse NotifyUserForPasswordReset(string emailAddress, string token); OperationResponse NotifyUserForAccountUpdate(string emailAddress, string token); OperationResponse NotifyUserForReminders(Vehicle vehicle, List emailAddresses, List reminders); } public class MailHelper : IMailHelper { private readonly MailConfig mailConfig; private readonly IFileHelper _fileHelper; private readonly ILogger _logger; public MailHelper( IConfigHelper config, IFileHelper fileHelper, ILogger logger ) { //load mailConfig from Configuration mailConfig = config.GetMailConfig(); _fileHelper = fileHelper; _logger = logger; } public OperationResponse NotifyUserForRegistration(string emailAddress, string token) { if (string.IsNullOrWhiteSpace(mailConfig.EmailServer)) { return OperationResponse.Failed("SMTP Server Not Setup"); } if (string.IsNullOrWhiteSpace(emailAddress) || string.IsNullOrWhiteSpace(token)) { return OperationResponse.Failed("Email Address or Token is invalid"); } string emailSubject = "Your Registration Token for LubeLogger"; string emailBody = $"A token has been generated on your behalf, please complete your registration for LubeLogger using the token: {token}"; var result = SendEmail(new List { emailAddress }, emailSubject, emailBody); if (result) { return OperationResponse.Succeed("Email Sent!"); } else { return OperationResponse.Failed(); } } public OperationResponse NotifyUserForPasswordReset(string emailAddress, string token) { if (string.IsNullOrWhiteSpace(mailConfig.EmailServer)) { return OperationResponse.Failed("SMTP Server Not Setup"); } if (string.IsNullOrWhiteSpace(emailAddress) || string.IsNullOrWhiteSpace(token)) { return OperationResponse.Failed("Email Address or Token is invalid"); } string emailSubject = "Your Password Reset Token for LubeLogger"; string emailBody = $"A token has been generated on your behalf, please reset your password for LubeLogger using the token: {token}"; var result = SendEmail(new List { emailAddress }, emailSubject, emailBody); if (result) { return OperationResponse.Succeed("Email Sent!"); } else { return OperationResponse.Failed(); } } public OperationResponse NotifyUserForAccountUpdate(string emailAddress, string token) { if (string.IsNullOrWhiteSpace(mailConfig.EmailServer)) { return OperationResponse.Failed("SMTP Server Not Setup"); } if (string.IsNullOrWhiteSpace(emailAddress) || string.IsNullOrWhiteSpace(token)) { return OperationResponse.Failed("Email Address or Token is invalid"); } string emailSubject = "Your User Account Update Token for LubeLogger"; string emailBody = $"A token has been generated on your behalf, please update your account for LubeLogger using the token: {token}"; var result = SendEmail(new List { emailAddress}, emailSubject, emailBody); if (result) { return OperationResponse.Succeed("Email Sent!"); } else { return OperationResponse.Failed(); } } public OperationResponse NotifyUserForReminders(Vehicle vehicle, List emailAddresses, List reminders) { if (string.IsNullOrWhiteSpace(mailConfig.EmailServer)) { return OperationResponse.Failed("SMTP Server Not Setup"); } if (!emailAddresses.Any()) { return OperationResponse.Failed("No recipients could be found"); } if (!reminders.Any()) { return OperationResponse.Failed("No reminders could be found"); } //get email template, this file has to exist since it's a static file. var emailTemplatePath = _fileHelper.GetFullFilePath(StaticHelper.ReminderEmailTemplate); string emailSubject = $"Vehicle Reminders From LubeLogger - {DateTime.Now.ToShortDateString()}"; //construct html table. string emailBody = File.ReadAllText(emailTemplatePath); emailBody = emailBody.Replace("{VehicleInformation}", $"{vehicle.Year} {vehicle.Make} {vehicle.Model} #{StaticHelper.GetVehicleIdentifier(vehicle)}"); string tableBody = ""; foreach(ReminderRecordViewModel reminder in reminders) { var dueOn = reminder.Metric == ReminderMetric.Both ? $"{reminder.Date.ToShortDateString()} or {reminder.Mileage}" : reminder.Metric == ReminderMetric.Date ? $"{reminder.Date.ToShortDateString()}" : $"{reminder.Mileage}"; tableBody += $"{StaticHelper.GetTitleCaseReminderUrgency(reminder.Urgency)}{reminder.Description}{dueOn}"; } emailBody = emailBody.Replace("{TableBody}", tableBody); try { var result = SendEmail(emailAddresses, emailSubject, emailBody); if (result) { return OperationResponse.Succeed("Email Sent!"); } else { return OperationResponse.Failed(); } } catch (Exception ex) { return OperationResponse.Failed(ex.Message); } } private bool SendEmail(List emailTo, string emailSubject, string emailBody) { string from = mailConfig.EmailFrom; var server = mailConfig.EmailServer; var message = new MimeMessage(); message.From.Add(new MailboxAddress(from, from)); foreach(string emailRecipient in emailTo) { message.To.Add(new MailboxAddress(emailRecipient, emailRecipient)); } message.Subject = emailSubject; var builder = new BodyBuilder(); builder.HtmlBody = emailBody; message.Body = builder.ToMessageBody(); using (var client = new SmtpClient()) { client.Connect(server, mailConfig.Port, SecureSocketOptions.Auto); //perform authentication if either username or password is provided. //do not perform authentication if neither are provided. if (!string.IsNullOrWhiteSpace(mailConfig.Username) || !string.IsNullOrWhiteSpace(mailConfig.Password)) { client.Authenticate(mailConfig.Username, mailConfig.Password); } try { client.Send(message); client.Disconnect(true); return true; } catch (Exception ex) { _logger.LogError(ex.Message); return false; } } } } }