Postgres 验证电子邮件地址的函数

发布于 2024-10-16 07:15:45 字数 515 浏览 1 评论 0原文

调用函数来验证电子邮件地址的检查约束对我来说效果不佳。

CREATE OR REPLACE FUNCTION f_IsValidEmail(text) returns BOOLEAN AS 
'select $1 ~ ''^[^@\s]+@[^@\s]+(\.[^@\s]+)+$'' as result
' LANGUAGE sql;



SELECT f_IsValidEmail('[email protected]');

该函数返回 false,这应该是 true。我尝试了其他几个正则表达式,但没有成功。谁能指出这个函数有什么问题吗?

屏幕截图

A check constraint which would call a function to validate email addresses is not working fine for me.

CREATE OR REPLACE FUNCTION f_IsValidEmail(text) returns BOOLEAN AS 
'select $1 ~ ''^[^@\s]+@[^@\s]+(\.[^@\s]+)+

The function is returning false, which should be true. I have tried a couple of other regexs but in vain. Can anyone point out what's wrong with this function?

Screenshot

' as result ' LANGUAGE sql; SELECT f_IsValidEmail('[email protected]');

The function is returning false, which should be true. I have tried a couple of other regexs but in vain. Can anyone point out what's wrong with this function?

Screenshot

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

神魇的王 2024-10-23 07:15:45

其中很多答案都接近正确的方式。这些就是我提交的要点。

  • 您想要使用域名 - 而不是规则系统。
  • 不想使用正则表达式验证这些电子邮件地址。(2017 年 3 月更新:不再正确)

我在 DBA.StackExchange.com 上展示了两种正确执行此操作的方法。既检查 MX 记录,又使用 HTML5 规范。这是简短而甜蜜的。

CREATE EXTENSION citext;
CREATE DOMAIN email AS citext
  CHECK ( value ~ '^[a-zA-Z0-9.!#$%&''*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*

如需了解更多信息,我强烈建议您完整阅读答案。在答案中,我还展示了如何通过 Email::Valid 创建 DOMAIN,并解释为什么我不再使用该方法。

); SELECT '[email protected]'::email; SELECT CAST('[email protected]' AS email);

如需了解更多信息,我强烈建议您完整阅读答案。在答案中,我还展示了如何通过 Email::Valid 创建 DOMAIN,并解释为什么我不再使用该方法。

A bunch of these answers are close to the right way. These are the points for my submission.

  • You want to use a domain -- NOT the rule system.
  • You do NOT want to validate these email addresses with a regex. (Update Mar 2017: not really true anymore)

I show two methods of how to do this the right on DBA.StackExchange.com. Both to check for the MX-record, and also using the HTML5 spec. Here is the short and sweet.

CREATE EXTENSION citext;
CREATE DOMAIN email AS citext
  CHECK ( value ~ '^[a-zA-Z0-9.!#$%&''*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*

For more information I highly suggest you read the answer in full. In the answer, I also show how you create a DOMAIN over Email::Valid, and explain why I no longer use that method.

); SELECT '[email protected]'::email; SELECT CAST('[email protected]' AS email);

For more information I highly suggest you read the answer in full. In the answer, I also show how you create a DOMAIN over Email::Valid, and explain why I no longer use that method.

变身佩奇 2024-10-23 07:15:45

在您投入大量精力之前,您要做的就是确保您没有删除有效的电子邮件地址。对于电子邮件地址中是否可以出现有各种疯狂的规则,如果您弄错了,方向错误,那么拥有完全有效的电子邮件地址的用户可能会被您的系统拒绝。

确定电子邮件地址是否有效的最佳方法是将其用作需要电子邮件的注册过程的一部分。任何其他事情都是劳而无功。

Before you go putting a lot of effort into this, the thing you want to do is make sure you're not kicking out valid email addresses. There's all kinds of insane rules for can or can't be in an email address, and if you get it wrong, in the wrong direction, a user with a perfectly valid email address might get rejected by your system.

The best way to determine if an email address is valid is to use it as part of a registration process where email is REQUIRED. Anything else is a lot of work for little gain.

一桥轻雨一伞开 2024-10-23 07:15:45

我推荐使用 PL/Perl 和 Email::Address 模块的解决方案。类似以下内容:

CREATE OR REPLACE FUNCTION email_valid(email text) RETURNS bool
LANGUAGE plperlu
AS $
use Email::Address;
my @addresses = Email::Address->parse($_[0]);
return scalar(@addresses) > 0 ? 1 : 0;
$;

另请参阅http://wiki.postgresql.org/wiki/Email_address_parsing

I recommend a solution using PL/Perl and the Email::Address module. Something like the following:

CREATE OR REPLACE FUNCTION email_valid(email text) RETURNS bool
LANGUAGE plperlu
AS $
use Email::Address;
my @addresses = Email::Address->parse($_[0]);
return scalar(@addresses) > 0 ? 1 : 0;
$;

See also http://wiki.postgresql.org/wiki/Email_address_parsing.

老旧海报 2024-10-23 07:15:45

如果您可以找出一个与电子邮件地址匹配的正则表达式,让您满意,请考虑它作为域而不是检查约束是否更有用。

对于一些陷阱,请参阅 regular-expressions.info

If you can figure out a regular expression that matches email addresses to your satisfaction, consider whether it might not be more useful as a domain rather than a check constraint.

For some of the pitfalls see regular-expressions.info.

未蓝澄海的烟 2024-10-23 07:15:45

不要尝试创建正则表达式来验证电子邮件!

众所周知,这是很难实现的。这是一个更好的解决方案:

假设您在数据库主机上安装了 Perl,请使用 CPAN 在同一主机上安装 Email::Valid 模块:

you@localhost$ cpan Email::Valid

然后确保您已安装 PL/Perl。在 psql 中连接到数据库并将 plperlu 添加为语言:(

CREATE EXTENSION plperlu;

请记住,这是一种不受信任的语言,因此您将向数据库提供直接文件访问权限,如果有人将恶意代码插入到数据库中,这可能会带来安全风险但是,您需要在下一步中执行此操作。)

将以下函数添加到数据库中:

CREATE FUNCTION validate_email() RETURNS trigger AS $
  use Email::Valid;
  return if Email::Valid->address($_TD->{new}{email});
  elog(ERROR, "invalid email address $_TD->{new}{email} inserted into $_TD->{table_name}(email)");
  return "SKIP";
$ LANGUAGE plperlu;

将触发器约束添加到列上的表中(假设您的表名为“users”)并且您的专栏名为“电子邮件”):

CREATE TRIGGER users_valid_email_trig
  BEFORE INSERT OR UPDATE ON users
  FOR EACH ROW EXECUTE PROCEDURE validate_email();

您就完成了!

该解决方案使用 Email::Valid Perl 模块来处理验证,而验证又依赖于正则表达式来确保 RFC 822 合规性。然而,它是一个正则表达式的怪物,所以不要尝试提出你自己的正则表达式。

如果您对启用 plperlu 而不是普通 plperl 感到不舒服,您可以将相关函数移植到数据库中。

Don't attempt to create a regex to validate e-mails!

It is notoriously difficult to accomplish. Here's a better solution:

Assuming that you have Perl installed on your database host, install the Email::Valid module on the same host using CPAN:

you@localhost$ cpan Email::Valid

Then make sure that you have PL/Perl installed. Connect to your database in psql and add plperlu as a language:

CREATE EXTENSION plperlu;

(Keep in mind that this is an untrusted language, so you'll be giving your db direct file access, which could pose a security risk if someone were to insert malicious code into your Perl modules or into the db functions. However, you need to do it for the next step.)

Add the following function to your database:

CREATE FUNCTION validate_email() RETURNS trigger AS $
  use Email::Valid;
  return if Email::Valid->address($_TD->{new}{email});
  elog(ERROR, "invalid email address $_TD->{new}{email} inserted into $_TD->{table_name}(email)");
  return "SKIP";
$ LANGUAGE plperlu;

Add a trigger constraint to your table on your column (assuming that your table is named "users" and your column is named "email"):

CREATE TRIGGER users_valid_email_trig
  BEFORE INSERT OR UPDATE ON users
  FOR EACH ROW EXECUTE PROCEDURE validate_email();

And you're done!

This solution uses the Email::Valid Perl module to handle validation, which in turn relies on a regex to ensure RFC 822 compliance. However, it is a monster of a regex, so don't try to come up with your own.

If you feel uncomfortable with enabling plperlu instead of plain plperl, you could probably port the relevant functions into your database.

感性 2024-10-23 07:15:45

对我有用:

psql (9.0.2)
Type "help" for help.

postgres=> CREATE OR REPLACE FUNCTION "f_IsValidEmail"(text) returns BOOLEAN AS
postgres-> 'select $1 ~ ''^[^@\s]+@[^@\s]+(\.[^@\s]+)+
' as result
postgres'> ' LANGUAGE sql;
CREATE FUNCTION
postgres=> commit;
COMMIT
postgres=> SELECT "f_IsValidEmail"('[email protected]');
 f_IsValidEmail
----------------
 t
(1 row)

postgres=>

Works for me:

psql (9.0.2)
Type "help" for help.

postgres=> CREATE OR REPLACE FUNCTION "f_IsValidEmail"(text) returns BOOLEAN AS
postgres-> 'select $1 ~ ''^[^@\s]+@[^@\s]+(\.[^@\s]+)+
' as result
postgres'> ' LANGUAGE sql;
CREATE FUNCTION
postgres=> commit;
COMMIT
postgres=> SELECT "f_IsValidEmail"('[email protected]');
 f_IsValidEmail
----------------
 t
(1 row)

postgres=>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文