免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 7375 | 回复: 29
打印 上一主题 下一主题

[Mail] postfix如何在mta层将邮件传给自己写的shell脚本 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-04-03 12:21 |只看该作者 |倒序浏览
请问:
postfix如何在mta层将邮件传给自己写的shell脚本(不在mda层来实现)
目前是用mailscanner去调用f-prot和spamassassin,而我想在让邮件能够先用自己的shell脚本实现其它功能,然后再去扫描

论坛徽章:
0
2 [报告]
发表于 2007-04-05 11:47 |只看该作者
哪位高人,提示一下
谢谢

论坛徽章:
0
3 [报告]
发表于 2007-04-05 14:55 |只看该作者
在master.cf 增加一个过滤器,可以参考此文件内maildrop 的例子 或 man pipe

然后修改main.cf 内的 transport_maps

如 transport_maps = hash:/etc/postfix/transport

transport 文件的内容为

postmaster@domain.com  info_filter    <----- master.cf 内的过滤器名

在你的shell script 内用sendmail 命令把邮件内容再送回postfix


以上是我的猜想而已。

论坛徽章:
0
4 [报告]
发表于 2007-04-05 16:15 |只看该作者
原帖由 anthonyfeng 于 2007-4-5 14:55 发表
在master.cf 增加一个过滤器,可以参考此文件内maildrop 的例子 或 man pipe

然后修改main.cf 内的 transport_maps

如 transport_maps = hash:/etc/postfix/transport

transport 文件的内容为

[email ...

改一下master.cf

论坛徽章:
0
5 [报告]
发表于 2007-04-05 17:30 |只看该作者
谢谢
的确可以这样做,用了transport,不用考虑是mta还是mda,最后都会relay过去
我参考了下oreilly_postfix_the_definitive_guide.chm,发现的确有点意思,感觉就是自动回复机制,不过有些postfix的原理还没理解透
(还有些问题:
1、应该可以直接用alias来调用pipe,但别名太多,比较麻烦
2、如果要用shell扫所有通过mta的邮件,再传回去,会不会邮件循环
3、想把它串联在mailscanner,因为我目前系统只做SMTP而已,目前这样做效率不太高

有几个地方想不明白,还在试验中
以下是目前的测试方法
[root@mail ~]# vi /etc/postfix/main.cf
transport_maps=hash:/etc/postfix/transport
inforeply_destination_recipient_limit=1
[root@mail ~]# vi /etc/postfix/transport
        test@test.com        inforeply
[root@mail ~]# postmap /etc/postfix/transport
[root@mail ~]# useradd autoresp
[root@mail ~]# vi /etc/postfix/master.cf
inforeply     unix  -       n       n       -       -       pipe
  flags=  user=autoresp argv=/usr/local/bin/inforeply.pl ${sender}

[root@mail ~]# ll /usr/local/bin/inforeply.pl
[root@mail ~]# vi /usr/local/bin/inforeply.pl
#!/usr/bin/perl -w
#my $UID = 500;this number may change to autoresp's uid
#
# inforeply.pl - Automatic email reply.
#
# All messages are logged to your mail log. Check the
# log after executing the script to see the results.
#
# Set $UID to the uid of the process that runs the script.
# Check the entry in master.cf that calls this script. Use
# the uid of the account you assign to the user= attribute.
# If you want to test the script from the command line,
# set $UID to your own uid.
#
# Set $ENV_FROM to the envelope FROM address you want on
# outgoing replies. By default it's blank, which will
# use the NULL sender address <>. You can set it to an
# address to receive bounces, but make sure you don't set
# it to the same address that invokes the program, or
# you'll create a mail loop.
#
# Point $INFOFILE to a text file that contains the text of
# the outgoing reply. Include any headers you want in the
# message such as Subject: and From:. The To: header is
# set automatically based on the sender's address. Make
# sure you have an empty line between your headers and the
# body of the message.
#
# If necessary, change the path to sendmail in $MAILBIN.
#
# @MAILOPTS contains options to sendmail. Make changes if
# necessary. The default options should work in most
# situations.
#
# The calls to syslog require that your Perl installation
# converted the necessary header files. See h2ph in your
# Perl distribution.
#

require 5.004;  # for setlogsock in Sys::Syslog module

use strict;
use Sys::Syslog qw(EFAULT setlogsock);

#
# Config options. Set these according to your needs.
#
my $UID = 500;
my $ENV_FROM = "";
my $INFOFILE = "/home/autoresp/inforeply.txt";
my $MAILBIN = "/usr/sbin/sendmail";
my @MAILOPTS = ("-oi", "-tr", "$ENV_FROM";
my $SELF = "inforeply.pl";
#
# end of config options

my $EX_TEMPFAIL = 75;
my $EX_UNAVAILABLE = 69;
my $EX_OK = 0;
my $sender;
my $euid = $>;

$SIG{PIPE} = \&ipeHandler;
$ENV{PATH} = "/bin:/usr/bin:/sbin:/usr/sbin";

setlogsock('unix');
openlog($SELF, 'ndelay,pid', 'user');

#
# Check our environment.
#
if ( $euid != $UID ) {
        syslog('mail|err',"error: invalid uid: $> (expecting: $UID)";
        exit($EX_TEMPFAIL);
}
if ( @ARGV != 1 ) {
        syslog('mail|err',"error: invalid invocation (expecting 1 argument)";
        exit($EX_TEMPFAIL);
} else {
        $sender = $ARGV[0];
        if ( $sender =~ /([\w\-.%]+\@[\w.-]+)/ ) {   # scrub address
                $sender = $1;
        } else {
                syslog('mail|err',"error: Illegal sender address";
                exit($EX_UNAVAILABLE);
        }
}
if (! -x $MAILBIN ) {
        syslog('mail|err', "error: $MAILBIN not found or not executable";
        exit($EX_TEMPFAIL);
}
if (! -f $INFOFILE ) {
        syslog('mail|err', "error: $INFOFILE not found";
        exit($EX_TEMPFAIL);
}

#
# Check sender exceptions.
#
if ($sender eq ""
    || $sender =~ /^owner-|-(request|owner)\@|^(mailer-daemon|postmaster)\@/i) {
    exit($EX_OK);
}

#
# Check message contents for Precedence header.
#
while ( <STDIN> ) {
        last if (/^$/);
        exit($EX_OK) if (/^precedence:\s+(bulk|list|junk)/i);
}

#
# Open info file.
#
if (! open(INFO, "<$INFOFILE" ) {
        syslog('mail|err',"error: can't open $INFOFILE: %m";
        exit($EX_TEMPFAIL);
}

#
# Open pipe to mailer.
#
my $pid = open(MAIL, "|-" || exec("$MAILBIN", @MAILOPTS);

#
# Send reply.
#
print MAIL "To: $sender\n";
print MAIL while (<INFO>;

if (! close(MAIL) ) {
        syslog('mail|err',"error: failure invoking $MAILBIN: %m");
        exit($EX_UNAVAILABLE);
}

close(INFO);
syslog('mail|info',"sent reply to $sender");
exit($EX_OK);


sub PipeHandler {
        syslog('mail|err',"error: broken pipe to mailer");
}

[ 本帖最后由 sprilich 于 2007-4-5 18:00 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2007-04-05 21:53 |只看该作者
那书的 14.1 Command-Based Filtering 章节能有帮助于1,2 问题

使用milter  亦是另一种选择

论坛徽章:
0
7 [报告]
发表于 2007-04-05 21:54 |只看该作者
1、应该可以直接用alias来调用pipe,但别名太多,比较麻烦
为什么可以使用alias来调用pipe?alias不是只用来对邮件的地址进行改写吗?


2、如果要用shell扫所有通过mta的邮件,再传回去,会不会邮件循环
要做2个postfix instant(实例?),例如:
postfix1--->shell script--->postfix2---->destination  
例如postfix1设置参数content_filter=mysciript.sh把邮件丢给shell script处理
而postfix2使用的content_filter就不能使用mysciript.sh,
因为一般postfix2都是在master。cf中设置,可以使用
-o content_filter=,也就是说postfix2不使用content_filter功能




3、想把它串联在mailscanner,因为我目前系统只做SMTP而已,目前这样做效率不太高

mailscanner一般的做法是:
让邮件HOLD在postfix的HOLD队列中,然后mailscanner每隔个时间段去HOLD队列中读取这些邮件,但是HOLD队列中的邮件并不是txt文件

debian:/var/spool/postfix/hold/A# file A73A7DB497
A73A7DB497: data


如果你要把shell script放在postfix与mailscanner中,
postfix---->shell script--->mailscanner
那么shell script把这个邮件处理后,还要把这个邮件的内容和相关信息转化为binary(不知道mailscanner是否会读txt的邮件)

[ 本帖最后由 sosogh 于 2007-4-5 22:04 编辑 ]

论坛徽章:
0
8 [报告]
发表于 2007-04-06 09:51 |只看该作者
原帖由 anthonyfeng 于 2007-4-5 21:53 发表
那书的 14.1 Command-Based Filtering 章节能有帮助于1,2 问题

使用milter  亦是另一种选择


仔细看看书,的确收获不少,以前看过,但涉及到具体问题就不会做了,现在再回头看看,又是一种感觉

论坛徽章:
0
9 [报告]
发表于 2007-04-06 10:54 |只看该作者
原帖由 sosogh 于 2007-4-5 21:54 发表
1、应该可以直接用alias来调用pipe,但别名太多,比较麻烦
为什么可以使用alias来调用pipe?alias不是只用来对邮件的地址进行改写吗?


2、如果要用shell扫所有通过mta的邮件,再传回去,会不会邮件循环
要 ...


1、别名文件不仅可以改变地址,还能传到一个文件(把文件当邮件箱使用)、并可以用"|/path/to/command"给外部命令(用 | 来实现的)、还能引入有额外目标的文件(这个我不太理解)
2、thonyfeng提示的做法是可以的,这样做不用两个smtp,而且效果不错
3、是我表述有问题,我是想先用header_checks调用外部程序后(想用动作FILTER调用自定义的进程),再交由mailscanner去hold,而不是去访问hold队列
如:
/^Received:/ FILTER inforeply:[localhost]
/^Received:/ HOLD
但这样做,真会循环了,效率也不高,还耗内存(还得研究一下才行)

[ 本帖最后由 sprilich 于 2007-4-6 11:31 编辑 ]

论坛徽章:
0
10 [报告]
发表于 2007-04-06 14:51 |只看该作者
3、是我表述有问题,我是想先用header_checks调用外部程序后(想用动作FILTER调用自定义的进程),再交由mailscanner去hold,而不是去访问hold队列


postfix把邮件丢给shell  script,
shell script把邮件加工后,直接丢给mailscanner,不知道mailscanner是否会处理txt邮件
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP