X-Git-Url: http://git.ieval.ro/?a=blobdiff_plain;f=lib%2FApp%2FEdwardNG.pm;h=e6cea876b36c13094f4a61f95749673a3cecd984;hb=d4b0b0760240ee6298914e421cea65236241fc3a;hp=f6b54a4254cffe720246bd503447c89763f024ac;hpb=d03d611f3dd49549200b266ff84b70bd7a69ba4f;p=app-edwardng.git diff --git a/lib/App/EdwardNG.pm b/lib/App/EdwardNG.pm index f6b54a4..e6cea87 100644 --- a/lib/App/EdwardNG.pm +++ b/lib/App/EdwardNG.pm @@ -5,12 +5,13 @@ use strict; use warnings; use parent qw/Exporter/; our $VERSION = '0.001'; -our @EXPORT = qw/process_message/; +our @EXPORT_OK = qw/import_pubkeys process_message/; use Email::Sender::Simple qw/sendmail/; use File::Share qw/dist_file/; use File::Slurp qw/read_file/; use File::Spec::Functions qw/rel2abs/; +use IO::Handle; use Getopt::Long; use MIME::Entity; use MIME::Parser; @@ -31,18 +32,41 @@ sub mg { @_); } +sub mp { + my $parser = MIME::Parser->new; + $parser->decode_bodies($_[0] // 0); + $parser->output_to_core(1); + $parser +} + sub first_part{ my ($ent) = @_; return first_part ($ent->parts(0)) if $ent->parts; stringify [$ent->bodyhandle->as_lines] } +sub import_pubkeys { + my ($ent, $mg) = @_; + my @keys; + if ($ent->mime_type eq 'application/pgp-keys') { + $ent = mp(1)->parse_data($ent->stringify); + my $gpg = GnuPG::Interface->new; + $mg->_set_options($gpg); + $gpg->options->quiet(1); + my ($input, $status) = (IO::Handle->new, IO::Handle->new); + my $pid = $gpg->import_keys(handles => GnuPG::Handles->new(stdin => $input, status => $status)); + my $read = Mail::GnuPG::_communicate([$status], [$input], {$input => $ent->bodyhandle->as_string}); + push @keys, map { /IMPORT_OK \d+ (\w+)/ } $read->{$status}; + waitpid $pid, 0 + } + push @keys, import_pubkeys ($_, $mg) for $ent->parts; + @keys +} + sub process_message { my ($in) = @_; my $msg; - my $parser = MIME::Parser->new; - $parser->decode_bodies(0); - $parser->output_to_core(1); + my $parser = mp; $msg = $in if ref $in eq 'MIME::Entity'; $msg = $parser->parse ($in) if ref $in eq 'IO'; @@ -86,7 +110,7 @@ sub process_message { } debug 'This mail doesn\'t seem to be signed or encrypted'; - return 'plain' + return 'plain', message => '' } sub run { @@ -104,11 +128,10 @@ sub run { my $tmpl_path = $ENV{EDWARDNG_TMPL_PATH} // 'en'; open STDERR, '>>', $ENV{EDWARDNG_LOGFILE} if $ENV{EDWARDNG_LOGFILE}; - my $parser = MIME::Parser->new; - $parser->decode_bodies(0); - $parser->output_to_core(1); - my $in = $parser->parse(\*STDIN); + my $in = mp->parse(\*STDIN); debug 'Received mail from ', $in->get('From'); + my @keys = import_pubkeys $in, mg; + say 'Found keys: ', join ' ', @keys if @keys; my ($tmpl, %params); try { @@ -121,13 +144,16 @@ sub run { $params{plaintext} = first_part $params{decrypted} if $params{decrypted}; my $tt = Template->new(INCLUDE_PATH => rel2abs $tmpl_path, dist_file 'App-EdwardNG', 'tmpl'); - my $data; - $tt->process($tmpl, \%params, \$data); + my ($keys, $result) = ('', ''); + $tt->process('keys', {keys => \@keys}, \$keys) if @keys; + $tt->process($tmpl, \%params, \$result); my $email = MIME::Entity->build( From => $ENV{EDWARDNG_FROM}, To => $in->get('From'), + Type => 'text/plain; charset=UTF-8', + Encoding=> '-SUGGEST', Subject => 'Re: ' . $in->get('Subject'), - Data => $data); + Data => $keys.$result); my $email_unencrypted = $email->dup; my $mg = mg always_trust => 1; @@ -171,7 +197,19 @@ App::EdwardNG - GnuPG email sign/encrypt testing bot EdwardNG is a reimplementation of the Edward reply bot referenced in L. -This module exports a single function, B, which takes a single parameter representing the message. This parameter can be: +=head1 EXPORTS + +None by default. + +=head2 B(I<$entity>, I<$gpg>) + +Scan a message for PGP public keys, and import them. I<$entity> is a L to scan, I<$gpg> is a L instance. + +Returns a list of fingerprints of keys found. + +=head2 B(I<$message>) + +Analyze a message, looking for PGP signatures and encryption. I<$message> can be: =over @@ -181,7 +219,7 @@ This module exports a single function, B, which takes a single =item A scalar which represents a path to a message. -=item A L object +=item A L object created with decode_bodies(0) =back