1

In my Node.js/MERN app, I get error 250 2.0.0 OK 1590267554 o18sm275551eje.40 - gsmtp & something went wrong when I register my user for authentication and receive an email with EMPTY body. I am using the code from https://blog.bitsrc.io/email-confirmation-with-react-257e5d9de725 I can see user is added to mongodb database with confirmed set to false. Why am I not getting the complete email with confirmation? Please find my attached code for my MERN application. I would really appreciate a reply! Thank you!

Register


Register route in users which takes you to login and on React side OnSubmit starts chain of sending and confirming email.

router.post("/register", type, function (req, res, next) {
    // var tmp_path = req.file.path;
    if(!req.file){
      console.log("File missing");
    }
    /** The original name of the uploaded file
      stored in the variable "originalname". **/
    // var target_path = 'uploads/' + req.file.originalname;
    // /** A better way to copy the uploaded file. **/
    // var src = fs.createReadStream(tmp_path);
    // var dest = fs.createWriteStream(target_path);
    // src.pipe(dest);
    // fs.unlink(tmp_path);
    // src.on('end', function() { res.render('complete'); });
    // src.on('error', function(err) { res.render('error'); });
  // Form validation
    const { errors, isValid } = validateRegisterInput(req.body);
    const url = req.protocol + '://' + req.get('host')


    // Check validation
    if (!isValid) {
      return res.status(400).json(errors);
    }

    //Checks email against registered emails in database
    registeredemails.findOne({ email: req.body.email}).select("email").lean().then(result => {
      if (!result) {
          return res.status(400).json({email: "Email not provided"});
      }
    });

    User.findOne({ email: req.body.email }).then(user => 
      {
        if (user) {return res.status(400).json({ email: "Email already exists" })
      } 
      else if(!user){
        const newUser = new User({
                firstName: req.body.firstName,
                lastName: req.body.lastName,
                email: req.body.email,
                password: req.body.password,
                fileimg: url + '/public/' + req.file.filename
            });
            // // Hash password before saving in database
            bcrypt.genSalt(10, (err, salt) => {
              bcrypt.hash(newUser.password, salt, (err, hash) => {
                if (err) throw err;
                newUser.password = hash;
                newUser
                .save()
                .then(newUser => 
                  sendEmail(newUser.email), 
                  templates.confirm(newUser._id)
                  )
                .then(() => res.json({ msg: msgs.confirm }))
                .catch(err => console.log(err))
            }
              )}
            )}
      else if (user && !user.confirmed) {
                  sendEmail(user.email, templates.confirm(user._id))
                    .then(() => res.json({ msg: msgs.resend })).catch(err => console.log(err))
                }

                // The user has already confirmed this email address
       else {
             res.json({ msg: msgs.alreadyConfirmed })
            }
     }).catch(err => console.log(err))

sendemail as used in the MEDIUM articles

const nodemailer = require('nodemailer');
const { CLIENT_ORIGIN } = require('../../config')
// const mg = require('nodemailer-mailgun-transport');
// The credentials for the email account you want to send mail from. 
const credentials = {
  secure: true,
  service: 'Gmail',
  auth: {
    user: process.env.MAIL_USER, 
    pass: process.env.MAIL_PASS 
    // These environment variables will be pulled from the .env file
    // apiKey: 'b61286bf9e28b149fac32220f0c7349f-e5e67e3e-00a38515',
    // domain: 'sandbox0b8a7f0ebcc74c0d8161304f24909bd2.mailgun.org'
  }
}

// Getting Nodemailer all setup with the credentials for when the 'sendEmail()'
// function is called.
const transporter = nodemailer.createTransport(credentials)

// exporting an 'async' function here allows 'await' to be used
// as the return value of this function.
module.exports = async (to, content) => {

  // The from and to addresses for the email that is about to be sent.
  const contacts = {
    from: process.env.MAIL_USER,
    to // An array if you have multiple recipients.
    // subject: 'React Confirm Email',
    // html: `
    //   <a href='${CLIENT_ORIGIN}/confirm/${id}'>
    //     click to confirm email
    //   </a>
    // `,      
    // text: `Copy and paste this link: ${CLIENT_ORIGIN}/confirm/${id}`
  }

  // Combining the content and contacts into a single object that can
  // be passed to Nodemailer.
  const email = Object.assign({}, content, contacts)

  // This file is imported into the controller as 'sendEmail'. Because 
  // 'transporter.sendMail()' below returns a promise we can write code like this
  // in the contoller when we are using the sendEmail() function.
  //
  //  sendEmail()
  //   .then(() => doSomethingElse())
  // 
  // If you are running into errors getting Nodemailer working, wrap the following 
  // line in a try/catch. Most likely is not loading the credentials properly in 
  // the .env file or failing to allow unsafe apps in your gmail settings.
  await transporter.sendMail(email, function(error, info){
    if(error)
      {
         return console.log(error);
      }
      else
      {
         return console.log(info.response);
      }      
  })

}

templates.confirm as used in Medium article

onst { CLIENT_ORIGIN } = require('../../config')

// This file is exporting an Object with a single key/value pair.
// However, because this is not a part of the logic of the application
// it makes sense to abstract it to another file. Plus, it is now easily 
// extensible if the application needs to send different email templates
// (eg. unsubscribe) in the future.
module.exports = {

  confirm: id => ({
    subject: 'React Confirm Email',
    html: `
      <a href='${CLIENT_ORIGIN}/confirm/${id}'>
        click to confirm email
      </a>
    `,      
    text: `Copy and paste this link: ${CLIENT_ORIGIN}/confirm/${id}`
  })

}
Bilal Hussain
  • 85
  • 2
  • 9

0 Answers0