From 2f00a029367e4922674434120bee23353a27ca46 Mon Sep 17 00:00:00 2001 From: Drew Gross Date: Tue, 22 Mar 2016 22:09:22 -0700 Subject: [PATCH] Document email adapter --- README.md | 32 +++++++++- src/Adapters/Email/SimpleMailgunAdapter.js | 4 +- src/Controllers/UserController.js | 10 ++-- src/ParseServer.js | 69 +++++++++++----------- src/index.js | 6 +- 5 files changed, 75 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 5dea9233..29f00306 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ We have provided a basic [Node.js application](https://github.com/ParsePlatform/ * [Digital Ocean](https://www.digitalocean.com/community/tutorials/how-to-run-parse-server-on-ubuntu-14-04) * [NodeChef](https://nodechef.com/blog/post/6/migrate-from-parse-to-nodechef%E2%80%99s-managed-parse-server) * [Google App Engine](https://medium.com/@justinbeckwith/deploying-parse-server-to-google-app-engine-6bc0b7451d50) -* [Microsoft Azure](https://azure.microsoft.com/en-us/blog/azure-welcomes-parse-developers/) +* [Microsoft Azure](https://azure.microsoft.com/en-us/blog/azure-welcomes-parse-developers/) * [Pivotal Web Services](https://github.com/cf-platform-eng/pws-parse-server) * [Back4app](http://blog.back4app.com/2016/03/01/quick-wizard-migration/) @@ -187,6 +187,36 @@ The client keys used with Parse are no longer necessary with Parse Server. If yo * `loggerAdapter` - The default behavior/transport (File) can be changed by creating an adapter class (see [`LoggerAdapter.js`](https://github.com/ParsePlatform/parse-server/blob/master/src/Adapters/Logger/LoggerAdapter.js)). * `databaseAdapter` - The backing store can be changed by creating an adapter class (see `DatabaseAdapter.js`). Defaults to `MongoStorageAdapter`. +##### Email verification and password reset + +Verifying user email addresses and enabling password reset via email requries an email adapter. As part of the `parse-server` package we provide an adapter for sending email through Mailgun. To use it, sign up for Mailgun, and add this to your initialization code: + +```js +var server = ParseServer({ + ...otherOptions, + // Enable email verification + verifyUserEmails: true, + // The public URL of your app. + // This will appear in the link that is used to verify email addresses and reset passwords. + publicServerURL: 'https://example.com', + // Your apps name. This will appear in the subject and body of the emails that are sent. + appName: 'Parse App', + // The email adapter + emailAdapter: { + module: 'parse-server/lib/Adapters/Email/SimpleMailgunAdapter', + options: { + // The addres that your emails come from + fromAddress: 'parse@example.com', + // Your domain from mailgun.com + domain: 'example.com', + // Your API key from mailgun.com + apiKey: 'key-mykey', + } + } +}); + +You can also use other email adapters contributed by the community such as [parse-server-sendgrid-adapter](https://www.npmjs.com/package/parse-server-sendgrid-adapter). + ### Using environment variables to configure Parse Server You may configure the Parse Server using environment variables: diff --git a/src/Adapters/Email/SimpleMailgunAdapter.js b/src/Adapters/Email/SimpleMailgunAdapter.js index a90a43d7..f670429b 100644 --- a/src/Adapters/Email/SimpleMailgunAdapter.js +++ b/src/Adapters/Email/SimpleMailgunAdapter.js @@ -1,8 +1,8 @@ import Mailgun from 'mailgun-js'; let SimpleMailgunAdapter = mailgunOptions => { - if (!mailgunOptions || !mailgunOptions.apiKey || !mailgunOptions.domain) { - throw 'SimpleMailgunAdapter requires an API Key and domain.'; + if (!mailgunOptions || !mailgunOptions.apiKey || !mailgunOptions.domain || !mailgunOptions.fromAddress) { + throw 'SimpleMailgunAdapter requires an API Key, domain, and fromAddress.'; } let mailgun = Mailgun(mailgunOptions); diff --git a/src/Controllers/UserController.js b/src/Controllers/UserController.js index 051ddebc..76c7d3d3 100644 --- a/src/Controllers/UserController.js +++ b/src/Controllers/UserController.js @@ -1,8 +1,8 @@ -import { randomString } from '../cryptoUtils'; -import { inflate } from '../triggers'; +import { randomString } from '../cryptoUtils'; +import { inflate } from '../triggers'; import AdaptableController from './AdaptableController'; -import MailAdapter from '../Adapters/Email/MailAdapter'; -import rest from '../rest'; +import MailAdapter from '../Adapters/Email/MailAdapter'; +import rest from '../rest'; var DatabaseAdapter = require('../DatabaseAdapter'); var RestWrite = require('../RestWrite'); @@ -181,7 +181,7 @@ export class UserController extends AdaptableController { defaultVerificationEmail({link, user, appName, }) { let text = "Hi,\n\n" + - "You are being asked to confirm the e-mail address " + user.email + " with " + appName + "\n\n" + + "You are being asked to confirm the e-mail address " + user.get("email") + " with " + appName + "\n\n" + "" + "Click here to confirm it:\n" + link; let to = user.get("email"); diff --git a/src/ParseServer.js b/src/ParseServer.js index ab51f3d2..cf33b616 100644 --- a/src/ParseServer.js +++ b/src/ParseServer.js @@ -11,41 +11,40 @@ var batch = require('./batch'), Parse = require('parse/node').Parse, authDataManager = require('./authDataManager'); -//import passwordReset from './passwordReset'; -import cache from './cache'; -import Config from './Config'; -import parseServerPackage from '../package.json'; -import ParsePushAdapter from './Adapters/Push/ParsePushAdapter'; -import PromiseRouter from './PromiseRouter'; -import requiredParameter from './requiredParameter'; -import { AnalyticsRouter } from './Routers/AnalyticsRouter'; -import { ClassesRouter } from './Routers/ClassesRouter'; -import { FeaturesRouter } from './Routers/FeaturesRouter'; -import { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter'; -import { FilesController } from './Controllers/FilesController'; -import { FilesRouter } from './Routers/FilesRouter'; -import { FunctionsRouter } from './Routers/FunctionsRouter'; -import { GlobalConfigRouter } from './Routers/GlobalConfigRouter'; -import { GridStoreAdapter } from './Adapters/Files/GridStoreAdapter'; -import { HooksController } from './Controllers/HooksController'; -import { HooksRouter } from './Routers/HooksRouter'; -import { IAPValidationRouter } from './Routers/IAPValidationRouter'; -import { InstallationsRouter } from './Routers/InstallationsRouter'; -import { loadAdapter } from './Adapters/AdapterLoader'; -import { LiveQueryController } from './Controllers/LiveQueryController'; -import { LoggerController } from './Controllers/LoggerController'; -import { LogsRouter } from './Routers/LogsRouter'; -import { ParseLiveQueryServer } from './LiveQuery/ParseLiveQueryServer'; -import { PublicAPIRouter } from './Routers/PublicAPIRouter'; -import { PushController } from './Controllers/PushController'; -import { PushRouter } from './Routers/PushRouter'; -import { randomString } from './cryptoUtils'; -import { RolesRouter } from './Routers/RolesRouter'; -import { SchemasRouter } from './Routers/SchemasRouter'; -import { SessionsRouter } from './Routers/SessionsRouter'; -import { setFeature } from './features'; -import { UserController } from './Controllers/UserController'; -import { UsersRouter } from './Routers/UsersRouter'; +import cache from './cache'; +import Config from './Config'; +import parseServerPackage from '../package.json'; +import ParsePushAdapter from './Adapters/Push/ParsePushAdapter'; +import PromiseRouter from './PromiseRouter'; +import requiredParameter from './requiredParameter'; +import { AnalyticsRouter } from './Routers/AnalyticsRouter'; +import { ClassesRouter } from './Routers/ClassesRouter'; +import { FeaturesRouter } from './Routers/FeaturesRouter'; +import { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter'; +import { FilesController } from './Controllers/FilesController'; +import { FilesRouter } from './Routers/FilesRouter'; +import { FunctionsRouter } from './Routers/FunctionsRouter'; +import { GlobalConfigRouter } from './Routers/GlobalConfigRouter'; +import { GridStoreAdapter } from './Adapters/Files/GridStoreAdapter'; +import { HooksController } from './Controllers/HooksController'; +import { HooksRouter } from './Routers/HooksRouter'; +import { IAPValidationRouter } from './Routers/IAPValidationRouter'; +import { InstallationsRouter } from './Routers/InstallationsRouter'; +import { loadAdapter } from './Adapters/AdapterLoader'; +import { LiveQueryController } from './Controllers/LiveQueryController'; +import { LoggerController } from './Controllers/LoggerController'; +import { LogsRouter } from './Routers/LogsRouter'; +import { ParseLiveQueryServer } from './LiveQuery/ParseLiveQueryServer'; +import { PublicAPIRouter } from './Routers/PublicAPIRouter'; +import { PushController } from './Controllers/PushController'; +import { PushRouter } from './Routers/PushRouter'; +import { randomString } from './cryptoUtils'; +import { RolesRouter } from './Routers/RolesRouter'; +import { SchemasRouter } from './Routers/SchemasRouter'; +import { SessionsRouter } from './Routers/SessionsRouter'; +import { setFeature } from './features'; +import { UserController } from './Controllers/UserController'; +import { UsersRouter } from './Routers/UsersRouter'; // Mutate the Parse object to add the Cloud Code handlers addParseCloud(); diff --git a/src/index.js b/src/index.js index 1427a5bf..791fea8d 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,7 @@ import ParseServer from './ParseServer' -import { GCSAdapter } from 'parse-server-gcs-adapter'; -import { S3Adapter } from 'parse-server-s3-adapter'; -import { FileSystemAdapter } from 'parse-server-fs-adapter'; +import { FileSystemAdapter } from './Adapters/Files/FileSystemAdapter'; +import { GCSAdapter } from './Adapters/Files/GCSAdapter'; +import { S3Adapter } from './Adapters/Files/S3Adapter'; // Factory function let _ParseServer = function(options) {