sub _mbox_hdr_buf ($$$) {
my ($eml, $type, $kw) = @_;
$eml->header_set($_) for (qw(Lines Bytes Content-Length));
- my %hdr; # set Status, X-Status
+
+ # Messages are always 'O' (non-\Recent in IMAP), it saves
+ # MUAs the trouble of rewriting the mbox if no other
+ # changes are made
+ my %hdr = (Status => [ 'O' ]); # set Status, X-Status
for my $k (@$kw) {
if (my $ent = $kw2status{$k}) {
push @{$hdr{$ent->[0]}}, $ent->[1];
$buf;
}
+sub _mboxcl_common ($$$) {
+ my ($buf, $bdy, $crlf) = @_;
+ # add Lines: so mutt won't have to add it on MUA close
+ my $lines = $$bdy =~ tr!\n!\n!;
+ $$buf .= 'Content-Length: '.length($$bdy).$crlf.
+ 'Lines: '.$lines.$crlf.$crlf;
+ substr($$bdy, 0, 0, $$buf); # prepend header
+ $_[0] = $bdy;
+}
+
# mboxcl still escapes "From " lines
sub eml2mboxcl {
my ($eml, $kw) = @_;
my $crlf = $eml->{crlf};
if (my $bdy = delete $eml->{bdy}) {
$$bdy =~ s/^From />From /gm;
- $$buf .= 'Content-Length: '.length($$bdy).$crlf.$crlf;
- substr($$bdy, 0, 0, $$buf); # prepend header
- $buf = $bdy;
+ _mboxcl_common($buf, $bdy, $crlf);
}
$$buf .= $crlf;
$buf;
my $buf = _mbox_hdr_buf($eml, 'mboxcl2', $kw);
my $crlf = $eml->{crlf};
if (my $bdy = delete $eml->{bdy}) {
- $$buf .= 'Content-Length: '.length($$bdy).$crlf.$crlf;
- substr($$bdy, 0, 0, $$buf); # prepend header
- $buf = $bdy;
+ _mboxcl_common($buf, $bdy, $crlf);
}
$$buf .= $crlf;
$buf;
} while (!sysopen($fh, $tmp, O_CREAT|O_EXCL|O_WRONLY) &&
$! == EEXIST && ($rand = int(rand 0x7fffffff).','));
if (print $fh $$buf and close($fh)) {
- $dst .= $sfx eq '' ? 'new/' : 'cur/';
+ # ignore new/ and write only to cur/, otherwise MUAs
+ # with R/W access to the Maildir will end up doing
+ # a mass rename which can take a while with thousands
+ # of messages.
+ $dst .= 'cur/';
$rand = '';
do {
$final = $dst.$rand."oid=$oid:2,$sfx";
my $s = $cb->(PublicInbox::Eml->new($from), $kw);
is(substr($$s, -1, 1), "\n", "trailing LF in normal $mbox");
my $eml = PublicInbox::Eml->new($s);
- is($eml->header('Status'), 'R', "Status: set by $m");
+ is($eml->header('Status'), 'OR', "Status: set by $m");
is($eml->header('X-Status'), 'AF', "X-Status: set by $m");
if ($mbox eq 'mboxcl2') {
like($eml->body_raw, qr/^From /, "From not escaped $m");
}
}
+my $as_orig = sub {
+ my ($eml) = @_;
+ $eml->header_set('Status');
+ $eml->as_string;
+};
+
unlink $fn or BAIL_OUT $!;
if ('default deduplication uses content_hash') {
my $wcb = $wcb_get->('mboxo', $fn);
undef $wcb; # undef to commit changes
my $cmp = '';
open my $fh, '<', $fn or BAIL_OUT $!;
- PublicInbox::MboxReader->mboxo($fh, sub { $cmp .= shift->as_string });
+ PublicInbox::MboxReader->mboxo($fh, sub { $cmp .= $as_orig->(@_) });
is($cmp, $buf, 'only one message written');
local $lei->{opt} = { augment => 1 };
undef $wcb; # undef to commit changes
open $fh, '<', $fn or BAIL_OUT $!;
my @x;
- PublicInbox::MboxReader->mboxo($fh, sub { push @x, shift->as_string });
+ PublicInbox::MboxReader->mboxo($fh, sub { push @x, $as_orig->(@_) });
is(scalar(@x), 2, 'augmented mboxo');
is($x[0], $cmp, 'original message preserved');
is($x[1], $buf . "\nx\n", 'new message appended');
undef $wcb; # commit
seek($tmp, 0, SEEK_SET) or BAIL_OUT $!;
my $cmp = '';
- PublicInbox::MboxReader->mboxrd($tmp, sub { $cmp .= shift->as_string });
+ PublicInbox::MboxReader->mboxrd($tmp, sub { $cmp .= $as_orig->(@_) });
is($cmp, $buf, 'message written to stdout');
}
$wcb->(\(my $x = $buf), 'deadbeef', []);
undef $wcb; # commit
my $cmp = '';
- PublicInbox::MboxReader->mboxo($cat, sub { $cmp .= shift->as_string });
+ PublicInbox::MboxReader->mboxo($cat, sub { $cmp .= $as_orig->(@_) });
is($cmp, $buf, 'message written to FIFO');
}