
我們有一個 postfix 安裝,其中有幾個虛擬網域,每個虛擬網域都有虛擬使用者。這些網域和使用者使用 mysql 資料庫進行對應。到目前為止,我一直透過解析 postfix 日誌檔案來追蹤退回郵件。我懷疑一定有更好、更有效的方法來做到這一點。我想到了三個,但我不確定哪個最好:
- 寫一個 Postfix 內容過濾器來記錄退回郵件並丟棄郵件
- 使用 procmail - 但我不確定 procmail 如何與沒有定義 $HOME 的虛擬用戶一起工作
- 編寫一個從郵箱中 POP 郵件的腳本;解析並記錄它們並刪除退回的電子郵件
我希望就從維護的角度來看哪種方式最好以及從節省伺服器資源的角度來看哪種方式最有效提出建議。謝謝
答案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/運輸
[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