Blazor (Wasm) – How to Send Email from a PWA

Recently, I was tasked with developing a simple Xamarin mobile application to collect user form inputs, perform calculations on that input, and generate output that could be emailed. Our client was on a budget and, with such basic requirements, jumping through all the app store hoops seemed like overkill for this project. I decided to do a proof-of-concept using a Blazor (Wasm) Progressive Web App (PWA). One risk area I identified for this architecture was the send email requirement.

Normally, I prefer to implement pre-existing email components that have some level of built-in template support, such as FluentEmail. If you have serious email needs, be sure to check out Tim Corey’s Sending Email in C# using FluentEmail video. It will help you get up and running quickly. That approach, unfortunately, would not work for my requirements given the client-side nature of Blazor WebAssembly. The reason is that a Blazor PWA is sandboxed to its browser platform such that sending email is not supported. Attempting to use classes such as SmtpClient should result in a compiler warning/error and, if ignored, will result in a System.PlatformNotSupportedException as described in this SO question: ‘Blazor Wasm sending mail throw exception‘. So, how did I get around this limitation?

Well, the answer for very basic email needs is to leverage the old-school technique of using “mailto:” anchor links combined with injecting Blazor’s IJSRuntime. I say “basic email” because this technique uses the query string and the MAILTO function. That means it has a limit of around 2000 characters and exceeding this limit may prevent the message from being opened in the user’s default mail app. If you can live with that limitation, then here is how you can make it work. From a button click or other trigger, invoke a function in your view model (or c# code):

protected void SendLocalEmail(string toEmailAddress, string subject, string body)
{
      JsRuntime.InvokeAsync<object>("blazorExtensions.SendLocalEmail",
      new object[] { toEmailAddress, subject, body });
}

Then, in your wwwroot folder, you should have a corresponding .js file (i.e. GlobalFunctions.js) that contains the corresponding JavaScript SendLocalEmail() function such as:

window.blazorExtensions = {
  SendLocalEmail: function (mailto, subject, body) {
    var link = document.createElement('a');
    var uri = "mailto:" + mailto + "?";
    if (!isEmpty(subject)) {
        uri = uri + "subject=" + subject;
    }

    if (!isEmpty(body)) {
        if (!isEmpty(subject)) { // We already appended one querystring parameter, add the '&' separator
            uri = uri + "&"
        }

        uri = uri + "body=" + body;
    }

    uri = encodeURI(uri);
    uri = uri.substring(0, 2000); // Avoid exceeding querystring limits.
    console.log('Clicking SendLocalEmail link:', uri);

    link.href = uri;
    document.body.appendChild(link); // Needed for Firefox
    link.click();
    document.body.removeChild(link);
  }
};

function isEmpty(str) {
  return (!str || str.length === 0);
}

Finally, be sure you include a reference to your .js file in the index.html file (also in the wwwroot folder):

<script src="GlobalFunctions.js"></script>

I place the above script reference below this line:

<script>navigator.serviceWorker.register('service-worker.js');</script>

Well, there you have it…this approach has been tested and works on desktop, Android, and iOS platforms. On the desktop platform, the default mail app is used. On mobile platforms, the user is given the choice of which email application should receive the email request.

Thanks for reading this post on how to Send Email from a Blazor (Wasm) PWA! Stay tuned for more posts!

Leave a Comment

Your email address will not be published. Required fields are marked *