Mail::Audit::KillDups - Mail::Audit plugin for duplicate suppression


Mail-Audit documentation Contained in the Mail-Audit distribution.

Index


Code Index:

NAME

Top

Mail::Audit::KillDups - Mail::Audit plugin for duplicate suppression

SYNOPSIS

Top

    use Mail::Audit qw(KillDups);
    $Mail::Audit::KillDups::dupfile = "/home/simon/.msgid-cache";
        my $mail = Mail::Audit->new;
    $mail->killdups;

DESCRIPTION

Top

This is a Mail::Audit plugin which provides a method for checking and supressing duplicate messages; that is, mails with message-ids which have been previously seen.

METHODS

killdups

Checks the incoming message against a file of previously seen message ids, ignores it if it's already seen, and adds it if it hasn't been. $Mail::Audit::KillDups::dupfile contains the name of the file used; if you don't set this, it will be .msgid-cache in the current directory. (Probably your home directory.)

The data in $Mail::Audit::KillDups::dupfile will be treated as a ring buffer, where the end of the buffer will be delimited by two newline characters. When the file size exceeds $Mail::Audit::KillDups::cache_bytes bytes, the message id will be written at the beginning of the file. Old message ids in the file will be overwritten. The default cache size is 10000 bytes, which is enough space for about 200 message-ids.

The semantics are tortured; the return values are as follows:

  false - not a duplicate
  +1    - an error occured during dupcheck
  -1    - message is a duplicate

AUTHOR

Top

Simon Cozens <simon@cpan.org>

SEE ALSO

Top

Mail::Audit


Mail-Audit documentation Contained in the Mail-Audit distribution.

package Mail::Audit::KillDups;
use Mail::Audit;
use vars qw(@VERSION $dupfile $cache_bytes);
$VERSION     = '2.225';
$dupfile     = ".msgid-cache";
$cache_bytes = 10000;
1;

package Mail::Audit;
use strict;
use Fcntl;

sub killdups {
  my $self        = shift;
  my $mid         = shift || $self->get("Message-Id");
  my $end_of_ring = 0;
  my $current_pos;

  unless (length $mid) {
    $self->_log(1, "message has no message-id; skipping duplicate check");
    return;
  }

  unless (sysopen MSGID, $Mail::Audit::KillDups::dupfile, O_RDWR | O_CREAT) {
    $self->_log(1, "Error opening $Mail::Audit::KillDups::dupfile: $!");
    return 1;
  }

  chomp $mid;
  while (<MSGID>) {
    chomp;
    if ($_ eq $mid) {
      $self->_log(1, "Duplicate, ignoring");
      $self->ignore;
      return -1;
    }

    $current_pos = tell MSGID;
    if ($current_pos > $Mail::Audit::KillDups::cache_bytes && $end_of_ring == 0)
    {
      # we've gotten too big, write this mid back at the top of the file
      last;
    } elsif ($_ eq "" && $end_of_ring == 0 && $current_pos > 0) {
      # Found the end of the ring buffer, so save position.
      $end_of_ring = $current_pos - 1;
    }
  }

  # Didn't find mid, so write it to the end of the ring buffer
  unless (seek MSGID, $end_of_ring, 0) {
    $self->_log(1, "seek to position $end_of_ring failed: $!");
    close MSGID;
    return 1;
  }

  print MSGID "$mid\n\n";
  close MSGID;

  return;
}

1;
__END__