将退回的邮件记录到数据库(带有虚拟域/用户的 Postfix)

将退回的邮件记录到数据库(带有虚拟域/用户的 Postfix)

我们安装了 Postfix,其中有几个虚拟域,每个域都有虚拟用户。这些域和用户使用 mysql 数据库进行映射。到目前为止,我一直通过解析 Postfix 日志文件来跟踪退回。我怀疑一定有更好、更有效的方法来做到这一点。我想到了三种,但我不确定哪种最好:

  1. 编写一个 Postfix 内容过滤器,记录退回邮件并丢弃邮件
  2. 使用 procmail - 但我不确定 procmail 如何与没有定义 $HOME 的虚拟用户一起工作
  3. 编写一个脚本,从邮箱中弹出邮件;解析并记录邮件,然后删除退回的电子邮件

我很想听听您的建议,从维护的角度来看哪种方法最好,从节省服务器资源的角度来看哪种方法最有效。谢谢

答案1

这一切都假设您想要收集有关退回的电子邮件的信息,而不是退回的电子邮件本身:

我对 postfix、mysql 和虚拟主机的设置基本相同。从硬件资源角度来看,跟踪此情况的最有效方法是在执行操作时解析日志文件。但如果您认为解析方式负担过重,则可以使用 Logwatch 等应用程序为您完成所有解析。然后设置 Postfix 以为您丢弃退回的文件。

现在,如果您决定确实要在某处收集这些电子邮件,您可以在 main.cf 文件中使用这些设置:

bounce_notice_recipient = [email protected]
error_notice_recipient = [email protected]

如果你想彻底销毁电子邮件,你可以添加虚拟用户并调整别名文件以将其发送到 dev/null

someone: /dev/null

至于脚本和数据库,我最近经常使用 PHP 和 MySQL,因此如果我要使用这些工具,我可以创建一些 php 代码来读取日志文件,查找退回邮件,然后将它们写入数据库。然后,我会在 mail.log 被截断之前运行代码。事实上,我会在编写代码后在此处发布代码。

如果您想使用 php/mysql 运行它,这里有一些代码(我相信它会更漂亮):

<?php
#parse_logs.php
# load local file into array
$val = file("mail.log");

$pattern = '/status=bounced/';

foreach ($val as &$value) {
if (preg_match($pattern,$value)) {
        $a = split('[<>]', $value);

       //if you prefer you can also use: preg_match_all('/<(.*)>/', '$value', $matches);
       #can be helpful to print the following to the screen during tests
       # echo $a[1];

        // Make a MySQL Connection
        mysql_connect("localhost", "username", "password") or die(mysql_error());
        mysql_select_db("postfix_db") or die(mysql_error());

        // Insert a row of information into the table "example"
        mysql_query("INSERT INTO emails (emailaddress) VALUES('$a[1]') ") 
        or die(mysql_error());  

        #again, if you want to see while running manually from cli
        #echo "Data Inserted!";

}
#again, if you want to see while running manually from cli
#echo "\n";
}

?>

然后,您可以在 mail.log 设置为回收之前启动一个 cron,或者在 cron 启动后清除日志。

跟踪退回邮件的电子邮件地址似乎需要付出很多努力。当然,您需要编写 mysql 查询才能访问此信息。

您也可以完全跳过 mysql 内容,只需将结果传输到测试文件或电子邮件地址(也可以使用 cron)

php parse.php > results.txt

或者

php parse_logs.php | /usr/sbin/sendmail [email protected]

答案2

我没有示例,因为我从未尝试过,但您可以使用 syslog-ng(取决于您的平台),并创建一个过滤器。过滤器有一个选项可以对消息本身执行正则表达式匹配。您需要做的就是将其发送到特定目的地,该目的地将是 mysql。快速搜索将告诉您如何将 syslog-ng 设置为 mysql,并且一些调整可能会让您获得一个发送到该目的地的过滤器。

答案3

您可以将退回通知通过管道传输到脚本。以下是您可以如何实现它的概述:

/etc/postfix/main.cf

notify_classes = bounce, 2bounce, resource, software
[email protected]
[email protected]

/etc/postfix/transport

[email protected]     bouncepipe:

/etc/postfix/master.cf

bouncepipe   unix  -       n       n       -       -       pipe
      flags=DRhu user=list argv=/etc/postfix/bouncepipe.pl

/etc/postfix/bouncepipe.pl

#!/usr/bin/perl                                                                                                                                                                                                                                                                       

my $message = '';
my $sender = '';
my $recipient = '';

foreach $line ( <STDIN> )
{
    $message .= $line;
    chomp( $line );
    if ( $line =~ /Final-Recipient: /)
    {
        my $index = index($line, ';');
        $recipient = substr($line, $index+2);
    }
    if ( $line =~ /X-Postfix-Sender: /)
    {
        my $index = index($line, ';');
        $sender = substr($line, $index+2);
    }
}
# Do whatever you need to do with $sender and $recipient

相关内容