POE::Filter::Postfix - Postfix (MTA) text attribute communication


POE-Filter-Postfix documentation Contained in the POE-Filter-Postfix distribution.

Index


Code Index:

NAME

Top

POE::Filter::Postfix - Postfix (MTA) text attribute communication

VERSION

Top

version 0.003

DESCRIPTION

Top

This filter translates between hashrefs and the key-value attribute protocols that the Postfix MTA uses for its internal communications.

Unless you're doing something complicated, you can probably use POE::Component::Server::Postfix instead of this module.

Don't use this module directly. See POE::Filter::Postfix::Null, POE::Filter::Postfix::Base64, and POE::Filter::Postfix::Plain instead.

METHODS

Top

new

Return a new POE::Filter::Postfix.

Call this on a subclass, not on POE::Filter::Postfix directly.

clone

See clone in POE::Filter.

get_one_start

See get_one_start in POE::Filter.

get_one

See get_one in POE::Filter.

get_pending

See get_pending in POE::Filter.

decode_key

decode_value

After parsing keys and values, these methods are called to decode them. See POE::Filter::Postfix::Base64 for an example.

The default is to pass keys and values through unchanged.

You do not need to call these methods by hand; get_one calls them automatically.

put

See put in POE::Filter.

encode_key

encode_value

Before packing keys and values into a string, these methods are called to encode them. See POE::Filter::Postfix::Base64 for an example.

The default is to pass keys and values through unchanged.

You do not need to call these methods by hand; put calls them automatically.

attribute_separator

attribute_terminator

request_terminator

These methods must be overridden by subclasses.

Each returns a string that will be used to parse and construct requests.

See existing subclasses for examples.

AUTHOR

Top

  Hans Dieter Pearcey <hdp@cpan.org>

COPYRIGHT AND LICENSE

Top


POE-Filter-Postfix documentation Contained in the POE-Filter-Postfix distribution.

use strict;
use warnings;

package POE::Filter::Postfix;
our $VERSION = '0.003';


# ABSTRACT: Postfix (MTA) text attribute communication
use base qw(POE::Filter);

sub _abstract {
  my $name = shift;
  eval sprintf <<'', ($name) x 2;
sub %s { 
  my $class = ref($_[0]) || $_[0];
  require Carp;
  Carp::croak("$class must override %s()");
}

}

BEGIN {
  _abstract($_) for qw(
    attribute_separator
    attribute_terminator
    request_terminator
  )
}


sub new {
  my $class = shift;
  bless {
    @_,
    buffer => '',
  } => $class;
}


sub clone {
  my $self = shift;
  $self->new(%$self);
}


sub get_one_start {
  my ($self, $buf) = @_;
  $self->{buffer} .= $_ for @$buf;
}


sub get_one {
  my ($self) = @_;
  my %attr;
  my $buf = $self->{buffer};
  my ($a_s, $a_t, $r_t) = (
    $self->attribute_separator,
    $self->attribute_terminator,
    $self->request_terminator,
  );
  while ($buf =~ s/^([^$r_t]+?)\Q$a_s\E//) {
    my $key = $self->decode_key("$1");
    $buf =~ s/^([^$r_t]*)?\Q$a_t\E// or return [];
    $attr{$key} = $self->decode_value("$1");
  }
  return [] unless $buf =~ s/^\Q$r_t\E//;
  $self->{buffer} = $buf;
  return [ \%attr ];
}


sub get_pending {
  my ($self) = @_;
  return [ $self->{buffer} ] if length $self->{buffer};
  return undef;
}


sub decode_key   { $_[1] }
sub decode_value { $_[1] }


sub put {
  my ($self, $chunks) = @_;

  return [ map { $self->_encode($_) } @$chunks ];
}

sub _encode {
  my ($self, $attr) = @_;
  return join $self->attribute_terminator,
    (map {
      join $self->attribute_separator,
        $self->encode_key($_),
        $self->encode_value($attr->{$_})
    } keys %$attr),
    $self->request_terminator;
}


sub encode_key   { $_[1] }
sub encode_value { $_[1] }


1;


__END__