npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

parse-server-api-mail-adapter

v4.1.0

Published

Universal Mail Adapter for Parse Server, supports any email provider REST API, with localization and templates.

Downloads

44,996

Readme

Parse Server API Mail Adapter

Build Status Snyk Badge Coverage auto-release

Node Version

npm latest version


The Parse Server API Mail Adapter enables Parse Server to send emails using any 3rd party API with built-in dynamic templates and localization.

Transfer

ℹ️ This repository has been transferred to the Parse Platform Organization on May 15, 2022. Please update any links that you may have to this repository, for example if you cloned or forked this repository and maintain a remote link to this original repository, or if you are referencing a GitHub commit directly as your dependency.


Content

Installation

  1. Install adapter:
    npm install --save parse-server-api-mail-adapter
  2. Add template files to a subdirectory.
  3. Add adapter configuration to Parse Server.

Demo

The demo script makes it easy to test adapter configurations and templates by sending emails without Parse Server via the email service provider Mailgun:

  1. Create a file mailgun.json in the demo directory with the following content:
    {
        "key": "MAILGUN_API_KEY", // e.g. abc123
        "domain": "MAILGUN_DOMAIN", // e.g. [email protected]
        "sender": "SENDER_EMAIL", // e.g. [email protected]
        "recipient": "RECIPIENT_EMAIL" // e.g. [email protected]
    }
  2. Run node ./demo to execute the script and send an email.

You can modify the script to use any other API you like or debug-step through the sending process to better understand the adapter internals.

Configuration

An example configuration to add the API Mail Adapter to Parse Server could look like this:

const Mailgun = require('mailgun.js');
const formData = require('form-data');
const { ApiPayloadConverter } = require('parse-server-api-mail-adapter');

// Configure mail client
const mailgun = new Mailgun(formData);
const mailgunClient = mailgun.client({ username: 'api', key: process.env.MAILGUN_API_KEY });
const mailgunDomain = process.env.MAILGUN_DOMAIN;

// Configure Parse Server
const server = new ParseServer({
    ...otherServerOptions,

    emailAdapter: {
        module: 'parse-server-api-mail-adapter',
        options: {
            // The email address from which emails are sent.
            sender: '[email protected]',
            // The email templates.
            templates: {
                // The template used by Parse Server to send an email for password
                // reset; this is a reserved template name.
                passwordResetEmail: {
                    subjectPath: './files/password_reset_email_subject.txt',
                    textPath: './files/password_reset_email.txt',
                    htmlPath: './files/password_reset_email.html'
                },
                // The template used by Parse Server to send an email for email
                // address verification; this is a reserved template name.
                verificationEmail: {
                    subjectPath: './files/verification_email_subject.txt',
                    textPath: './files/verification_email.txt',
                    htmlPath: './files/verification_email.html'
                },
                // A custom email template that can be used when sending emails
                // from Cloud Code; the template name can be chosen freely; it
                // is possible to add various custom templates.
                customEmail: {
                    subjectPath: './files/custom_email_subject.txt',
                    textPath: './files/custom_email.txt',
                    htmlPath: './files/custom_email.html',
                    // Placeholders are filled into the template file contents.
                    // For example, the placeholder `{{appName}}` in the email
                    // will be replaced the value defined here.
                    placeholders: {
                        appName: "ExampleApp"
                    },
                    // Extras to add to the email payload that is accessible in the
                    // `apiCallback`.
                    extra: {
                        replyTo: '[email protected]'
                    },
                    // A callback that makes the Parse User accessible and allows
                    // to return user-customized placeholders that will override
                    // the default template placeholders. It also makes the user
                    // locale accessible, if it was returned by the `localeCallback`,
                    // and the current placeholders that will be augmented.
                    placeholderCallback: async ({ user, locale, placeholders }) => {
                        return {
                            phone: user.get('phone');
                        };
                    },
                    // A callback that makes the Parse User accessible and allows
                    // to return the locale of the user for template localization.
                    localeCallback: async (user) => {
                        return user.get('locale');
                    }
                }
            },
            // The asynchronous callback that contains the composed email payload to
            // be passed on to an 3rd party API and optional meta data. The payload
            // may need to be converted specifically for the API; conversion for
            // common APIs is conveniently available in the `ApiPayloadConverter`.
            // Below is an example for the Mailgun client.
            apiCallback: async ({ payload, locale }) => {
                const mailgunPayload = ApiPayloadConverter.mailgun(payload);
                await mailgunClient.messages.create(mailgunDomain, mailgunPayload);
            }
        }
    }
});

Templates

Emails are composed using templates. A template defines the paths to its content files, for example:

templates: {
    exampleTemplate: {
        subjectPath: './files/custom_email_subject.txt',
        textPath: './files/custom_email.txt',
        htmlPath: './files/custom_email.html',
    }
},

There are different files for different parts of the email:

  • subject (subjectPath)
  • plain-text content (textPath)
  • HTML content (htmlPath)

See the templates for examples how placeholders can be used.

Placeholders

Placeholders allow to dynamically insert text into the template content. The placeholder values are filled in according to the key-value definitions returned by the placeholder callback in the adapter configuration.

This is using the mustache template syntax. The most commonly used tags are:

  • {{double-mustache}}: The most basic form of tag; inserts text as HTML escaped by default.
  • {{{triple-mustache}}}: Inserts text with unescaped HTML, which is required to insert a URL for example.

Password Reset and Email Verification

By default, the following placeholders are available in the password reset and email verification templates:

  • {{appName}}: The app name as set in the Parse Server configuration.
  • {{username}}: The username of the user who requested the email.
  • {{link}}: The URL to the Parse Server endpoint for password reset or email verification.

Localization

Localization allows to use a specific template depending on the user locale. To turn on localization for a template, add a localeCallback to the template configuration.

The locale returned by localeCallback will be used to look for locale-specific template files. If the callback returns an invalid locale or nothing at all (undefined), localization will be ignored and the default files will be used.

The locale-specific files are placed in sub-folders with the name of either the whole locale (e.g. de-AT), or only the language (e.g. de). The locale has to be in format [language]-[country] as specified in IETF BCP 47, e.g. de-AT.

Localized files are placed in sub-folders of the given path, for example:

base/
├── example.html         // default file
└── de/                  // de language folder
│   └── example.html     // de localized file
└── de-AT/               // de-AT locale folder
│   └── example.html     // de-AT localized file

Files are matched with the user locale in the following order:

  1. Locale (locale de-AT matches file in folder de-AT)
  2. Language (locale de-AT matches file in folder de if there is no file in folder de-AT)
  3. Default (default file in base folder is returned if there is no file in folders de-AT and de)

Cloud Code

Sending an email directly from Cloud Code is possible since Parse Server > 4.5.0. This adapter supports this convenience method.

Example

If the user provided has an email address set, it is not necessary to set a recipient because the mail adapter will by default use the mail address of the user.

Parse.Cloud.sendEmail({
  templateName: "next_level_email",
  placeholders: { gameScore: 100, nextLevel: 2 },
  user: parseUser // user with email address
});

Parameters

| Parameter | Type | Optional | Default Value | Example Value | Description | |----------------|--------------|----------|---------------|-----------------------------|------------------------------------------------------------------------------------------------| | sender | String | | - | [email protected] | The email sender address; overrides the sender address specified in the adapter configuration. | | recipient | String | | - | [email protected] | The email recipient; if set overrides the email address of the user. | | subject | String | | - | Welcome | The email subject. | | text | String | | - | Thank you for signing up! | The plain-text email content. | | html | String | yes | undefined | <html>...</html> | The HTML email content. | | templateName | String | yes | undefined | customTemplate | The template name. | | placeholders | Object | yes | {} | { key: value } | The template placeholders. | | extra | Object | yes | {} | { key: value } | Any additional variables to pass to the mail provider API. | | user | Parse.User | yes | undefined | - | The Parse User that the is the recipient of the email. |

Supported APIs

This adapter supports any REST API by adapting the API payload in the adapter configuration apiCallback according to the API specification.

Providers

For convenience, support for common APIs is already built into this adapter and available via the ApiPayloadConverter. The following is a list of currently supported API providers:

If the provider you are using is not already supported, please feel free to open a PR.

Example for Mailgun

This is an example for the Mailgun client:

// Configure mail client
const mailgun = require('mailgun.js');
const mailgunClient = mailgun.client({ username: 'api', key: process.env.MAILGUN_API_KEY });
const mailgunDomain = process.env.MAILGUN_DOMAIN;

// Configure Parse Server
const server = new ParseServer({
    ...otherServerOptions,

    emailAdapter: {
        module: 'parse-server-api-mail-adapter',
        options: {
            ... otherAdapterOptions,

            apiCallback: async ({ payload, locale }) => {
                const mailgunPayload = ApiPayloadConverter.mailgun(payload);
                await mailgunClient.messages.create(mailgunDomain, mailgunPayload);
            }
        }
    }
});

Example for AWS Simple Email Service

This is an example for the AWS Simple Email Service client using the AWS JavaScript SDK v3:

// Configure mail client
const { SES, SendEmailCommand } = require('@aws-sdk/client-ses');

const {
  fromInstanceMetadata, // Get credentials via IMDS from the AWS instance (when deployed on AWS instance)
  fromEnv, // Get AWS credentials from environment variables (when testing locally)
} = require('@aws-sdk/credential-providers');

// Get AWS credentials depending on environment
const credentialProvider= process.env.NODE_ENV == 'production' ? fromInstanceMetadata() : fromEnv();
const credentials = await credentialProvider();

const sesClient = new SES({
    credentials,
    region: 'eu-west-1',
    apiVersion: '2010-12-01'
});

// Configure Parse Server
const server = new ParseServer({
    ...otherServerOptions,

    emailAdapter: {
        module: 'parse-server-api-mail-adapter',
        options: {
            ... otherAdapterOptions,

            apiCallback: async ({ payload, locale }) => {
                const awsSesPayload = ApiPayloadConverter.awsSes(payload);
                const command = new SendEmailCommand(awsSesPayload);
                await sesClient.send(command);
            }
        }
    }
});

Example for ZeptoMail Service

This is an example for the ZeptoMail Service client using the ZeptoMail JavaScript SDK. Provide comma separated email adddresses in recepient parameter to send to multiple.

// Configure mail client
var { SendMailClient } = require('zeptomail');

const url = process.env.ZEPTOMAIL_URL;
const token = process.env.ZEPTOMAIL_TOKEN;
const zeptoMaiClient = new SendMailClient({ url, token });


// Configure Parse Server
const server = new ParseServer({
    ...otherServerOptions,

    emailAdapter: {
        module: 'parse-server-api-mail-adapter',
        options: {
            ... otherAdapterOptions,

            apiCallback: async ({ payload, locale }) => {
                const zeptoMailPayload = ApiPayloadConverter.zeptomail({ api: '1.1', payload });
                await zeptoMaiClient.sendMail(zeptoMailPayload);
            },
        }
    }
});

Custom API

This is an example of how the API payload can be adapted in the adapter configuration apiCallback according to a custom email provider's API specification.

// Configure mail client
const customMail = require('customMail.js');
const customMailClient = customMail.configure({ ... });

// Configure Parse Server
const server = new ParseServer({
    ...otherOptions,

    emailAdapter: {
        module: 'parse-server-api-mail-adapter',
        options: {
            ... otherOptions,

            apiCallback: async ({ payload, locale }) => {
                const customPayload = {
                    customFrom: payload.from,
                    customTo: payload.to,
                    customSubject: payload.subject,
                    customText: payload.text
                };
                await customMailClient.sendEmail(customPayload);
            }
        }
    }
});

Need help?

  • Ask on StackOverflow using the parse-server tag.
  • Search through existing issues or open a new issue.