Skip to content

Commit 7738d33

Browse files
committed
Merge pull request #1144 from drew-gross/document-email-adapter
Document email adapter
2 parents f4ad4c1 + 27a3198 commit 7738d33

File tree

8 files changed

+89
-85
lines changed

8 files changed

+89
-85
lines changed

README.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ We have provided a basic [Node.js application](https://github.com/ParsePlatform/
109109
* [Digital Ocean](https://www.digitalocean.com/community/tutorials/how-to-run-parse-server-on-ubuntu-14-04)
110110
* [NodeChef](https://nodechef.com/blog/post/6/migrate-from-parse-to-nodechef%E2%80%99s-managed-parse-server)
111111
* [Google App Engine](https://medium.com/@justinbeckwith/deploying-parse-server-to-google-app-engine-6bc0b7451d50)
112-
* [Microsoft Azure](https://azure.microsoft.com/en-us/blog/azure-welcomes-parse-developers/)
112+
* [Microsoft Azure](https://azure.microsoft.com/en-us/blog/azure-welcomes-parse-developers/)
113113
* [Pivotal Web Services](https://github.com/cf-platform-eng/pws-parse-server)
114114
* [Back4app](http://blog.back4app.com/2016/03/01/quick-wizard-migration/)
115115

@@ -187,6 +187,36 @@ The client keys used with Parse are no longer necessary with Parse Server. If yo
187187
* `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)).
188188
* `databaseAdapter` - The backing store can be changed by creating an adapter class (see `DatabaseAdapter.js`). Defaults to `MongoStorageAdapter`.
189189

190+
##### Email verification and password reset
191+
192+
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:
193+
194+
```js
195+
var server = ParseServer({
196+
...otherOptions,
197+
// Enable email verification
198+
verifyUserEmails: true,
199+
// The public URL of your app.
200+
// This will appear in the link that is used to verify email addresses and reset passwords.
201+
publicServerURL: 'https://example.com',
202+
// Your apps name. This will appear in the subject and body of the emails that are sent.
203+
appName: 'Parse App',
204+
// The email adapter
205+
emailAdapter: {
206+
module: 'parse-server-simple-mailgun-adapter',
207+
options: {
208+
// The address that your emails come from
209+
fromAddress: '[email protected]',
210+
// Your domain from mailgun.com
211+
domain: 'example.com',
212+
// Your API key from mailgun.com
213+
apiKey: 'key-mykey',
214+
}
215+
}
216+
});
217+
218+
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).
219+
190220
### Using environment variables to configure Parse Server
191221

192222
You may configure the Parse Server using environment variables:

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"parse-server-fs-adapter": "^1.0.0",
3838
"parse-server-gcs-adapter": "^1.0.0",
3939
"parse-server-s3-adapter": "^1.0.0",
40+
"parse-server-simple-mailgun-adapter": "^1.0.0",
4041
"redis": "^2.5.0-1",
4142
"request": "^2.65.0",
4243
"tv4": "^1.2.7",

spec/index.spec.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ describe('server', () => {
5656
fileKey: 'test',
5757
verifyUserEmails: true,
5858
emailAdapter: MockEmailAdapterWithOptions({
59+
fromAddress: '[email protected]',
5960
apiKey: 'k',
6061
domain: 'd',
6162
}),
@@ -80,6 +81,7 @@ describe('server', () => {
8081
emailAdapter: {
8182
class: MockEmailAdapterWithOptions,
8283
options: {
84+
fromAddress: '[email protected]',
8385
apiKey: 'k',
8486
domain: 'd',
8587
}
@@ -103,8 +105,9 @@ describe('server', () => {
103105
fileKey: 'test',
104106
verifyUserEmails: true,
105107
emailAdapter: {
106-
module: './Email/SimpleMailgunAdapter',
108+
module: 'parse-server-simple-mailgun-adapter',
107109
options: {
110+
fromAddress: '[email protected]',
108111
apiKey: 'k',
109112
domain: 'd',
110113
}
@@ -127,9 +130,9 @@ describe('server', () => {
127130
collectionPrefix: 'test_',
128131
fileKey: 'test',
129132
verifyUserEmails: true,
130-
emailAdapter: './Email/SimpleMailgunAdapter',
133+
emailAdapter: 'parse-server-simple-mailgun-adapter',
131134
publicServerURL: 'http://localhost:8378/1'
132-
})).toThrow('SimpleMailgunAdapter requires an API Key and domain.');
135+
})).toThrow('SimpleMailgunAdapter requires an API Key, domain, and fromAddress.');
133136
done();
134137
});
135138

@@ -147,13 +150,13 @@ describe('server', () => {
147150
fileKey: 'test',
148151
verifyUserEmails: true,
149152
emailAdapter: {
150-
module: './Email/SimpleMailgunAdapter',
153+
module: 'parse-server-simple-mailgun-adapter',
151154
options: {
152155
domain: 'd',
153156
}
154157
},
155158
publicServerURL: 'http://localhost:8378/1'
156-
})).toThrow('SimpleMailgunAdapter requires an API Key and domain.');
159+
})).toThrow('SimpleMailgunAdapter requires an API Key, domain, and fromAddress.');
157160
done();
158161
});
159162

src/Adapters/AdapterLoader.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,19 @@ export function loadAdapter(adapter, defaultAdapter, options) {
1010
try {
1111
return adapter(options);
1212
} catch(e) {
13-
var Adapter = adapter;
14-
return new Adapter(options);
13+
if (e.name === 'TypeError') {
14+
var Adapter = adapter;
15+
return new Adapter(options);
16+
} else {
17+
throw e;
18+
}
1519
}
1620
} else if (typeof adapter === "string") {
1721
adapter = require(adapter);
1822
// If it's define as a module, get the default
1923
if (adapter.default) {
2024
adapter = adapter.default;
2125
}
22-
2326
return loadAdapter(adapter, undefined, options);
2427
} else if (adapter.module) {
2528
return loadAdapter(adapter.module, undefined, adapter.options);

src/Adapters/Email/SimpleMailgunAdapter.js

Lines changed: 0 additions & 32 deletions
This file was deleted.

src/Controllers/UserController.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { randomString } from '../cryptoUtils';
2-
import { inflate } from '../triggers';
1+
import { randomString } from '../cryptoUtils';
2+
import { inflate } from '../triggers';
33
import AdaptableController from './AdaptableController';
4-
import MailAdapter from '../Adapters/Email/MailAdapter';
5-
import rest from '../rest';
4+
import MailAdapter from '../Adapters/Email/MailAdapter';
5+
import rest from '../rest';
66

77
var DatabaseAdapter = require('../DatabaseAdapter');
88
var RestWrite = require('../RestWrite');
@@ -181,7 +181,7 @@ export class UserController extends AdaptableController {
181181

182182
defaultVerificationEmail({link, user, appName, }) {
183183
let text = "Hi,\n\n" +
184-
"You are being asked to confirm the e-mail address " + user.email + " with " + appName + "\n\n" +
184+
"You are being asked to confirm the e-mail address " + user.get("email") + " with " + appName + "\n\n" +
185185
"" +
186186
"Click here to confirm it:\n" + link;
187187
let to = user.get("email");

src/ParseServer.js

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -11,41 +11,40 @@ var batch = require('./batch'),
1111
Parse = require('parse/node').Parse,
1212
authDataManager = require('./authDataManager');
1313

14-
//import passwordReset from './passwordReset';
15-
import cache from './cache';
16-
import Config from './Config';
17-
import parseServerPackage from '../package.json';
18-
import ParsePushAdapter from './Adapters/Push/ParsePushAdapter';
19-
import PromiseRouter from './PromiseRouter';
20-
import requiredParameter from './requiredParameter';
21-
import { AnalyticsRouter } from './Routers/AnalyticsRouter';
22-
import { ClassesRouter } from './Routers/ClassesRouter';
23-
import { FeaturesRouter } from './Routers/FeaturesRouter';
24-
import { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter';
25-
import { FilesController } from './Controllers/FilesController';
26-
import { FilesRouter } from './Routers/FilesRouter';
27-
import { FunctionsRouter } from './Routers/FunctionsRouter';
28-
import { GlobalConfigRouter } from './Routers/GlobalConfigRouter';
29-
import { GridStoreAdapter } from './Adapters/Files/GridStoreAdapter';
30-
import { HooksController } from './Controllers/HooksController';
31-
import { HooksRouter } from './Routers/HooksRouter';
32-
import { IAPValidationRouter } from './Routers/IAPValidationRouter';
33-
import { InstallationsRouter } from './Routers/InstallationsRouter';
34-
import { loadAdapter } from './Adapters/AdapterLoader';
35-
import { LiveQueryController } from './Controllers/LiveQueryController';
36-
import { LoggerController } from './Controllers/LoggerController';
37-
import { LogsRouter } from './Routers/LogsRouter';
38-
import { ParseLiveQueryServer } from './LiveQuery/ParseLiveQueryServer';
39-
import { PublicAPIRouter } from './Routers/PublicAPIRouter';
40-
import { PushController } from './Controllers/PushController';
41-
import { PushRouter } from './Routers/PushRouter';
42-
import { randomString } from './cryptoUtils';
43-
import { RolesRouter } from './Routers/RolesRouter';
44-
import { SchemasRouter } from './Routers/SchemasRouter';
45-
import { SessionsRouter } from './Routers/SessionsRouter';
46-
import { setFeature } from './features';
47-
import { UserController } from './Controllers/UserController';
48-
import { UsersRouter } from './Routers/UsersRouter';
14+
import cache from './cache';
15+
import Config from './Config';
16+
import parseServerPackage from '../package.json';
17+
import ParsePushAdapter from './Adapters/Push/ParsePushAdapter';
18+
import PromiseRouter from './PromiseRouter';
19+
import requiredParameter from './requiredParameter';
20+
import { AnalyticsRouter } from './Routers/AnalyticsRouter';
21+
import { ClassesRouter } from './Routers/ClassesRouter';
22+
import { FeaturesRouter } from './Routers/FeaturesRouter';
23+
import { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter';
24+
import { FilesController } from './Controllers/FilesController';
25+
import { FilesRouter } from './Routers/FilesRouter';
26+
import { FunctionsRouter } from './Routers/FunctionsRouter';
27+
import { GlobalConfigRouter } from './Routers/GlobalConfigRouter';
28+
import { GridStoreAdapter } from './Adapters/Files/GridStoreAdapter';
29+
import { HooksController } from './Controllers/HooksController';
30+
import { HooksRouter } from './Routers/HooksRouter';
31+
import { IAPValidationRouter } from './Routers/IAPValidationRouter';
32+
import { InstallationsRouter } from './Routers/InstallationsRouter';
33+
import { loadAdapter } from './Adapters/AdapterLoader';
34+
import { LiveQueryController } from './Controllers/LiveQueryController';
35+
import { LoggerController } from './Controllers/LoggerController';
36+
import { LogsRouter } from './Routers/LogsRouter';
37+
import { ParseLiveQueryServer } from './LiveQuery/ParseLiveQueryServer';
38+
import { PublicAPIRouter } from './Routers/PublicAPIRouter';
39+
import { PushController } from './Controllers/PushController';
40+
import { PushRouter } from './Routers/PushRouter';
41+
import { randomString } from './cryptoUtils';
42+
import { RolesRouter } from './Routers/RolesRouter';
43+
import { SchemasRouter } from './Routers/SchemasRouter';
44+
import { SessionsRouter } from './Routers/SessionsRouter';
45+
import { setFeature } from './features';
46+
import { UserController } from './Controllers/UserController';
47+
import { UsersRouter } from './Routers/UsersRouter';
4948

5049
// Mutate the Parse object to add the Cloud Code handlers
5150
addParseCloud();

src/index.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import ParseServer from './ParseServer'
2-
import { GCSAdapter } from 'parse-server-gcs-adapter';
3-
import { S3Adapter } from 'parse-server-s3-adapter';
4-
import { FileSystemAdapter } from 'parse-server-fs-adapter';
1+
import ParseServer from './ParseServer';
2+
import { GCSAdapter } from 'parse-server-gcs-adapter';
3+
import { S3Adapter } from 'parse-server-s3-adapter';
4+
import { FileSystemAdapter } from 'parse-server-fs-adapter';
55

66
// Factory function
77
let _ParseServer = function(options) {

0 commit comments

Comments
 (0)