如何用express / node确认电子邮件地址?

时间:2016-08-23 05:09:46

标签: node.js express

我正在尝试为用户构建确认电子邮件地址,以验证他们的电子邮件是否真实。我应该用什么软件包来确认用户的电子邮件地址。到目前为止我使用mongoose并表达

代码示例

var UserSchema = new mongoose.Schema({
    email: { type: String, unique: true, lowercase: true }
    password: String
});

var User = mongoose.model('User', UserSchema);

app.post('/signup', function(req, res, next) {
   // Create a new User
   var user = new User();
   user.email = req.body.email;
   user.password = req.body.password;
   user.save();
});

在app.post代码中,如何确认用户的电子邮件地址?

8 个答案:

答案 0 :(得分:109)

您要查找的内容称为“帐户验证”或“电子邮件验证”。有很多Node模块可以执行此操作,但原理如下:

  • 您的用户模型应具有默认为active的{​​{1}}属性
  • 当用户提交有效的注册表单时,请创建一个新用户(最初false active}
  • 创建随机哈希并将其存储在数据库中,并引用用户ID
  • 发送电子邮件至提供的电子邮件地址,并将哈希作为指向服务器上路由的链接的一部分
  • 当用户点击链接并点击您的路线时,请检查网址
  • 中传递的哈希值
  • 如果数据库中存在哈希,请获取相关用户并将其false属性设置为active
  • 从数据库中删除哈希值,不再需要

您的用户现已经过验证。

答案 1 :(得分:20)

var express=require('express');
var nodemailer = require("nodemailer");
var app=express();
/*
    Here we are configuring our SMTP Server details.
    STMP is mail server which is responsible for sending and recieving email.
*/
var smtpTransport = nodemailer.createTransport("SMTP",{
    service: "Gmail",
    auth: {
        user: "Your Gmail ID",
        pass: "Gmail Password"
    }
});
var rand,mailOptions,host,link;
/*------------------SMTP Over-----------------------------*/

/*------------------Routing Started ------------------------*/

app.get('/',function(req,res){
    res.sendfile('index.html');
});
app.get('/send',function(req,res){
        rand=Math.floor((Math.random() * 100) + 54);
    host=req.get('host');
    link="http://"+req.get('host')+"/verify?id="+rand;
    mailOptions={
        to : req.query.to,
        subject : "Please confirm your Email account",
        html : "Hello,<br> Please Click on the link to verify your email.<br><a href="+link+">Click here to verify</a>" 
    }
    console.log(mailOptions);
    smtpTransport.sendMail(mailOptions, function(error, response){
     if(error){
            console.log(error);
        res.end("error");
     }else{
            console.log("Message sent: " + response.message);
        res.end("sent");
         }
});
});

app.get('/verify',function(req,res){
console.log(req.protocol+":/"+req.get('host'));
if((req.protocol+"://"+req.get('host'))==("http://"+host))
{
    console.log("Domain is matched. Information is from Authentic email");
    if(req.query.id==rand)
    {
        console.log("email is verified");
        res.end("<h1>Email "+mailOptions.to+" is been Successfully verified");
    }
    else
    {
        console.log("email is not verified");
        res.end("<h1>Bad Request</h1>");
    }
}
else
{
    res.end("<h1>Request is from unknown source");
}
});

/*--------------------Routing Over----------------------------*/

app.listen(3000,function(){
    console.log("Express Started on Port 3000");
});

按照代码示例,您可以使用nodemailer发送链接,然后验证它。 这是一个链接:https://codeforgeek.com/2014/07/node-email-verification-script/

答案 2 :(得分:8)

我想提出一种与提议的方法略有不同的方法。

此方法不会将哈希放入数据库(因此与哈希的交互较少)

您不需要在数据库中注册哈希。收到注册请求后的概述如下:

  1. 您对用户ID +注册时间进行编码
  2. 您将令牌发送给用户
  3. 当用户触发他的注册请求时,您对令牌进行解码。
  4. 因为解码后的令牌包含用户ID +时间,所以您可以 通过增加其角色将用户标记为已注册 (注册,订户,管理员等)

翻译成代码,您将得到以下内容:

1-编码令牌

function encodeRegistrationToken()
{
    // jsonweb automatically adds a key that determines the time, but you can use any module
    const jwt = require('jsonwebtoken');

    // The information we need to find our user in the database (not sensible info)
    let info = {id: yourUserId};

    // The hash we will be sending to the user
    const token = jwt.sign(info, "yoursecretkey");

    return token;
}

// ... 
let token = encodeRegistrationToken();

2-通过任何适当的方式将令牌发送给用户

// Your implementation of sending the token
sendTokenToUser(token);

3-解码令牌

function decodeRegistrationToken(token)
{   
    const jwt = require('jsonwebtoken');
    let decoded = jwt.verify(token, "yoursecretkey");

    let userId = decoded.id;

    // Check that the user didn't take too long
    let dateNow = new Date();
    let tokenTime = decoded.iat * 1000;

    // Two hours
    let hours = 2;
    let tokenLife = hours * 60 * 1000;

    // User took too long to enter the code
    if (tokenTime + tokenLife < dateNow.getTime())
    {
        return {            
            expired: true
        };
    }

    // User registered in time
    return {
        userID
    };

}

4-更新数据库

  • 将用户角色升级为订户

  • 将其“注册”键设置为true

快速说明:如果需要,您可以在对令牌进行编码时进一步对用户ID进行编码(易于访问)。

答案 3 :(得分:6)

步骤1:

用户模型

var userSchema = new mongoose.Schema({
    email: { type: String, unique: true },
    isVerified: { type: Boolean, default: false },
    password: String,
  });

令牌模型

const tokenSchema = new mongoose.Schema({
    _userId: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'User' },
    token: { type: String, required: true },
    expireAt: { type: Date, default: Date.now, index: { expires: 86400000 } }
});

第2步:登录

exports.login = function(req, res, next) {
    User.findOne({ email: req.body.email }, function(err, user) {
        // error occur
        if(err){
            return res.status(500).send({msg: err.message});
        }
        // user is not found in database i.e. user is not registered yet.
        else if (!user){
            return res.status(401).send({ msg:'The email address ' + req.body.email + ' is not associated with any account. please check and try again!'});
        }
        // comapre user's password if user is find in above step
        else if(!Bcrypt.compareSync(req.body.password, user.password)){
            return res.status(401).send({msg:'Wrong Password!'});
        }
        // check user is verified or not
        else if (!user.isVerified){
            return res.status(401).send({msg:'Your Email has not been verified. Please click on resend'});
        } 
        // user successfully logged in
        else{
            return res.status(200).send('User successfully logged in.');
        }
    });

});

第3步:注册

exports.signup = function(req, res, next) {
  User.findOne({ email: req.body.email }, function (err, user) {
    // error occur
    if(err){
        return res.status(500).send({msg: err.message});
    }
    // if email is exist into database i.e. email is associated with another user.
    else if (user) {
        return res.status(400).send({msg:'This email address is already associated with another account.'});
    }
    // if user is not exist into database then save the user into database for register account
    else{
        // password hashing for save into databse
        req.body.password = Bcrypt.hashSync(req.body.password, 10);
        // create and save user
        user = new User({ name: req.body.name, email: req.body.email, password: req.body.password });
        user.save(function (err) {
            if (err) { 
              return res.status(500).send({msg:err.message});
            }
            
            // generate token and save
            var token = new Token({ _userId: user._id, token: crypto.randomBytes(16).toString('hex') });
            token.save(function (err) {
              if(err){
                return res.status(500).send({msg:err.message});
              }

                // Send email (use credintials of SendGrid)
                var transporter = nodemailer.createTransport({ service: 'Sendgrid', auth: { user: process.env.SENDGRID_USERNAME, pass: process.env.SENDGRID_PASSWORD } });
                var mailOptions = { from: 'no-reply@example.com', to: user.email, subject: 'Account Verification Link', text: 'Hello '+ req.body.name +',\n\n' + 'Please verify your account by clicking the link: \nhttp:\/\/' + req.headers.host + '\/confirmation\/' + user.email + '\/' + token.token + '\n\nThank You!\n' };
                transporter.sendMail(mailOptions, function (err) {
                    if (err) { 
                        return res.status(500).send({msg:'Technical Issue!, Please click on resend for verify your Email.'});
                     }
                    return res.status(200).send('A verification email has been sent to ' + user.email + '. It will be expire after one day. If you not get verification Email click on resend token.');
                });
            });
        });
    }
    
  });

});

第4步:验证帐户

// It is GET method, you have to write like that
//    app.get('/confirmation/:email/:token',confirmEmail)

exports.confirmEmail = function (req, res, next) {
    Token.findOne({ token: req.params.token }, function (err, token) {
        // token is not found into database i.e. token may have expired 
        if (!token){
            return res.status(400).send({msg:'Your verification link may have expired. Please click on resend for verify your Email.'});
        }
        // if token is found then check valid user 
        else{
            User.findOne({ _id: token._userId, email: req.params.email }, function (err, user) {
                // not valid user
                if (!user){
                    return res.status(401).send({msg:'We were unable to find a user for this verification. Please SignUp!'});
                } 
                // user is already verified
                else if (user.isVerified){
                    return res.status(200).send('User has been already verified. Please Login');
                }
                // verify user
                else{
                    // change isVerified to true
                    user.isVerified = true;
                    user.save(function (err) {
                        // error occur
                        if(err){
                            return res.status(500).send({msg: err.message});
                        }
                        // account successfully verified
                        else{
                          return res.status(200).send('Your account has been successfully verified');
                        }
                    });
                }
            });
        }
        
    });
});

第5步:重新发送链接

exports.resendLink = function (req, res, next) {

    User.findOne({ email: req.body.email }, function (err, user) {
        // user is not found into database
        if (!user){
            return res.status(400).send({msg:'We were unable to find a user with that email. Make sure your Email is correct!'});
        }
        // user has been already verified
        else if (user.isVerified){
            return res.status(200).send('This account has been already verified. Please log in.');
    
        } 
        // send verification link
        else{
            // generate token and save
            var token = new Token({ _userId: user._id, token: crypto.randomBytes(16).toString('hex') });
            token.save(function (err) {
                if (err) {
                  return res.status(500).send({msg:err.message});
                }
    
                // Send email (use credintials of SendGrid)
                    var transporter = nodemailer.createTransport({ service: 'Sendgrid', auth: { user: process.env.SENDGRID_USERNAME, pass: process.env.SENDGRID_PASSWORD } });
                    var mailOptions = { from: 'no-reply@example.com', to: user.email, subject: 'Account Verification Link', text: 'Hello '+ user.name +',\n\n' + 'Please verify your account by clicking the link: \nhttp:\/\/' + req.headers.host + '\/confirmation\/' + user.email + '\/' + token.token + '\n\nThank You!\n' };
                    transporter.sendMail(mailOptions, function (err) {
                       if (err) { 
                        return res.status(500).send({msg:'Technical Issue!, Please click on resend for verify your Email.'});
                     }
                    return res.status(200).send('A verification email has been sent to ' + user.email + '. It will be expire after one day. If you not get verification Email click on resend token.');
                });
            });
        }
    });
});

您可以从以下链接获取帮助:https://medium.com/@slgupta022/email-verification-using-sendgrid-in-node-js-express-js-mongodb-c5803f643e09

答案 4 :(得分:5)

我花了很多时间弄清楚发送确认邮件的完美方式。这是我使用的方法。

图书馆

const jwt = require('jsonwebtoken');
const nodemailer = require("nodemailer");

第1步 将用户ID编码为带有到期日期的jwt令牌

var date = new Date();
var mail = {
            "id": user.id,
            "created": date.toString()
            }

const token_mail_verification = jwt.sign(mail, config.jwt_secret_mail, { expiresIn: '1d' });

var url = config.baseUrl + "verify?id=" + token_mail_verification;

第2步 使用nodemailer库将令牌发送到用户电子邮件地址

 let transporter = nodemailer.createTransport({
        name: "www.domain.com",
        host: "smtp.domain.com",
        port: 323,
        secure: false, // use SSL
        auth: {
            user: "user@domain.com", // username for your mail server
            pass: "Password", // password
        },

    });

    // send mail with defined transport object
    let info = await transporter.sendMail({
        from: '"NAME" <user@domain.com>', // sender address
        to: user.email, // list of receivers seperated by comma
        subject: "Account Verification", // Subject line
        text: "Click on the link below to veriy your account " + url, // plain text body
    }, (error, info) => {

        if (error) {
            console.log(error)
            return;
        }
        console.log('Message sent successfully!');
        console.log(info);
        transporter.close();
    });

第3步 接受验证链接

app.get('/verify', function(req, res) {
    token = req.query.id;
    if (token) {
        try {
            jwt.verify(token, config.jwt_secret_mail, (e, decoded) => {
                if (e) {
                    console.log(e)
                    return res.sendStatus(403)
                } else {
                    id = decoded.id;

                
//Update your database here with whatever the verification flag you are using 



                }

            });
        } catch (err) {

            console.log(err)
            return res.sendStatus(403)
        }
    } else {
        return res.sendStatus(403)

    }

})

第4步 喝杯咖啡,谢谢,可以节省很多时间

PS:此nodemailer SMTP方法甚至可以与您的主机一起使用。因此,无需去寻求第三方。您还可以找到将gmail与nodemailer结合使用的方法。

答案 5 :(得分:4)

如果您只是在本地计算机上进行测试,了解如何操作的一种简单方法可以是:

假设您已经知道通过nodemailer发送邮件..

用户注册后,在您的数据库中存储注册数据后,在您的服务器端从收到的注册数据和随机生成的数字中获取用户电子邮件,并构建一个自定义网址,其中包含用户所在页面的地址在他/她点击邮件中给出的链接后执导。

var customUrl = "http://"+ your host + "/" + your verification web-page + "?email=" + userEmail + "&id=" + randomNumber;

一个例子可以是:

var userEmail = someone@example.com
var host = localhost:8080
var directWebPage = verifyUserEmail.html
var randomNumber = // generate with math.random() // lets say 111

使用上面的customUrl格式,它看起来像这样

customUrl:http://localhost:8080/verifyUserEmail.htmlemail=someone@example.com&id=111

将此customUrl保存在某处(可能在您的数据库中) 现在,使用包含此cutomUrl链接的电子邮件正文向用户发送电子邮件。

<a href="customUrl">Click to verify your email</a>

当用户点击链接时,他/她将被定向到 verifyUserEmail.html 页面,当发生这种情况时,您可以提取页面 网址 包含 电子邮件 id 信息

例如,在角度我就像这样 -

var urlVerifyData = $location.url(); or $location.absUrl();

现在使用javascript字符串方法从 电子邮件 表单 urlVerifyData 字符串

使用此 电子邮件 urlVerifyData

请求您的服务器

现在向您的数据库查询此电子邮件,并使用用户的 urlVerifyData

验证以前存储的 customUrl

如果匹配,hola!你有一个真正的用户!!!

答案 6 :(得分:0)

请使用NPM软件包(两步身份验证)

我制作了一个NPM软件包,可以用来验证您提供的电子邮件ID,该软件包将接收电子邮件ID并返回给您一个OTP,然后发送与您提供相同OTP的电子邮件ID,您可以进行验证然后将散列的邮件ID轻松存储在您的数据库中,并确保它们是真实的:)

Kindly check the full procedures with example here

用法

const {Auth} = require('two-step-auth');

async function login(emailId){
    const res = await Auth(emailId);
    // You can follw the above approach, But we recommend you to follow the one below, as the mails will be treated as important
    const res = await Auth(emailId, "Company Name");
    console.log(res);
    console.log(res.mail);
    console.log(res.OTP);
    console.log(res.success);
}

login("YourEmail@anyDomain.com")

输出

enter image description here 这将帮助您在HOOD下进行很多验证工作:)

答案 7 :(得分:-2)

    function generateLink() {
        var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        var token = '';
        for (var i = 16; i > 0; --i) {
            var rand = Math.round(Math.random() * (chars.length - 1))
            token += chars[rand];
        }
        var link = "http://localhost" + "/verify?id=" + token;
        return link;
    }

    // npm install @sendGrid/mail --save

    //library for generating link using SendGrid
    const sgMail = require('@sendgrid/mail');
    sgMail.setApiKey("SENDGRID_API_KEY"); //create an account on sendgrid and get an API key

    // generated link is send to the user's email for email verification
    let sendVerifyEmailLink = (req, res) => {
        var link = generateLink();
        const msg = {
            to: 'test@gmail.com',
            from: 'test@gmail.com',
            subject: 'Account Verifictaion',
            text: 'Hello,\n\n' + 'Please verify your account by clicking the link:\/\/\n',
            html: 'Hello,\n\n <br> Please verify your account by clicking the link: \n <br> <strong><a href = ' + link + '>http:\/\/ Click here to verify the given Link </a></strong>.\n .<br>Thanks<br>',
        };
        sgMail.send(msg).then(() => { }, error => {
            console.error(error);

            if (error.response) {
                console.error(error.response.body)
            }
        });
        console.log(msg)
    }