about summary refs log tree commit homepage
diff options
context:
space:
mode:
-rw-r--r--lib/PublicInbox/LeiToMail.pm30
-rw-r--r--t/lei_to_mail.t16
-rw-r--r--t/mbox_reader.t2
3 files changed, 35 insertions, 13 deletions
diff --git a/lib/PublicInbox/LeiToMail.pm b/lib/PublicInbox/LeiToMail.pm
index 8d030227..dcf6d8a3 100644
--- a/lib/PublicInbox/LeiToMail.pm
+++ b/lib/PublicInbox/LeiToMail.pm
@@ -34,7 +34,11 @@ my %kw2status = (
 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];
@@ -92,6 +96,16 @@ sub eml2mboxo {
         $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) = @_;
@@ -99,9 +113,7 @@ sub eml2mboxcl {
         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;
@@ -113,9 +125,7 @@ sub eml2mboxcl2 {
         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;
@@ -276,7 +286,11 @@ sub _buf2maildir {
         } 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";
diff --git a/t/lei_to_mail.t b/t/lei_to_mail.t
index 083e0df4..e5ac8eac 100644
--- a/t/lei_to_mail.t
+++ b/t/lei_to_mail.t
@@ -25,7 +25,7 @@ for my $mbox (@MBOX) {
         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");
@@ -170,6 +170,12 @@ for my $zsfx (qw(gz bz2 xz)) { # XXX should we support zst, zz, lzo, lzma?
         }
 }
 
+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);
@@ -177,7 +183,7 @@ if ('default deduplication uses content_hash') {
         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 };
@@ -186,7 +192,7 @@ if ('default deduplication uses content_hash') {
         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');
@@ -200,7 +206,7 @@ if ('default deduplication uses content_hash') {
         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');
 }
 
@@ -213,7 +219,7 @@ SKIP: { # FIFO support
         $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');
 }
 
diff --git a/t/mbox_reader.t b/t/mbox_reader.t
index 4ea2ae29..30a5e6e3 100644
--- a/t/mbox_reader.t
+++ b/t/mbox_reader.t
@@ -45,6 +45,8 @@ my $check_fmt = sub {
         seek($fh, 0, SEEK_SET) or BAIL_OUT "seek: $!";
         $reader->$fmt($fh, sub {
                 my ($eml) = @_;
+                $eml->header_set('Status');
+                $eml->header_set('Lines');
                 my $cur = shift @order;
                 my @cl = $eml->header_raw('Content-Length');
                 if ($fmt =~ /\Amboxcl/) {