# DESCRIPTION
ssoma uses a git repository to store each email as a git blob. The tree
-filename of the blob is based on the SHA1 hexdigest of the Message-Id
+filename of the blob is based on the SHA1 hexdigest of the Message-ID
header. A commit is made for each message delivered. The commit SHA-1
identifier is used by ssoma clients to track synchronization state.
# PATHNAMES IN TREES
-A Message-Id may be extremely long and also contain slashes, so using
+A Message-ID may be extremely long and also contain slashes, so using
them as a path name is challenging. Instead we use the SHA-1 hexdigest
-of the Message-Id (including the "<" and ">") to generate a path name.
-Leading and trailing white space in the Message-Id header is ignored
+of the Message-ID (including the "<" and ">") to generate a path name.
+Leading and trailing white space in the Message-ID header is ignored
for hashing.
-A message with Message-Id of: <20131106023245.GA20224@dcvr.yhbt.net>
+A message with Message-ID of: <20131106023245.GA20224@dcvr.yhbt.net>
Would be stored as: 21/4527ce3741f50bb9afa65e7c5003c8a8ddc4b1
Thus it is easy to look up the contents of a message matching a given
-a Message-Id.
+a Message-ID.
# CONFLICTS
-Message-Id is a unique-enough identifier for practical purposes, but
+Message-ID is a unique-enough identifier for practical purposes, but
they may still conflict (especially in case of malicious clients and
-timing issues). In the case of identical Message-Id and different
+timing issues). In the case of identical Message-ID and different
messages, the blob shall become a tree with multiple messages.
-Likewise, if there is a (rare) SHA-1 conflict on different Message-Id
-headers, the tree will contain each message (with different Message-Id
+Likewise, if there is a (rare) SHA-1 conflict on different Message-ID
+headers, the tree will contain each message (with different Message-ID
headers).
-Thus the blobs for conflicting Message-Ids will be the SHA-1 hexdigest
+Thus the blobs for conflicting Message-IDs will be the SHA-1 hexdigest
of the Subject header and raw body (no extra whitespace delimiting the
two).
ssoma-mda handles all steps once invoked.
2. Mail transport agent invokes ssoma-mda
-3. reads message via stdin, extracting Message-Id
+3. reads message via stdin, extracting Message-ID
4. acquires fcntl lock on $GIT_DIR/ssoma.lock
5. creates or updates the blob of associated 2/38 SHA-1 path
6. updates the index and commits
# leaving <> out of Message-IDs on the command-line is
# common and practical since it frees the user from
# quoting/escaping in most cases, so do not require
- # Message-Ids have <> around themh
+ # Message-IDs have <> around them
if ($message_id =~ /\A<.+>\z/) { # rare
$self->_midextract($message_id, $mbox);
} else { # common
my $simple = Email::Simple->new(<<'EOF');
From: me@example.com
To: u@example.com
-Message-Id: <666@example.com>
+Message-ID: <666@example.com>
Subject: zzz
OMFG
my $simple = Email::Simple->new(<<'EOF');
From: moi@example.com
To: you@example.com
-Message-Id: <666666@example.com>
+Message-ID: <666666@example.com>
Subject: xxx
OMFG
my @full = `$cli cat \\<666\@example.com\\>`;
my $from = shift @full;
like($from, qr/^From /, "ssoma cat mbox has From_ line");
- is(scalar grep(/^Message-Id: <666\@example\.com>/, @full), 1,
+ is(scalar grep(/^Message-ID: <666\@example\.com>/, @full), 1,
"correct message returned from ssoma cat");
my @lazy = `$cli cat 666\@example.com`;
$from = shift @lazy;
my @full = `$cli cat \\<666\@example.com\\> $tmp/input.git`;
my $from = shift @full;
like($from, qr/^From /, "ssoma cat mbox has From_ line");
- is(scalar grep(/^Message-Id: <666\@example\.com>/, @full), 1,
+ is(scalar grep(/^Message-ID: <666\@example\.com>/, @full), 1,
"correct message returned from ssoma cat");
}
my $dup = Email::Simple->new(<<'EOF');
From: me@example.com
To: u@example.com
-Message-Id: <666@example.com>
+Message-ID: <666@example.com>
Subject: duplicate
EOF
is(system(@cmd), 0, "sync $name with ssoma(1)");
my @both = `$cli cat \\<666\@example.com\\>`;
- is(scalar grep(/^Message-Id: <666\@example\.com>/, @both), 2,
+ is(scalar grep(/^Message-ID: <666\@example\.com>/, @both), 2,
"correct messages returned from ssoma cat");
is(scalar grep(/^From /, @both), 2,
"From_ line from both messages returned from ssoma cat");
my $simple = Email::Simple->new(<<'EOF');
From: me@example.com
To: u@example.com
-Message-Id: <666@example.com>
+Message-ID: <666@example.com>
Subject: zzz
OMFG
my $simple = Email::Simple->new(<<'EOF');
From: moi@example.com
To: you@example.com
-Message-Id: <666666@example.com>
+Message-ID: <666666@example.com>
Subject: xxx
OMFG
my $email = Email::Simple->new(<<'EOF');
From: U <u@example.com>
To: Me <me@example.com>
-Message-Id: <666@example.com>
+Message-ID: <666@example.com>
Subject: :o
HIHI
my $another = Email::Simple->new(<<'EOF');
From: U <u@example.com>
To: Me <me@example.com>
-Message-Id: <666666@example.com>
+Message-ID: <666666@example.com>
Subject: byebye
*yawn*
my $conflict = Email::Simple->new(<<'EOF');
From: U <u@example.com>
To: Me <me@example.com>
-Message-Id: <666666@example.com>
+Message-ID: <666666@example.com>
Subject: BYE
*YAWN*
my @lines = <$fh>;
my @subjects = grep /^Subject:/, @lines;
my @from = grep /^From:/, @lines;
- my @mid = grep /^Message-Id:/i, @lines;
+ my @mid = grep /^Message-ID:/i, @lines;
is(scalar @subjects, 3, "3 subjects in dump");
is(scalar @mid, 3, "3 message-ids in dump");
is(scalar @from, 3, "3 From: lines in dump");
my $email = Email::Simple->new(<<'EOF');
From: me@example.com
To: u@example.com
-Message-Id: <666@example.com>
+Message-ID: <666@example.com>
Subject: zzz
OMFG