How to code a Meteor method for a contact form


#1

The following method definition for a contact form does not work for me:
I have tried with Meteor.defer and thi.unblock but they both do not work.
Please help, I am blocked.

import { Meteor } from 'meteor/meteor';
import { ValidatedMethod } from 'meteor/mdg:validated-method';
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
import { DDPRateLimiter } from 'meteor/ddp-rate-limiter';
import { Email } from 'meteor/email';
import { _ } from 'meteor/underscore';

export const sendMessage = new ValidatedMethod({
  name: 'contact.sendMessage',
  validate: new SimpleSchema({
    name: { type: String },
    email: { type: String, regEx: SimpleSchema.RegEx.Email },
    subject: { type: String },
    message: { type: String },
  }).validator({ clean: true, filter: true }),
  run({ name, email, subject, message }) {
      let options = {};
      options.to = Meteor.settings.private.admin.email;
      options.from = email;
      options.subject = subject;
      options.text = `Name ${name}\nEmail ${email}\nSubject ${subject}\nMessage\n${message}`;
    //this.unblock();
    Meteor.defer(() => {
      Email.send(options);
    });
  },
});

#2

I assume this doesn’t send any email ?
Try replacing the argument passed to Email.send with this:

{
 to: toEmail,
 from: fromEmail,
 subject,
 text: emailMessage
}

What you’re doing, using the shorthand for object properties, is like passing:

{
 toEmail: toEmail,
 fromEmail: fromEmail,
 etc...
}

Which isn’t the properties expected by Email.send, so it’s probably why it’s not working.


#3

The problem I have is with this.unblock and Meteor.defer(function() { })

Meteor.defer throws the following error:
Exception while simulating the effect of invoking 'contact.sendMessage’
Error: Can’t set timers inside simulations

this.unblock(); throws the following error:
Exception while simulating the effect of invoking 'contact.sendMessage’
TypeError: Cannot read property ‘send’ of undefined
Email is undefined


#4

Sounds like your issue is in the client side simulation of the method. Which makes sense, since Email is unavailable to the client.

Just wrap that part in a if (!this.isSimulation) { ... } block like so:

  run({ name, email, subject, message }) {
      let options = {};
      options.to = Meteor.settings.private.admin.email;
      options.from = email;
      options.subject = subject;
      options.text = `Name ${name}\nEmail ${email}\nSubject ${subject}\nMessage\n${message}`;
      if (!this.isSimulation) {
        this.unblock();
        Email.send(options);
      }
    });
  },

#5

Meteor.settings.private.admin.email;
that line is also server only

Is the following correct?

  run({ name, email, subject, message }) {
    if (!this.isSimulation) {
      let options = {};
      options.to = Meteor.settings.private.admin.email;
      options.from = email;
      options.subject = subject;
      options.text = `Name ${name}\nEmail ${email}\nSubject ${subject}\nMessage\n${message}`;
      this.unblock();
      Email.send(options);
    }
    
    return true;
  },

#6

Oops, I missed that part.

Yep that’ll work!