/// <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);
            }
        }
Example #2
0
        /// <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(""));
 }
Example #5
0
        /// <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);
         }
     }
 }
Example #7
0
        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");
        }
Example #10
0
        /// <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);
        }
Example #11
0
        /// <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);
        }
Example #13
0
        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);
        }
Example #14
0
        /// <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;
        }
Example #15
0
        /// <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
                        }
                    });
                }
            }
        }
Example #16
0
        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);
        }
Example #17
0
        /// <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);
            }
        }
Example #18
0
        /// <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;
            }
        }
Example #19
0
        /// <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);
            }
        }
Example #20
0
 /// <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));
 }
Example #22
0
 /// <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(" &lt;", "&gt;"));
Example #27
0
 /// <summary>
 /// Raises the Sending event.
 /// </summary>
 internal static void OnSending(IEmailQueueItem item, MailMessage message)
 {
     Sending?.Invoke(item, new EventArgs <MailMessage>(message));
 }