PL / Perl在Postgresql中发送邮件

时间:2012-09-03 07:04:52

标签: perl postgresql plpgsql

  

可能重复:
  psql trigger send email

我使用PL / Perl语言在Postgresql中发送邮件。当数据集表upload_status更改为已发布时,它会将邮件发送到数据集表中作者的电子邮件地址。并且在信中包含此作者在数据集中的一些记录。数据集PK是标识符。

像 从xx@mail.com发送到(dataset.email)@ mail.com

亲爱的博士(dataset.author)

你的......(dataset.product)已经.......

那么如何使用PL / Perl和触发函数来编写函数。

谢谢, 我使用这种方法http://evilrouters.net/2008/02/01/send-email-from-postgresql/

mydb=# CREATE OR REPLACE FUNCTION mydb_mytable_insert_send_mail_function()
mydb-# RETURNS "trigger" AS
mydb-# $BODY$
mydb$# use Mail::Sendmail;
mydb$#
mydb$# $message = "A new entry has been added to the 'mytable' table.\n\n";
mydb$# $message .= "The new name is: $_TD->{new}{name}\n\n";
mydb$#
mydb$# %mail = ( From => $_[0], To => $_[1], Subject => $_[2], Message => $message);
mydb$#
mydb$# sendmail(%mail) or die $Mail::Sendmail::error;
mydb$# return undef;
mydb$# $BODY$
mydb-# LANGUAGE 'plperlu' VOLATILE;

mydb=# CREATE TRIGGER mydb_mytable_insert_send_mail_trigger
mydb=# AFTER INSERT ON mytable
mydb=# FOR EACH ROW
mydb=# EXECUTE PROCEDURE mydb_mytable_insert_send_mail_function('from@domain.com',          'to@domain.com', 'subject here');

但它显示已发生错误无法在@INC中找到Mail / Sendmail.pm(@INC包含:/ usr /...

2 个答案:

答案 0 :(得分:10)

仅仅因为你不能意味着你应该这样做。有更好的方法来做到这一点。不要直接从PL做。如果你想忽略我的警告,请使用PL / PerlU并像任何其他电子邮件客户端一样编写它。您可以使用任何您喜欢的CPAN模块,让您的生活更轻松。

有两个原因:

1)如果您的交易中止/回滚怎么办?您已发送电子邮件但未对数据库进行相应更改。你在交易中做非交易的东西。

2)如果您的电子邮件在2分钟后获得tcp超时之前等待响应,该怎么办?你会忘记给客户发电子邮件吗?中止交易(无法发送电子邮件,不能说我们已经发货了!)?

这是一个糟糕的想法。不要这样做。感谢PostgreSQL发生此错误并将其移至另一个守护进程。

好得多的方法是使用LISTEN和NOTIFY以及队列表。然后,您可以创建一个这样的表:

CREATE TABLE email_queue (
    id serial not null unique,
    email_from text,
    email_to text not null,
    body text not null
); 

CREATE FUNCTION email_queue_trigger() RETURNS TRIGGER 
LANGUAGE PLPGSQL AS $F$
    BEGIN
        NOTIFY emails_waiting;
    END;
$F$;

然后将存储过程插入该表中。

然后,让第二个客户端应用程序在emails_waiting上侦听(sql语句LISTEN emails_waiting),然后执行以下操作:

  1. 检查email_queue中是否有记录。如果没有,请转到3。
  2. 读取数据,发送电子邮件,删除记录和提交。
  3. 当队列为空时,睡眠时间为x秒
  4. 在唤醒时,检查异步。通知(取决于客户端库,检查文档)。如果有,请转到1,如果没有,请转到3.
  5. 这允许您的电子邮件排队等待在您的交易中发送,并且这会自动传递到另一个应用程序,然后可以选择与MTA连接。

    第二个客户端应用程序可以使用您所知的任何工具以您选择的语言编写。它具有从事务中执行所有网络操作的优点,因此如果您通过第二个SMTP服务器发送,并且连接挂起,则整个数据库事务不会等待2分钟以使其超时并中止事务。因此,对未来的需求变化也更加安全。

答案 1 :(得分:6)

简答:不要。

答案很长:使用单独的流程发送电子邮件,只记录要在数据库中发送的要求。

发送电子邮件可能会暂时失败,可能会永久失败。迟早你会想要暂停发送电子邮件而不停止数据库的其余部分。然后有人会希望更改消息模板,而你真的不想为此更新数据库。

您的解决方案可以像message_queue表和每分钟运行一次的cron-job或使用LISTEN / NOTIFY的守护程序一样简单。我已经完成了几次这样的事情并且拥有一个单独的电子邮件发件人一直是更好的选择。