Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MailAdapter design #275

Closed
drew-gross opened this issue Feb 6, 2016 · 72 comments
Closed

MailAdapter design #275

drew-gross opened this issue Feb 6, 2016 · 72 comments

Comments

@drew-gross
Copy link
Contributor

Hey, we are super excited to see everybody jumping to help with email verification! Since so many people are working on this, I thought it would be a good idea to get everyone working on it together to discuss what the API should look like. We want to have the smallest API possible to reduce the burden on implementers of the interface, while still being enough to satisfy the needs of Parse.

We also want to open the door for implementers of the MailAdapter interface to bring some new innovations to the table, such as customizing the emails content based on fields on the Parse.User object.

I think the ideal interface for a MailAdapter to expose would be a small handful of functions: sendEmailVerificationEmail(user, link) to send the email on signup, and sendPasswordResetEmail(user, link) for password resets. We could also ask the MailAdapter provider to provide the 4 user facing page templates with some other functions such as generateChooseNewPasswordPage(user), generatePasswordChangedPage(user), generateEmailVerifiedPage(user) and generateInvalidLinkPage(user).

To kick off the conversation about what else we might want from this interface, here some ideas to discuss:

A sendPasswordResetSuccess(user) function. A lot of services will email you when you change your password, as a defense against hacking. Maybe the Parse server should also do this.

Should the user facing pages generation be mandatory? We could provide defaults, or choose not to.

Should we think of a way to expose the MailAdapter in Cloud Code? That would increase the burden on the implementer of MailAdapter, as they would have to create a very general purpose interface, but it could also be very useful.

Parse.com implements user facing pages by asking you to provide a link to a template. Should we re-use that concept? It would aid in transitioning off of Parse.com.

Do we want to give the MailAdapter any other information to work with? Like a Parse.Installation object, maybe? We could even give the adapter the full power of the Parse JS SDK, so it can add some features like the ability to write to the user object, so it can, for example, save when the password was last reset. Of course, any MailAdapter can accept data in it's constructor that lets it do that anyway, but we could make it easier.

I'll leave the 3 PRs working on email verification open, and we can take the best ideas from those 3 PRs, plus what we can come up with here.

@taylorstine @jamiechapman @maysale01 @gfosco @nlutsenko @lucianmat @flovilmart

@flovilmart
Copy link
Contributor

Top of my mind and architercturally speaking:

Mail requests should be stored in separated objects, leaving just emailVerified in _User.

We should pass the full Parse.User object to the methods, that would allow external implementation to have a better control, tracking of sends etc.. Installation seem irrelevant at that point as it is unlikely to be linked to a particular User.

@flovilmart
Copy link
Contributor

The question about the templates begets a bigger question. What is the use case of parse-server? Standalone or as a module. Personally, I'd go the standalone approach, to replicate, and isolate the concerns.

Going the standalone approach, implies that the templates should be provided by configuration. Do we want to go that way?

@drew-gross
Copy link
Contributor Author

I agree with the standalone approach and having the templates provided by choosing a configuration (ie. by choosing a MailAdapter) having the configuration be done in JS at the time of MailAdapter instantiation could be very powerful, and let the power users do awesome things by using an advanced MailAdapter, while also letting the beginner developers get started with a simple MailAdapter that chooses most of the defaults automatically.

Storing mail requests in a separate object is a great idea, but enabling that by default would cause backwards compatibility issues due to existing apps potentially already having data in that place. Making it possible for an advanced MailAdapter that stores requests wherever the user wants sounds like a good idea though.

@gnz00
Copy link

gnz00 commented Feb 6, 2016

I personally believe that email handling and template rendering are beyond the scope of the Parse Server project. I'm leaning towards Express plugin over standalone.

We could effectively plug this whole issue by adding some CloudCode mechanism to hook into. For example, a user could import a parse-server/cloudcode-mailgun-hooks plugin that automatically registers hooks for certain classes, i.e. email verification, password change notifications, password reset for _User with Mailgun, or write their own handlers with any node library they want.

However, if the consensus is to include some core mailing ability, here is an approach that keeps things flexible https://gist.github.com/maysale01/5390485e676ee3745960. Could also add a locals hook to each template definition:

const myMailTemplates = {
    password_reset: {
        html: require("./views/password_reset_html.js")(dust), // Precompiled dust template
        text: require("./views/password_reset_text.js")(dust),
        locals: function(req) {
            return {
                title: "Some hardcoded stuff",
                name: `${req.user.firstname} ${req.user.lastname}`,
                address: [`${req.user.addr_num} ${req.user.addr_street}`, req.user.addr_city, req.user.addr_state, req.user.addr_zip].join(","),
                tracking: req.Parse.server.analyticsProvider.tracking
            }
        }
    }
};

Sidebar: logic for a shouldSendUserConfirmation shouldn't be baked directly into RestWrite.js (or at least not in the runDatabaseOperation method), rather there should be a step in the handler flow where a model is validated against some configurable constraints. Possibly a system defined afterSave trigger for '_User' that checks configuration to see if email verification is required, a validator service, or model classes with static validate methods.

@flovilmart
Copy link
Contributor

Also, for the whole modularization of the project, we should be able to pass a module name, from configuration or command line in order to load a 3rd party adapter when it makes sense.
In this scenario, we could decouple the main package from the adapters, providing base adapters, but letting anyone who wants a sendgrid adapter use that one without actually requiring any code besides the configuration.

@flovilmart
Copy link
Contributor

The mail adapter should also provide a simple send method that would take standard parameters.

@drew-gross
Copy link
Contributor Author

That seems reasonable, they would really need to implement that in order to make the other functions anyway.

@corbanb
Copy link
Contributor

corbanb commented Feb 16, 2016

Are there any ideas on when this will be merged in for us to start working off of? Seems like its gone quite here for a little bit.

@flovilmart
Copy link
Contributor

@corbanb there are multiple concerns about the mail sending architecture and actually adapter architecture in general: in #290.

@rendragon83
Copy link

Is this still being worked on or ready? I have been going through all the conversations about this and it looks like all of the other ones have been closed except this one.

@jamiechapman
Copy link

@rendragon83 not sure, not much discussion has happened for a couple of weeks regarding this side of things. I guess we probably need to reach a decision soon so we can ensure that password resets etc are working for standalone API server(s).

@taylorstine
Copy link
Contributor

Let's hop on the green button express with one of these two #250 #583

@corbanb
Copy link
Contributor

corbanb commented Feb 26, 2016

+1

@maruthi-wal
Copy link

@flovilmart @gfosco

If any one did the password reset functionality, Please provide me the steps??

I need to implement this feature with my local parse server.

Thanks,
Maruthi.

@drew-gross
Copy link
Contributor Author

Hey, @maruthi-wal, Parse Server 2.1.4 has experimental support for sending password reset emails. Because it's still experimental, it's not documented and could change in the next version. I wouldn't recommend using it in production just yet, but if you want to help us test the feature before marking it as non-experimental, you can set verifyUserEmails: true in your Parse Config, and add an email adapter such as our SimpleMailgunAdapter.

@dcdspace
Copy link

dcdspace commented Mar 4, 2016

I use Sendgrid with custom email templates for transactional email via cloud code, so would I be able to send password reset/email verification emails using Sendgrid as oppose to Mailgun? It would be great if I could simply access the url to the reset page and pop that in my email HTML. Thanks!

@drew-gross
Copy link
Contributor Author

That is coming and will be possible by the time password reset becomes non-experimental

@432player
Copy link

Verification and reset emails not working since migrating my Parse app's MongoDB

I've completed step 1 of my Parse migration by moving to my own MongoDB server. Everything is working fine except emails sent by Parse.com. Again, I've only migrated the DB so the cloud code (and Parse REST API) are still being hosted by Parse.com.

Clicking on any email verification or password reset email link ends with the "Invalid Link" error page. I've confirmed the token and username in the emails are correct.

My only thought is the Parse.com hosted email verification handler is not able to communicate with the external MongoDB server I migrated to (but the the Parse.com REST API is working fine so that doesn't make sense).

A CLUE THOUGH:

I've noticed that the reset link sent to my email worked fine before the migration, and a minute after the migration it creates a new link with a new _perishable_token in the mongoDB and is the same in the new link sent in the email but is an Invalid Link. And the funny part is the link before the migration to mongoDB STILL WORKS. It's like the old _perishable_token before the migration is somehow cached in the Parse server and allows me to even reset the password as many times as I like (each time same old token before the migration) but the new tokens being generated are not being checked in the request_password_reset Rest API function I guess.

Any ideas? Is this happening to anyone else?

@flovilmart
Copy link
Contributor

@432player how did you configure parse-server?

@432player
Copy link

The Parse Server is still running on Parse.com. We havent migrated to our own Parse-Server. We've migrated only the DB to our mLab mongoDB

@alarrosa14
Copy link

alarrosa14 commented Sep 12, 2016

For those looking for custom templates for password reset and verification emails, go to parse-server-mandrill-adapter. v1.2.0 of that adapter supports Mandrill's templates.

@rowntreerob
Copy link

rowntreerob commented Sep 30, 2016

FWIW : native parse-server && std-parse-mailgun-adapter working fine in localhost / express testing..

mongo connected to DEV instance on mLab's cloud ( NOT localhost/mongo )

Details of node config ( using heroku's $HOME/proj/.env ) to inject local env...

NOTE: - check for inmail in 'spam' folder.

env:
DATABASE_URI=mongodb://me:34@ds0.mlab.com:13931/beacontst
SERVER_URL=http://localhost:1337/parse
PUBLIC_SERVER_URL=http://localhost:1337/parse
index.js:
new ParseServer({
  databaseURI: databaseUri || 'mongodb:..',
  serverURL: process.env.SERVER_URL || 'https://mighty-id-65221.herokuapp.com/parse',
  verifyUserEmails: true,
  publicServerURL: process.env.PUBLIC_SERVER_URL || 'https://mighty-id-65221.herokuapp.com/parse',
  emailAdapter: {
  module: 'parse-server-simple-mailgun-adapter',
  options: {
    fromAddress: 'no-reply@yayatv.tv',
    domain: 'sandbox2babd8b07fca4fe81e.mailgun.org',
    apiKey: 'key-f16d78'
  }

@gowridev
Copy link

Can we send mail invites using cloud code which uses mail adapter? If possible,could you share sample cloud code?

@majidhassan
Copy link

@gowridev I'm not sure what exactly you meant with "send mail invites". But I send regular emails using the Mailgun adapter. Here's some sample code:

var Mailgun = require("mailgun-js")({apiKey: mailgun_apikey, domain: mailgun_domain});

function mailgunSend(data, promise) {
    Mailgun.messages().send(data, function (error, body) {
        if (error) {
            promise.reject(error);
        }
        else {
            promise.resolve();
        }
    });
}

var promise = new Parse.Promise();

var data = {
    from: "Some Email <no-reply@somedomain.com>",
    to: "receiver@somedomain.com",
    subject: "Hello",
    html: "<html><body>Hello</body></html>"
};

mailgunSend(data, promise);

Env:
parse-server-mailgun@2.1.12
parse-server@2.2.25-beta.1

@flovilmart
Copy link
Contributor

There is a default form for password resets, as long as you provide a mail adapter, this will work

@valdezm
Copy link

valdezm commented Feb 15, 2017

Awesome, yeah I see that now, Thanks @flovilmart I appreciate it! My mistake was that I didn't set the following correctly:
publicServerURL: 'https://example.com/parse',

That really should be specified more accurately to be:
publicServerURL: 'https://thestandaloneparseserverURL.com/parse',

I thought it was just what the companies website was, not the actual endpoint that has the form which exists on the ParseServer through that project....

Appreciate your help though, much appreciated!

@funkenstrahlen
Copy link
Contributor

The parse server guide still says mail verification is not available.

This is not supported out of the box. But, you can use a beforeSave to send out emails using a provider like Mailgun and add logic for verification. Subscribe to this issue to be notified if email verification support is added to Parse Server.
https://parseplatform.github.io/docs/parse-server/guide/

This should be updated.

@neilpoulin
Copy link

Hi, I have a custom email adapter that uses Amazon's SES for sending emails, and it has been working great for months for password resets. I now want to implement email verification, but am having trouble getting the email to trigger.

I saw one comment from @drew-gross about commenting out any beforeSave or afterSave triggers on the _User object, and tried it. That got the mail to trigger and work as expected. However, I'm hoping that I don't need to remove any before/afterSave hooks to get this feature working. Does anyone have any thoughts on how to get verification emails to send out when using other beforeSave triggers?

@flovilmart
Copy link
Contributor

Can you open a specific issue so I can have a look?

@acinader
Copy link
Contributor

@neilpoulin any interest in open sourcing you're ses adapter? that would be useful for the community.

@neilpoulin
Copy link

@flovilmart, sure thing, i'll get a separate issue opened to track this specifically.

@acinader, I think that's a great idea. I'll start working on breaking it out into a standalone module.

Thanks for the responses!

@flovilmart
Copy link
Contributor

@neilpoulin sorry for the late response. Did you open another issue or found what you were looking for?

@ghost
Copy link

ghost commented May 9, 2017

Mail verification and password reset are available or not ?

@flovilmart
Copy link
Contributor

Yes they should be, all endpoints are available, configured when your provide a mail adapter.

@ghost
Copy link

ghost commented May 9, 2017

Because it tried to add this to my ParseServer configuration in index.js

verifyUserEmails: true,
publicServerURL: process.env.SERVER_URL || 'http://localhost:1337/parse',
appName: 'Parse App',
emailAdapter: {
    module: 'parse-server-simple-mailgun-adapter',
    options: {
        fromAddress: 'MYMAIL',
        domain: 'MYDOMAIN.mailgun.org',
        apiKey: 'APIKEY',
    }
},

And when I reset a password I have this error (node:17) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: Forbidden

@ghost
Copy link

ghost commented May 9, 2017

I need to add another module ? in package.json

@flovilmart
Copy link
Contributor

Can you provide the logs when running with VERBOSE=1?

@albaqawi
Copy link

albaqawi commented Sep 4, 2017

hi @flovilmart and @drew-gross I am following your works here and trying not to drown as I am very new to Swift3 and Heroku/Parse backend..... as many others I want to enable the reset password feature call within parse with (requestPasswordResetForEmailInBackground:block:)

I have my Heroku hosted on node.js platform and not sure what I need to do, as I see many recommend to use mailgun....

the close to a complete answer is @FeleciaGente in post #1063

and I am waiting for @flovilmart response on it...

I really appreciate if you can guide me to a step by step tutorial or how to guide.

thanks

@fadwafb
Copy link

fadwafb commented Sep 18, 2017

Do anyone used the simple-parse-smtp-adapter? because it's not working for me, i didn't get any e-mail.

@flovilmart
Copy link
Contributor

@fadwafb reach out to to maintainer of this adapter. We don’t maintain it.

@fadwafb
Copy link

fadwafb commented Sep 18, 2017

Thank you so much @flovilmart for the answer, so can i use the SendGrid adapter? if not tell which adapters are working?

@flovilmart
Copy link
Contributor

I think so, all adapters on the parse-server modules org should be properly functional.

@Abderezai
Copy link

Abderezai commented Sep 19, 2017

something is wrong with the simple mail adapter. I tried using my mailgun credentials on an older project that was runing parse + mailgun and the mail was sent no problem. On this new project those credentials are not working.
"express": "^4.13.4",
"kerberos": "~0.0.x",
"parse": "1.10.0",
"parse-dashboard": "~1.1.0",
"parse-server": "2.5.3"

error:
'An appName, publicServerURL, and emailAdapter are required for password reset and email verification functionality.' }

Parse options:
appName: 'Example App',
serverURL: process.env.SERVER_URL,
publicServerUrl: process.env.SERVER_URL,
emailAdapter: {
module: 'parse-server-simple-mailgun-adapter',
options: {
fromAddress: 'noreply@example.com',
domain: 'mailgun.example.com',
apiKey: 'key-####',
}

I tried parse-server-mailgun and same issue

@flovilmart
Copy link
Contributor

@Abderezai publicServerUrl seems to have a typo

@Abderezai
Copy link

Abderezai commented Sep 19, 2017

Thank you man. And damn dyslexia.
Is there an editor out there that would catch something like this?

@Nes-si
Copy link
Contributor

Nes-si commented Apr 3, 2018

Do you have any plans to update docs? Isn't it time?
http://docs.parseplatform.org/parse-server/guide/#welcome-emails-and-email-verification

@flovilmart
Copy link
Contributor

@Nes-si feel free to open a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests