Mail-Milter-Authentication

 view release on metacpan or  search on metacpan

lib/Mail/Milter/Authentication/Handler.pm  view on Meta::CPAN

    return;
}

sub top_connect_callback {

    # On Connect
    my ( $self, $hostname, $ip ) = @_;
    $self->metric_count( 'connect_total' );
    $self->status('connect');
    $self->dbgout( 'CALLBACK', 'Connect', LOG_DEBUG );
    $self->set_return( $self->smfis_continue() );
    my $config = $self->config();
    eval {
        local $SIG{'ALRM'} = sub{ die "Timeout\n" };
        if ( $config->{'connect_timeout'} ) {
            alarm( $config->{'connect_timeout'} );
        }

        $self->{'ip_object'} = $ip;

        $self->dbgout( 'ConnectFrom', $ip->ip(), LOG_DEBUG );

        my $callbacks = $self->get_callbacks( 'connect' );
        foreach my $handler ( @$callbacks ) {
            my $start_time = $self->get_microseconds();
            eval{ $self->get_handler($handler)->connect_callback( $hostname, $ip ); };
            if ( my $error = $@ ) {
                $self->log_error( 'Connect callback error ' . $error );
                $self->exit_on_close();
                $self->tempfail_on_error();
                $self->metric_count( 'callback_error_total', { 'stage' => 'connect', 'handler' => $handler } );
                if ( $error =~ /Timeout/ ) {
                    alarm( 1 );
                }
            }
            $self->metric_count( 'time_microseconds_total', { 'callback' => 'connect', 'handler' => $handler }, $self->get_microseconds() - $start_time );
        }
        alarm(0);
    };
    if ( my $error = $@ ) {
        $self->log_error( 'Connect callback error ' . $error );
        $self->exit_on_close();
        $self->tempfail_on_error();
        $self->metric_count( 'callback_error_total', { 'stage' => 'connect' } );
    }
    $self->status('postconnect');
    return $self->get_return();
}

sub top_helo_callback {

    # On HELO
    my ( $self, $helo_host ) = @_;
    $self->status('helo');
    $self->dbgout( 'CALLBACK', 'Helo', LOG_DEBUG );
    $self->set_return( $self->smfis_continue() );
    $helo_host = q{} if not $helo_host;
    my $config = $self->config();
    eval {
        local $SIG{'ALRM'} = sub{ die "Timeout\n" };
        if ( $config->{'command_timeout'} ) {
            alarm( $config->{'command_timeout'} );
        }

        # Take only the first HELO from a connection
        if ( !( $self->{'helo_name'} ) ) {
            $self->{'helo_name'} = $helo_host;
            my $callbacks = $self->get_callbacks( 'helo' );
            foreach my $handler ( @$callbacks ) {
                my $start_time = $self->get_microseconds();
                eval{ $self->get_handler($handler)->helo_callback($helo_host); };
                if ( my $error = $@ ) {
                    $self->log_error( 'HELO callback error ' . $error );
                    $self->exit_on_close();
                    $self->tempfail_on_error();
                    $self->metric_count( 'callback_error_total', { 'stage' => 'helo', 'handler' => $handler } );
                    if ( $error =~ /Timeout/ ) {
                        alarm( 1 );
                    }
                }
                $self->metric_count( 'time_microseconds_total', { 'callback' => 'helo', 'handler' => $handler }, $self->get_microseconds() - $start_time );
            }
        }
        else {
            $self->dbgout('Multiple HELO callbacks detected and ignored', $self->{'helo_name'} . ' / ' . $helo_host, LOG_DEBUG );
        }

        alarm(0);
    };
    if ( my $error = $@ ) {
        $self->metric_count( 'callback_error_total', { 'stage' => 'helo' } );
        $self->log_error( 'HELO callback error ' . $error );
        $self->exit_on_close();
        $self->tempfail_on_error();
    }
    $self->status('posthelo');
    return $self->get_return();
}

sub top_envfrom_callback {

    # On MAILFROM
    #...
    my ( $self, $env_from ) = @_;
    $self->status('envfrom');
    $self->dbgout( 'CALLBACK', 'EnvFrom', LOG_DEBUG );
    $self->set_return( $self->smfis_continue() );
    $env_from = q{} if not $env_from;
    my $config = $self->config();
    eval {
        local $SIG{'ALRM'} = sub{ die "Timeout\n" };
        if ( $config->{'command_timeout'} ) {
            alarm( $config->{'command_timeout'} );
        }

        # Reset private data for this MAIL transaction
        delete $self->{'auth_headers'};
        delete $self->{'pre_headers'};
        delete $self->{'add_headers'};

        my $callbacks = $self->get_callbacks( 'envfrom' );
        foreach my $handler ( @$callbacks ) {
            my $start_time = $self->get_microseconds();
            eval { $self->get_handler($handler)->envfrom_callback($env_from); };
            if ( my $error = $@ ) {
                $self->log_error( 'Env From callback error ' . $error );
                $self->exit_on_close();
                $self->tempfail_on_error();
                $self->metric_count( 'callback_error_total', { 'stage' => 'envfrom', 'handler' => $handler } );
                if ( $error =~ /Timeout/ ) {
                    alarm( 1 );
                }
            }
            $self->metric_count( 'time_microseconds_total', { 'callback' => 'envfrom', 'handler' => $handler }, $self->get_microseconds() - $start_time );
        }
        alarm(0);
    };
    if ( my $error = $@ ) {
        $self->metric_count( 'callback_error_total', { 'stage' => 'envfrom' } );
        $self->log_error( 'Env From callback error ' . $error );
        $self->exit_on_close();
        $self->tempfail_on_error();
    }
    $self->status('postenvfrom');
    return $self->get_return();
}

sub top_envrcpt_callback {

    # On RCPTTO
    #...
    my ( $self, $env_to ) = @_;
    $self->status('envrcpt');
    $self->dbgout( 'CALLBACK', 'EnvRcpt', LOG_DEBUG );
    $self->set_return( $self->smfis_continue() );
    $env_to = q{} if not $env_to;
    my $config = $self->config();
    eval {
        local $SIG{'ALRM'} = sub{ die "Timeout\n" };
        if ( $config->{'command_timeout'} ) {
            alarm( $config->{'command_timeout'} );
        }
        my $callbacks = $self->get_callbacks( 'envrcpt' );
        foreach my $handler ( @$callbacks ) {
            my $start_time = $self->get_microseconds();
            eval{ $self->get_handler($handler)->envrcpt_callback($env_to); };
            if ( my $error = $@ ) {
                $self->log_error( 'Rcpt To callback error ' . $error );
                $self->exit_on_close();
                $self->tempfail_on_error();
                $self->metric_count( 'callback_error_total', { 'stage' => 'rcptto', 'handler' => $handler } );
                if ( $error =~ /Timeout/ ) {
                    alarm( 1 );
                }
            }
            $self->metric_count( 'time_microseconds_total', { 'callback' => 'rcptto', 'handler' => $handler }, $self->get_microseconds() - $start_time );
        }
        alarm(0);
    };
    if ( my $error = $@ ) {
        $self->metric_count( 'callback_error_total', { 'stage' => 'rcptto' } );
        $self->log_error( 'Rcpt To callback error ' . $error );
        $self->exit_on_close();
        $self->tempfail_on_error();
    }
    $self->status('postenvrcpt');
    return $self->get_return();
}

sub top_header_callback {

    # On Each Header
    my ( $self, $header, $value ) = @_;
    $self->status('header');
    $self->dbgout( 'CALLBACK', 'Header', LOG_DEBUG );
    $self->set_return( $self->smfis_continue() );
    $value = q{} if not $value;
    my $config = $self->config();
    eval {
        local $SIG{'ALRM'} = sub{ die "Timeout\n" };
        if ( $config->{'content_timeout'} ) {
            $self->dbgout( 'Content Timeout set', $config->{'content_timeout'}, LOG_DEBUG );
            alarm( $config->{'content_timeout'} );
        }
        if ( my $error = $@ ) {
            $self->dbgout( 'inline error $error', '', LOG_DEBUG );
        }

        my $callbacks = $self->get_callbacks( 'header' );
        foreach my $handler ( @$callbacks ) {
            my $start_time = $self->get_microseconds();
            eval{ $self->get_handler($handler)->header_callback( $header, $value ); };
            if ( my $error = $@ ) {
                $self->log_error( 'Header callback error ' . $error );
                $self->exit_on_close();
                $self->tempfail_on_error();
                $self->metric_count( 'callback_error_total', { 'stage' => 'header', 'handler' => $handler } );
                if ( $error =~ /Timeout/ ) {
                    alarm( 1 );
                }
            }

lib/Mail/Milter/Authentication/Handler.pm  view on Meta::CPAN

        }
        else {
            # We have another entry
            ( $key, $value, $header ) = $self->_parse_auth_header_entry( $header );
            my $entry = {
                'class'    => 'entry',
                'key'      => $key,
                'value'    => $value,
                'children' => [],
            };
            $comment_on = \$entry;
            push @{ ${$acting_on}->{ 'children' } }, $entry;
        }
    }

    return;
}

sub _parse_auth_header_comment {
    my ($self,$remain) = @_;
    my $value = q{};
    my $depth = 0;

    while ( length $remain > 0 ) {
        my $first = substr( $remain,0,1 );
        $remain   = substr( $remain,1 );
        $value .= $first;
        if ( $value eq '(' ) {
            $depth++;
        }
        elsif ( $value eq ')' ) {
            $depth--;
            last if $depth == 0;
        }
    }

    return($value,$remain);
}

sub _parse_auth_header_entry {
    my ($self,$remain) = @_;
    my $key;
    my $value;
    ( $key, $remain )   = split( '=', $remain, 2 );
    $remain = q{} if ! defined $remain;
    ( $value, $remain ) = split( ' ', $remain, 2 );

    return ($key,$value,$remain);
}

sub top_abort_callback {

    # On any out of our control abort
    my ($self) = @_;
    $self->status('abort');
    $self->dbgout( 'CALLBACK', 'Abort', LOG_DEBUG );
    $self->set_return( $self->smfis_continue() );
    my $config = $self->config();
    eval {
        local $SIG{'ALRM'} = sub{ die "Timeout\n" };
        if ( $config->{'command_timeout'} ) {
            alarm( $config->{'command_timeout'} );
        }
        my $callbacks = $self->get_callbacks( 'abort' );
        foreach my $handler ( @$callbacks ) {
            my $start_time = $self->get_microseconds();
            eval{ $self->get_handler($handler)->abort_callback(); };
            if ( my $error = $@ ) {
                $self->log_error( 'Abort callback error ' . $error );
                $self->exit_on_close();
                $self->tempfail_on_error();
                $self->metric_count( 'callback_error_total', { 'stage' => 'abort', 'handler' => $handler } );
                if ( $error =~ /Timeout/ ) {
                    alarm( 1 );
                }
            }
            $self->metric_count( 'time_microseconds_total', { 'callback' => 'abort', 'handler' => $handler }, $self->get_microseconds() - $start_time );
        }
        alarm(0);
    };
    if ( my $error = $@ ) {
        $self->metric_count( 'callback_error_total', { 'stage' => 'abort' } );
        $self->log_error( 'Abort callback error ' . $error );
        $self->exit_on_close();
        $self->tempfail_on_error();
    }
    $self->status('postabort');
    return $self->get_return();
}

sub top_close_callback {

    # On end of connection
    my ($self) = @_;
    $self->status('close');
    $self->dbgout( 'CALLBACK', 'Close', LOG_DEBUG );
    $self->set_return( $self->smfis_continue() );
    my $config = $self->config();
    eval {
        local $SIG{'ALRM'} = sub{ die "Timeout\n" };
        if ( $config->{'content_timeout'} ) {
            alarm( $config->{'content_timeout'} );
        }
        my $callbacks = $self->get_callbacks( 'close' );
        foreach my $handler ( @$callbacks ) {
            my $start_time = $self->get_microseconds();
            eval{ $self->get_handler($handler)->close_callback(); };
            if ( my $error = $@ ) {
                $self->log_error( 'Close callback error ' . $error );
                $self->exit_on_close();
                $self->tempfail_on_error();
                $self->metric_count( 'callback_error_total', { 'stage' => 'close', 'handler' => $handler } );
                if ( $error =~ /Timeout/ ) {
                    alarm( 1 );
                }
            }
            $self->metric_count( 'time_microseconds_total', { 'callback' => 'close', 'handler' => $handler }, $self->get_microseconds() - $start_time );
        }
        alarm(0);
    };
    if ( my $error = $@ ) {
        $self->metric_count( 'callback_error_total', { 'stage' => 'close' } );



( run in 0.336 second using v1.01-cache-2.11-cpan-39bf76dae61 )