lib/PublicInbox/NNTP.pm | 16 ++++++++++++++++ t/nntpd.t | 17 +++++++++++++++++ diff --git a/lib/PublicInbox/NNTP.pm b/lib/PublicInbox/NNTP.pm index d409e7828f29e2d6d75f8d8309fee027d3665c69..8a31b910be76a317df6838879a5918a32d0c46b2 100644 --- a/lib/PublicInbox/NNTP.pm +++ b/lib/PublicInbox/NNTP.pm @@ -438,6 +438,22 @@ # why? leafnode requires a Path: header for some inexplicable # reason. We'll fake the shortest one possible. $hdr->header_set('Path', 'y'); + # leafnode (and maybe other NNTP clients) have trouble dealing + # with v2 messages which have multiple Message-IDs (either due + # to our own content-based dedupe or buggy git-send-email versions). + my @mids = $hdr->header('Message-ID'); + if (scalar(@mids) > 1) { + my $mid0 = "<$mid>"; + $hdr->header_set('Message-ID', $mid0); + my @alt = $hdr->header('X-Alt-Message-ID'); + my %seen = map { $_ => 1 } (@alt, $mid0); + foreach my $m (@mids) { + next if $seen{$m}++; + push @alt, $m; + } + $hdr->header_set('X-Alt-Message-ID', @alt); + } + # clobber some my $xref = xref($self, $ng, $n, $mid); $hdr->header_set('Xref', $xref); diff --git a/t/nntpd.t b/t/nntpd.t index cce21eeb620d09bfc9c783993ce5de743b94d9fa..a95fb6fca8801d66ac4a97efa61bdd342fa0a8ac 100644 --- a/t/nntpd.t +++ b/t/nntpd.t @@ -250,6 +250,23 @@ my $hdr = $n->head("<$long_hdr>"); my $expect = qr/\AMessage-ID: /i . qr/\Q<$long_hdr>\E/; ok(scalar(grep(/$expect/, @$hdr)), 'Message-ID not folded'); ok(scalar(grep(/^Path:/, @$hdr)), 'Path: header found'); + + # it's possible for v2 messages to have 2+ Message-IDs, + # but leafnode can't handle it + if ($version != 1) { + my @mids = ("<$long_hdr>", '<2mid@wtf>'); + $for_leafnode->header_set('Message-ID', @mids); + $for_leafnode->body_set('not-a-dupe'); + my $warn = ''; + $SIG{__WARN__} = sub { $warn .= join('', @_) }; + $im->add($for_leafnode); + $im->done; + like($warn, qr/reused/, 'warned for reused MID'); + $hdr = $n->head('<2mid@wtf>'); + my @hmids = grep(/\AMessage-ID: /i, @$hdr); + is(scalar(@hmids), 1, 'Single Message-ID in header'); + like($hmids[0], qr/: <2mid\@wtf>/, 'got expected mid'); + } } # pipelined requests: