]> Sergey Matveev's repositories - public-inbox.git/blob - lib/PublicInbox/Reply.pm
07288aab3c4fd21f34df3f28cb416144242cecb3
[public-inbox.git] / lib / PublicInbox / Reply.pm
1 # Copyright (C) 2014-2017 all contributors <meta@public-inbox.org>
2 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
3 package PublicInbox::Reply;
4 use strict;
5 use warnings;
6 use URI::Escape qw/uri_escape_utf8/;
7 use PublicInbox::Hval qw/ascii_html/;
8 use PublicInbox::Address;
9 use PublicInbox::MID qw/mid_clean mid_escape/;
10
11 sub squote_maybe ($) {
12         my ($val) = @_;
13         if ($val =~ m{([^\w@\./,\%\+\-])}) {
14                 $val =~ s/(['!])/'\\$1'/g; # '!' for csh
15                 return "'$val'";
16         }
17         $val;
18 }
19
20 sub add_addrs {
21         my ($to, $cc, @addrs) = @_;
22         foreach my $address (@addrs) {
23                 my $dst = lc($address);
24                 $cc->{$dst} ||= $address;
25                 $$to ||= $dst;
26         }
27 }
28
29 my @reply_headers = qw(From To Cc Reply-To);
30 my $reply_headers = join('|', @reply_headers);
31
32 sub mailto_arg_link {
33         my ($ibx, $hdr) = @_;
34         my $cc = {}; # everyone else
35         my $to; # this is the From address by defaultq
36         my $reply_to_all = 'reply-to-all'; # the only good default :P
37
38         foreach my $rt (split(/\s*,\s*/, $ibx->{replyto} || ':all')) {
39                 if ($rt eq ':all') {
40                         foreach my $h (@reply_headers) {
41                                 my $v = $hdr->header($h);
42                                 defined($v) && ($v ne '') or next;
43                                 my @addrs = PublicInbox::Address::emails($v);
44                                 add_addrs(\$to, $cc, @addrs);
45                         }
46                 } elsif ($rt eq ':list') {
47                         $reply_to_all = 'reply-to-list';
48                         add_addrs(\$to, $cc, $ibx->{-primary_address});
49                 } elsif ($rt =~ /\A(?:$reply_headers)\z/io) {
50                         # ugh, this is weird...
51                         my $v = $hdr->header($rt);
52                         if (defined($v) && ($v ne '')) {
53                                 my @addrs = PublicInbox::Address::emails($v);
54                                 add_addrs(\$to, $cc, @addrs);
55                         }
56                 } elsif ($rt =~ /@/) {
57                         add_addrs(\$to, $cc, $rt);
58                 } else {
59                         warn "Unrecognized replyto = '$rt' in config\n";
60                 }
61         }
62
63         my @arg;
64         my $obfs = $ibx->{obfuscate};
65         my $subj = $hdr->header('Subject') || '';
66         $subj = "Re: $subj" unless $subj =~ /\bRe:/i;
67         my $mid = $hdr->header_raw('Message-ID');
68         push @arg, '--in-reply-to='.squote_maybe(mid_clean($mid));
69         my $irt = mid_escape($mid);
70         delete $cc->{$to};
71         if ($obfs) {
72                 my $arg_to = $to;
73                 $arg_to =~ s/\./\$(echo .)/;
74                 push @arg, "--to=$arg_to";
75         } else {
76                 push @arg, "--to=$to";
77                 $to = uri_escape_utf8($to);
78                 $subj = uri_escape_utf8($subj);
79         }
80         my @cc = sort values %$cc;
81         $cc = '';
82         if (@cc) {
83                 if ($obfs) {
84                         push(@arg, map {
85                                 s/\./\$(echo .)/;
86                                 "--cc=$_";
87                         } @cc);
88                 } else {
89                         $cc = '&Cc=' . uri_escape_utf8(join(',', @cc));
90                         push(@arg, map { "--cc=$_" } @cc);
91                 }
92         }
93
94         # I'm not sure if address obfuscation and mailto: links can
95         # be made compatible; and address obfuscation is misguided,
96         # anyways.
97         return (\@arg, '', $reply_to_all) if $obfs;
98
99         # order matters, Subject is the least important header,
100         # so it is last in case it's lost/truncated in a copy+paste
101         my $href = "mailto:$to?In-Reply-To=$irt${cc}&Subject=$subj";
102
103         (\@arg, ascii_html($href), $reply_to_all);
104 }
105
106 1;