Sending Emails
SocialStack aims to have one way of rendering content which is going out to end users by default; i.e. if someone is visiting via the web they'll see React components. If they see an email it's the same - the server renders React components into the email for them. So, creating an email is somewhat similar to creating a page - the only notable difference is it's done in the "Email Templates" section of the admin panel.
The components used need to be email friendly too. Most email clients don't currently support things like flexbox for example. Components in the Email/* group must always be email friendly; components in UI/* group may or may not be. It's suggested to copy the JSON of one of the default email templates as a starting point.
Email Key
Once you've created an email template, make sure you give it a key. This value is a textual ID for your template which you should avoid changing once created - that's because it is referenced from the codebase. It is typically in English, lowercase and contains underscores instead of spaces. This key is then what is used to send the email in the API, typically in an AfterCreate/ AfterUpdate/ time based event handler.
Sending a particular template
To send a template, use the EmailTemplateService.SendAsync method:
// To get a reference to the EmailTemplateService, either add it in to your service constructor like this:
// public MyService(EmailTemplateService emails)
// or you can use Services.Get<EmailTemplateService>() - Services is in the Api.Startup namespace.
User aUserObject; // The User you want to send the email to.
var recipients = new List<Recipient>();
recipients.Add(new Recipient(aUserObject)); // Add as many recipients as you'd like
await emails.SendAsync(
recipients,
"template_to_send" // The email template key goes here
);
If you don't need to wait for it to send, call SendAsync from within a _= Task.Run().
Custom Data
Firstly, an email can use Loop and Content. When this happens it is in the context of the user receiving the email and the locale used is based on the LocaleId of the User object. The email renderer does not actually send a request to "itself" - the code is short circuited to effectively directly mount the targeted API service.
Often though when you send an email it will contain some dynamic information - i.e. information which is specific to "this" email. For example in a password reset request, the email contains a URL with a token which is unique to the reset request. This is done by passing "Custom data" which is set per recipient, allowing each recipient to vary too.
EmailTemplateService emails; // Either via Services.Get<EmailTemplateService>() or pulled in by your service constructor (dependency injection)
User aUserObject; // The User you want to send the email to.
var recipients = new List<Recipient>();
var recipient = new Recipient(aUserObject);
recipient.CustomData = new { // This object must be JSON serialisable.
Token = "SomeMagicTokenValue",
Anything = 123123 // Add as many fields as you need.
};
recipients.Add(recipient); // Add as many recipients as you'd like
await emails.SendAsync(
recipients,
"template_to_send" // The email template key goes here
);
The custom data acts like the primary object on the page. This then means there are a few ways of accessing the values - for example, via Content:
import Content from 'UI/Content';
..
<Content primary>
{customData => {
return customData.token + ' is the token!';
}}
</Content>
Or, the more popular way in emails, with a token resolver:
import {useTokens} from 'UI/Token';
..
// Usually passed in as a prop allowing people to change or translate the sentence in the email editor
var inputTitle = 'The force is strong with tokens like ${customData.token}';
// useTokens will swap out the ${tokens} for their actual value.
var processedTitle = useTokens(inputTitle);
// We're inside a react render function:
return <h1>{processedTitle}</h1>;
Tokens are directly available as a feature from the editor as well, so you can use them with no code necessary. If you want to pass a potentially token containing, visually editable value into your component as a prop, simply specify a propType of "jsx" for the prop.