about summary refs log tree commit homepage
path: root/lib/PublicInbox/IMAP.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/PublicInbox/IMAP.pm')
-rw-r--r--lib/PublicInbox/IMAP.pm26
1 files changed, 12 insertions, 14 deletions
diff --git a/lib/PublicInbox/IMAP.pm b/lib/PublicInbox/IMAP.pm
index 1f65aa65..b12533cb 100644
--- a/lib/PublicInbox/IMAP.pm
+++ b/lib/PublicInbox/IMAP.pm
@@ -39,14 +39,7 @@ use PublicInbox::DS qw(now);
 use PublicInbox::GitAsyncCat;
 use Text::ParseWords qw(parse_line);
 use Errno qw(EAGAIN);
-use PublicInbox::IMAPsearchqp;
-
-my $Address;
-for my $mod (qw(Email::Address::XS Mail::Address)) {
-        eval "require $mod" or next;
-        $Address = $mod and last;
-}
-die "neither Email::Address::XS nor Mail::Address loaded: $@" if !$Address;
+use PublicInbox::Address;
 
 sub LINE_MAX () { 8000 } # RFC 2683 3.2.1.5
 
@@ -426,8 +419,10 @@ sub _esc ($) {
         if (!defined($v)) {
                 'NIL';
         } elsif ($v =~ /[{"\r\n%*\\\[]/) { # literal string
+                utf8::encode($v);
                 '{' . length($v) . "}\r\n" . $v;
         } else { # quoted string
+                utf8::encode($v);
                 qq{"$v"}
         }
 }
@@ -437,7 +432,7 @@ sub addr_envelope ($$;$) {
         my $v = $eml->header_raw($x) //
                 ($y ? $eml->header_raw($y) : undef) // return 'NIL';
 
-        my @x = $Address->parse($v) or return 'NIL';
+        my @x = PublicInbox::Address::objects($v) or return 'NIL';
         '(' . join('',
                 map { '(' . join(' ',
                                 _esc($_->name), 'NIL',
@@ -590,14 +585,16 @@ sub fetch_blob_cb { # called by git->cat_async via ibx_async_cat
         my ($self, undef, $msgs, $range_info, $ops, $partial) = @$fetch_arg;
         my $ibx = $self->{ibx} or return $self->close; # client disconnected
         my $smsg = shift @$msgs or die 'BUG: no smsg';
-        if (!defined($oid)) {
+        if (!defined($type)) {
+                warn "E: git aborted on $oid / $smsg->{blob} $ibx->{inboxdir}";
+                return $self->close;
+        } elsif ($type ne 'blob') {
                 # it's possible to have TOCTOU if an admin runs
                 # public-inbox-(edit|purge), just move onto the next message
-                warn "E: $smsg->{blob} missing in $ibx->{inboxdir}\n";
+                warn "E: $smsg->{blob} $type in $ibx->{inboxdir}\n";
                 return $self->requeue_once;
-        } else {
-                $smsg->{blob} eq $oid or die "BUG: $smsg->{blob} != $oid";
         }
+        $smsg->{blob} eq $oid or die "BUG: $smsg->{blob} != $oid";
         my $pre;
         ($self->{anon} && !$self->{wbuf} && $msgs->[0]) and
                 $pre = ibx_async_prefetch($ibx, $msgs->[0]->{blob},
@@ -661,7 +658,7 @@ sub op_eml_new { $_[4] = PublicInbox::Eml->new($_[3]) }
 # s/From / fixes old bug from import (pre-a0c07cba0e5d8b6a)
 sub to_crlf_full {
         ${$_[0]} =~ s/(?<!\r)\n/\r\n/sg;
-        ${$_[0]} =~ s/\A[\r\n]*From [^\r\n]*\r\n//s;
+        PublicInbox::Eml::strip_from(${$_[0]});
 }
 
 sub op_crlf_bref { to_crlf_full($_[3]) }
@@ -1084,6 +1081,7 @@ sub search_uid_range { # long_response
 
 sub parse_imap_query ($$) {
         my ($self, $query) = @_;
+        # IMAPsearchqp gets loaded in IMAPD->refresh_groups
         my $q = PublicInbox::IMAPsearchqp::parse($self, $query);
         if (ref($q)) {
                 my $max = $self->{ibx}->over(1)->max;