App-Eduard

 view release on metacpan or  search on metacpan

MANIFEST  view on Meta::CPAN

t/App-Eduard.t
t/data/contains-pubkey
t/data/inline-encrypted
t/data/inline-encrypted-attachment
t/data/inline-signed
t/data/inline-signed-attachment
t/data/inline-signed-encrypted
t/data/mime-encrypted
t/data/mime-signed
t/data/mime-signed-encrypted
t/keydir/pubring.gpg
t/keydir/secring.gpg
share/tmpl/en/encrypt
share/tmpl/en/encrypt_error
share/tmpl/en/error
share/tmpl/en/keys
share/tmpl/en/plain
share/tmpl/en/sign
share/tmpl/en/sign_error
share/tmpl/en/signencrypt
META.yml                                 Module YAML meta-data (added by MakeMaker)
META.json                                Module JSON meta-data (added by MakeMaker)

README  view on Meta::CPAN

   make
   make test
   make install

USAGE

Typical usage of Eduard is as follows:

1. Create a new GPG homedir
   $ mkdir /srv/eduard
2. Create a suitable gpg.conf
   $ cat > /srv/eduard/gpg.conf <<END
   no-greeting
   keyserver hkp://keys.gnupg.net
   auto-key-locate keyserver
   keyserver-options auto-key-retrieve
   END
3. Generate a new key
   $ gpg --homedir /srv/eduard --gen-key
4. Add an entry to /etc/aliases
   $ echo 'eduard: |/path/to/eduard --keydir=/srv/eduard --key=KEYID --from=eduard@hostname.tld' >> /etc/aliases
   For multiple language support, add multiple entries to /etc/aliases of the form:
   $ echo 'eduard-lang: |/path/to/eduard --keydir=/srv/eduard --key=KEYID --from=eduard@hostname.tld --tmpl=lang' >>/etc/aliases

DEPENDENCIES

This module requires these other modules and libraries:

 * Email::Sender

SIGNATURE  view on Meta::CPAN

SHA1 016e4f0429e73f85dbfec2d98672d5db3b1a98bb t/App-Eduard.t
SHA1 d80a6379a9fad261587caa3aa631d26f5c552ff3 t/data/contains-pubkey
SHA1 052a9473becfebcf8ae4dedde64c9c839600c0d6 t/data/inline-encrypted
SHA1 2ebeff7efdf1dcd6c48af9078639f492f733a282 t/data/inline-encrypted-attachment
SHA1 7a3473b4be8d31ea46eaf34b28788201472a3846 t/data/inline-signed
SHA1 1c7904ccac2a4fbf6ea9565e91cccc5e5967396d t/data/inline-signed-attachment
SHA1 2bac2e28ed9b53c5496b754d1c3525326f2450c8 t/data/inline-signed-encrypted
SHA1 57bd261514d397946d2dc997fbe3d278dd1a8a0c t/data/mime-encrypted
SHA1 3cfff105472b47414f272be06e0649e60f6f1b0a t/data/mime-signed
SHA1 9c67bed693e85e821047d2dfa5282a1ba28e61c2 t/data/mime-signed-encrypted
SHA1 59c25e0d4a8a1b400d75e8892723b84d88db7954 t/keydir/pubring.gpg
SHA1 d071b8efe7c2d59b6260bb07c194708054e8630b t/keydir/secring.gpg
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQIcBAEBCgAGBQJUQs+2AAoJEMoENb5ewbNi6xkQAJaJOxPfbNfQamzcvaHyZ2KF
0oVLJr9X+CKvQx65otlFbGRR2jKWq03+Y8YYDyHFYDvGqekfFptx83ZUwpQkP+3P
O1fjN6ehjts1cANY1/KCYNlLJ9NzK/k8x7fRw7Htm+8G7BbNnaV2SedwlDCuos7I
VvZRRnlDznGE0J6GG4lD31cv5z10gHQyJ08S5qeko8pj1kDd8MK6NMk6gyk82Z5V
HkrKqmroLtF2XtQ28Y8yNF/35JQyhKMWhrLhUaEsgrZMgwF1y0zOjYYVdWFQEBr9
WHtO4PU2su/7p9iC9zcS62SPC+tefhj7qMnYVM0NIooiVrt1KrdSVm9O894KWRuL
qF60v6ltE5djESzt1mNCt+2iOuXp6MddC/6LjFj/erh8Hoa9qGNMgwx9fXvH+xre

eduard  view on Meta::CPAN

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

It reads an email from STDIN, checks it for PGP signatures and encryption, then replies appropriately.

=head1 OPTIONS

=over

=item B<--always-trust>, B<--no-always-trust>

If B<--always-trust>, skip key validation and assume that used keys are always fully trusted. See the gpg(1) manpage, option C<--trust-model always> for more information. Defaults to B<--no-always-trust>.

=item B<--debug>, B<--no-debug>

If B<--debug>, output some debugging information on STDERR. Defaults to B<--no-debug>

=item B<--from>=I<address>

Mail address to send messages from.

=item B<--key>=I<keyid>

eduard  view on Meta::CPAN

=item B<--passphrase>=I<passphrase>

Private key passphrase.

=item B<--tmpl-path>=I<path>

Path to the template directory. Users of the default templates can select the language with this argument. Available languages: en. Defaults to B<--tmpl-path=en>.

=item B<--use-agent>, B<--no-use-agent>

If B<--use-agent>, use L<gpg-agent(1)>. Defaults to B<--no-gpg-agent>.

=back

=head1 ENVIRONMENT

Configuration can also be done via the environment. Use 1 for true and 0 for false. Command-line options override environment variables.

=over

=item EDUARD_ALWAYS_TRUST

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

	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 find_pgp_part {
	my ($ent, $mg) = @_;

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

	$msg = $parser->parse_data ($in)  if     ref $in eq 'SCALAR';
	$msg = $parser->parse_open ($in)  unless ref $in;
	die "Don't know how to parse $in" unless $msg;

	if ($msg->mime_type ne 'multipart/signed' && $msg->mime_type ne 'multipart/encrypted') {
		# PGP/Inline requires decoding
		$parser->decode_bodies(1);
		$msg = $parser->parse_data($msg->stringify)
	}

	my $gpg = mg;
	if ($msg->effective_type ne 'multipart/signed' && $msg->effective_type ne 'multipart/encrypted' && !$msg->bodyhandle) {
		debug 'This is (probably) a PGP/Inline mail with attachments. Working around...';
		$msg = find_pgp_part $msg, $gpg
	}

	if ($gpg->is_signed($msg)) {
		debug 'This mail looks signed';
		my ($code, $keyid, $email) = $gpg->verify($msg);
		return sign_error => (
			message => stringify $gpg->{last_message}) if $code;
		return sign => (
			keyid   => $keyid,
			email   => $email,
			message => stringify $gpg->{last_message});
	}

	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},

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

  }

=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:

=over

=item A filehandle reference, e.g. C<\*STDIN>.

t/App-Eduard.t  view on Meta::CPAN

use constant EMAIL => 'Eduard (Key for testing Eduard) <eduard@ceata.org>';

use File::Copy qw/cp/;
use File::Temp qw/tempdir/;
use Test::More tests => 25;
BEGIN { use_ok('App::Eduard', qw/import_pubkeys process_message/) };

umask 0077; # GPG doesn't like group-/world-readable homedirs
$ENV{EDUARD_DEBUG} = $ENV{TEST_VERBOSE};
$ENV{EDUARD_KEYDIR} = tempdir 'App-Eduard-test.XXXX', TMPDIR => 1, CLEANUP => 1;
cp "t/keydir/$_", $ENV{EDUARD_KEYDIR} for qw/pubring.gpg secring.gpg/;

my $contains_pubkey = App::Eduard::mp->parse_open('t/data/contains-pubkey');
my @keys = import_pubkeys ($contains_pubkey, App::Eduard::mg);
is $keys[0], 'DE12658069C2F09BF996CC855AAF79E969137654', 'import_pubkeys';

my ($tmpl, %params);

sub process {
	my ($name, $expected) = @_;
	($tmpl, %params) = process_message("t/data/$name");



( run in 0.616 second using v1.01-cache-2.11-cpan-df04353d9ac )