|
| 1 | +# parse-server-api-mail-adapter |
| 2 | + |
| 3 | +[](https://badge.fury.io/js/parse-server-api-mail-adapter) |
| 4 | + |
| 5 | +The Parse Server API Mail Adapter enables Parse Server to send emails using any 3rd party API with built-in dynamic templates and localization. |
| 6 | + |
| 7 | + |
| 8 | +# Content |
| 9 | + |
| 10 | +- [Getting Started](#getting-started) |
| 11 | +- [Demo](#demo) |
| 12 | +- [Configuration](#configuration) |
| 13 | +- [Templates](#templates) |
| 14 | +- [Localization](#localization) |
| 15 | +- [Need help?](#need-help) |
| 16 | + |
| 17 | +# Getting Started |
| 18 | + |
| 19 | +1. Install adapter: |
| 20 | + ``` |
| 21 | + npm install --save parse-server-api-mail-adapter |
| 22 | + ``` |
| 23 | +2. Add [template files](#templates) to a subdirectory. |
| 24 | +2. Add [adapter configuration](#configuration) to Parse Server. |
| 25 | +
|
| 26 | +# Demo |
| 27 | +
|
| 28 | +The demo script makes it easy to test adapter configurations and templates by sending emails without Parse Server via the email service provider [Mailgun](https://www.mailgun.com): |
| 29 | +
|
| 30 | +1. Create a file `mailgun.json` in the `demo` directory with the following content: |
| 31 | + ```js |
| 32 | + { |
| 33 | + "key": "MAILGUN_API_KEY", // e.g. abc123 |
| 34 | + "domain": "MAILGUN_DOMAIN", // e.g. [email protected] |
| 35 | + "sender": "SENDER_EMAIL", // e.g. [email protected] |
| 36 | + "recipient": "RECIPIENT_EMAIL" // e.g. [email protected] |
| 37 | + } |
| 38 | + ``` |
| 39 | +2. Run `node ./demo` to execute the script and send an email. |
| 40 | +
|
| 41 | +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. |
| 42 | +
|
| 43 | +# Configuration |
| 44 | +
|
| 45 | +An example configuation to add the API Mail Adapter to Parse Server could look like this: |
| 46 | +
|
| 47 | +```js |
| 48 | +// Declare a mail client |
| 49 | +const mailgun = require('mailgun.js'); |
| 50 | +const mailgunClient = mailgun.client({ username: 'api', key: process.env.MAILGUN_API_KEY }); |
| 51 | +const mailgunDomain = process.env.MAILGUN_DOMAIN; |
| 52 | +
|
| 53 | +// Configure Parse Server |
| 54 | +const server = new ParseServer({ |
| 55 | + ...otherOptions, |
| 56 | +
|
| 57 | + emailAdapter: { |
| 58 | + module: 'parse-server-api-mail-adapter', |
| 59 | + options: { |
| 60 | + // The email address from which email are sent. |
| 61 | + |
| 62 | + // The email templates. |
| 63 | + templates: { |
| 64 | + // The template used by Parse Server to send an email for password reset; this is a reserved template name. |
| 65 | + passwordResetEmail: { |
| 66 | + subjectPath: './files/password_reset_email_subject.txt'), |
| 67 | + textPath: './files/password_reset_email.txt'), |
| 68 | + htmlPath: './files/password_reset_email.html') |
| 69 | + }, |
| 70 | + // The template used by Parse Server to send an email for email address verification; this is a reserved template name. |
| 71 | + verificationEmail: { |
| 72 | + subjectPath: './files/verification_email_subject.txt'), |
| 73 | + textPath: './files/verification_email.txt'), |
| 74 | + htmlPath: './files/verification_email.html') |
| 75 | + }, |
| 76 | + // A custom email template that can be used when sending emails from Cloud Code; the template name can be choosen freely; it is possible to add various custom templates. |
| 77 | + customEmail: { |
| 78 | + subjectPath: './files/custom_email_subject.txt'), |
| 79 | + textPath: './files/custom_email.txt'), |
| 80 | + htmlPath: './files/custom_email.html'), |
| 81 | + // Placeholders contain the values to be filled into the placeholder keys in the file content. A placeholder `{{appName}}` in the email will be replaced the value defined here. |
| 82 | + placeholders: { |
| 83 | + appName: "ExampleApp" |
| 84 | + }, |
| 85 | + // Extras to add to the email payload that is accessible in the `apiCallback`. |
| 86 | + extra: { |
| 87 | + |
| 88 | + }, |
| 89 | + // A callback that makes the Parse User accessible and allows to return user-customized placeholders that will override the default template placeholders. |
| 90 | + placeholderCallback: async (user) => { |
| 91 | + return { |
| 92 | + phone: user.get('phone') |
| 93 | + }; |
| 94 | + }, |
| 95 | + // A callback that makes the Parse User accessible and allows to return the locale of the user for template localization. |
| 96 | + localeCallback: async (user) => { |
| 97 | + return user.get('locale'); |
| 98 | + }, |
| 99 | + // Is true if localization of template files should be enabled. |
| 100 | + enableLocalization: true |
| 101 | + } |
| 102 | + }, |
| 103 | + // The asynronous callback that contains the composed email payload to be passed on to an 3rd party API. The payload may need to be convert specifically for the API; conversion for common APIs is conveniently available in the `ApiPayloadConverter`. Below is an example for the Mailgun client. |
| 104 | + apiCallback: async (payload) => { |
| 105 | + const mailgunPayload = ApiPayloadConverter.mailgun(payload); |
| 106 | + await mailgunClient.messages.create(mailgunDomain, mailgunPayload); |
| 107 | + } |
| 108 | + } |
| 109 | + } |
| 110 | +}); |
| 111 | +``` |
| 112 | + |
| 113 | +## Templates |
| 114 | + |
| 115 | +Emails are composed using templates. A template defines the paths to its content files, for example: |
| 116 | + |
| 117 | +```js |
| 118 | +templates: { |
| 119 | + exampleTemplate: { |
| 120 | + subjectPath: './files/custom_email_subject.txt'), |
| 121 | + textPath: './files/custom_email.txt'), |
| 122 | + htmlPath: './files/custom_email.html'), |
| 123 | + } |
| 124 | +}, |
| 125 | +``` |
| 126 | + |
| 127 | +There are different files for different parts of the email: |
| 128 | +- subject (`subjectPath`) |
| 129 | +- plain-text content (`textPath`) |
| 130 | +- HTML content (`htmlPath`) |
| 131 | + |
| 132 | +# Localization |
| 133 | + |
| 134 | +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. |
| 135 | + |
| 136 | +The locale returned by `localeCallback` will be used to look for locale-specific template files. If the callback return an invalid locale or nothing at all (`undefined`), localization will be ignored and the default files will be used. |
| 137 | + |
| 138 | +The locale-specific files are placed in subfolders 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](https://tools.ietf.org/html/bcp47), e.g. `de-AT`. |
| 139 | + |
| 140 | +Localized files are placed in subfolders of the given path, for example: |
| 141 | +``` |
| 142 | +path/ |
| 143 | +├── example.html // default file |
| 144 | +└── de/ // de language folder |
| 145 | +│ └── example.html // de localized file |
| 146 | +└── de-AT/ // de-AT locale folder |
| 147 | +│ └── example.html // de-AT localized file |
| 148 | +```` |
| 149 | +
|
| 150 | +Files are matched with the user locale in the following order: |
| 151 | +1. Locale match, e.g. locale `de-AT` matches file in folder `de-AT`. |
| 152 | +2. Language match, e.g. locale `de-AT` matches file in folder `de`. |
| 153 | +3. Default match: file in base folder is returned. |
| 154 | +
|
| 155 | +# Need help? |
| 156 | +
|
| 157 | +- Search through existing issues or open a new issue. |
| 158 | +- Ask on StackOverflow using the tag `parse-server` and `api-mail-adapter`. |
0 commit comments