Sending welcome message AFTER email verification using onEmailVerificationLink

I was originally sending the welcome message immediately after registration, but it makes more sense to give a full welcome after the email address is verified, because the user is not allowed to log in until that happens.

So I tried to use Accounts.onEmailVerificationLink.

It’s actually a client-side function, which I found strange, as I would think that things would need to be done on the server after a user is fully verified, so a server-side callback would make more sense. Anyway, I guess it just means that a server method call needs to be done from the client.

So I added this code in a .js file under /client:

Accounts.onEmailVerificationLink((token, done) => {
    console.log("token: ", token);
    Accounts.verifyEmail(token, (err) => {
        if (err) {
            console.log("Error: ", err);
        } else {
            console.log("Calling Meteor.methods.emailSendWelcome");
            Meteor.call("Meteor.methods.emailSendWelcome", null, (error, result) => {
                if (error) console.log("Error: ", error);
            });

            done();
        }
    });
});

However it doesn’t get triggered at all, as none of those console.log() calls output anything.

Is this a bug in Meteor? Or am I doing something wrong?

1 Like

I really think there should be a server-side hook, called something like “onVerifiedEmail” that would execute after Accounts.verifyEmail, just as you have a server-side onCreateUser. At the moment using onEmailVerificationLink we need to include a call to Accounts.verifyEmail.

Given the verification link is a client-side route this is why it first needs to land there. Also, you will probably want a client-side route to redirect to once the verification is complete. So, that means you are responsible for passing the token back to the server with that call. Additionally, the Accounts package is router agnostic (if it had to have a fixed route then you would need to install a specific router or be restricted in what routes you could use).

In regard to the code - it looks perfectly fine to me. You should ensure you are calling it outside of a Meteor.startup() and also probably see if avoiding ES6 syntax for the callbacks works (that is how I use it and it seems to work fine).

Doco says: “This function should be called in top-level code, not inside Meteor.startup().”

1 Like

What the user tab00 wants is perfectly reasonable.

The meteor method he has written would not be optimal, since he would have to check the current verification state of the Meteor user in order to know not to send the welcome email more than once, in the case that the server method is called n-times (this check needs to exist otherwise a hacker could abuse the website). Forcing users to check Meteor internals to make a decision is fragile and therefore not best practice.

Would be nice to either have either the requested onVerifiedEmail hook, or provide a server route (which is again perfectly reasonable) so that people can intercept the verification email link and do whatever they want. Now I have to repeat the same weird workflow that users like tab00 (and others) have implemented.

1 Like

As a workaround, i used an after update collection hook on Meteor.users collection.

Looking at meteor verifyEmail method, there is this update at the end :

Meteor.users.update(
        {_id: user._id,
         'emails.address': tokenRecord.address},
        {$set: {'emails.$.verified': true},
         $pull: {'services.email.verificationTokens': {address: tokenRecord.address}}});

So the hook check for an update modifier that has $set that equals to {'emails.$.verified': true}

Meteor.users.after.update((userId, doc, fieldNames, modifier) => {
  if (_.isEqual(modifier.$set, { 'emails.$.verified': true })) {
    // your code here
  }
});

Where is the documentation for using after?

It’s from collection-hooks package

1 Like

This is necroing an old thread, but it’s still a top result on Google for performing actions on email verification when using accounts-ui, and this may be useful if you’re looking for that. This does not require additional packages.

With useraccounts you can configure an onSubmitHook function that will be called when a user logs in. This function takes two parameters, error and state. The documentation mentions that state can be signIn or signUp, but it can apparently also be verifyEmail:

const onSubmitHook = (error, state) => {
  if (!error) {
    // Successfully logged in

    // Logging in with email verification
    if (state === 'verifyEmail') {
      console.log('do things on email verification');
    }
  }
};

AccountsTemplates.configure({
  /* other configuration options omitted */
  onSubmitHook,
});

useraccounts configuration API

HTH

1 Like