カスタム検索
tomo.gif (1144 ツバツイツト)line.gif (927 ツバツイツト)line.gif (927 ツバツイツト)line.gif (927 ツバツイツト)To previous pageTo home pageMailing to me

pop-before-smtpの実験

Modified: 20 September 2006

"pop-before-smtp"は、多くのプロバイダで使われているのに、ほとんど解説書や解説ページがありませんので、ずいぶん苦労しましたが、何とか成功しましたので紹介します。

参考になったページ
http://popbsmtp.sourceforge.net/quickstart.shtml
http://www.kozupon.com/mail/pop_before_smtp.html
http://www.tatsuyoshi.net/toyota/dovecot/PopBSMTPAndDovecot.html


ダウンロードからインストール
動作するように設定する
動作確認する


 ダウンロードからインストール 

ダウンロードする

以下のページが本家サイトで、「Download」と書かれたところからダウンロードできます。

http://popbsmtp.sourceforge.net/


 インストールマニュアルは以下にあります。
http://popbsmtp.sourceforge.net/quickstart.shtml


インストールする

解凍します。

# tar zxvf pop-before-smtp-1.41.tar.gz

解凍したフォルダに移り、cpコマンドでインストールします。

# cd pop-before-smtp-1.41
# cp pop-before-smtp.init /etc/init.d/pop-before-smtp
# cp pop-before-smtp /usr/sbin/
# cp pop-before-smtp-conf.pl /etc

 動作するように設定する 

"pop-before-smtp-conf.pl"を設定

"/etc/pop-before-smtp-conf.pl" を、以下のように編集します。

# This config file is a perl library that can override various aspects of the
# pop-before-smtp script's setup.  Install it as /etc/pop-before-smtp-conf.pl

# There's quite a bit of sample stuff after the options, so you probably don't
# need to read through all of this.  If you're using Postfix and UW POP/IMAP,
# you can likely just use the default setup without any changes.  The most
# common changes needed are to pick the right $pat variable for your POP/IMAP
# software, ensure that the mail-log name is right, and perhaps uncomment a
# section with the support for a different SMTP (other than Postfix).  See the
# contrib/README.QUICKSTART file for step-by-step instructions on how to
# install and test your setup.

use strict;
use vars qw(
    $pat $out_pat $write $flock $debug $reprocess $grace $logto %file_tail
    @mynets %db $dbfile $dbvalue $logtime_pat
    $mynet_func $tie_func $flock_func $add_func $del_func $sync_func
    $tail_init_func $tail_getline_func $log_func
    $PID_pat $IP_pat $OK_pat $FAIL_pat $OUT_pat
);

#
# Override the default options here (or use the command-line options):
#

# Clear to avoid our exclusive file locking when updating the DB.
#$flock = 0;

# Set $debug to output some extra log messages (if logging is enabled).
$debug = 1;
#$logto = '-'; # Log to stdout.
$logto = '/var/log/pop-before-smtp';

# Override the DB hash file we will create/update (".db" gets appended).
$dbfile = '/etc/postfix/pop-before-smtp';

# Override the value that gets put into the DB hash.
$dbvalue = 'ok';

# A 30-minute grace period before the IP address is expired.
$grace = 30*60;

# Set the log file we will watch for pop3d/imapd records.
$file_tail{'name'} = '/var/log/maillog';
#$file_tail{'name'} = '/Library/Logs/MailService/AppleMailServer.IMAP.log';

# ... or we'll try to figure it out for you.
if (!-f $file_tail{'name'}) {
    foreach (qw( /var/log/mail/info /var/log/mail.log
                 /var/log/messages /var/adm/messages )) {
        if (-f $_) {
            $file_tail{'name'} = $_;
            last;
        }
    }
}

# If you need to define a custom PATH (for instance, if you're using Postfix
# and postconf is someplace wierd), uncomment and customize this.
#$ENV{'PATH'} = '/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/sbin:/usr/local/bin';

# These parameters control how closely the watcher tries to follow the
# logfile, which affects how much resources it consumes, and how quickly
# people can smtp after they have popped.  These values are documented in
# the File::Tail pod (run "perldoc File::Tail" to find out details).
# These commented-out values are the ones Daniel Roesen prefers.

#$file_tail{'maxinterval'} = 2;
#$file_tail{'interval'} = 1;
#$file_tail{'adjustafter'} = 3;
#$file_tail{'resetafter'} = 30;
#$file_tail{'tail'} = -1;

#-------------------------- File::Tail ---------------------------START-
# If you want to use the File::Tail module to read the logfile, comment-out
# the two surrounding =cut lines.  (By default pop-before-smtp now uses its
# own, simpler file-tailing functions.)

use File::Tail;

$tail_init_func = \&init_FileTail;
$tail_getline_func = \&getline_FileTail;

sub init_FileTail
{
    $::ft_handle = File::Tail->new(%file_tail);
}

sub getline_FileTail
{
    $::ft_handle->read;
}

#-------------------------- File::Tail -----------------------------END-

############################# START OF PATTERNS #############################
#
# Pick one of these values for the $pat variable OR define a subroutine
# named "custom_match" to handle a more complex match scenario (there's
# an example below).  Feel free to delete all the stuff you don't need.
#
# To enable an entry, just delete the "#" at the start of all the lines
# *after* the initial comment line(s).  If the entry of your choice also
# provides $out_pat, you should uncomment that variable as well, which
# allows us to keep track of users who are still connected to the server
# (e.g. Thunderbird caches open IMAP connections).
#
# Note also that the servers that require multiple log lines be read to
# get all the needed info have a setup with 3 $NAME_pat variables instead
# of a single "$pat" variable.  Uncomment all 3 and we'll define a multi-
# line-matching custom_match() subroutine for you.
#
# Technical:  if you want to define a new $pat regex, make sure that you
# include the string "[LOGTIME]" near the start because this string will
# be replaced by the final value of the $logtime_pat variable, and this
# handles the matching and returning of the first value the code needs:
# the line's timestamp.  There must also be a 2nd value returned from the
# regular expression:  the IP number.
#
############################# START OF PATTERNS #############################

# If your logfile has a non-standard time-stamp, you may need to define the
# $logtime_pat value here, or use one of the known variations included next
# to the relevant patterns.  The value should include parentheses, and (for
# maximum flexibility) should be able to match the time on any log line.
# This defaults to "(\w\w\w +\d+ \d+:\d+:\d+)" if left undefined.

#$logtime_pat = '(\d\d\d\d-\d\d-\d\d \d+:\d+:\d+)';

$pat = '^(... .. ..:..:..) \S+ (?:ipop3s?d|imaps?d)\[\d+\]: ' .
    '(?:Login|Authenticated|Auth|APOP) user=\S+ ' .
    'host=(?:\S+ )?\[(\d+\.\d+\.\d+\.\d+)\]';

# For UW POP/IMAP. This is the DEFAULT $pat (without an $out_pat, by default).
#$pat = '^[LOGTIME] \S+ (?:ipop3s?d|imaps?d)\[\d+\]: ' .
#    '(?:Login|Authenticated|Auth|APOP) user=\S+ ' .
#    'host=(?:\S+ )?\[(\d+\.\d+\.\d+\.\d+)\]';
#$out_pat = '^[LOGTIME] \S+ (?:ipop3s?d|imaps?d)\[\d+\]: ' .
#    '(?:Logout|Autologout|Killed.*?|Command stream end of file.*?) user=\S+ host=(?:\S+ )?\[(\d+\.\d+\.\d+\.\d+)\]';

# Some folks need a little different match for UW ipop3d/imapd:
#$pat = '^[LOGTIME] \S+ (?:ipop3s?d|imaps?d)\[\d+\]: \[[^]]+\]' .
#    '(?:Login|Authenticated|Auth|APOP) user=\S+ ' .
#    'host=(?:\S+ )?\[(\d+\.\d+\.\d+\.\d+)\]';

# For GNU pop3d
#$pat = '^[LOGTIME] \S+ gnu-pop3d\[\d+\]: ' .
#    'User .+ logged in with mailbox .+ from (\d+\.\d+\.\d+\.\d+)';

# A fairly modern Qpopper pattern, when using syslog.
#$pat = '^[LOGTIME] \S+ (?:in\.q|q)?popper[^[]*\[\d+\]: \([^)]*\) ' .
#    'POP login by user "[^"]+" at \([^)]+\) (\d+\.\d+\.\d+\.\d+)';

# The same Qpopper pattern as above, but matches Qpopper's own logging.
#$pat = '^[LOGTIME] \[popper\] \([^)]*\) ' .
#    'POP login by user (?:"[^"]+"|\S+) at \([^)]+\) (\d+\.\d+\.\d+\.\d+)';

# For Qpopper POP/APOP Server (matches in.qpopper, qpopper, and popper).
#$pat = '^[LOGTIME] \S+ (?:in\.q|q)?popper\[\d+\]: Stats: \S+ ' .
#    '\d+ \d+ \d+ \d+ (?:\S+ )?(\d+\.\d+\.\d+\.\d+)';

# Chris D.Halverson's pattern for Qpopper 3.0b29 on Solaris 2.6
#$logtime_pat = '(... ... .. \d+:\d+:\d+ \d{4})';
#$pat = '^[LOGTIME] \[\d+\] Stats:\s+\w+ ' .
#    '\d \d \d \d [\w\.]+ (\d+\.\d+\.\d+\.\d+)';

# For Cyrus (including a tweak for IP addrs that don't resolve):
#$pat = '^[LOGTIME] \S+ (?:cyrus/)?(?:pop3|imap)[ds]?\[\d+\]: ' .
#    'login: .*?\[[:f]*(\d+\.\d+\.\d+\.\d+)\]';

# For Courier-POP3 and Courier-IMAP:
#$pat = '^[LOGTIME] (?:\[|\S+ )(?:pop3|imap|couriertcp)(?:d|d-ssl|login)\]?: ' .
#    'LOGIN, user=\S+, ip=\[[:f]*(\d+\.\d+\.\d+\.\d+)\]';
#$out_pat = '^[LOGTIME] (?:\[|\S+ )(?:pop3|imap|couriertcp)(?:d|d-ssl|login)\]?: ' .
#    '(?:LOGOUT|DISCONNECTED), user=\S+, ip=\[[:f]*(\d+\.\d+\.\d+\.\d+)\]';

# For qmail's pop3d:
#$pat = '^[LOGTIME] \S+ vpopmail\[\d+\]: vchkpw: ' .
#    'login \[\S+\] from (\d+\.\d+\.\d+\.\d+)';

# For cucipop, matching a sample from Daniel Roesen:
#$pat = '^[LOGTIME] \S+ cucipop\[\d+\]: \S+ ' .
#    '(\d+\.\d+\.\d+\.\d+) \d+, \d+ \(\d+\), \d+ \(\d+\)';

# A Modern vm-pop3d can use a normal, 1-line pattern:
#$pat = '^[LOGTIME] \S+ vm-pop3d\[\d+\]: ' .
#    'User .+? logged in from (\d+\.\d+\.\d+\.\d+)';

# Older vm-pop3d -- needs to match 2 log entries (uncomment all 3 *_pat lines).
#$PID_pat = '^[LOGTIME] \S+ vm-pop3d\[(\d+)\]: ';
#$IP_pat = $PID_pat . 'Connect from (\d+\.\d+\.\d+\.\d+)';
#$OK_pat = $PID_pat . 'User .+? logged in';

# For popa3d -- needs to match 2 log entries (uncomment all 3 *_pat lines).
#$PID_pat = '^[LOGTIME] \S+ popa3d\[(\d+)\]: ';
#$IP_pat = $PID_pat . 'Session from (\d+\.\d+\.\d+\.\d+)';
#$OK_pat = $PID_pat . 'Authentication passed for ';

# For *patched* popa3d (see the patch in the contrib/popa3d dir).
#$pat = '^[LOGTIME] \S+ popa3d\[\d+\]: ' .
#    'Authentication passed for \S+ -- \[(\d+\.\d+\.\d+\.\d+)\]';

# A Perdition pattern.
#$pat = '^[LOGTIME] \S+ perdition\[\d+\]: ' .
#    'Auth: (\d+\.\d+\.\d+\.\d+)\-\>\d+\.\d+\.\d+\.\d+ ' .
#    'user=\"\S+\" server=\"\S+\" port=\"\S+\" status=\"ok\"';

# For solidpop3d (aka spop3d) ** if configured with --enable-logextend! **
#$pat = '^[LOGTIME] \S+ spop3d\[\d+\]: ' .
#    'user \S+ authenticated - (\d+\.\d+\.\d+\.\d+)';

# For spop3d w/o --enabled-logextend (uncomment all 3 *_pat lines).
#$PID_pat = '^[LOGTIME] \S+ spop3d\[(\d+)\]: ';
#$IP_pat = $PID_pat . 'connect from (\d+\.\d+\.\d+\.\d+)';
#$OK_pat = $PID_pat . 'user \S+ authenticated';

# Pattern for teapop (http://www.toontown.org/teapop/) by Patrick Prasse.
#$pat = '^[LOGTIME] \S+ teapop\[\d+\]: ' .
#    'Successful login for .+? \[(\d+\.\d+\.\d+\.\d+)\]';

# For Dovecot POP3/IMAP when using syslog.
#$pat = '^[LOGTIME] \S+ (?:dovecot: )?(?:imap|pop3)-login: ' .
#    'Login: .*? (?:\[|rip=)[:f]*(\d+\.\d+\.\d+\.\d+)[],]';
#$out_pat = '^[LOGTIME] \S+ (?:dovecot: )?(?:imap|pop3)-login: ' .
#    'Disconnected.*? (?:\[|rip=)[:f]*(\d+\.\d+\.\d+\.\d+)[],]';

# For Dovecot POP3/IMAP when it does its own logging.
##$logtime_pat = '(\d\d\d\d-\d+-\d+ \d+:\d+:\d+)';
#$pat = '^dovecot: [LOGTIME] Info: (?:imap|pop3)-login: ' .
#    'Login: .+? rip=[:f]*(\d+\.\d+\.\d+\.\d+),';
#$out_pat = '^dovecot: [LOGTIME] Info: (?:imap|pop3)-login: ' .
#    'Disconnected.*? rip=[:f]*(\d+\.\d+\.\d+\.\d+),';

# For older Dovecot POP3/IMAP when it does its own logging.
#$pat = '^(?:imap|pop3)-login: [LOGTIME] Info: ' .
#    'Login: \S+ \[[:f]*(\d+\.\d+\.\d+\.\d+)\]';
#$out_pat = '^(?:imap|pop3)-login: [LOGTIME] Info: ' .
#    'Disconnected.*? \[[:f]*(\d+\.\d+\.\d+\.\d+)\]';

# For Apple IMAP MAIL Server
#$logtime_pat = '(\w\w\w +\d+ \d\d\d\d \d+:\d+:\d+)';
#$pat = '^[LOGTIME].* IMAP User "[^"]+" ' .
#    'log on successful from (\d+\.\d+\.\d+\.\d+)';

############################## END OF PATTERNS ##############################

#====================== Match Many Patterns ======================START=
# Comment-out (or remove) the two surrounding =cut lines to use this function.

# This is an example of using the custom_match() function to match
# several patterns (allowing you to match multiple pop/imap servers
# at the same time).  Note that you can define logout patterns for
# some, all, or none of the login patterns, as needed.

my(@login, @logout);

$login[0] = $pat;
#$logout[0] = $out_pat;

$login[1] = '... define an extra login pattern here ...';
#$logout[1] = '... define an extra logout pattern, if needed ...';

# ... plus any other patterns you want to define ...

foreach (@login, @logout) {
    next unless defined $_;
    $_ = qr/$_/;        # Pre-compile the regular expressions.
}

# The mail-log line to match is in $_.
sub custom_match
{
    my($timestamp, $ipaddr);
    foreach my $regex (@logout) {
        if (defined($regex) && (($timestamp, $ipaddr) = /$regex/)) {
            return ($timestamp, $ipaddr, -1);
        }
    }
    my $j = 0;
    foreach my $regex (@login) {
        if (($timestamp, $ipaddr) = /$regex/) {
            my $increment = defined($logout[$j]) ? 1 : 0;
            return ($timestamp, $ipaddr, $increment);
        }
        $j++;
    }
    ( );
}
#====================== Match Many Patterns ========================END=

#====================== Postfix BerkeleyDB =======================START=
# If you comment-out (or remove) the two surrounding =cut lines, we'll use
# BerkeleyDB instead of DB_File.

use BerkeleyDB;

#$mynet_func = \&mynet_postfix; # Use the default
$tie_func = \&tie_BerkeleyDB;
$sync_func = \&sync_BerkeleyDB;
$flock = 0;

my $dbh;

# We must tie the global %db using the global $dbfile.  Also sets $dbh for
# our sync function.
sub tie_BerkeleyDB
{
    $dbh = tie %db,'BerkeleyDB::Hash',-Filename=>"$dbfile.db",-Flags=>DB_CREATE
        or die "$0: cannot dbopen $dbfile: $!\n";
}

sub sync_BerkeleyDB
{
    $dbh->db_sync and die "$0: sync $dbfile: $!\n";
}
#====================== Postfix BerkeleyDB =========================END=

############################# Support Routines ##############################

# This section takes care of defining a multi-line-match custom_match()
# subroutine, but only if the user configured our 3 required patterns.

if (defined($PID_pat) && defined($IP_pat) && defined($OK_pat)) {
    eval <<'EOT';
# Some pop services don't put the IP on the line that lets us know that a
# user was properly authenticated.  For these programs, we scan the IP off
# an earlier line and the check the validation by comparing the PID values.
# The regex $IP_pat is used to match the IP number and cache it.  The regex
# $OK_pat is used to match a success message that follows from the same PID.
# If $FAIL_pat is not defined, there can be no intermediate log messages
# with the same PID prior to the $OK_pat.  If $FAIL_pat is defined, we'll
# continue trying to match the $OK_pat value on matching PID lines until we
# either match the $FAIL_pat (in which case the IP is ignored) or the $OK_pat
# (in which case the IP is accepted).  Thus, $FAIL_pat can be either a
# failure log line or a this-PID-is-finished log line common to both success
# and failure.  Finally, an optional $OUT_pat may be defined if you want to
# track active connections -- when defined, any PID that matches the $OK_pat
# will be considered connected until we find a match for $OUT_pat.  It is
# fine if lines that match $OUT_pat would also match $FAIL_pat (such as a
# disconnect message) -- this won't confuse the code.
#
# Keep in mind that $IP_pat, $OK_pat, $OUT_pat, and $FAIL_pat will only be
# applied to lines that match the $PID_pat regex.

    my(%popIPs, %popConnected);

    $FAIL_pat = '.' if !defined $FAIL_pat;
    foreach ($PID_pat, $IP_pat, $OK_pat, $FAIL_pat, $OUT_pat) {
        s/\[LOGTIME\]/$logtime_pat/g if defined $_;
    }

    # The mail-log line to match is in $_.
    sub custom_match
    {
        if (/$PID_pat/o) {
            my($ts, $pid) = ($1, $2);
            if (/$IP_pat/o) {
                $popIPs{$pid} = $3;
            } else {
                my $ip = $popIPs{$pid};
                if (defined $ip) {
                    if ($popConnected{$pid}) {
                        if (/$OUT_pat/o) {
                            delete $popConnected{$pid};
                            delete $popIPs{$pid};
                            return ($ts, $ip, -1);
                        }
                    } else {
                        if (/$OK_pat/o) {
                            if (defined $OUT_pat) {
                                $popConnected{$pid} = 1;
                                return ($ts, $ip, 1);
                            }
                            delete $popIPs{$pid};
                            return ($ts, $ip, 0);
                        }
                        if (/$FAIL_pat/o) {
                            delete $popIPs{$pid};
                        }
                    }
                }
            }
        }
        ( );
    }
EOT
}

1; ## THIS LINE MUST REMAIN LAST IN THE FILE! ##


サービスの起動

# service pop-before-smtp start

起動すると、Perlのモジュールが足らないと聞いてきますので、エラーになったものをインストールします。

私の試した環境では、以下のPerlモジュールの追加インストールが必要でした。

自動起動に設定します。

# chkconfig pop-before-smtp on


Postfixの"main.cf"の設定

smtpd_recipient_restrictions =
     permit_mynetworks,
     check_client_access hash:/etc/postfix/pop-before-smtp,
     reject_unauth_destination

 動作確認する 

動作確認

まずメーラーで、いきなり送信してみて、エラーになることを確認します。

次に、メール受信してから送信してみます。エラーにならず送信できることを確認します。

ログ、"/var/log/pop-before-smtp"、を見てみます。

Sep 21 22:03:45 starting up
Sep 21 22:03:45 Using 2 values for pre-authorized networks: `192.168.3.0/26', `127.0.0.0/8'
Sep 21 22:03:47 startup log-scan complete
Sep 21 22:03:47 found ip=203.140.77.26 (0)
Sep 21 22:03:47 setting expiration time for ip=23.40.77.26 to 1158844156
Sep 21 22:03:47 added 23.40.77.26 to DB

一旦受信したので、送信を許可するデータベースにIPアドレスが加えられていますので、送信できます。

一度受信すると、デフォルトで、30分間は、送信が許可されます。

Sep 21 22:34:44 removed old ip=23.40.77.26 from DB

To previous pageTo home pageMailing to meJump to Top of pageline.gif (927 ツバツイツト)line.gif (927 ツバツイツト)tomo.gif (1144 ツバツイツト)
カスタム検索


Tweet