Exemplo n.º 1
0
 public IActionResult Lists()
 {
     using (MailDemonDatabase db = dbProvider.GetDatabase())
     {
         return(View(db.Lists.OrderBy(l => l.Name).ToArray()));
     }
 }
Exemplo n.º 2
0
        public IActionResult Unsubscribe(string id, string token)
        {
            id = (id ?? string.Empty).Trim();
            if (id.Length == 0)
            {
                return(NotFound());
            }
            int pos = id.IndexOf('@');

            if (pos >= 0)
            {
                id = id.Substring(0, pos);
            }

            // stupid bing/outlook email preview
            string userAgent = Request.Headers["User-Agent"].ToString();

            if (string.IsNullOrWhiteSpace(userAgent) || userAgent.Contains("preview", StringComparison.OrdinalIgnoreCase))
            {
                return(Content(string.Empty));
            }

            token = (token ?? string.Empty).Trim();
            using (MailDemonDatabase db = dbProvider.GetDatabase())
            {
                if (db.UnsubscribeFromMailingList(id, token))
                {
                    string success = Resources.UnsubscribeSuccess.FormatHtml(id);
                    return(View((object)success));
                }
            }
            string error = Resources.UnsubscribeError.FormatHtml(id);

            return(View((object)error));
        }
Exemplo n.º 3
0
        private IActionResult EditTemplateSend(string id, bool all)
        {
            id = (id ?? string.Empty).Trim();
            if (id.Length == 0)
            {
                return(NotFound());
            }
            string   listName = MailTemplate.GetListName(id);
            MailList list;

            using (MailDemonDatabase db = dbProvider.GetDatabase())
            {
                list = db.Lists.FirstOrDefault(l => l.Name == listName);
            }
            if (list == null)
            {
                return(NotFound());
            }
            if (bulkMailSender == null)
            {
                return(NotFound());
            }
            string unsubscribeUrl = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}/{nameof(Unsubscribe)}/{id}?token={{0}}";

            bulkMailSender.SendBulkMail(list, mailCreator, mailSender, GetViewBagForTemplate(), all, id, unsubscribeUrl).ConfigureAwait(false).GetAwaiter();
            TempData["Message"] = Resources.SendStarted;
            return(RedirectToAction(nameof(HomeController.EditTemplate), new { id }));
        }
Exemplo n.º 4
0
        public IActionResult EditTemplatePost(string id, MailTemplateModel model, string action)
        {
            memoryCache?.Remove("Template_" + id);

            if (action == "delete")
            {
                return(EditTemplateDelete(id));
            }
            else if (action == "send")
            {
                model.All = Request.Form.ContainsKey("All");
                return(EditTemplateSend(id, model.All));
            }

            try
            {
                model.Value.Name = model.Value.Name?.Trim();
                if (model.Value.Name.Length > 64)
                {
                    throw new ArgumentException(Resources.NameIsTooLong.FormatHtml(64));
                }
                if (!model.Value.GetListNameAndTemplateName(out string listName, out string templateName) ||
                    !MailTemplate.ValidateName(listName) ||
                    !MailTemplate.ValidateName(templateName))
                {
                    throw new ArgumentException(Resources.TemplateNameInvalidChars.FormatHtml(MailTemplate.FullNameSeparator));
                }
                using (MailDemonDatabase db = dbProvider.GetDatabase())
                {
                    if (db.Lists.FirstOrDefault(l => l.Name == listName) == null)
                    {
                        throw new ArgumentException(string.Format(Resources.ListNotFound, listName));
                    }
                    model.Value.LastModified = DateTime.UtcNow;
                    model.Value.Dirty        = true;
                    if (model.Value.Id == 0)
                    {
                        db.Templates.Add(model.Value);
                    }
                    else
                    {
                        db.Update(model.Value);
                    }
                    db.SaveChanges();
                }
                TempData["Message"] = Resources.Success;
                return(RedirectToAction(nameof(EditTemplate), new { id = model.Value.Name }));
            }
            catch (Exception ex)
            {
                MailDemonLog.Error(ex);
                model.Error   = true;
                model.Message = ex.Message;
                return(View(model));
            }
        }
Exemplo n.º 5
0
        public IActionResult EditList(string id)
        {
            MailList list;

            using (MailDemonDatabase db = dbProvider.GetDatabase())
            {
                list = db.Lists.FirstOrDefault(l => l.Name == id) ?? new MailList();
            }
            return(View(new MailListModel {
                Value = list, Message = TempData["Message"] as string
            }));
        }
Exemplo n.º 6
0
 protected override async Task ExecuteAsync(CancellationToken stoppingToken)
 {
     do
     {
         DateTime dt = DateTime.UtcNow;
         using (MailDemonDatabase db = serviceProvider.GetService <MailDemonDatabase>())
         {
             db.Subscriptions.RemoveRange(db.Subscriptions.Where(r => r.Expires <= dt && r.UnsubscribeToken == null));
             db.SaveChanges();
         }
     }while (!(await stoppingToken.WaitHandle.WaitOneAsync(loopTimeSpan, stoppingToken)));
 }
Exemplo n.º 7
0
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                DateTime dt = DateTime.UtcNow;
                using MailDemonDatabase db = dbProvider.GetDatabase();
                db.Subscriptions.RemoveRange(db.Subscriptions.Where(r => r.Expires <= dt && r.UnsubscribeToken == null));
                await db.SaveChangesAsync();

                await Task.Delay(loopTimeSpan, stoppingToken);
            }
        }
Exemplo n.º 8
0
        public IActionResult EditListPost(string id, MailListModel model, string action)
        {
            if (action == "delete")
            {
                return(EditListDelete(id));
            }

            try
            {
                model.Value.Name = model.Value.Name?.Trim();
                if (model.Value.Name.Length > 16)
                {
                    throw new ArgumentException(Resources.NameIsTooLong.FormatHtml(16));
                }
                else if (!model.Value.FromEmailAddress.TryParseEmailAddress(out _))
                {
                    throw new ArgumentException(Resources.EmailIsInvalid);
                }
                model.Value.Company = model.Value.Company?.Trim();
                model.Value.Website = model.Value.Website?.Trim();
                if (!MailTemplate.ValidateName(model.Value.Name))
                {
                    throw new ArgumentException(Resources.NameInvalidChars);
                }
                using (MailDemonDatabase db = dbProvider.GetDatabase())
                {
                    MailList existingList = db.Lists.FirstOrDefault(l => l.Name == model.Value.Name);
                    if (existingList != null && (existingList.Name != model.Value.Name || model.Value.Id == 0))
                    {
                        throw new ArgumentException(Resources.NameCannotChange);
                    }
                    if (model.Value.Id == 0)
                    {
                        db.Lists.Add(model.Value);
                    }
                    else
                    {
                        db.Update(model.Value);
                    }
                    db.SaveChanges();
                }
                TempData["Message"] = Resources.Success;
                return(RedirectToAction(nameof(EditList), new { id = model.Value.Name }));
            }
            catch (Exception ex)
            {
                MailDemonLog.Error(ex);
                model.Error   = true;
                model.Message = ex.Message;
                return(View(model));
            }
        }
Exemplo n.º 9
0
        public async Task <IActionResult> DebugTemplate(string id)
        {
            if (HttpContext.Request.Method == "POST")
            {
                // switch to GET request, to avoid stupid double form post popup
                return(RedirectToAction(nameof(DebugTemplate), new { id }));
            }

            id = (id ?? string.Empty).Trim();
            if (id.Length == 0)
            {
                return(NotFound());
            }
            string   listName = MailTemplate.GetListName(id);
            MailList list;

            using (MailDemonDatabase db = dbProvider.GetDatabase())
            {
                list = db.Lists.FirstOrDefault(l => l.Name == listName);
            }
            if (list == null)
            {
                return(NotFound());
            }

            string unsubscribeToken      = Guid.NewGuid().ToString("N");
            MailListSubscription tempReg = new MailListSubscription
            {
                EmailAddress     = "*****@*****.**",
                IPAddress        = HttpContext.GetRemoteIPAddress().ToString(),
                FirstName        = "Bob",
                LastName         = "Smith",
                Company          = "Fake Company",
                ListName         = list.Name,
                SubscribedDate   = DateTime.UtcNow,
                SubscribeToken   = Guid.NewGuid().ToString("N"),
                Expires          = DateTime.MinValue,
                MailList         = list,
                UnsubscribeToken = unsubscribeToken,
                UnsubscribeUrl   = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}/{nameof(Unsubscribe)}/{list.Name}?token={unsubscribeToken}"
            };
            MimeMessage msg = await mailCreator.CreateMailAsync(id, tempReg, GetViewBagForTemplate(), (_html, subject) =>
            {
                return(_html.Replace("<body>", "<body><div style='padding: 10px; width: 100%; background-color: #2A2A2A; border-bottom: 1px solid #444444;'>SUBJECT: " + System.Web.HttpUtility.HtmlEncode(subject) + "</div>"));
            });

            string html = msg.HtmlBody;

            return(Content(msg.HtmlBody, "text/html"));
        }
Exemplo n.º 10
0
 public IActionResult Subscribers(string id, string action, long?subId)
 {
     if (action == "delete" && subId != null)
     {
         using MailDemonDatabase db = dbProvider.GetDatabase();
         MailListSubscription sub = db.Subscriptions.FirstOrDefault(s => s.Id == subId);
         if (sub != null)
         {
             db.Subscriptions.Remove(sub);
             db.SaveChanges();
         }
     }
     return(RedirectToAction(nameof(Subscribers), new { id }));
 }
Exemplo n.º 11
0
        /// <summary>
        /// Unsubscribe from a mailing list
        /// </summary>
        /// <param name="db">DB</param>
        /// <param name="listName">List name</param>
        /// <param name="token">Unsubscribe token</param>
        /// <returns>True if unsubscribed, false if not</returns>
        public static bool UnsubscribeFromMailingList(this MailDemonDatabase db, string listName, string token)
        {
            MailListSubscription foundReg = db.Subscriptions.FirstOrDefault(r => r.UnsubscribeToken == token && r.ListName == listName && r.UnsubscribedDate == default);

            if (foundReg != null)
            {
                foundReg.UnsubscribedDate = DateTime.UtcNow;
                foundReg.SubscribeToken   = null;
                db.SaveChanges();
                return(true);
            }
            ;
            return(false);
        }
Exemplo n.º 12
0
        public IActionResult Templates(string id)
        {
            List <MailTemplateBase> templates = new List <MailTemplateBase>();

            using (MailDemonDatabase db = dbProvider.GetDatabase())
            {
                foreach (MailTemplate template in db.Templates.Where(t => string.IsNullOrWhiteSpace(id) || t.Name.StartsWith(id + MailTemplate.FullNameSeparator)))
                {
                    templates.Add(new MailTemplateBase {
                        Id = template.Id, LastModified = template.LastModified, Name = template.Name
                    });
                }
            }
            return(View(templates.OrderBy(t => t.Name)));
        }
Exemplo n.º 13
0
 private IActionResult EditTemplateDelete(string id)
 {
     try
     {
         using MailDemonDatabase db = dbProvider.GetDatabase();
         MailTemplate template = db.Templates.FirstOrDefault(t => t.Name == id);
         if (template != null)
         {
             db.Templates.Remove(template);
             db.SaveChanges();
         }
     }
     catch (Exception ex)
     {
         MailDemonLog.Error(ex);
     }
     return(RedirectToAction(nameof(EditTemplate)));
 }
Exemplo n.º 14
0
        /// <summary>
        /// Confirm subscribe to a mailing list
        /// </summary>
        /// <param name="db">DB</param>
        /// <param name="listName">List name</param>
        /// <param name="token">Subscribe token</param>
        /// <returns>Registration or null if not found</returns>
        public static MailListSubscription ConfirmSubscribeToMailingList(this MailDemonDatabase db, string listName, string token)
        {
            MailListSubscription reg      = null;
            MailListSubscription foundReg = db.Subscriptions.FirstOrDefault(r => r.SubscribeToken == token);

            if (foundReg != null && foundReg.ListName == listName && foundReg.SubscribedDate == default && foundReg.SubscribeToken == token)
            {
                reg = foundReg;
                foundReg.Expires          = DateTime.MaxValue;
                foundReg.SubscribedDate   = DateTime.UtcNow;
                foundReg.UnsubscribedDate = default;
                foundReg.UnsubscribeToken = Guid.NewGuid().ToString("N");
                foundReg.MailList         = db.Lists.FirstOrDefault(l => l.Name == listName);
                foundReg.Result           = "New";
                db.SaveChanges();
            }
            return(reg);
        }
Exemplo n.º 15
0
        public IActionResult EditTemplate(string id)
        {
            MailTemplate template;

            using (MailDemonDatabase db = dbProvider.GetDatabase())
            {
                template = db.Templates.FirstOrDefault(t => t.Name == id) ?? new MailTemplate {
                    Text = "<!-- Subject: ReplaceWithYourSubject -->\r\n"
                };
            }
            if (template.Id == 0 && string.IsNullOrWhiteSpace(template.Name) && id.IndexOf(MailTemplate.FullNameSeparator) < 0)
            {
                template.Name = id + MailTemplate.FullNameSeparator;
            }
            return(View(new MailTemplateModel {
                Value = template, Message = TempData["Message"] as string
            }));
        }
Exemplo n.º 16
0
        public IActionResult Subscribers(string id)
        {
            id = (id ?? string.Empty).Trim();
            if (id.Length == 0)
            {
                return(NotFound());
            }
            using MailDemonDatabase db = dbProvider.GetDatabase();
            MailList list = db.Lists.FirstOrDefault(l => l.Name == id);

            if (list == null)
            {
                return(NotFound());
            }
            ICollection <MailListSubscription> subscribers = db.Subscriptions.Where(s => s.ListName == id).OrderByDescending(s => s.Result).ThenByDescending(s => s.Id).Take(1000).ToList();

            ViewBag.ListName = id;
            return(View(subscribers));
        }
Exemplo n.º 17
0
        private void InitializeDB(IApplicationBuilder app)
        {
            using var db = new MailDemonDatabase(Configuration);
            db.Initialize();

            // migrate away from litedb
            string migrationPath = Path.Combine(Directory.GetCurrentDirectory(), "MailDemon.db");

            if (File.Exists(migrationPath))
            {
                MailDemonLog.Warn("Migrating from old database {0}", migrationPath);
                var tran = db.Database.BeginTransaction();
                try
                {
                    using (FileStream fs = File.OpenRead(migrationPath))
                        using (LiteDB.LiteDatabase oldDb = new LiteDB.LiteDatabase(fs))
                        {
                            foreach (MailList list in oldDb.GetCollection <MailList>().FindAll())
                            {
                                db.Lists.Add(list);
                            }
                            foreach (MailTemplate template in oldDb.GetCollection <MailTemplate>().FindAll())
                            {
                                db.Templates.Add(template);
                            }
                            foreach (MailListSubscription sub in oldDb.GetCollection <MailListSubscription>().FindAll())
                            {
                                db.Subscriptions.Add(sub);
                            }
                            db.SaveChanges();
                            tran.Commit();
                            tran = null;
                            MailDemonLog.Warn("Migration success");
                        }
                    File.Delete(migrationPath);
                }
                finally
                {
                    tran?.Rollback();
                }
            }
        }
Exemplo n.º 18
0
 private IActionResult EditListDelete(string id)
 {
     try
     {
         using MailDemonDatabase db = dbProvider.GetDatabase();
         MailList list = db.Lists.FirstOrDefault(l => l.Name == id);
         if (list != null)
         {
             db.Subscriptions.RemoveRange(db.Subscriptions.Where(r => r.ListName == id));
             db.Templates.RemoveRange(db.Templates.Where(t => t.Name.StartsWith(list.Name + MailTemplate.FullNameSeparator)));
             db.Lists.Remove(list);
             db.SaveChanges();
         }
     }
     catch (Exception ex)
     {
         MailDemonLog.Error(ex);
     }
     return(RedirectToAction(nameof(EditList)));
 }
Exemplo n.º 19
0
        public IActionResult SubscribeConfirm(string id)
        {
            id = (id ?? string.Empty).Trim();
            if (id.Length == 0)
            {
                return(NotFound());
            }
            MailList list;

            using (MailDemonDatabase db = dbProvider.GetDatabase())
            {
                list = db.Lists.FirstOrDefault(l => l.Name == id);
            }
            if (list == null)
            {
                return(View("SubscribeExpired"));
            }

            // the link will be sent via email
            return(View("SubscribeConfirmNoLink", list));
        }
Exemplo n.º 20
0
        /// <summary>
        /// Pre subscribe to a mailing list
        /// </summary>
        /// <param name="db">DB</param>
        /// <param name="reg">Registration, receives new registration if success</param>
        /// <returns>True if success, false if already subscribed</returns>
        public static bool PreSubscribeToMailingList(this MailDemonDatabase db, ref MailListSubscription reg)
        {
            bool   result = false;
            string token  = string.Empty;
            MailListSubscription final = reg;
            MailListSubscription dbReg = db.Subscriptions.FirstOrDefault(r => r.EmailAddress == final.EmailAddress && r.ListName == final.ListName);

            if (dbReg != null)
            {
                dbReg.Fields.Clear();
                foreach (var kv in final.Fields)
                {
                    dbReg.SetField(kv.Key, kv.Value);
                }
                dbReg.Error        = final.Error;
                dbReg.Message      = final.Message;
                dbReg.IPAddress    = final.IPAddress;
                dbReg.MailList     = final.MailList;
                dbReg.TemplateName = final.TemplateName;
                final = dbReg;
            }
            reg = final;
            if (reg.SubscribeToken == null)
            {
                reg.SubscribeToken = Guid.NewGuid().ToString("N");
                reg.Expires        = DateTime.UtcNow.AddHours(1.0);
                if (reg.Id == 0)
                {
                    db.Subscriptions.Add(reg);
                }
                else
                {
                    db.Update(reg);
                }
                result = true;
            }
            db.SaveChanges();
            return(result);
        }
Exemplo n.º 21
0
        public IActionResult SubscribeInitial(string id)
        {
            string result = TempData["result"] as string;

            id = (id ?? string.Empty).Trim();
            if (id.Length == 0)
            {
                return(NotFound());
            }
            MailListSubscription model = (string.IsNullOrWhiteSpace(result) ? new MailListSubscription() : JsonConvert.DeserializeObject <MailListSubscription>(result));

            using (MailDemonDatabase db = dbProvider.GetDatabase())
            {
                model.MailList = db.Lists.FirstOrDefault(l => l.Name == id);
            }
            if (model.MailList == null)
            {
                return(NotFound());
            }
            model.ListName     = id;
            model.TemplateName = MailTemplate.GetFullTemplateName(id, MailTemplate.NameSubscribeInitial);
            return(View(model));
        }
Exemplo n.º 22
0
        public async Task <IActionResult> SubscribeWelcome(string id, string token)
        {
            id = (id ?? string.Empty).Trim();
            if (id.Length == 0)
            {
                return(NotFound());
            }

            // stupid bing/outlook email preview
            string userAgent = Request.Headers["User-Agent"].ToString();

            if (string.IsNullOrWhiteSpace(userAgent) || userAgent.Contains("preview", StringComparison.OrdinalIgnoreCase))
            {
                return(Content(string.Empty));
            }

            token = (token ?? string.Empty).Trim();
            MailListSubscription reg;

            using (MailDemonDatabase db = dbProvider.GetDatabase())
            {
                reg = db.ConfirmSubscribeToMailingList(id, token);
            }
            if (reg == null)
            {
                return(View("SubscribeExpired"));
            }

            // temp property does not go in db
            reg.UnsubscribeUrl = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}/{nameof(Unsubscribe)}/{id}?token={reg.UnsubscribeToken}";

            string templateFullName = MailTemplate.GetFullTemplateName(id, MailTemplate.NameSubscribeWelcome);

            await SendMailAsync(reg, templateFullName);

            return(View(reg));
        }
Exemplo n.º 23
0
        /// <summary>
        /// Bulk email
        /// </summary>
        /// <param name="db">Database</param>
        /// <param name="list">List</param>
        /// <param name="unsubscribeUrl">Unsubscribe url</param>
        /// <param name="all">True to email all, false to only email error registrations (those that have not yet or failed to send)</param>
        /// <returns>Subscriptions to send to, grouped by domain</returns>
        public static IEnumerable <KeyValuePair <string, List <MailListSubscription> > > BeginBulkEmail(this MailDemonDatabase db, MailList list, string unsubscribeUrl, bool all)
        {
            if (all)
            {
                db.Database.ExecuteSqlRaw("UPDATE Subscriptions SET Result = 'Pending', ResultTimestamp = {0} WHERE ListName = {1}", DateTime.UtcNow, list.Name);
            }
            else
            {
                db.Database.ExecuteSqlRaw("UPDATE Subscriptions SET Result = 'Pending', ResultTimestamp = {0} WHERE ListName = {1} AND Result <> ''", DateTime.UtcNow, list.Name);
            }
            List <MailListSubscription> subs = new List <MailListSubscription>();
            string domain = null;

            foreach (MailListSubscription sub in db.Subscriptions.Where(s => s.ListName == list.Name && s.Result == "Pending")
                     .OrderBy(s => s.EmailAddressDomain))
            {
                if (domain is null || sub.EmailAddressDomain != domain)
                {
                    if (subs.Count != 0)
                    {
                        yield return(new KeyValuePair <string, List <MailListSubscription> >(domain, subs));

                        subs = new List <MailListSubscription>();
                    }
                    domain = sub.EmailAddressDomain;
                }
                sub.MailList       = list;
                sub.UnsubscribeUrl = string.Format(unsubscribeUrl, sub.UnsubscribeToken);
                subs.Add(sub);
            }
            if (subs.Count != 0)
            {
                yield return(new KeyValuePair <string, List <MailListSubscription> >(domain, subs));
            }
        }
Exemplo n.º 24
0
        public async Task <IActionResult> SubscribeInitialPost(string id, Dictionary <string, string> formFields)
        {
            id = (id ?? string.Empty).Trim();
            if (id.Length == 0)
            {
                return(NotFound());
            }
            string error = null;

            if (RequireCaptcha)
            {
                formFields.TryGetValue("captcha", out string captchaValue);
                error = await MailDemonWebApp.Instance.Recaptcha.Verify(Request.GetDisplayUrl(), captchaValue, nameof(SubscribeInitial), HttpContext.GetRemoteIPAddress().ToString(), formFields);
            }
            MailListSubscription model = new MailListSubscription {
                Message = error, Error = !string.IsNullOrWhiteSpace(error)
            };
            MailList list;

            using (MailDemonDatabase db = dbProvider.GetDatabase())
            {
                list = db.Lists.FirstOrDefault(l => l.Name == id);
            }
            if (list == null)
            {
                return(NotFound());
            }
            model.MailList = list;
            model.ListName = model.MailList.Name;
            if (formFields.ContainsKey("TemplateName"))
            {
                model.TemplateName = formFields["TemplateName"];
            }
            string email = null;

            foreach (KeyValuePair <string, string> field in formFields)
            {
                if (field.Key.StartsWith("ff_"))
                {
                    string value = field.Value?.Trim();
                    string name  = field.Key.Split('_')[1];
                    if (string.IsNullOrWhiteSpace(value))
                    {
                        if (field.Key.EndsWith("_optional", StringComparison.OrdinalIgnoreCase))
                        {
                            model.Fields[name] = string.Empty;
                        }
                        else
                        {
                            model.Message += "<br/>" + field.Key.Split('_')[1] + " is required";
                            model.Error    = true;
                        }
                    }
                    else if (name.Contains("email", StringComparison.OrdinalIgnoreCase))
                    {
                        if (value.TryParseEmailAddress(out _))
                        {
                            email = (email ?? value);
                            model.EmailAddress = email;
                        }
                        else
                        {
                            model.Error = true;
                        }
                    }
                    else
                    {
                        model.Fields[name] = value;
                    }
                }
            }
            model.EmailAddressDomain = model.GetDomainFromEmailAddress();
            TempData["result"]       = JsonConvert.SerializeObject(model);
            if (model.Error || email == null)
            {
                if (email == null)
                {
                    model.Error    = true;
                    model.Message += "<br/>" + Resources.EmailIsInvalid;
                }
                return(View(nameof(SubscribeInitial), model));
            }
            else
            {
                try
                {
                    model.IPAddress = HttpContext.GetRemoteIPAddress().ToString();
                    using (MailDemonDatabase db = dbProvider.GetDatabase())
                    {
                        if (!db.PreSubscribeToMailingList(ref model))
                        {
                            throw new InvalidOperationException(Resources.AlreadySubscribed.FormatHtml(id));
                        }
                    }
                    string url = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}/{nameof(SubscribeWelcome)}/{id}?token={model.SubscribeToken}";
                    model.SubscribeUrl = url;
                    string templateFullName = MailTemplate.GetFullTemplateName(id, MailTemplate.NameSubscribeConfirm);
                    await SendMailAsync(model, templateFullName);

                    return(RedirectToAction(nameof(SubscribeConfirm), new { id = model.ListName }));
                }
                catch (Exception ex)
                {
                    MailDemonLog.Error(ex);
                    model.Error    = true;
                    model.Message += "<br/>" + ex.Message;
                    return(View(nameof(SubscribeInitial), model));
                }
            }
        }