App-Eduard

 view release on metacpan or  search on metacpan

lib/App/Eduard.pm  view on Meta::CPAN

	}

	if ($gpg->is_encrypted($msg)) {
		debug 'This mail looks encrypted';
		my ($code, $keyid, $email) = $gpg->decrypt($msg);
		return encrypt_error => (
			message   => stringify $gpg->{last_message}) if $code;
		return encrypt => (
			plaintext => stringify $gpg->{plaintext},
			decrypted => $gpg->{decrypted},
			message   => stringify $gpg->{last_message}) unless defined $keyid;
		return signencrypt => (
			keyid     => $keyid,
			email     => $email,
			plaintext => stringify $gpg->{plaintext},
			decrypted => $gpg->{decrypted},
			message   => stringify $gpg->{last_message});
	}

	debug 'This mail doesn\'t seem to be signed or encrypted';
	return 'plain', message => ''
}

sub run {
	GetOptions(
		'always-trust!' => \$ENV{EDUARD_ALWAYS_TRUST},
		'debug!'        => \$ENV{EDUARD_DEBUG},
		'from=s'        => \$ENV{EDUARD_FROM},
		'key=s'         => \$ENV{EDUARD_KEY},
		'keydir=s'      => \$ENV{EDUARD_KEYDIR},
		'logfile=s'     => \$ENV{EDUARD_LOGFILE},
		'passphrase=s'  => \$ENV{EDUARD_PASSPHRASE},
		'tmpl-path=s'   => \$ENV{EDUARD_TMPL_PATH},
		'use-agent!'    => \$ENV{EDUARD_USE_AGENT},
	);
	my $tmpl_path = $ENV{EDUARD_TMPL_PATH} // 'en';
	open STDERR, '>>', $ENV{EDUARD_LOGFILE} if $ENV{EDUARD_LOGFILE};

	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 {
		($tmpl, %params) = process_message $in
	} catch {
		($tmpl, %params) = (error => message => $_)
	};
	debug "Result is $tmpl, GnuPG said:\n", $params{message};

	$params{plaintext} = first_part $params{decrypted} if $params{decrypted};

	my $tt = Template->new(INCLUDE_PATH => rel2abs $tmpl_path, dist_file 'App-Eduard', 'tmpl');
	my ($keys, $result) = ('', '');
	$tt->process('keys', {keys => \@keys}, \$keys) if @keys;
	$tt->process($tmpl, \%params, \$result);
	my $email = MIME::Entity->build(
		From    => $ENV{EDUARD_FROM},
		To      => $in->get('From'),
		Type    => 'text/plain; charset=UTF-8',
		Encoding=> '-SUGGEST',
		Subject => 'Re: ' . $in->get('Subject'),
		Data    => $keys.$result);

	my $email_unencrypted = $email->dup;
	my $mg = mg always_trust => 1;
	my $encrypt_failed = $mg->mime_signencrypt($email, $in->get('From') =~ /<(.*)>/);
	debug 'Could not encrypt message, sending unencrypted. GnuPG said:', "\n", stringify $mg->{last_message} if $encrypt_failed;
	sendmail $encrypt_failed ? $email_unencrypted : $email
}

1;
__END__

=encoding utf-8

=head1 NAME

App::Eduard - GnuPG email sign/encrypt testing bot

=head1 SYNOPSIS

  use App::Eduard;
  my ($status, %params) = process_message '/path/to/message';
  if ($status eq 'signencrypt') {
    say 'This message is encrypted and signed with key ', $params{keyid}, ' from ', $params{email};
    say 'Its contents are: ', $params{plaintext};
  } elsif ($status eq 'encrypt') {
    say 'This message is encrypted but not signed';
    say 'Its contents are: ', $params{plaintext};
  } elsif ($status eq 'encrypt_error') {
    say 'This message is encrypted but I was unable to decrypt it. GnuPG output: ', $params{message};
  } elsif ($status eq 'sign') {
    say 'This message is signed with key ', $params{keyid}, ' from ', $params{email};
  } elsif ($status eq 'sign_error') {
    say 'This message is signed but I was unable to verify the signature. GnuPG output: ', $params{message};
  } elsif ($status eq 'plain') {
    say 'This message is neither signed nor encrypted';
  } elsif ($status eq 'error') {
    say 'There was an error processing the message: ', $params{message};
  }

=head1 DESCRIPTION

Eduard is Ceata's reimplementation of the Edward reply bot referenced in L<https://emailselfdefense.fsf.org/>.

=head1 EXPORTS

None by default.

=head2 B<import_keys>(I<$entity>, I<$gpg>)

Scan a message for PGP public keys, and import them. I<$entity> is a L<MIME::Entity> to scan, I<$gpg> is a L<Mail::GnuPG> instance.

Returns a list of fingerprints of keys found.

=head2 B<process_message>(I<$message>)

Analyze a message, looking for PGP signatures and encryption. I<$message> can be:



( run in 1.940 second using v1.01-cache-2.11-cpan-99c4e6809bf )