Skip to content

Commit 17d6c79

Browse files
authored
Merge pull request #893 from metacpan/oalders/pause-email
Move email sending to a model class
2 parents 7fafb54 + 287f163 commit 17d6c79

File tree

10 files changed

+244
-56
lines changed

10 files changed

+244
-56
lines changed

cpanfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ requires 'perl', '5.010';
22

33
requires 'Archive::Any', 0.0942;
44
requires 'Archive::Tar', '2.04';
5+
requires 'Authen::SASL', '2.16';
56
requires 'BackPAN::Index', '0.42';
67
requires 'CHI', '0.60';
78
requires 'CPAN::DistnameInfo', '0.12';
@@ -95,6 +96,7 @@ requires 'Log::Log4perl::Appender::ScreenColoredLevels';
9596
requires 'MetaCPAN::Moose';
9697
requires 'MetaCPAN::Pod::XHTML';
9798
requires 'MetaCPAN::Role', '0.06';
99+
requires 'MIME::Base64', '3.15';
98100
requires 'Minion', '>= 9.03';
99101
requires 'Minion::Backend::SQLite';
100102
requires 'Module::Load';

cpanfile.snapshot

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,27 @@ DISTRIBUTIONS
198198
Array::Iterator::Reusable 0.11
199199
requirements:
200200
ExtUtils::MakeMaker 6.30
201+
Authen-SASL-2.16
202+
pathname: G/GB/GBARR/Authen-SASL-2.16.tar.gz
203+
provides:
204+
Authen::SASL 2.16
205+
Authen::SASL::CRAM_MD5 2.14
206+
Authen::SASL::EXTERNAL 2.14
207+
Authen::SASL::Perl 2.14
208+
Authen::SASL::Perl::ANONYMOUS 2.14
209+
Authen::SASL::Perl::CRAM_MD5 2.14
210+
Authen::SASL::Perl::DIGEST_MD5 2.14
211+
Authen::SASL::Perl::EXTERNAL 2.14
212+
Authen::SASL::Perl::GSSAPI 0.05
213+
Authen::SASL::Perl::LOGIN 2.14
214+
Authen::SASL::Perl::Layer 2.14
215+
Authen::SASL::Perl::PLAIN 2.14
216+
requirements:
217+
Digest::HMAC_MD5 0
218+
Digest::MD5 0
219+
ExtUtils::MakeMaker 6.42
220+
Test::More 0
221+
perl 5.005
201222
B-Hooks-EndOfScope-0.21
202223
pathname: E/ET/ETHER/B-Hooks-EndOfScope-0.21.tar.gz
203224
provides:
@@ -310,6 +331,7 @@ DISTRIBUTIONS
310331
CGI::Simple::Standard 1.114
311332
CGI::Simple::Util 1.114
312333
requirements:
334+
ExtUtils::MakeMaker 0
313335
IO::Scalar 0
314336
Test::More 0
315337
CGI-Struct-1.21
@@ -1208,6 +1230,7 @@ DISTRIBUTIONS
12081230
Config::Any::XML undef
12091231
Config::Any::YAML undef
12101232
requirements:
1233+
Config::General 2.47
12111234
Module::Pluggable::Object 3.6
12121235
Config-General-2.63
12131236
pathname: T/TL/TLINDEN/Config-General-2.63.tar.gz
@@ -3688,6 +3711,7 @@ DISTRIBUTIONS
36883711
IO::Prompt 0.997004
36893712
IO::Prompt::ReturnVal 0.997004
36903713
requirements:
3714+
ExtUtils::MakeMaker 0
36913715
IO::Handle 0
36923716
Term::ReadKey 0
36933717
Test::More 0

lib/MetaCPAN/Model/Email/PAUSE.pm

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package MetaCPAN::Model::Email::PAUSE;
2+
3+
use MetaCPAN::Moose;
4+
5+
use Email::Sender::Simple qw( sendmail );
6+
use Email::Sender::Transport::SMTP ();
7+
use Email::Simple ();
8+
use Encode ();
9+
use MetaCPAN::Types qw( Object Uri );
10+
use Try::Tiny qw( catch try );
11+
12+
with('MetaCPAN::Role::HasConfig');
13+
14+
has _author => (
15+
is => 'ro',
16+
isa => Object,
17+
init_arg => 'author',
18+
required => 1,
19+
);
20+
21+
has _url => (
22+
is => 'ro',
23+
isa => Uri,
24+
init_arg => 'url',
25+
required => 1,
26+
);
27+
28+
sub send {
29+
my $self = shift;
30+
31+
my $email = Email::Simple->create(
32+
header => [
33+
'Content-Type' => 'text/plain; charset=utf-8',
34+
To => $self->_author->{email}->[0],
35+
From => '[email protected]',
36+
Subject => 'Connect MetaCPAN with your PAUSE account',
37+
'MIME-Version' => '1.0',
38+
],
39+
body => $self->_email_body,
40+
);
41+
42+
my $config = $self->config->{smtp};
43+
my $transport = Email::Sender::Transport::SMTP->new(
44+
{
45+
debug => 1,
46+
host => $config->{host},
47+
port => $config->{port},
48+
sasl_username => $config->{username},
49+
sasl_password => $config->{password},
50+
ssl => 1,
51+
}
52+
);
53+
54+
my $success = 0;
55+
try {
56+
$success = sendmail( $email, { transport => $transport } );
57+
}
58+
catch {
59+
warn 'Could not send message: ' . $_;
60+
};
61+
62+
return $success;
63+
}
64+
65+
sub _email_body {
66+
my $self = shift;
67+
my $name = $self->_author->name;
68+
my $uri = $self->_url;
69+
70+
my $body = <<EMAIL_BODY;
71+
Hi ${name},
72+
73+
please click on the following link to verify your PAUSE account:
74+
75+
$uri
76+
77+
Cheers,
78+
MetaCPAN
79+
EMAIL_BODY
80+
81+
try {
82+
$body = Encode::encode( 'UTF-8', $body,
83+
Encode::FB_CROAK | Encode::LEAVE_SRC );
84+
}
85+
catch {
86+
warn $_[0];
87+
};
88+
89+
return $body;
90+
}
91+
92+
1;

lib/MetaCPAN/Role/HasConfig.pm

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ use Moose::Role;
55
use FindBin;
66
use Config::ZOMG ();
77
use MetaCPAN::Types qw(HashRef);
8+
use Module::Runtime qw( require_module );
89

9-
# Done like this so can be required by a roles
10+
# Done like this so can be required by a role
1011
sub config {
1112
return $_[0]->_config;
1213
}
@@ -19,11 +20,29 @@ has _config => (
1920
);
2021

2122
sub _build_config {
23+
my $self = shift;
24+
my $config = $self->_zomg("$FindBin::RealBin/..");
25+
return $config if $config;
26+
27+
require_module('Git::Helpers');
28+
$config = $self->_zomg( Git::Helpers::checkout_root() );
29+
30+
return $config if $config;
31+
32+
die "Couldn't find config file in $FindBin::RealBin/.. or "
33+
. Git::Helpers::checkout_root();
34+
}
35+
36+
sub _zomg {
2237
my $self = shift;
23-
return Config::ZOMG->new(
38+
my $path = shift;
39+
40+
my $config = Config::ZOMG->new(
2441
name => 'metacpan_server',
25-
path => "$FindBin::RealBin/..",
26-
)->load;
42+
path => $path,
43+
);
44+
45+
return $config->open;
2746
}
2847

2948
1;

lib/MetaCPAN/Server/Controller/Login/PAUSE.pm

Lines changed: 19 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,18 @@ use strict;
44
use warnings;
55
use namespace::autoclean;
66

7-
use CHI ();
8-
use Email::Sender::Simple ();
9-
use Email::Simple ();
10-
use Encode ();
11-
use Cpanel::JSON::XS;
7+
use CHI ();
8+
use Log::Contextual qw( :log :dlog );
129
use Moose;
13-
use Try::Tiny;
14-
use MetaCPAN::Util;
10+
use Try::Tiny qw( catch try );
11+
use MetaCPAN::Model::Email::PAUSE ();
12+
use MetaCPAN::Util qw( generate_sid );
1513

1614
BEGIN { extends 'MetaCPAN::Server::Controller::Login' }
1715

1816
has cache => (
1917
is => 'ro',
18+
isa => 'CHI::Driver',
2019
builder => '_build_cache',
2120
);
2221

@@ -44,48 +43,26 @@ sub index : Path {
4443
my $author = $c->model('CPAN::Author')->get( uc($id) );
4544
$c->controller('OAuth2')->redirect( $c, error => "author_not_found" )
4645
unless ($author);
47-
my $code = MetaCPAN::Util::generate_sid;
48-
$self->cache->set( $code, $author->pauseid, 86400 );
49-
my $uri = $c->request->uri->clone;
50-
$uri->query("code=$code");
51-
my $email = Email::Simple->create(
52-
header => [
53-
'Content-Type' => 'text/plain; charset=utf-8',
54-
To => $author->{email}->[0],
55-
From => '[email protected]',
56-
Subject => "Connect MetaCPAN with your PAUSE account",
57-
'MIME-Version' => '1.0',
58-
],
59-
body => $self->email_body( $author->name, $uri ),
60-
);
61-
Email::Sender::Simple->send($email);
62-
$c->controller('OAuth2')->redirect( $c, success => "mail_sent" );
63-
}
64-
}
6546

66-
sub email_body {
67-
my ( $self, $name, $uri ) = @_;
47+
my $code = generate_sid();
48+
$self->cache->set( $code, $author->pauseid, 86400 );
6849

69-
my $body = <<EMAIL_BODY;
70-
Hi ${name},
50+
my $url = $c->request->uri->clone;
51+
$url->query("code=$code");
7152

72-
please click on the following link to verify your PAUSE account:
53+
my $email = MetaCPAN::Model::Email::PAUSE->new(
54+
author => $author,
55+
url => $url,
56+
);
7357

74-
$uri
58+
my $sent = $email->send;
7559

76-
Cheers,
77-
MetaCPAN
78-
EMAIL_BODY
60+
if ( !$sent ) {
61+
log_error { 'Could not send PAUSE email to ' . $author->pauseid };
62+
}
7963

80-
try {
81-
$body = Encode::encode( 'UTF-8', $body,
82-
Encode::FB_CROAK | Encode::LEAVE_SRC );
64+
$c->controller('OAuth2')->redirect( $c, success => 'mail_sent' );
8365
}
84-
catch {
85-
warn $_[0];
86-
};
87-
88-
return $body;
8966
}
9067

9168
1;

lib/MetaCPAN/Util.pm

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,27 @@ use strict;
66
use warnings;
77
use version;
88

9-
use Digest::SHA;
10-
use Encode;
9+
use Digest::SHA qw( sha1_base64 sha1_hex );
10+
use Encode qw( decode_utf8 );
1111
use Ref::Util qw( is_arrayref is_hashref );
1212
use Sub::Exporter -setup => {
1313
exports => [
1414
'author_dir', 'digest',
1515
'extract_section', 'fix_pod',
16-
'fix_version', 'numify_version',
17-
'pod_lines', 'strip_pod',
18-
'single_valued_arrayref_to_scalar'
16+
'fix_version', 'generate_sid',
17+
'numify_version', 'pod_lines',
18+
'strip_pod', 'single_valued_arrayref_to_scalar'
1919
]
2020
};
2121

2222
sub digest {
23-
my $digest = Digest::SHA::sha1_base64( join( "\0", grep {defined} @_ ) );
23+
my $digest = sha1_base64( join( "\0", grep {defined} @_ ) );
2424
$digest =~ tr/[+\/]/-_/;
2525
return $digest;
2626
}
2727

2828
sub generate_sid {
29-
Digest::SHA::sha1_hex( rand() . $$ . {} . time );
29+
return sha1_hex( rand . $$ . {} . time );
3030
}
3131

3232
sub numify_version {
@@ -76,7 +76,7 @@ sub strip_pod {
7676

7777
sub extract_section {
7878
my ( $pod, $section ) = @_;
79-
eval { $pod = Encode::decode_utf8( $pod, Encode::FB_CROAK ) };
79+
eval { $pod = decode_utf8( $pod, Encode::FB_CROAK ) };
8080
return undef
8181
unless ( $pod =~ /^=head1\s+$section\b(.*?)(^((\=head1)|(\=cut)))/msi
8282
|| $pod =~ /^=head1\s+$section\b(.*)/msi );

metacpan_server.conf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,10 @@ minion_dsn = postgresql:///minion_queue
1010
<controller Login::OpenID>
1111
secret_key 8225b1874fdc431cedb1cf7d454a92b8fde3a5e6
1212
</controller>
13+
14+
<smtp>
15+
host smtp.fastmail.com
16+
port 465
17+
18+
password seekrit
19+
</smtp>

metacpan_server_testing.conf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,10 @@ github_key = foo
2222
github_secret = bar
2323

2424
secret weak
25+
26+
<smtp>
27+
host smtp.fastmail.com
28+
port 465
29+
30+
password seekrit
31+
</smtp>

0 commit comments

Comments
 (0)