# EmailSender extensibility

### What this is

Use this extensibility point when you want The Wallet Crew to send emails through a provider you control. This is a script-level integration. It lets you keep Wallet Crew templates and rendering logic, while delegating the final “send” to your own API calls.

This design separates rendering from delivery. That makes your email layer easier to test and easier to swap. It also keeps culture handling explicit, because the caller decides which cultures exist and how templates are resolved.

### How `SendEmail` works

The platform calls `runtime.scriptable.emailEngine.SendEmail` when it needs to send an email and the email provider is set to `script`. The function receives the recipient address, the template name, a data payload, and the list of supported cultures.

The last parameter, `buildEmail`, is a callback supplied by the platform. Your provider calls it to obtain the final rendered content. That callback returns an object with a `Subject` and a `Body`. Once you have that payload, your script is responsible for sending it.

### Reference implementation (signature)

```js
/**
 * @typedef {Object} EmailData
 * @property {string} Subject - Rendered subject line.
 * @property {string} Body - Rendered body content.
 */

/**
 * Send an email using the provided template name and data.
 * The caller supplies the supported cultures and a callback
 * to build the rendered email content.
 *
 * @param {string} recipient - Target email address.
 * @param {string} emailTemplate - Template name to render.
 * @param {Object.<string, any>} data - Template data passed to the script.
 * @param {string[]} cultures - Available culture names from the culture provider.
 * @param {(templateName: string) => Promise<EmailData>} buildEmail
 * Callback that returns the final rendered email content.
 *
 * @returns {Promise<void>}
 */
async function sendEmail(recipient, emailTemplate, data, cultures, buildEmail){
   // call any API to send email
}

export default function(context) {
  context.register('runtime.scriptable.emailEngine', {
    SendEmail: sendEmail 
  })
}
```

### Enable the script email provider

Switching to the script email provider is a configuration change. It tells The Wallet Crew to call your `SendEmail` implementation for outgoing emails.

{% stepper %}
{% step %}

#### Edit `/server/emails.yml`

Open the advanced configuration editor, then create or edit `/server/emails.yml`. Set the provider type to `script`. Keep `resources` pointing to your email template directory.
{% endstep %}
{% endstepper %}

```yaml
provider:
  type: script
resources:
  - /locales/emails/

```

### Template and culture notes

Email templates are loaded from the paths listed under `resources`. Keep this aligned with where your HTML templates live, because the rendering callback uses those templates.

Culture handling is part of the contract. The platform passes a `cultures` array, but your provider decides how to use it. In practice, most setups either pick a single culture per recipient or fall back to a default culture when no specific template exists.

### Troubleshooting

If emails stop sending after enabling the script provider, start by confirming that `/server/emails.yml` is valid YAML and saved in the right tenant. Then confirm your script is actually registered under `runtime.scriptable.emailEngine` and exports `SendEmail`.

If you see provider-side errors, log the template name and culture choices, but avoid logging full rendered bodies. Email content can contain personal data.

### FAQ

<details>

<summary><strong>Is this a public HTTP endpoint?</strong></summary>

No. This page documents a script runtime interface that your tenant script implements. If you want to call an external HTTP API, you do it from inside `SendEmail`.

</details>

<details>

<summary><strong>Where do email templates live?</strong></summary>

They live under the directories listed in `resources`. By default, this points to `/locales/emails/`.

</details>

<details>

<summary><strong>Can we mix a script provider with SendGrid or Mailchimp?</strong></summary>

Not at the same time for a given tenant. The active provider is selected in `/server/emails.yml`.

</details>

<details>

<summary><strong>What should we return from <code>SendEmail</code>?</strong></summary>

Return normally when the email is accepted by your provider. Throw an error when sending fails, so the platform can surface it.

</details>

<details>

<summary><strong>What’s the fastest way to validate the setup?</strong></summary>

Enable the `script` provider, trigger a single transactional email, then check your provider logs for the send event.

</details>
