# SYNOPSIS
-ssoma-mda /path/to/ssoma/repository.git < message
+ssoma-mda [-1] /path/to/ssoma/repository.git < message
# DESCRIPTION
permissions. This must be done by the MTA or MDA which invokes
ssoma-mda.
+# OPTIONS
+
+-1
+: Only allow a Message-ID to appear once in the database.
+ Future messages with an identical Message-ID will not be allowed.
+
# FILES
See ssoma_repository(5) for details.
# this appends the given message-id to the git repo, requires locking
# (Ssoma::Git::sync_do)
sub append {
- my ($self, $path, $simple) = @_;
+ my ($self, $path, $simple, $once) = @_;
my $git = $self->{git};
my $ref = $self->{ref};
if ($? == 0) { # rare, object already exists
chomp $type;
+ if ($once) {
+ my $mid = $simple->header("Message-ID");
+ die "CONFLICT: Message-ID: $mid exists ($path)\n";
+ }
# we return undef here if the message already exists
if ($type eq "blob") {
# the main entry point takes an Email::Simple object
sub deliver {
- my ($self, $simple) = @_;
+ my ($self, $simple, $once) = @_;
my $git = $self->{git};
# convert the Message-ID into a path
my $sub = sub {
$git->tmp_index_do(sub {
- $self->append($path, $simple);
+ $self->append($path, $simple, $once);
});
};
$git->sync_do(sub { $git->tmp_git_do($sub) });
# This is the command-line mail delivery agent for servers.
# Try to keep this small as it may be invoked frequently for each message
# delivered.
-my $usage = "ssoma-mda /path/to/git/repo < /path/to/rfc2822_message";
+my $usage = "ssoma-mda [-1] /path/to/git/repo < /path/to/rfc2822_message";
use strict;
use warnings;
use Ssoma::MDA;
use Ssoma::Git;
use Email::Simple;
-my $repo = shift @ARGV or die "Usage: $usage\n";
+my $once = $ARGV[0] eq "-1";
+my $repo = pop @ARGV or die "Usage: $usage\n";
my $git = Ssoma::Git->new($repo);
my $mda = Ssoma::MDA->new($git);
my $simple;
{
local $/;
- $simple = Email::Simple->new(<>);
+ $simple = Email::Simple->new(<STDIN>);
}
-$mda->deliver($simple);
+$mda->deliver($simple, $once);
my $tmp = tempdir(CLEANUP => 1);
use File::Temp qw/tempdir/;
use Email::Simple;
+use IPC::Run qw(run);
ok(-x $mda, "$mda is executable");
ok(-x $cli, "$cli is executable");
is(scalar @tree, 2, "two messages sitting in a tree");
}
+# duplicate detection
+{
+ my $simple = Email::Simple->new(<<'EOF');
+From: moi@example.com
+To: you@example.com
+Message-Id: <666666@example.com>
+Subject: xxx
+
+OMFG
+EOF
+ $simple = $simple->as_string;
+ my ($out, $err) = ("", "");
+ run([$mda, "-1", "$tmp/input.git"], \$simple, \$out, \$err);
+ isnt($?, 0, "$mda exited with failure");
+ like($err, qr/CONFLICT/, "conflict message detected");
+}
+
done_testing();