Docs > Framework >

Mail

This feature is demonstrated in the Cofoundry.Samples.Mail sample project.

Cofoundry includes a mail service abstraction that makes it easy to create and send email from anywhere in your application.

The default implementation simply writes out mail to text files to a directory for debugging purposes, but you can use plugins to change this behavior and scale your mail solution as your application demands it.

Currently Available Plugins:

Mail Templates

In order to send an email you first need to create a mail template. A mail template comprises of a .NET class implementing IMailTemplate and either an HTML view file or a plain text view file, or both.

Although most email recipients will be able to view HTML emails, it may be blocked or unreadable by some. A plain text email will have the best change of being delivered and read.

If you create both an HTML and plain text view file then a multi-part email will be sent, where the plain text version is only used as a fallback when the HTML version is not permitted. Using both is good practice and will ensure your email can be received and read by all recipients.

Here's an example of a multi-part email:

ExampleNotificationMailTemplate.cs

using Cofoundry.Core.Mail;

public class ExampleNotificationMailTemplate : IMailTemplate
{
    /// <summary>
    /// We need to specify the path and name of the mail template view
    /// file. The convention is to exclude the part of the file name 
    /// that indicates the template type and the file extension
    /// </summary>
    public string ViewFile => "~/Views/EmailTemplates/ExampleNotificationMailTemplate";
     
    /// <summary>
    /// All templates require a subject
    /// </summary>
    public string Subject => "New Contact Request";
     
    /// <summary>
    /// We can include any additional data that we
    /// want to render in the template file as properties
    /// in this class
    /// </summary>
    public string Message { get; set; } = string.Empty;
}

ExampleNotificationMailTemplate_html.cshtml

Note that the html template file should have the '_html' postfix

@model ExampleNotificationMailTemplate

@{
    Layout = "/Views/EmailTemplates/OptionalLayoutFile_html.cshtml";
}

<h2>Hi there</h2>

<p>
    @Model.Message 
</p>

<p>
    Thanks,<br />
    Cofoundry
</p>

ExampleNotificationMailTemplate_text.cshtml

Note that the plain text template file should have the '_text' postfix

@model ExampleNotificationMailTemplate

@{
    Layout = "/Views/EmailTemplates/OptionalLayoutFile_Text.cshtml";
}

Hi there

@Model.Message 

Thanks,
Cofoundry

Template Rendering

Templates are rendered using razor, and is done outside of the http request scope using a faked ViewContext. This provides the important benefit of being able to render razor templates outside of a web request, e.g. in a background task or external service. Most razor features should work, however be aware that anything that relies on an http request will fail.

You can customize the mail rending process by implementing IMailViewRenderer and overriding the base implementation using the DI system.

File Placement

Where you place your template files is up to you, but here's two suggested scenarios:

Simple

Place your IMailTemplate code files with your models or domain and place your template files in your views directory. For an example of this see Cofoundry.Samples.SimpleSite.

Or if you preferred to keep your files together, you could place them next to each other, as shown in the Cofoundry.Samples.Mail sample.

In a separate project

If you have a separate project for your domain or want to keep all your template classes and views together in one place you can do so, but to keep views in a separate assembly you'll need to mark them as embedded resources and you'll need to tell Cofoundry that you have embedded resources in your application by including a class that implements IAssemblyResourceRegistration. Cofoundry itself is a good example of this.

Sending Mail

Sending mail is pretty straightforward. Simply new up an instance of your template, populate the data and use IMailService to send it:

using Cofoundry.Core.Mail;

public class MailExample
{
    private readonly IMailService _mailService;

    public MailExample(IMailService mailService)
    {
        _mailService = mailService;
    }

    public Task SendMail()
    {
        var template = new ExampleNotificationMailTemplate
        {
            Message = "Wibble, wibble"
        };

        return _mailService.SendAsync("[email protected]", template);
    }
}

Note that by default SendMode setting is set to LocalDrop to prevent accidentally sending out emails when debugging. In a production scenario you'll want to change the setting to Send. I.e. in your production config:

{
  "Cofoundry": {
    "Mail": {
      "SendMode": "Send"
    }
  }
}

From Addresses

You can set the default from address using the Cofoundry:Mail:DefaultFromAddress setting in your config file.

Alternatively you can inherit from IMailTemplateWithCustomFromAddress in your template file to specify a custom from address rather than using the site-wide default.

MailSettings

The following mail settings are available:

  • Cofoundry:Mail:SendMode Indicates whether emails should be sent and how. Uses the MailSendMode enum (LocalDrop, Send, SendToDebugAddress, DoNotSend)
  • Cofoundry:Mail:DebugEmailAddress An email address to redirect all mail to when using MailSendMode.SendToDebugAddress
  • Cofoundry:Mail:DefaultFromAddress The default address to send emails
  • Cofoundry:Mail:DefaultFromAddressDisplayName Optionally the name to display with the default From Address
  • Cofoundry:Mail:MailDropDirectory The path to the folder to save mail to when using SendMode.LocalDrop. Defaults to ~/App_Data/Emails