aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEdmund von der Burg <evdb@mysociety.org>2011-03-02 13:55:37 +0000
committerEdmund von der Burg <evdb@mysociety.org>2011-03-02 13:55:37 +0000
commit90395716d892de1d1134a7d0e68866e699c19406 (patch)
tree9fe5e0b1247ad1f6c0da774ea17fc225667b87b8
parentc5a4a6e496f4aebd496336c44a61c0b1c64dfccd (diff)
Simple email sending
-rw-r--r--Makefile.PL5
-rw-r--r--perllib/FixMyStreet.pm22
-rw-r--r--perllib/FixMyStreet/App.pm49
-rw-r--r--perllib/FixMyStreet/App/Model/EmailSend.pm51
-rw-r--r--perllib/FixMyStreet/App/View/Email.pm43
-rw-r--r--perllib/FixMyStreet/App/View/Web.pm2
-rw-r--r--perllib/FixMyStreet/Cobrand/Default.pm14
-rw-r--r--t/app/helpers/send_email.t48
-rw-r--r--t/app/view/email.t8
-rw-r--r--templates/email/default/test9
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.