diff options
-rw-r--r-- | Makefile.PL | 5 | ||||
-rw-r--r-- | perllib/FixMyStreet.pm | 22 | ||||
-rw-r--r-- | perllib/FixMyStreet/App.pm | 49 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Model/EmailSend.pm | 51 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/View/Email.pm | 43 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/View/Web.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Default.pm | 14 | ||||
-rw-r--r-- | t/app/helpers/send_email.t | 48 | ||||
-rw-r--r-- | t/app/view/email.t | 8 | ||||
-rw-r--r-- | templates/email/default/test | 9 |
10 files changed, 247 insertions, 4 deletions
diff --git a/Makefile.PL b/Makefile.PL index 7e94a47a4..3677f0b5e 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -10,13 +10,16 @@ name 'FixMyStreet-App'; all_from 'perllib/FixMyStreet/App.pm'; requires 'Catalyst::Action::RenderView'; +requires 'Catalyst::Authentication::Store::DBIx::Class'; +requires 'Catalyst::Model::Adaptor'; requires 'Catalyst::Plugin::Authentication'; requires 'Catalyst::Plugin::ConfigLoader'; requires 'Catalyst::Plugin::Session::Store::DBIC'; -requires 'Catalyst::Authentication::Store::DBIx::Class'; requires 'Catalyst::Plugin::Static::Simple'; requires 'Catalyst::Runtime' => '5.80031'; requires 'Config::General'; +requires 'Email::Send'; +requires 'Email::Simple'; requires 'Moose'; requires 'namespace::autoclean'; requires 'Path::Class'; diff --git a/perllib/FixMyStreet.pm b/perllib/FixMyStreet.pm index 645780629..f581631cf 100644 --- a/perllib/FixMyStreet.pm +++ b/perllib/FixMyStreet.pm @@ -27,6 +27,28 @@ Thus module has utility functions for the FMS project. =head1 METHODS +=head2 test_mode + + FixMyStreet->test_mode( $bool ); + my $in_test_mode_bool = FixMyStreet->test_mode; + +Put the FixMyStreet into test mode - inteded for the unit tests: + + BEGIN { + use FixMyStreet; + FixMyStreet->test_mode(1); + } + +=cut + +my $TEST_MODE = undef; + +sub test_mode { + my $class = shift; + $TEST_MODE = shift if scalar @_; + return $TEST_MODE; +} + =head2 path_to $path = FixMyStreet->path_to( 'conf/general' ); diff --git a/perllib/FixMyStreet/App.pm b/perllib/FixMyStreet/App.pm index 4f99a367b..f5d2f7d62 100644 --- a/perllib/FixMyStreet/App.pm +++ b/perllib/FixMyStreet/App.pm @@ -30,6 +30,9 @@ __PACKAGE__->config( # Disable deprecated behavior needed by old applications disable_component_resolution_regex_fallback => 1, + # Some generic stuff + default_view => 'Web', + # Serve anything in web dir that is not a .cgi script static => { # include_path => [ FixMyStreet->path_to("web") . "" ], @@ -115,7 +118,7 @@ sub setup_cobrand { # append the cobrand templates to the include path $c->stash->{additional_template_paths} = - [ $cobrand->path_to_web_templates . '' ] + [ $cobrand->path_to_web_templates->stringify ] unless $cobrand->is_default; my $host = $c->req->uri->host; @@ -143,6 +146,50 @@ sub setup_cobrand { return $cobrand; } +=head2 send_email + + $email_sent = $c->send_email( 'email_template', $extra_stash_values ); + +Send an email by filling in the given template with values in the stash. + +You can specify extra values to those already in the stash by passing a hashref +as the second argument. + +The stash (or extra_stash_values) keys 'to', 'from' and 'subject' are used to +set those fields in the email if they are present. + +If a 'from' is not specified then the default from the config is used. + +=cut + +sub send_email { + my $c = shift; + my $template = shift; + my $extra_stash_values = shift || {}; + + # create the vars to pass to the email template + my $vars = { + from => FixMyStreet->config('CONTACT_EMAIL'), + %{ $c->stash }, + %$extra_stash_values, + additional_template_paths => + [ $c->cobrand->path_to_email_templates->stringify ] + }; + + # render the template + my $content = $c->view('Email')->render( $c, $template, $vars ); + + # create an email + my $email = Email::Simple->new($content); + $email->header_set( ucfirst($_), $vars->{$_} ) + for grep { $vars->{$_} } qw( to from subject); + + # send the email + $c->model('EmailSend')->send($email); + + return $email; +} + =head1 SEE ALSO L<FixMyStreet::App::Controller::Root>, L<Catalyst> diff --git a/perllib/FixMyStreet/App/Model/EmailSend.pm b/perllib/FixMyStreet/App/Model/EmailSend.pm new file mode 100644 index 000000000..de85857f7 --- /dev/null +++ b/perllib/FixMyStreet/App/Model/EmailSend.pm @@ -0,0 +1,51 @@ +package FixMyStreet::App::Model::EmailSend; +use base 'Catalyst::Model::Adaptor'; + +use strict; +use warnings; + +use FixMyStreet; +use Email::Send; + +=head1 NAME + +FixMyStreet::App::Model::EmailSend + +=head1 DESCRIPTION + +Thin wrapper around Email::Send - configuring it correctly acording to our config. + +If the config value 'SMTP_SMARTHOST' is set then email is routed via SMTP to +that. Otherwise it is sent using a 'sendmail' like binary on the local system. + +And finally if if FixMyStreet->test_mode returns true then emails are not sent +at all but are stored in memory for the test suite to inspect (using +Email::Send::Test). + +=cut + +my $args = undef; + +if ( FixMyStreet->test_mode ) { + + # Email::Send::Test + $args = { mailer => 'Test', }; +} +elsif ( my $smtp_host = FixMyStreet->config('SMTP_SMARTHOST') ) { + + # Email::Send::SMTP + $args = { + mailer => 'SMTP', + mailer_args => { Host => $smtp_host }, + }; +} +else { + + # Email::Send::Sendmail + $args = { mailer => 'Sendmail' }; +} + +__PACKAGE__->config( + class => 'Email::Send', + args => $args, +); diff --git a/perllib/FixMyStreet/App/View/Email.pm b/perllib/FixMyStreet/App/View/Email.pm new file mode 100644 index 000000000..646615d36 --- /dev/null +++ b/perllib/FixMyStreet/App/View/Email.pm @@ -0,0 +1,43 @@ +package FixMyStreet::App::View::Email; +use base 'Catalyst::View::TT'; + +use strict; +use warnings; + +use mySociety::Locale; +use FixMyStreet; + +__PACKAGE__->config( + TEMPLATE_EXTENSION => '.html', + INCLUDE_PATH => [ # + FixMyStreet->path_to( 'templates', 'email', 'default' ), + ], + render_die => 1, + expose_methods => ['loc'], +); + +=head1 NAME + +FixMyStreet::App::View::Email - TT View for FixMyStreet::App + +=head1 DESCRIPTION + +TT View for FixMyStreet::App. + +=cut + +=head2 loc + + [% loc('Some text to localize') %] + +Passes the text to the localisation engine for translations. + +=cut + +sub loc { + my ( $self, $c, @args ) = @_; + return _(@args); +} + +1; + diff --git a/perllib/FixMyStreet/App/View/Web.pm b/perllib/FixMyStreet/App/View/Web.pm index 306e4c5a7..1c6d73ca7 100644 --- a/perllib/FixMyStreet/App/View/Web.pm +++ b/perllib/FixMyStreet/App/View/Web.pm @@ -32,8 +32,6 @@ TT View for FixMyStreet::App. Passes the text to the localisation engine for translations. -FIXME - currently just passes through. - =cut sub loc { diff --git a/perllib/FixMyStreet/Cobrand/Default.pm b/perllib/FixMyStreet/Cobrand/Default.pm index a40ae2c2d..9054af81c 100644 --- a/perllib/FixMyStreet/Cobrand/Default.pm +++ b/perllib/FixMyStreet/Cobrand/Default.pm @@ -86,6 +86,20 @@ sub path_to_web_templates { return FixMyStreet->path_to( 'templates/web', $self->moniker ); } +=head2 path_to_email_templates + + $path = $cobrand->path_to_email_templates( ); + +Returns the path to the templates for this cobrand - by default +"templates/email/$moniker" + +=cut + +sub path_to_email_templates { + my $self = shift; + return FixMyStreet->path_to( 'templates/email', $self->moniker ); +} + =head1 site_restriction Return a site restriction clause and a site key if the cobrand uses a subset of diff --git a/t/app/helpers/send_email.t b/t/app/helpers/send_email.t new file mode 100644 index 000000000..6a7d77c0b --- /dev/null +++ b/t/app/helpers/send_email.t @@ -0,0 +1,48 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +BEGIN { + use FixMyStreet; + FixMyStreet->test_mode(1); +} + +use Test::More tests => 4; + +use Email::Send::Test; + +use_ok 'FixMyStreet::App'; +my $c = FixMyStreet::App->new; + +# fake up the request a little +$c->req->uri( URI->new('http://localhost/') ); +$c->req->base( $c->req->uri ); + + +# set some values in the stash +$c->stash->{foo} = 'bar'; + +# clear the email queue +Email::Send::Test->clear; + +# send the test email +ok $c->send_email( 'test', { to => 'test@recipient.com' } ), "sent an email"; + +# check it got templated and sent correctly +my @emails = Email::Send::Test->emails; +is scalar(@emails), 1, "caught one email"; + +is $emails[0]->as_string, << 'END_OF_BODY', "email is as expected"; +Subject: test email +From: evdb@ecclestoad.co.uk +To: test@recipient.com + +Hello, + +This is a test email where foo: bar. + +Yours, + FixMyStreet. +END_OF_BODY + diff --git a/t/app/view/email.t b/t/app/view/email.t new file mode 100644 index 000000000..4d7bbe8ff --- /dev/null +++ b/t/app/view/email.t @@ -0,0 +1,8 @@ +use strict; +use warnings; + +use Test::More; + +BEGIN { use_ok 'FixMyStreet::App::View::Email' } + +done_testing(); diff --git a/templates/email/default/test b/templates/email/default/test new file mode 100644 index 000000000..0a751dac2 --- /dev/null +++ b/templates/email/default/test @@ -0,0 +1,9 @@ +Subject: test email +From: bad-sender@duff.com + +Hello, + +This is a test email where foo: [% foo %]. + +Yours, + FixMyStreet. |