using System; using System.Configuration; using System.Net; using System.Net.Mail; using log4net; using LeafWeb.Core.DAL; using LeafWeb.Core.Entities; using LeafWeb.Core.Utility; using LeafWeb.WebCms.Models; using Umbraco.Core; namespace LeafWeb.WebCms.Services { public class EmailNotificationService : IDisposable { private static readonly ILog Logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private readonly string _emailFromAddress; private const string SuccessSubject = "LeafWeb results"; private const string ErrorSubject = "LeafWeb processing error"; private const string SystemErrorSubject = "LeafWeb system error"; private const string CancelledSubject = "LeafWeb cancelled"; private const string ContactSubject = "LeafWeb Contact Message"; /// /// comma separated values /// private readonly string _adminEmailAddresses; private readonly SmtpClient _smtpClient; private readonly DataService _dataService; private readonly UrlService _urlService; private string FormatSubject(string subject, LeafInput leafInput) { return subject + $" - '{leafInput.Identifier}'"; } public EmailNotificationService(DataService dataService) { _dataService = dataService; _urlService = new UrlService(); _smtpClient = new SmtpClient( ConfigurationManager.AppSettings["SmtpHost"], Convert.ToInt32(ConfigurationManager.AppSettings["SmtpPort"])); if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["SmtpUserName"])) _smtpClient.Credentials = new NetworkCredential( ConfigurationManager.AppSettings["SmtpUserName"], ConfigurationManager.AppSettings["SmtpPassword"] ); _emailFromAddress = ConfigurationManager.AppSettings["EmailFromAddress"]; _adminEmailAddresses = ConfigurationManager.AppSettings["AdminEmailAddresses"]; } public EmailNotificationService() : this(new DataService()) { } public void SendLeafWebComplete(int leafInputId) { var leafInput = _dataService.GetLeafInput(leafInputId); if (leafInput.CurrentStatus != LeafInputStatusType.Complete) { var notComplete = "Attempting to SendLeafWebComplete when status is not complete" + $" for leafInput: {leafInput}, current status: {leafInput.CurrentStatus}"; Logger.Error(notComplete); throw new ArgumentException(notComplete); } var outputErrorMessage = leafInput.OutputErrorMessage; if (outputErrorMessage != null) SendLeafWebError(leafInput, outputErrorMessage.FileContents.Contents.GetString()); else SendLeafWebSuccess(leafInput); } public void SendLeafWebCancelled(int leafInputId) { var leafInput = _dataService.GetLeafInput(leafInputId); if (leafInput.CurrentStatus != LeafInputStatusType.Cancelled) { var notComplete = "Attempting to SendLeafWebCancelled when status is not complete " + $"for leafInput: {leafInput}, current status: {leafInput.CurrentStatus}"; Logger.Error(notComplete); throw new ArgumentException(notComplete); } var body = $"Your leaf analysis job, {leafInput.Identifier}, has been cancelled. " + "Contact the administrator with any questions."; using (var message = new MailMessage( _emailFromAddress, leafInput.Email, FormatSubject(CancelledSubject, leafInput), body)) SendMessage(message); } public void SendAdministratorMessage(string subject, string body) { using (var message = new MailMessage( _emailFromAddress, _adminEmailAddresses, subject, body )) SendMessage(message); } private void SendLeafWebSuccess(LeafInput leafInput) { var body = $"Your leaf analysis job '{leafInput.Identifier}' has completed. "; body += FormatWarningMessage(leafInput); var downloadLink = true; if (downloadLink) { var downloadUrl = _urlService.GetDownloadUrl(leafInput); var chartUrl = _urlService.GetChartUrl(leafInput); body += Environment.NewLine + Environment.NewLine + "Download results with the following link:" + Environment.NewLine + Environment.NewLine + downloadUrl; body += Environment.NewLine + Environment.NewLine + "Chart results with the following link:" + Environment.NewLine + Environment.NewLine + chartUrl; using (var message = new MailMessage( _emailFromAddress, leafInput.Email, FormatSubject(SuccessSubject, leafInput), body)) SendMessage(message); } //else //{ // body += "Please see the attached results."; // var message = new MailMessage(_emailFromAddress, leafInput.Email, SuccessSubject, body); // var fileStreams = // (from outputFile in // leafInput.OutputFiles // select Tuple.Create(outputFile, new MemoryStream(outputFile.FileContents.Contents))).ToList(); // try // { // foreach (var fileStream in fileStreams) // { // var attachment = new Attachment(fileStream.Item2, fileStream.Item1.Filename); // message.Attachments.Add(attachment); // } // SendMessage(message); // } // finally // { // // can't dispose those memory streams until the message is sent // foreach (var stream in fileStreams.Select(f => f.Item2)) // { // stream.Dispose(); // } // } //} } private void SendLeafWebError(LeafInput leafInput, string errorMessage) { var body = $"Your leaf analysis job '{leafInput.Identifier}' encountered the following errors." + Environment.NewLine + Environment.NewLine + Environment.NewLine + errorMessage + Environment.NewLine + Environment.NewLine + "You will need to correct your input and resubmit."; body += FormatWarningMessage(leafInput); using (var message = new MailMessage( _emailFromAddress, leafInput.Email, FormatSubject(ErrorSubject, leafInput), body)) SendMessage(message); } public void SendLeafWebSystemException(string leafInputIdentifier, string leafInputEmail) { var body = $"A system error occured while processing your leaf analysis job '{leafInputIdentifier}'." + Environment.NewLine + "System administrators have been notified. You will be notified again when the system error " + "has been resolved and your data has been processed."; using (var message = new MailMessage( _emailFromAddress, leafInputEmail, SystemErrorSubject, body)) SendMessage(message); } public void SendContactEmail(ContactForm contact) { var body = $"via LeafWeb, {contact.Name} sent the following message from the Contact form." + Environment.NewLine + Environment.NewLine + "Message" + Environment.NewLine + Environment.NewLine + "--------" + Environment.NewLine + Environment.NewLine + contact.Message; using (var message = new MailMessage( _emailFromAddress, _adminEmailAddresses, ContactSubject, body) { From = new MailAddress(contact.Email, contact.Name) }) SendMessage(message); } public void SendVerifyMemberEmail(string memberEmail) { var member = ApplicationContext.Current.Services.MemberService.GetByEmail(memberEmail); var verifyEmailURl = _urlService.GetVerifyEmailUrl(member); var body = "Welcome to LeafWeb!" + Environment.NewLine + Environment.NewLine + "Please verify your email address with this link: " + verifyEmailURl + Environment.NewLine + Environment.NewLine + "Read more information about LeafWeb on the site here: https://leafweb.org/information/about/" + Environment.NewLine + Environment.NewLine + "Thank you!"; using (var message = new MailMessage( _emailFromAddress, member.Email, "Welcome to LeafWeb, please verify your email address", body)) SendMessage(message); } public void SendPasswordResetNotMemberEmail(string memberEmail) { var body = "A password reset has been requested for leafweb.org" + Environment.NewLine + Environment.NewLine + "We do not have an account attached to this email address, " + "if you'd like to create one click here " + _urlService.GetRegisterUrl(); using (var message = new MailMessage( _emailFromAddress, memberEmail, "Reset LeafWeb Password", body)) SendMessage(message); } public void SendPasswordResetEmail(string memberEmail) { var member = ApplicationContext.Current.Services.MemberService.GetByEmail(memberEmail); var passwordResetURl = _urlService.GetPasswordResetUrl(member); var body = "A password reset has been requested for leafweb.org" + Environment.NewLine + Environment.NewLine + "Please click here to enter a new password " + passwordResetURl; using (var message = new MailMessage( _emailFromAddress, member.Email, "Reset LeafWeb Password", body)) SendMessage(message); } private string FormatWarningMessage(LeafInput leafInput) { if (leafInput.OutputWarningMessage != null) return Environment.NewLine + Environment.NewLine + "The following warning message was generated." + Environment.NewLine + Environment.NewLine + leafInput.OutputWarningMessage.FileContents.Contents.GetString() + Environment.NewLine; return string.Empty; } private void SendMessage(MailMessage mailMessage) { try { Logger.Info($"Email sending to {mailMessage.To}, subject: {mailMessage.Subject}"); _smtpClient.Send(mailMessage); } catch (SmtpException ex) { Logger.Error($"Failed to send mail: {ex.Message}", ex); } } public void Dispose() { _dataService.Dispose(); } } }