Skip to content

MailAdapter design #275

Description

@drew-gross

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

Activity

  1. flovilmart commented on Feb 6, 2016

    @flovilmart
    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.

  2. flovilmart commented on Feb 6, 2016

    @flovilmart
    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?

  3. drew-gross commented on Feb 6, 2016

    @drew-gross
    ContributorAuthor

    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.

  4. gnz00 commented on Feb 6, 2016

    @gnz00

    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.

  5. flovilmart commented on Feb 7, 2016

    @flovilmart
    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.

  6. flovilmart commented on Feb 8, 2016

    @flovilmart
    Contributor

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

  7. drew-gross commented on Feb 8, 2016

    @drew-gross
    ContributorAuthor

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

  8. corbanb commented on Feb 16, 2016

    @corbanb
    Contributor

    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.

  9. flovilmart commented on Feb 16, 2016

    @flovilmart
    Contributor

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

  10. rendragon83 commented on Feb 24, 2016

    @rendragon83

    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.

  11. jamiechapman commented on Feb 24, 2016

    @jamiechapman

    @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).

  12. taylorstine commented on Feb 24, 2016

    @taylorstine
    Contributor

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

  13. corbanb commented on Feb 26, 2016

    @corbanb
    Contributor

    +1

  14. maruthi-wal commented on Mar 4, 2016

    @maruthi-wal

    @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.

  15. 44 remaining items

  16. flovilmart commented on May 9, 2017

    @flovilmart
    Contributor

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

  17. flovilmart commented on May 9, 2017

    @flovilmart
    Contributor

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

  18. albaqawi commented on Sep 4, 2017

    @albaqawi

    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

  19. fadwafb commented on Sep 18, 2017

    @fadwafb

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

  20. flovilmart commented on Sep 18, 2017

    @flovilmart
    Contributor

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

  21. fadwafb commented on Sep 18, 2017

    @fadwafb

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

  22. flovilmart commented on Sep 18, 2017

    @flovilmart
    Contributor

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

  23. Abderezai commented on Sep 19, 2017

    @Abderezai

    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: '[email protected]',
    domain: 'mailgun.example.com',
    apiKey: 'key-####',
    }

    I tried parse-server-mailgun and same issue

  24. flovilmart commented on Sep 19, 2017

    @flovilmart
    Contributor

    @Abderezai publicServerUrl seems to have a typo

  25. Abderezai commented on Sep 19, 2017

    @Abderezai

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

  26. Nes-si commented on Apr 3, 2018

    @Nes-si
    Contributor
  27. flovilmart commented on Apr 3, 2018

    @flovilmart
    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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions