diff options
Diffstat (limited to 'lib/PublicInbox/Eml.pm')
-rw-r--r-- | lib/PublicInbox/Eml.pm | 43 |
1 files changed, 28 insertions, 15 deletions
diff --git a/lib/PublicInbox/Eml.pm b/lib/PublicInbox/Eml.pm index 3c681ba5..d59d7c3f 100644 --- a/lib/PublicInbox/Eml.pm +++ b/lib/PublicInbox/Eml.pm @@ -1,4 +1,4 @@ -# Copyright (C) 2020-2021 all contributors <meta@public-inbox.org> +# Copyright (C) all contributors <meta@public-inbox.org> # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt> # # Lazy MIME parser, it still slurps the full message but keeps short @@ -122,9 +122,10 @@ sub new { my $hdr = substr($$ref, 0, $header_size_limit + 1); hdr_truncate($hdr) if length($hdr) > $header_size_limit; bless { hdr => \$hdr, crlf => $1 }, __PACKAGE__; - } else { # nothing useful - my $hdr = $$ref = ''; - bless { hdr => \$hdr, crlf => "\n" }, __PACKAGE__; + } else { # just a body w/o header? + my $hdr = ''; + my $eol = ($$ref =~ /(\r?\n)/) ? $1 : "\n"; + bless { hdr => \$hdr, crlf => $eol, bdy => $ref }, __PACKAGE__; } } @@ -143,6 +144,7 @@ sub header_raw { my $re = re_memo($_[1]); my @v = (${ $_[0]->{hdr} } =~ /$re/g); for (@v) { + utf8::decode($_); # SMTPUTF8 # for compatibility w/ Email::Simple::Header, s/\s+\z//s; s/\A\s+//s; @@ -332,6 +334,11 @@ sub body_set { undef; } +# workaround https://rt.cpan.org/Public/Bug/Display.html?id=139622 +# Encode 2.87..3.12 leaks on croak, so we defer and croak ourselves +our @enc_warn; +my $enc_warn = sub { push @enc_warn, @_ }; + sub body_str_set { my ($self, $str) = @_; my $cs = ct($self)->{attributes}->{charset} // @@ -339,10 +346,10 @@ sub body_str_set { my $enc = find_encoding($cs) // croak "unknown encoding `$cs'"; my $tmp; { - my @w; - local $SIG{__WARN__} = sub { push @w, @_ }; + local @enc_warn; + local $SIG{__WARN__} = $enc_warn; $tmp = $enc->encode($str, Encode::FB_WARN); - croak(@w) if @w; + croak(@enc_warn) if @enc_warn; }; body_set($self, \$tmp); } @@ -358,14 +365,15 @@ sub header_set { $pfx .= ': '; my $len = 78 - length($pfx); @vals = map {; + utf8::encode(my $v = $_); # to bytes, support SMTPUTF8 # folding differs from Email::Simple::Header, # we favor tabs for visibility (and space savings :P) if (length($_) >= $len && (/\n[^ \t]/s || !/\n/s)) { local $Text::Wrap::columns = $len; local $Text::Wrap::huge = 'overflow'; - $pfx . wrap('', "\t", $_) . $self->{crlf}; + $pfx . wrap('', "\t", $v) . $self->{crlf}; } else { - $pfx . $_ . $self->{crlf}; + $pfx . $v . $self->{crlf}; } } @vals; $$hdr =~ s!$re!shift(@vals) // ''!ge; # replace current headers, first @@ -467,12 +475,11 @@ sub body_str { join("\n\t", header_raw($self, 'Content-Type'))); }; my $enc = find_encoding($cs) or croak "unknown encoding `$cs'"; - my $tmp = body($self); - # workaround https://rt.cpan.org/Public/Bug/Display.html?id=139622 - my @w; - local $SIG{__WARN__} = sub { push @w, @_ }; - my $ret = $enc->decode($tmp, Encode::FB_WARN); - croak(@w) if @w; + my $ret = body($self); + local @enc_warn; + local $SIG{__WARN__} = $enc_warn; + $ret = $enc->decode($ret, Encode::FB_WARN); + croak(@enc_warn) if @enc_warn; $ret; } @@ -525,4 +532,10 @@ sub willneed { re_memo($_) for @_ } willneed(qw(From To Cc Date Subject Content-Type In-Reply-To References Message-ID X-Alt-Message-ID)); +# This fixes an old bug from import (pre-a0c07cba0e5d8b6a) +# mutt also pipes single RFC822 messages with a "From " line, +# but no Content-Length or "From " escaping. +# "git format-patch" also generates such files by default. +sub strip_from { $_[0] =~ s/\A[\r\n]*From [^\n]*\n//s } + 1; |