How to code a Meteor method for a contact form

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);
    });
  },
});

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.

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

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);
      }
    });
  },

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;
  },
1 Like

Oops, I missed that part.

Yep that’ll work!

1 Like