/// <summary>
        /// Gets the pages due to expire in the next <c>inTheNextHowManyDays</c> days, collated by the users responsible for the pages.
        /// </summary>
        /// <param name="inTheNextHowManyDays">The date range to look for expiring pages, based on the number of days from today.</param>
        /// <returns></returns>
        /// <exception cref="WebException"></exception>
        public async Task <IList <UmbracoPagesForUser> > GetExpiringPagesByUser(int inTheNextHowManyDays)
        {
            var url      = _client.BaseAddress + string.Format("CheckForExpiringPages?inTheNextHowManyDays={0}", inTheNextHowManyDays);
            var response = await _client.GetAsync(url);

            if (!response.IsSuccessStatusCode)
            {
                throw new WebException(((int)response.StatusCode).ToString(CultureInfo.InvariantCulture) + $" {response.ReasonPhrase} requesting {url}");
            }
            var pages = await response.Content.ReadAsAsync <IEnumerable <UmbracoPage> >();

            // For each page:
            var allUsersWithPages = new Dictionary <int, UmbracoPagesForUser>();

            // Create a admin account record. Use -1 as an Id as there won't be a valid Umbraco user with that value.
            var admin = new UmbracoPagesForUser()
            {
                User = new UmbracoUser
                {
                    Id    = -1,
                    Email = ConfigurationManager.AppSettings["AdminEmail"]
                }
            };

            allUsersWithPages.Add(admin.User.Id, admin);

            foreach (var userPage in pages)
            {
                url      = _client.BaseAddress + string.Format("GroupsWithPermissionsForPage?pageId={0}", userPage.PageId);
                response = await _client.GetAsync(url);

                if (!response.IsSuccessStatusCode)
                {
                    throw new WebException(((int)response.StatusCode).ToString(CultureInfo.InvariantCulture) + $" {response.ReasonPhrase} requesting {url}");
                }
                var groupsWithPermissionsForNode = await response.Content.ReadAsAsync <IEnumerable <int> >();

                var usersInGroups = new Dictionary <int, IList <UmbracoUser> >();

                // If there are no active users with permissions to the page, add the page to the admin list
                var pageHasActiveUserWithPermissions = false;
                foreach (var groupId in groupsWithPermissionsForNode)
                {
                    if (!usersInGroups.ContainsKey(groupId))
                    {
                        url      = _client.BaseAddress + string.Format("ActiveUsersInGroup?groupId={0}", groupId);
                        response = await _client.GetAsync(url);

                        if (!response.IsSuccessStatusCode)
                        {
                            throw new WebException(((int)response.StatusCode).ToString(CultureInfo.InvariantCulture) + $" {response.ReasonPhrase} requesting {url}");
                        }
                        usersInGroups[groupId] = await response.Content.ReadAsAsync <IList <UmbracoUser> >();
                    }
                    pageHasActiveUserWithPermissions = (pageHasActiveUserWithPermissions || usersInGroups[groupId].Count > 0);
                }
                if (!pageHasActiveUserWithPermissions)
                {
                    admin.Pages.Add(userPage);
                    continue;
                }

                // Add the current page to each user that has edit rights
                foreach (var groupId in groupsWithPermissionsForNode)
                {
                    foreach (var user in usersInGroups[groupId])
                    {
                        // Create a User record if one does not yet exist
                        if (!allUsersWithPages.ContainsKey(user.Id))
                        {
                            var pagesForUser = new UmbracoPagesForUser
                            {
                                User = user
                            };
                            allUsersWithPages.Add(user.Id, pagesForUser);
                        }

                        // Assign the current page to this author, unless they already have it
                        // through their membership of another group.
                        if (!allUsersWithPages[user.Id].Pages.Any(page => page.PageId == userPage.PageId))
                        {
                            allUsersWithPages[user.Id].Pages.Add(userPage);
                        }
                    }
                }
            }

            // Return a list of users responsible, along with the page details
            return(allUsersWithPages.Values.ToList());
        }
        /// <summary>
        /// Send expiry warning emails to users (Web Authors) of pages about to expire
        /// </summary>
        /// <param name="emailTo">
        /// who to send the email to
        /// </param>
        /// <param name="userPages">
        /// User details and list of expiring pages for this user
        /// </param>
        public string UserPageExpiryEmail(UmbracoPagesForUser userPages)
        {
            foreach (var item in userPages.Pages)
            {
                if (item.PageUrl == null || item.PageUrl == "#")
                {
                    item.PageUrl = "This page is not visible on the live site.";
                }
            }

            var subject = string.Format("ACTION: Your {0} pages expire in under 14 days", _websiteName);
            var body    = new StringBuilder();

            body.AppendFormatLine("<p>Your {0} pages will expire within the next two weeks. After this they will no longer be available to the public. The dates for each page are given below.</p>", _websiteName);
            body.AppendLine("<p>After you’ve logged in, click on each page below and:</p>");
            body.AppendLine("<ul>");
            body.AppendLine("<li>check they are up to date</li>");
            body.AppendLine("<li>check the information is still needed</li>");
            body.AppendLine("<li>go to Info tab and set a new 'Unpublish at' date in the 'Scheduled Publishing' box</li>");
            body.AppendLine("<li>then click 'Save and publish'.</li>");
            body.AppendLine("</ul>");
            body.AppendLine("<p>For details on updating your pages, see <a href=\"" + _webAuthorGuidanceUrl + "\">Guidance for web authors</a>.</p>");

            var otherTitle       = "Expiring Pages:";
            var warningDate      = DateTime.Now.AddDays(2);
            var lastWarningPages = userPages.Pages.Where(d => d.ExpiryDate <= warningDate).ToList();

            if (lastWarningPages.Any())
            {
                body.AppendLine("<strong>Pages Expiring Tomorrow:</strong>");
                body.AppendLine("<ol>");
                foreach (var page in lastWarningPages)
                {
                    var linkUrl = string.Format("{0}#/content/content/edit/{1}", _websiteUrl, page.PageId);
                    body.Append("<li>");
                    body.AppendFormat("<a href=\"{0}\">{1}</a> (expires {2}, {3})", linkUrl, page.PageName, page.ExpiryDate.Value.ToLongDateString(), page.ExpiryDate.Value.ToShortTimeString());
                    body.AppendFormat("<br/>{0}", page.PageUrl);
                    body.Append("</li>");
                }
                body.AppendLine("</ol>");

                otherTitle = "Other Pages:";
            }

            // Process remaining pages
            var nonWarningPages = userPages.Pages.Where(d => d.ExpiryDate > warningDate).ToList();

            if (nonWarningPages.Any())
            {
                body.AppendFormatLine("<strong>{0}</strong>", otherTitle);
                body.AppendLine("<ol>");
                foreach (var page in nonWarningPages)
                {
                    var linkUrl = string.Format("{0}#/content/content/edit/{1}", _websiteUrl, page.PageId);
                    body.Append("<li>");
                    body.AppendFormat("<a href=\"{0}\">{1}</a> (expires {2}, {3})", linkUrl, page.PageName, page.ExpiryDate.Value.ToLongDateString(), page.ExpiryDate.Value.ToShortTimeString());
                    body.AppendFormat("<br/>{0}", page.PageUrl);
                    body.Append("</li>");
                }
                body.AppendLine("</ol>");
            }

            var neverExpiringPages = userPages.Pages.Where(d => d.ExpiryDate == null).ToList();

            if (neverExpiringPages.Any() && (nonWarningPages.Any() || lastWarningPages.Any()))
            {
                body.AppendLine("<strong>Pages Never Expiring:</strong>");
                body.AppendLine("<p>As these pages never expire, its important to check them periodically.<p>");
                body.AppendLine("<p>After you’ve logged in, click on each page below and:</p>");
                body.AppendLine("<ul>");
                body.AppendLine("<li>check they are up to date</li>");
                body.AppendLine("<li>check the information is still needed</li>");
                body.AppendLine("<li>then click 'Save and publish'.</li>");
                body.AppendLine("</ul>");
                body.AppendLine("<p>You don't need to worry about setting any dates</p>");
                body.AppendLine("<ol>");
                foreach (var page in neverExpiringPages)
                {
                    var linkUrl = string.Format("{0}#/content/content/edit/{1}", _websiteUrl, page.PageId);
                    body.Append("<li>");
                    body.AppendFormat("<a href=\"{0}\">{1}</a>", linkUrl, page.PageName);
                    body.AppendFormat("<br/>{0}", page.PageUrl);
                    body.Append("</li>");
                }
                body.AppendLine("</ol>");
            }
            if (lastWarningPages.Any() || nonWarningPages.Any())
            {
                var emailTo = userPages.User.Email;

                // If "ForceEmailTo" is set, send all emails there instead (for Testing)
                if (!string.IsNullOrEmpty(_forceSendTo))
                {
                    emailTo = _forceSendTo;
                }

                SmtpSendEmail(emailTo, subject, body.ToString());

                return(emailTo);
            }
            return(null);
        }