/// <summary> /// Will try to send the specified email and returns true for successful sending. /// </summary> public static bool Send(IEmailQueueItem mailItem) { if (mailItem == null) { throw new ArgumentNullException("mailItem"); } if (mailItem.Retries >= MaximumRetries) { return(false); } try { using (var mail = CreateMailMessage(mailItem)) { if (mail == null) { return(false); } return(EmailDispatcher(mailItem, mail)); } } catch (Exception ex) { OnSendError(mailItem, ex); mailItem.RecordRetry(); Log.Error("Error in sending an email for this EmailQueueItem of '" + mailItem.GetId() + "'", ex); return(false); } }
/// <summary> /// Will try to send the specified email and returns true for successful sending. /// </summary> public static async Task <bool> Send(IEmailQueueItem mailItem) { if (mailItem == null) { throw new ArgumentNullException(nameof(mailItem)); } if (mailItem.Retries >= MaximumRetries) { return(false); } MailMessage mail = null; try { using (mail = await CreateMailMessage(mailItem)) { if (mail == null) { return(false); } return(await EmailDispatcher(mailItem, mail)); } } catch (Exception ex) { await SendError.Raise(new EmailSendingEventArgs(mailItem, mail) { Error = ex }); await mailItem.RecordRetry(); Log.Error($"Error in sending an email for this EmailQueueItem of '{mailItem.GetId()}'", ex); return(false); } }
public static MailAddress GetSender(this IEmailQueueItem mailItem) { var addressPart = mailItem.SenderAddress.Or(Config.Get("Email.Sender.Address")); var displayNamePart = mailItem.SenderName.Or(Config.Get("Email.Sender.Name")); return(new MailAddress(addressPart, displayNamePart)); }
async Task <string> GetAttachmentLinks(IEmailQueueItem email) { return((await email.Attachments.OrEmpty().Split('|').Trim() .Select(async f => $"<form action='/?Web.Test.Command=testEmail&To={To}&ReturnUrl={ReturnUrl.UrlEncode()}' " + $"method='post'><input type=hidden name='attachmentInfo' value='{f.HtmlEncode()}'/><a href='#' " + $"onclick='this.parentElement.submit()'>{(await EmailService.ParseAttachment(f))?.Name.HtmlEncode()}</a></form>") .AwaitAll()).ToString("")); }
/// <summary> /// Raises the Sent event. /// </summary> internal static void OnSent(IEmailQueueItem item, MailMessage message) { if (!item.IsNew) { Database.Delete(item); } Sent?.Invoke(item, new EventArgs <MailMessage>(message)); }
/// <summary> /// Gets the Attachment objects to be attached to this email. /// </summary> public static IEnumerable <Attachment> GetAttachments(this IEmailQueueItem mail) { foreach (var attachmentInfo in mail.Attachments.OrEmpty().Split('|').Trim()) { var item = ParseAttachment(attachmentInfo); if (item != null) { yield return(item); } } }
public static MailAddress GetReplyTo(this IEmailQueueItem mailItem) { var result = mailItem.GetSender(); var asCustomReplyTo = mailItem as ICustomReplyToEmailQueueItem; if (asCustomReplyTo == null) { return(result); } return(new MailAddress(asCustomReplyTo.ReplyToAddress.Or(result.Address), asCustomReplyTo.ReplyToName.Or(result.DisplayName))); }
/// <summary> /// Attaches the specified byte array content to this email as an attachment. /// </summary> public static void Attach(this IEmailQueueItem mail, byte[] fileData, string name, string contentId, bool isLinkedResource = false) { var data = new { Contents = fileData.ToBase64String(), Name = name, ContentId = contentId, IsLinkedResource = isLinkedResource }; var json = JsonConvert.SerializeObject(data); if (mail.Attachments.IsEmpty()) { mail.Attachments = json; } else { mail.Attachments += "|" + json; } }
public EmailTestService(HttpRequest request, HttpResponse response) { Request = request; Response = response; To = Request["to"].ToStringOrEmpty().ToLower(); ReturnUrl = Request.GetReturnUrl(); if (Request.Has("attachmentInfo")) { AttachmentFile = EmailService.ParseAttachment(Request["attachmentInfo"]); } using (new SoftDeleteAttribute.Context(bypassSoftdelete: true)) Email = Request.GetOrDefault <IEmailQueueItem>("id"); }
/// <summary> /// Gets the Attachment objects to be attached to this email. /// </summary> public static async Task <IEnumerable <Attachment> > GetAttachments(this IEmailQueueItem mail) { var result = new List <Attachment>(); foreach (var attachmentInfo in mail.Attachments.OrEmpty().Split('|').Trim()) { var item = await ParseAttachment(attachmentInfo); if (item != null) { result.Add(item); } } return(result); }
/// <summary> /// Attaches the specified byte array content to this email as an attachment. /// </summary> public static void Attach(this IEmailQueueItem mail, byte[] fileData, string name, string contentId, bool isLinkedResource = false) { var data = new { Contents = fileData.ToBase64String(), Name = name, ContentId = contentId, IsLinkedResource = isLinkedResource }; var json = new JavaScriptSerializer { MaxJsonLength = int.MaxValue }.Serialize(data); if (mail.Attachments.IsEmpty()) { mail.Attachments = json; } else { mail.Attachments += "|" + json; } }
public async Task <EmailTestService> Initialize() { To = Request.Param("to").ToStringOrEmpty().ToLower(); ReturnUrl = Request.GetReturnUrl(); if (Request.Has("attachmentInfo")) { AttachmentFile = await EmailService.ParseAttachment(Request.Param("attachmentInfo")); } using (new SoftDeleteAttribute.Context(bypassSoftdelete: true)) Email = await Request.GetOrDefault <IEmailQueueItem>("id"); IsInitialized = true; return(this); }
static bool SendViaSmtp(IEmailQueueItem mailItem, MailMessage mail) { // Developer note: Web.config setting for SSL is designed to take priority over the specific setting of the email. // If in your application you want the email item's setting to take priority, do this: // 1. Remove the 'Email.Enable.Ssl' setting from web.config totally. // 2. If you need a default value, use your application's Global Settings object and use that value everywhere you create an EmailQueueItem. if (Configurator == null) { throw new InvalidOperationException($"{nameof(EmailService)} is not initialized."); } using (var smtpClient = new SmtpClient { EnableSsl = Config.Get <bool>("Email.Enable.Ssl", mailItem.EnableSsl) }) { Configurator.Configure(smtpClient); if (mailItem.SmtpHost.HasValue()) { smtpClient.Host = mailItem.SmtpHost; } if (mailItem.SmtpPort.HasValue) { smtpClient.Port = mailItem.SmtpPort.Value; } if (mailItem.Username.HasValue()) { smtpClient.Credentials = new NetworkCredential(mailItem.Username, mailItem.Password.Or((smtpClient.Credentials as NetworkCredential).Get(c => c.Password))); } if (Config.IsDefined("Email.Random.Usernames")) { var userName = Config.Get("Email.Random.Usernames").Split(',').Trim().PickRandom(); smtpClient.Credentials = new NetworkCredential(userName, Config.Get("Email.Password")); } OnSending(mailItem, mail); smtpClient.Send(mail); OnSent(mailItem, mail); } return(true); }
/// <summary> /// Records an unsuccessful attempt to send this email. /// </summary> public static async Task RecordRetry(this IEmailQueueItem emailItem) { if (emailItem.IsNew) { throw new InvalidOperationException(); } var retries = emailItem.Retries + 1; if (!emailItem.IsNew) { await Entity.Database.Update(emailItem, e => e.Retries = retries); } // Also update this local instance: emailItem.Retries = retries; }
/// <summary> /// Gets the Linked Resource objects to be attached to this email. /// </summary> public static IEnumerable <LinkedResource> GetLinkedResources(this IEmailQueueItem mail) { if (mail.Attachments.HasValue()) { foreach (var resource in mail.Attachments.Trim().Split('|').Where(x => x.StartsWith("{"))) { var data = new JavaScriptSerializer { MaxJsonLength = int.MaxValue }.Deserialize <Dictionary <string, object> >(resource); if (data == null) { continue; } var contents = data.GetOrDefault("Contents") as string; if (contents.IsEmpty()) { continue; } var isLinkedResource = data.GetOrDefault("IsLinkedResource").ToStringOrEmpty().TryParseAs <bool>() ?? false; if (!isLinkedResource) { continue; } var stream = new MemoryStream(Convert.FromBase64String(contents)); var name = data["Name"] as string; var contentId = data["ContentId"] as string; yield return(new LinkedResource(stream) { ContentId = contentId, ContentType = new System.Net.Mime.ContentType { Name = name } }); } } }
static async Task <bool> SendViaSmtp(IEmailQueueItem mailItem, MailMessage mail) { // Developer note: Web.config setting for SSL is designed to take priority over the specific setting of the email. // If in your application you want the email item's setting to take priority, do this: // 1. Remove the 'Email->Enable.Ssl' setting from appsettings.json totally. // 2. If you need a default value, use your application's Global Settings object and use that value everywhere you create an EmailQueueItem. using (var smtpClient = new SmtpClient { EnableSsl = Config.Get("Email:Enable.Ssl", mailItem.EnableSsl) }) { smtpClient.Configure(); if (mailItem.SmtpHost.HasValue()) { smtpClient.Host = mailItem.SmtpHost; } if (mailItem.SmtpPort.HasValue) { smtpClient.Port = mailItem.SmtpPort.Value; } if (mailItem.Username.HasValue()) { smtpClient.Credentials = new NetworkCredential(mailItem.Username, mailItem.Password.Or((smtpClient.Credentials as NetworkCredential).Get(c => c.Password))); } if (Config.IsDefined("Email:Random.Usernames")) { var userName = Config.Get("Email:Random.Usernames").Split(',').Trim().PickRandom(); smtpClient.Credentials = new NetworkCredential(userName, Config.Get("Email:Password")); } await Sending.Raise(new EmailSendingEventArgs(mailItem, mail)); await smtpClient.SendMailAsync(mail); await Sent.Raise(new EmailSendingEventArgs(mailItem, mail)); } return(true); }
/// <summary> /// Attaches a file to this email. /// </summary> public static void Attach(this IEmailQueueItem mail, Document file) { if (file == null) { throw new ArgumentNullException(nameof(file)); } if (file.IsEmpty()) { return; } if (file.LocalPath.IsEmpty()) { throw new ArgumentException("In-memory document instances cannot be used for email attachment. It should be saved on disk first."); } var reference = file.GetOwnerPropertyReference(); if (reference.HasValue()) { var json = new JavaScriptSerializer { MaxJsonLength = int.MaxValue }.Serialize(new { PropertyReference = reference }); if (mail.Attachments.IsEmpty()) { mail.Attachments = json; } else { mail.Attachments += "|" + json; } } else { Attach(mail, file.LocalPath); } }
/// <summary> /// Attaches a file to this email. /// </summary> /// <param name="mail">The email queue item.</param> /// <param name="filePath">The path of the attachment file. /// This must be the physical path of a file inside the running application.</param> public static void Attach(this IEmailQueueItem mail, string filePath) { if (filePath.IsEmpty()) { throw new ArgumentNullException(nameof(filePath)); } var basePath = AppDomain.CurrentDomain.WebsiteRoot().FullName.ToLower(); if (filePath.ToLower().StartsWith(basePath)) // Relative: { filePath = filePath.Substring(basePath.Length).TrimStart("\\"); } if (mail.Attachments.IsEmpty()) { mail.Attachments = filePath; } else { mail.Attachments += "|" + filePath; } }
/// <summary> /// Attaches a file to this email. /// </summary> public static void Attach(this IEmailQueueItem mail, Blob file) { if (file == null) { throw new ArgumentNullException(nameof(file)); } if (file.IsEmpty()) { return; } if (file.LocalPath.IsEmpty()) { throw new ArgumentException("In-memory blob instances cannot be used for email attachment. It should be saved on disk first."); } var reference = file.GetOwnerPropertyReference(); if (reference.HasValue()) { var json = JsonConvert.SerializeObject(new { PropertyReference = reference }); if (mail.Attachments.IsEmpty()) { mail.Attachments = json; } else { mail.Attachments += "|" + json; } } else { Attach(mail, file.LocalPath); } }
/// <summary> /// Will send an email and returns true for successful sending. /// </summary> public static Task <bool> Send(this IEmailQueueItem mailItem) => EmailService.Send(mailItem);
/// <summary> /// Raises the Sent event. /// </summary> internal static void OnSent(IEmailQueueItem item, System.Net.Mail.MailMessage message) { Sent?.Invoke(item, new EventArgs <System.Net.Mail.MailMessage>(message)); }
/// <summary> /// Will send an email and returns true for successful sending. /// </summary> public static bool Send(this IEmailQueueItem mailItem) { return(EmailService.Send(mailItem)); }
static void OnSendError(IEmailQueueItem email, Exception error) { SendError?.Invoke(email, new EventArgs <Exception>(error)); }
public EmailSendingEventArgs(IEmailQueueItem item, MailMessage message) { MailMessage = message; Item = item; }
/// <summary> /// Creates an SMTP mail message for a specified mail item. /// </summary> static MailMessage CreateMailMessage(IEmailQueueItem mailItem) { // Make sure it's due: if (mailItem.Date > LocalTime.Now) { return(null); } var mail = new MailMessage { Subject = mailItem.Subject.Or("[NO SUBJECT]").Remove("\r", "\n") }; #region Set Body if (mailItem.Html) { var htmlView = AlternateView.CreateAlternateViewFromString(mailItem.Body, new ContentType("text/html; charset=UTF-8")); //Add Linked Resources htmlView.LinkedResources.AddRange <LinkedResource>(mailItem.GetLinkedResources()); mail.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(mailItem.Body.RemoveHtmlTags(), new ContentType("text/plain; charset=UTF-8"))); mail.AlternateViews.Add(htmlView); } else { mail.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(mailItem.Body.RemoveHtmlTags(), new ContentType("text/plain; charset=UTF-8"))); } if (mailItem.VCalendarView.HasValue()) { var calendarType = new ContentType("text/calendar"); calendarType.Parameters.Add("method", "REQUEST"); calendarType.Parameters.Add("name", "meeting.ics"); var calendarView = AlternateView.CreateAlternateViewFromString(mailItem.VCalendarView, calendarType); calendarView.TransferEncoding = TransferEncoding.SevenBit; mail.AlternateViews.Add(calendarView); } #endregion #region Set Sender mail.From = mailItem.GetSender(); mail.ReplyToList.Add(mail.From); #endregion #region Set Receivers // Add To: foreach (var address in mailItem.To.Or("").Split(',').Trim().Where(a => IsSendingPermitted(a))) { mail.To.Add(address); } // Add Cc: foreach (var address in mailItem.Cc.Or("").Split(',').Trim().Where(a => IsSendingPermitted(a))) { mail.CC.Add(address); } foreach (var address in Config.Get("Email.Auto.CC.Address").Or("").Split(',').Trim().Where(a => IsSendingPermitted(a))) { mail.CC.Add(address); } // Add Bcc: foreach (var address in mailItem.Bcc.Or("").Split(',').Trim().Where(a => IsSendingPermitted(a))) { mail.Bcc.Add(address); } if (mail.To.None() && mail.CC.None() && mail.Bcc.None()) { return(null); } #endregion // Add attachments mail.Attachments.AddRange(mailItem.GetAttachments()); return(mail); }
string GetFrom(IEmailQueueItem email) => email.GetSender().Get(s => s.DisplayName.Or("").HtmlEncode() + s.Address.WithWrappers(" <", ">"));
/// <summary> /// Raises the Sending event. /// </summary> internal static void OnSending(IEmailQueueItem item, MailMessage message) { Sending?.Invoke(item, new EventArgs <MailMessage>(message)); }