我想要postfix咨询一个简单的(bash / python)脚本,以便找出(virtual_alias_maps – style)在队列之前,不pipe收件人的地址是否合法。 例如,我想使用类似的邮件地址
[email protected]
如果$ EXIPRYDATE尚未通过,并且$ CHECKSUM通过,或者否则拒绝,则接受$ USER。
如果它简化了解决scheme,我可以这样做一个单一的,恒定的用户,所以后缀只需要从一些地址检查脚本观察真/假。
我对那些需要postfix首先接受邮件的解决scheme不感兴趣,如果收件人地址被发现无效(“队列后”),那么稍后会popup。 我需要postfix拒绝在最初的SMTP会话(“前队列”)。
我和你有类似的问题。 预排队要求留给我们三个选项
因为我们只是检查收件人,那么SMTP访问策略委托就足够了。 如果我们需要访问标题和主体,则使用Milter和SMTPD代理。
我的检查脚本是由开发人员提供的。 该程序的用法是只调用./myscript recipient_address哪个recipient_address通过postfix。 为此,我使用perl脚本的修改版本。 这个Perl脚本允许我读取标准input,每行拆分string,并用=符号拆分行。
然后我在master.cf中声明spawn守护进程
policy unix - nn - - spawn user=mydedicateduser argv=/path/to/perl/script.pl
然后在main.cf定义它
smtpd_recipient_restrictions = ... reject_unauth_destination check_policy_service unix:private/policy ...
下面的脚本可以用另一种编程语言来替代。 这里的伪代码来解释它是如何工作的。
while True: get the stdin if stdin = '' # ---> the end of parameter call the external script with recipient parameter get the return code if recipient valid print "dunno" else if recipient not valid print "reject" else # ---> command error print "defer if permit" break else validate the stdin, the proper format is 'parameter=value' if valid put it in array
对于python代码 ,你可以修改这段代码 。 不需要设置spawn守护进程。
为了完整,这里是/path/to/perl/script.pl的完整源代码
#!/usr/bin/perl -w use strict; use Sys::Syslog qw(:DEFAULT setlogsock); use Getopt::Long; # # Syslogging options for verbose mode and for fatal errors. # NOTE: comment out the $syslog_socktype line if syslogging does not # work on your system. # my $syslog_socktype = 'unix'; # inet, unix, stream, console my $syslog_facility = 'mail'; my $syslog_options = 'pid'; my $syslog_priority = 'info'; # Configuration my $executable_path = '/my/execute/script.sh'; # # Procedures # # # Log an error and abort. # sub fatal_exit { my $first = shift @_; syslog "err", "fatal: $first", @_; exit 1; } # SMTPD access policy routine. The result is an action just like # it would be specified on the right-hand side of a Postfix access # table. Request attributes are available via the %attr hash. sub smtpd_access_policy() { system($executable_path, $attr{'recipient'}); # -1 command error # 0 user isn't valid # else user valud if ( $? == -1 ) { # command error return "defer_if_permit Something error" } if ( $? == 0 ) { return "reject user not found"; } return "dunno"; } # # Main program # # # This process runs as a daemon, so it can't log to a terminal. Use # syslog so that people can actually see our messages. # setlogsock $syslog_socktype; openlog $0, $syslog_options, $syslog_facility; unless(GetOptions('v:+' => \$verbose)) { syslog $syslog_priority, "Invalid option. Usage: %s [-v] [-v] ...", $0; exit 1; } # # Unbuffer standard output. # select((select(STDOUT), $| = 1)[0]); # # Receive a bunch of attributes, evaluate the policy, send the result. # while (<STDIN>) { chomp; if (/^([^=]+)=(.*)$/) { $attr{substr($1, 0, 512)} = substr($2, 0, 512); } elsif ($_ eq '') { if ($verbose>2) { for (keys %attr) { syslog $syslog_priority, "Attribute: %s=%s", $_, $attr{$_}; } } fatal_exit "unrecognized request type: '%s'", $attr{'request'} unless $attr{'request'} eq 'smtpd_access_policy'; my $action = smtpd_access_policy(); syslog $syslog_priority, "Action: %s", $action if $verbose>1; print STDOUT "action=$action\n\n"; %attr = (); } else { syslog $syslog_priority, "warning: ignoring garbage: %.100s", $_; } } exit 0;