use MIME::Parser;
use MIME::Entity;

sub register {
  my ($self, $qp, @args) = @_;

  $self->log(LOGERROR, "Bad parameters for the disclaimer plugin")
    if @_ % 2;

  %{$self->{_args}} = @args;
}

sub read_disclaimer {
  my ($self, $disclaimer_file) = @_;
  my $disclaimer_dir = $self->{_args}->{disclaimer_dir} || "/service/qpsmtpd/config/";
    return () unless open DISCLAIMER, "<$disclaimer_dir/$disclaimer_file";
  my @lines = <DISCLAIMER>;
  chomp @lines;
  close DISCLAIMER;
    return @lines;
}

sub hook_data_post {
  my ($self, $transaction) = @_;

  if ( $transaction->header->get('X-Qpsmtp-Disclaimer') ) {
    $self->log(LOGNOTICE, "Message already has disclaimer attached");
    return DECLINED;
  }

  $self->qp->version =~ m/([\.\d]+).*/;
  my $versionnum = $1;

  my @rcpt_hosts = ($self->qp->config("me"), $self->qp->config("rcpthosts"));
  my $fromhost = $transaction->sender->host;
  unless ( $self->{_args}->{tag_all} ) {
    my $fromlocal = 0;

    for my $allowed (@rcpt_hosts) {
      $allowed =~ s/^\s*(\S+)/$1/;
      ($fromlocal = 1, last) if (($fromhost eq lc $allowed) or (substr($allowed,0,1) eq "." and
                                                   $fromhost =~ m/\Q$allowed\E$/i));
    }

    if (($versionnum >= 0.26) and ($fromlocal == 0)) {
      my $more_rcpt_hosts = $self->qp->config('morercpthosts', 'map');
      $fromlocal = 1 if exists $more_rcpt_hosts->{$fromhost};
    }

    unless ($fromlocal) {
      $self->log(LOGDEBUG, "Not from local domain");
      return DECLINED;
    }
  }

  my $specific = 0;
  my @lines;
  if ( @lines = $self->read_disclaimer("disclaimer_$fromhost") ) {
    $self->log(LOGDEBUG, "Found disclaimer for domain: $fromhost");
    $specific = 1;
  } elsif ( @lines = $self->read_disclaimer("disclaimer") ) {
    $self->log(LOGDEBUG, "Found general disclaimer");
  } else {
    $self->log(LOGERROR, "No disclaimer found for domain: $fromhost");
    return DECLINED;
  }

  unless ( $self->{_args}->{tag_all} ) {
    my $toexternal=0;
    foreach my $rcpt ( $transaction->recipients ) {
      my $local = 0;
      my $host = $rcpt->host;

      ($toexternal = 1, last) if ( $specific && $host ne $fromhost);

      for my $allowed (@rcpt_hosts) {
        $allowed =~ s/^\s*(\S+)/$1/;
        ($local = 1, last) if (($host eq lc $allowed) or (substr($allowed,0,1) eq "." and
                                                   $host =~ m/\Q$allowed\E$/i));
      }

      if (($versionnum >= 0.26) and ($local == 0)) {
        my $more_rcpt_hosts = $self->qp->config('morercpthosts', 'map');
        $local = 1 if exists $more_rcpt_hosts->{$host};
      }

      ($toexternal = 1, last) unless $local;
    }

    unless ($toexternal) {
      $self->log(LOGDEBUG, "Not to any external domain");
      return DECLINED;
    }
  }

  my $parser = new MIME::Parser;
  $parser->output_under( $self->spool_dir() );
  $parser->extract_uuencode(1);
  my $ent = $parser->parse_open( $transaction->body_filename() );

  $ent->make_multipart( 'mixed', Force => 1 ) if $ent->mime_type ne 'multipart/mixed';
  $ent->attach( Data => join("\n", @lines),  
                Encoding => $self->{_args}->{mime_encoding} || '-SUGGEST',
                Filename => $self->{_args}->{mime_filename} || 'disclaimer.txt',
                Type => $self->{_args}->{mime_type} || 'text/plain');
  if ($ent->parts <= 2) {
    $transaction->header->empty();
    $transaction->header($ent->head());
  }
  $transaction->header->replace( 'X-Qpsmtp-Disclaimer', $fromhost );
  $self->log(LOGNOTICE, "Attached disclaimer for domain: $fromhost");

  open BFN, ">" . $transaction->body_filename();
  $ent->print(\*BFN);
  close BFN;
  $transaction->body_resetpos();

  $ent->purge();
  rmdir( $parser->output_dir );

  return DECLINED; 
}

# vi: ft=perl ts=4