如何编写与不区分大小写的电子邮件匹配的正则表达式?

时间:2016-05-29 09:57:37

标签: regex mongoose

我有以下代码可以通过电子邮件找到用户。

User.findOne({
        email: { $regex: new RegExp('^' + req.body.email.toLowerCase() + '$','i') }
})

它通过小写字母和不区分大小写的搜索找到给定电子邮件的用户。

问题是,我们有一些电子邮件,例如 john+doe@johndoe.com ,这个正则表达式与这些电子邮件不匹配。

我应该在正则表达式中添加什么才能找到那种电子邮件?

2 个答案:

答案 0 :(得分:1)

问题是您使用的电子邮件地址为req.body.email,未转义为正则表达式。

正如您所注意到的,在正则表达式中具有特殊含义的字符(如+)将导致问题。更糟糕的是,当用户输入.*作为其电子邮件地址时,您的查询将与任何用户匹配,这是一个安全问题。

你想要的是逃避电子邮件地址输入,以便按原样搜索任何特殊字符(从中删除它们的“特殊含义”)。

最简单的方法是使用像regex-escape这样的模块来完成这项工作:

var escape = require('regex-escape');

...

User.findOne({
  email: { $regex: new RegExp('^' + escape(req.body.email) + '$','i') }
})

由于正则表达式已设置为不区分大小写,因此不需要小写字符串。

答案 1 :(得分:-1)

描述

我使用这个表达式,它并不完美,因为有一些边缘情况会漏掉但是这些很容易通过简单发送测试邮件进行测试:

^[_a-z0-9-+]+(?:\.[_a-z0-9-+]+)*@[a-z0-9-]+(?:\.[a-z0-9-]+)*(?:\.[a-z]{2,4})$

Regular expression visualization

通过向每个字符类添加A-Z,我使相同的表达式不区分大小写。

^[_a-zA-Z0-9-+]+(?:\.[_a-zA-Z0-9-+]+)*@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*(?:\.[a-zA-Z]{2,4})$

实施例

现场演示

https://regex101.com/r/uC5oG4/1

解释

NODE                     EXPLANATION
----------------------------------------------------------------------
  ^                        the beginning of a "line"
----------------------------------------------------------------------
  [_a-z0-9-+]+             any character of: '_', 'a' to 'z', '0' to
                           '9', '-', '+' (1 or more times (matching
                           the most amount possible))
----------------------------------------------------------------------
  (?:                      group, but do not capture (0 or more times
                           (matching the most amount possible)):
----------------------------------------------------------------------
    \.                       '.'
----------------------------------------------------------------------
    [_a-z0-9-+]+             any character of: '_', 'a' to 'z', '0'
                             to '9', '-', '+' (1 or more times
                             (matching the most amount possible))
----------------------------------------------------------------------
  )*                       end of grouping
----------------------------------------------------------------------
  @                        '@'
----------------------------------------------------------------------
  [a-z0-9-]+               any character of: 'a' to 'z', '0' to '9',
                           '-' (1 or more times (matching the most
                           amount possible))
----------------------------------------------------------------------
  (?:                      group, but do not capture (0 or more times
                           (matching the most amount possible)):
----------------------------------------------------------------------
    \.                       '.'
----------------------------------------------------------------------
    [a-z0-9-]+               any character of: 'a' to 'z', '0' to
                             '9', '-' (1 or more times (matching the
                             most amount possible))
----------------------------------------------------------------------
  )*                       end of grouping
----------------------------------------------------------------------
  (?:                      group, but do not capture:
----------------------------------------------------------------------
    \.                       '.'
----------------------------------------------------------------------
    [a-z]{2,4}               any character of: 'a' to 'z' (between 2
                             and 4 times (matching the most amount
                             possible))
----------------------------------------------------------------------
  )                        end of grouping
----------------------------------------------------------------------
  $                        before an optional \n, and the end of a
                           "line"
----------------------------------------------------------------------