├── .gitignore ├── package.json ├── README.md └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .idea/ -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "parse-server-mandrill-adapter", 3 | "version": "1.2.1", 4 | "description": "Used to send Parse Server password reset and email verification emails through Mandrill, supporting templates.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/back4app/parse-server-mandrill-adapter.git" 12 | }, 13 | "keywords": [ 14 | "parse", 15 | "parse-server", 16 | "email-adapter", 17 | "mandrill", 18 | "back4app" 19 | ], 20 | "author": "Davi Macedo", 21 | "contributors": [ 22 | "Alvaro Larrosa " 23 | ], 24 | "bugs": { 25 | "url": "https://github.com/back4app/parse-server-mandrill-adapter/issues" 26 | }, 27 | "homepage": "https://github.com/back4app/parse-server-mandrill-adapter#readme", 28 | "dependencies": { 29 | "mandrill-api": "^1.0.45" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # parse-server-mandrill-adapter 2 | Used to send Parse Server password reset and email verification emails through Mandrill, supporting templates. 3 | 4 | How to install: 5 | ``` 6 | $ npm install parse-server-mandrill-adapter --save 7 | ``` 8 | 9 | How to use: 10 | ```javascript 11 | var server = ParseServer({ 12 | ... 13 | // App Name 14 | appName: 'YourAppName', 15 | // Environment where the user can confirm his e-mail address or reset his password (most likely the same as your 'serverURL') 16 | publicServerURL: 'YourPublicServerURL', 17 | emailAdapter: { 18 | module: 'parse-server-mandrill-adapter', 19 | options: { 20 | // API key from Mandrill account 21 | apiKey: 'API-KEY', 22 | // From email address 23 | fromEmail: 'no-reply@yourdomain.com', 24 | // Display name 25 | displayName: 'no-reply@yourdomain.com', 26 | // Reply-to email address 27 | replyTo: 'no-reply@yourdomain.com', 28 | // Verification email subject 29 | verificationSubject: 'Please verify your e-mail for *|appname|*', 30 | // Verification email body. This will be ignored when verificationTemplateName is used. 31 | verificationBody: 'Hi *|username|*,\n\nYou are being asked to confirm the e-mail address *|email|* with *|appname|*\n\nClick here to confirm it:\n*|link|*', 32 | // Password reset email subject 33 | passwordResetSubject: 'Password Reset Request for *|appname|*', 34 | // Password reset email body. This will be ignored when passwordResetTemplateName is used. 35 | passwordResetBody: 'Hi *|username|*,\n\nYou requested a password reset for *|appname|*.\n\nClick here to reset it:\n*|link|*', 36 | 37 | /**************************************** 38 | * If you are using Mandrill templates: * 39 | ****************************************/ 40 | 41 | // 42 | // If you want to use other custom User attributes in the emails 43 | // (for example: firstName, lastName), add them to the list (username and email 44 | // are pre-loaded). 45 | // The merge tag in the template must be equal to the attribute's name. 46 | customUserAttributesMergeTags: ['firstname', 'lastname'], 47 | 48 | // 49 | // The name of your Mandrill template for the password reset email: 50 | // If you add this attribute, then passwordResetBody will be ignored. 51 | // IMPORTANT: Make sure the email has the *|link|* merge tag, 52 | // it will render the url to reset the password. 53 | passwordResetTemplateName: 'password-reset-template-name', 54 | 55 | // 56 | // The name of your Mandrill template for the verification email: 57 | // If you add this attribute, then verificationBody will be ignored. 58 | // IMPORTANT: Make sure the email has the *|link|* merge tag, 59 | // it will render the url to verify the user. 60 | verificationTemplateName: 'email-verification-template-name', 61 | 62 | } 63 | } 64 | ... 65 | }); 66 | ``` 67 | 68 | You can use the following variables in the subjects and bodies and they will be replaced with their appropriate values: 69 | 70 | `*|appname|*` - your application's display name 71 | 72 | `*|username|*` - the user's display name 73 | 74 | `*|email|*` - the user's email address 75 | 76 | `*|link|*` - the link the user must click to perform the requested action 77 | 78 | Note that these variable tokens are formatted using the `MailChimp` merge language. If your Mandrill account is using the `Handlebars` merge language, you should use the alternative format, e.g. `{{appname}}`, `{{username}}`, etc. The Mandrill merge language style can be configured in your Mandrill settings under 'Sending Defaults'. 79 | 80 | Developers groups: 81 | https://groups.google.com/forum/#!forum/back4app 82 | 83 | Parse hosting: 84 | https://www.back4app.com 85 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var mandrill = require('mandrill-api/mandrill'); 2 | 3 | var MandrillAdapter = mandrillOptions => { 4 | 5 | if ( 6 | !mandrillOptions || 7 | !mandrillOptions.apiKey || 8 | !mandrillOptions.fromEmail 9 | ) { 10 | throw 'MandrillAdapter requires an API Key and a From Email Address.'; 11 | } 12 | 13 | mandrillOptions.replyTo = 14 | mandrillOptions.replyTo || 15 | mandrillOptions.fromEmail; 16 | mandrillOptions.displayName = 17 | mandrillOptions.displayName || 18 | mandrillOptions.replyTo; 19 | mandrillOptions.verificationSubject = 20 | mandrillOptions.verificationSubject || 21 | 'Please verify your e-mail for *|appname|*'; 22 | mandrillOptions.verificationBody = 23 | mandrillOptions.verificationBody || 24 | 'Hi,\n\nYou are being asked to confirm the e-mail address *|email|* ' + 25 | 'with *|appname|*\n\nClick here to confirm it:\n*|link|*'; 26 | mandrillOptions.passwordResetSubject = 27 | mandrillOptions.passwordResetSubject || 28 | 'Password Reset Request for *|appname|*'; 29 | mandrillOptions.passwordResetBody = 30 | mandrillOptions.passwordResetBody || 31 | 'Hi,\n\nYou requested a password reset for *|appname|*.\n\nClick here ' + 32 | 'to reset it:\n*|link|*'; 33 | mandrillOptions.customUserAttributesMergeTags = mandrillOptions.customUserAttributesMergeTags || []; 34 | 35 | var mandrill_client = new mandrill.Mandrill(mandrillOptions.apiKey); 36 | 37 | var sendVerificationEmail = options => { 38 | var global_merge_vars = [ 39 | { name: 'appname', content: options.appName}, 40 | { name: 'username', content: options.user.get("username")}, 41 | { name: 'email', content: options.user.get("email")}, 42 | { name: 'link', content: options.link} 43 | ]; 44 | 45 | if (typeof mandrillOptions.customUserAttributesMergeTags !== 'undefined') { 46 | for (var extra_attr of mandrillOptions.customUserAttributesMergeTags) { 47 | global_merge_vars.push({ name: extra_attr, content: options.user.get(extra_attr) || '' }); 48 | } 49 | } 50 | 51 | var message = { 52 | from_email: mandrillOptions.fromEmail, 53 | from_name: mandrillOptions.displayName, 54 | headers: { 55 | 'Reply-To': mandrillOptions.replyTo 56 | }, 57 | to: [{ 58 | email: options.user.get("email") 59 | }], 60 | subject: mandrillOptions.verificationSubject, 61 | text: mandrillOptions.verificationBody, 62 | global_merge_vars: global_merge_vars 63 | } 64 | 65 | return new Promise((resolve, reject) => { 66 | if (mandrillOptions.verificationTemplateName) { 67 | mandrill_client.messages.sendTemplate( 68 | { 69 | template_name: mandrillOptions.verificationTemplateName, 70 | template_content: [], 71 | message: message, 72 | async: true 73 | }, 74 | resolve, 75 | reject 76 | ) 77 | } else { 78 | mandrill_client.messages.send( 79 | { 80 | message: message, 81 | async: true 82 | }, 83 | resolve, 84 | reject 85 | ) 86 | } 87 | }); 88 | } 89 | 90 | var sendPasswordResetEmail = options => { 91 | 92 | var global_merge_vars = [ 93 | { name: 'appname', content: options.appName}, 94 | { name: 'username', content: options.user.get("username")}, 95 | { name: 'email', content: options.user.get("email")}, 96 | { name: 'link', content: options.link} 97 | ]; 98 | 99 | if (typeof mandrillOptions.customUserAttributesMergeTags !== 'undefined') { 100 | for (var extra_attr of mandrillOptions.customUserAttributesMergeTags) { 101 | global_merge_vars.push({ name: extra_attr, content: options.user.get(extra_attr) || '' }); 102 | } 103 | } 104 | 105 | var message = { 106 | from_email: mandrillOptions.fromEmail, 107 | from_name: mandrillOptions.displayName, 108 | headers: { 109 | 'Reply-To': mandrillOptions.replyTo 110 | }, 111 | to: [{ 112 | email: options.user.get("email") || options.user.get("username") 113 | }], 114 | subject: mandrillOptions.passwordResetSubject, 115 | text: mandrillOptions.passwordResetBody, 116 | global_merge_vars: global_merge_vars 117 | } 118 | 119 | return new Promise((resolve, reject) => { 120 | if (mandrillOptions.passwordResetTemplateName) { 121 | mandrill_client.messages.sendTemplate( 122 | { 123 | template_name: mandrillOptions.passwordResetTemplateName, 124 | template_content: [], 125 | message: message, 126 | async: true 127 | }, 128 | resolve, 129 | reject 130 | ) 131 | } else { 132 | mandrill_client.messages.send( 133 | { 134 | message: message, 135 | async: true 136 | }, 137 | resolve, 138 | reject 139 | ) 140 | } 141 | }); 142 | } 143 | 144 | var sendMail = options => { 145 | var message = { 146 | from_email: mandrillOptions.fromEmail, 147 | from_name: mandrillOptions.displayName, 148 | headers: { 149 | 'Reply-To': mandrillOptions.replyTo 150 | }, 151 | to: [{ 152 | email: options.to 153 | }], 154 | subject: options.subject, 155 | text: options.text 156 | } 157 | 158 | return new Promise((resolve, reject) => { 159 | mandrill_client.messages.send( 160 | { 161 | message: message, 162 | async: true 163 | }, 164 | resolve, 165 | reject 166 | ) 167 | }); 168 | } 169 | 170 | return Object.freeze({ 171 | sendVerificationEmail: sendVerificationEmail, 172 | sendPasswordResetEmail: sendPasswordResetEmail, 173 | sendMail: sendMail 174 | }); 175 | } 176 | 177 | module.exports = MandrillAdapter; 178 | --------------------------------------------------------------------------------