Postfix/Dovecot
我想创造我的简单定制例如,使用 Python 编写的 Postfix 自动回复程序。我不需要任何第三方现成的程序。
我希望它具有一些自定义条件,例如“仅当‘来自 == A’或/和‘到 == B’或/和“今天没有对该电子邮件进行自动回复”时自动回复”等...
我发现我需要在 master.cf 中使用 content_filter 或 spawn。而不是 milter,因为 milter 是在消息被放入队列时触发的,而我需要自动回复已经收到的消息。可能吧。
其他更好的选择吗?
如何实现呢?
答案1
我认为没有简单(即琐碎)的方法可以做到这一点,而且很可能有多种解决方案。
我为我的邮件系统(它托管了相当数量的箱子和域)实现了这个功能,并且挂接到一个自定义的 CMS(BLISS3),如下所示:
添加到 /etc/postfix/master.cf
autoresponder
unix - n n - - pipe flags=Rq
user=mailuser argv=/etc/postfix/scripts/autoresponder.php ${sender} ${recipient}
这将执行我的脚本 autoresponder.php,解析发件人和收件人。如果您愿意,可以用 python 编写适当的自动回复程序。
然后我将以下内容添加到 /etc/postfix/transport
.autoresponder autoresponder:
当我将电子邮件副本转发给一个特殊的“[电子邮件保护]“电子邮件。如果您希望小规模地执行此操作,并且不需要保留收到的电子邮件的副本,那么您可能只需将“autoresponder”替换为您的电子邮件地址即可。
剩下的就是自动回复脚本本身。
我的PHP脚本如下:
#! /usr/bin/php
<?php
#########################################################################################
# Davids Autoresponder for BLISS3. This has been designed to query a database to pull
# the message contents from.
#########################################################################################
# How frequently to resend messages, ie only send 1 message per person every period.
# The idea of this is to prevent mail loops.
$period='1 day';
$dbconnection="mysql://username:[email protected]/mail";
# We take the input, and strip off the ".autoresponder" part, revealing our actual address.
$from=mysqli_real_escape_string(substr($argv[2],0,-14));
$to=mysqli_real_escape_string($argv[1]);
#########################################################################################
include "/usr/share/php/adodb/adodb.inc.php";
$ADODB_FETCH_MODE=ADODB_FETCH_ASSOC;
$conn=ADONewConnection($dbconnection);
$theargs=$argv[0]." ".$argv[1]." ".$argv[2]."\n";
syslog (LOG_WARNING,"Called autoresponder - $theargs");
# Check if the email is in our database of recently sent messages. If not, add it.
# If it is, do not resend. Also do not send emails if from = to
$sent=$conn->GetAll("select count(uid) from autoresponded where mailfrom='$from' and mailto='$to' and date > current_timestamp - interval '$period'");
if ( $sent[0]['count'] < 1 and $from != $to )
{
$q=$conn->Execute("insert into autoresponded (date,mailfrom,mailto) values (current_timestamp,'$from','$to')");
$messages=$conn->GetAll("select ar_subject, ar_body from virtual where mailfrom='".$from."'");
# No point in sending if we don't have a message to send.
if ($messages[0]['ar_subject'] != '' or $messages[0]['ar_body'] != '')
{
$headers='From: '.$from."\r\n";
$subject=pg_unescape_bytea($messages[0]['ar_subject']);
$message=pg_unescape_bytea($messages[0]['ar_body']);
mail ($to, $subject, $message,$headers);
}
}
# Automatically clean up after ourself.
$cleanup=$conn->Execute("delete from autoresponded where date < current_timestamp - interval '$period'");
如您所见,我使用一个简单的数据库来跟踪电子邮件最后一次发送到给定地址的时间,我会检查该地址以确保每天每个发件人发送的回复不超过 1 条,以防止邮件循环和其他烦恼。实际的回复电子邮件是通过一个简单的邮件命令完成的(倒数第 6 行)
如果你想做一些非常类似的事情,我的自动回复表的模式是:
Table "public.autoresponded"
Column | Type | Collation | Nullable | Default
----------+-----------------------------+-----------+----------+--------------------------------------------
uid | integer | | not null | nextval('autoresponded_uid_seq'::regclass)
date | timestamp without time zone | | | now()
mailfrom | character varying | | |
mailto | character varying | | |
引用 ar_header 和 ar_body 的行从数据库中提取适当的自动回复标题和正文。您可以创建/修改自己的表来执行此操作或对其进行硬编码。
希望以上内容能为您提供一个坚实的起点,让您可以做自己想做的事情。根据下面的 @TobiM 评论,将其用作代码的基础 - 您可能应该用准备好的语句替换 sql。我实际上还没有检查修改后的版本是否有效,并且它假设一个 mysql 数据库。