Mongoose - validate email syntax

node.jsMongodbMongoose

node.js Problem Overview


I have a mongoose schema for users (UserSchema) and I'd like to validate whether the email has the right syntax. The validation that I currently use is the following:

UserSchema.path('email').validate(function (email) {
  return email.length
}, 'The e-mail field cannot be empty.')

However, this only checks if the field is empty or not, and not for the syntax.

Does something already exist that I could re-use or would I have to come up with my own method and call that inside the validate function?

node.js Solutions


Solution 1 - node.js

you could also use the match or the validate property for validation in the schema

example

var validateEmail = function(email) {
    var re = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
    return re.test(email)
};

var EmailSchema = new Schema({
    email: {
	    type: String,
	    trim: true,
        lowercase: true,
        unique: true,
        required: 'Email address is required',
	    validate: [validateEmail, 'Please fill a valid email address'],
	    match: [/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/, 'Please fill a valid email address']
    }
});

Solution 2 - node.js

I use validator for my input sanitation, and it can be used in a pretty cool way.

Install it, and then use it like so:

import { isEmail } from 'validator';
// ... 

const EmailSchema = new Schema({
    email: { 
        //... other setup
        validate: [ isEmail, 'invalid email' ]
    }
});

works a treat, and reads nicely.

Solution 3 - node.js

You can use a regex. Take a look at this question: https://stackoverflow.com/questions/46155/validate-email-address-in-javascript

I've used this in the past.

UserSchema.path('email').validate(function (email) {
   var emailRegex = /^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/;
   return emailRegex.test(email.text); // Assuming email has a text attribute
}, 'The e-mail field cannot be empty.')

Solution 4 - node.js

The validator dosn't play well with mongoose to get rid of the warning set isAsync to false

const validator = require('validator');

email:{
type:String,
validate:{
      validator: validator.isEmail,
      message: '{VALUE} is not a valid email',
      isAsync: false
    }
}

Solution 5 - node.js

I know this is old, but I don't see this solution so thought I would share:

const schema = new mongoose.Schema({
    email: {
        type: String,
        trim: true,
        lowercase: true,
        unique: true,
        validate: {
            validator: function(v) {
                return /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(v);
            },
            message: "Please enter a valid email"
        },
        required: [true, "Email required"]
    }
});

You can do this for any type you want to validate and just pass the appropriate regex expression. If you google the type you want to validate and it's related regex expression it's easy to find a solution. This will keep your validations consistent and puts all the code in the schema instead of hanging functions.

Solution 6 - node.js

For some reason validate: [ isEmail, 'Invalid email.'] doesn't play well with validate() tests.

const user = new User({ email: 'invalid' });
try {
  const isValid = await user.validate();
} catch(error) {
  expect(error.errors.email).to.exist; // ... it never gets to that point.
}

But mongoose 4.x (it might work for older versions too) has other alternative options which work hand in hand with Unit tests.

Single validator:

email: {
  type: String,
  validate: {
    validator: function(value) {
      return value === 'correct@example.com';
    },
    message: 'Invalid email.',
  },
},

Multiple validators:

email: {
  type: String,
  validate: [
    { validator: function(value) { return value === 'handsome@example.com'; }, msg: 'Email is not handsome.' },
    { validator: function(value) { return value === 'awesome@example.com'; }, msg: 'Email is not awesome.' },
  ],
},

How to validate email:

My recommendation: Leave that to experts who have invested hundreds of hours into building proper validation tools. (already answered in here as well)

npm install --save-dev validator

import { isEmail } from 'validator';
...
validate: { validator: isEmail , message: 'Invalid email.' }

Solution 7 - node.js

Email type for schemas - mongoose-type-email

var mongoose = require('mongoose');
require('mongoose-type-email');
 
var UserSchema = new mongoose.Schema({
    email: mongoose.SchemaTypes.Email
});

Possible Reference:

Solution 8 - node.js

email: {
    type: String,
    match: [/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, `Please fill valid email address`],
    validate: {
      validator: function() {
        return new Promise((res, rej) =>{
          User.findOne({email: this.email, _id: {$ne: this._id}})
              .then(data => {
                  if(data) {
                      res(false)
                  } else {
                      res(true)
                  }
              })
              .catch(err => {
                  res(false)
              })
        })
      }, message: 'Email Already Taken'
    }
  }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTamasView Question on Stackoverflow
Solution 1 - node.jsramon22View Answer on Stackoverflow
Solution 2 - node.jsKris SelbekkView Answer on Stackoverflow
Solution 3 - node.jsdannyp32View Answer on Stackoverflow
Solution 4 - node.jsPatryk AcuñaView Answer on Stackoverflow
Solution 5 - node.jsIsaac S. WeaverView Answer on Stackoverflow
Solution 6 - node.jszurfyxView Answer on Stackoverflow
Solution 7 - node.jso.zView Answer on Stackoverflow
Solution 8 - node.jsEka CiptaView Answer on Stackoverflow