DEV Community

Cover image for A simple send umbraco page as test mail content app
Tim Geyssens
Tim Geyssens

Posted on

4 3

A simple send umbraco page as test mail content app

Content Apps are companions to the editing experience when working with content or media in the Umbraco backoffice.

So unlike prop editors they don't store any data against the current document.

A usecase I recently encountered was the ability to generate newsletters from Umbraco and send them with a third party tool (so import the outputted html with a mailing service like mailchimp).

But the editors also wanted the ability to first send a single test mail from within Umbraco before migrating the markup.

Send test email

The solution consists of an API Controller that fetches the rendered output and sends that as an email.



using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Core.Logging;
using Umbraco.Web.WebApi;
using Umbraco.Web;
using Umbraco.Core.Models.PublishedContent;
using System.Web.Http;

namespace Acme.Core.Controllers.API
{
    public class NewsLetterController : UmbracoAuthorizedApiController
    {
        private readonly ILogger _logger;
        private readonly IProfilingLogger _profilingLogger;
        public NewsLetterController(ILogger logger, IProfilingLogger profilingLogger)
        {

            this._logger = logger;
            this._profilingLogger = profilingLogger;
        }

        [HttpGet]
        public bool SendTestMail(int newsletterId, string email)
        {
            var doc = this.Umbraco.Content(newsletterId);

            if (doc != null)
            {
                string markup = string.Empty;

                if (this.GetHtmlByUrl(doc.Url(mode: UrlMode.Absolute), out markup))
                {
                    var message = new MailMessage("noreply@acme.com", email);
                    message.Subject = doc.Name;
                    message.Body = markup;
                    message.IsBodyHtml = true;
                    var client = new SmtpClient();
                    client.Send(message);

                    return true;
                }
            }

            return false;
        }

        private bool GetHtmlByUrl(string url, out string fullHtml)
        {
            using (this._profilingLogger.DebugDuration<NewsLetterController>("GetHtmlByUrl(" + url + ")", "GetHtmlByUrl(" + url + ") done"))
            {

                if (!Uri.TryCreate(url, UriKind.Absolute, out Uri uri))
                {
                    fullHtml = "";
                    return false;
                }

                try
                {
                    var httpTimeout = 1000;

                    var cookieDictionary = new Dictionary<string, string>();
                    var webRequest = (HttpWebRequest)WebRequest.Create(uri);
                    httpTimeout *= 1000;
                    webRequest.Timeout = httpTimeout;
                    webRequest.UserAgent = "NewsLetterController";

                    if (cookieDictionary != null && cookieDictionary.Count > 0)
                    {
                        var container = new CookieContainer();
                        var domain = webRequest.Address.DnsSafeHost;
                        foreach (var cookie in cookieDictionary)
                        {
                            container.Add(new Cookie(cookie.Key, cookie.Value, "/", domain));
                        }

                        webRequest.CookieContainer = container;
                    }

                    var webResponse = (HttpWebResponse)webRequest.GetResponse();
                    using (var sr = new StreamReader(webResponse.GetResponseStream()))
                    {
                        fullHtml = sr.ReadToEnd();
                    }

                    return true;
                }
                catch (WebException ex)
                {
                    this._logger.Error<NewsLetterController>(ex, $"Error in NewsLetterController retrieval. Url: {url}");
                    fullHtml = string.Empty;
                }

                return false;
            }
        }
    }
}



Enter fullscreen mode Exit fullscreen mode

And the actual content app, that outputs a text input and a submit button.

View



<div ng-controller="Custom.SendPageAsMail as vm">
  <umb-box>
    <umb-box-header title="Send test mail"></umb-box-header>
    <umb-box-content>
      <input type="text" ng-model="vm.emailAddress" class="umb-property-editor umb-textstring textstring" required no-dirty-check />
      <a class="control__button btn">
        <i class="icon icon-message" ng-click="sendTestMail()">Send</i>
      </a>
    </umb-box-content>
  </umb-box>
</div>



Enter fullscreen mode Exit fullscreen mode

Controller (also populates the input with current user email)



angular.module("umbraco")
    .controller("Custom.SendPageAsMail", function ($scope, editorState, $http, userService) {
        var vm = this;
        vm.CurrentNodeId = editorState.current.id;
        vm.emailAddress = "";

        function _sendTestMail() {

            $http.get('/Umbraco/backoffice/Api/NewsLetter/SendTestMail?newsletterId=' + vm.CurrentNodeId + '&email=' + vm.emailAddress).then(function (response) {

            });


        }

        function _init() {

            $scope.sendTestMail = _sendTestMail;

            userService.getCurrentUser().then(function (user) {
                vm.emailAddress = user.email;
            });
        }

        _init();



});



Enter fullscreen mode Exit fullscreen mode

Package manifest



{

    "contentApps": [
    {
        "name": "Send testmail", 
        "alias": "sendpageasmail", 
        "weight": 0, 
        "icon": "icon-message",
        "view": "~/App_Plugins/SendPageAsMail/SendPageAsMail.html",
        "show": [

            "+content/newsLetter",
            "+contentType/newsLetter"
        ]

    }
    ],

    "javascript": [
        "~/App_Plugins/SendPageAsMail/SendPageAsMail.controller.js"
    ]
}



Enter fullscreen mode Exit fullscreen mode

AWS GenAI LIVE image

How is generative AI increasing efficiency?

Join AWS GenAI LIVE! to find out how gen AI is reshaping productivity, streamlining processes, and driving innovation.

Learn more

Top comments (0)

Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

Rather than just generating snippets, our agents understand your entire project context, can make decisions, use tools, and carry out tasks autonomously.

Read full post

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay