aboutsummaryrefslogtreecommitdiffstats
path: root/perllib
diff options
context:
space:
mode:
Diffstat (limited to 'perllib')
-rw-r--r--perllib/FixMyStreet.pm17
-rw-r--r--perllib/FixMyStreet/App.pm3
-rw-r--r--perllib/FixMyStreet/Cobrand/Zurich.pm8
-rw-r--r--perllib/FixMyStreet/Email.pm111
-rw-r--r--perllib/FixMyStreet/Script/Alerts.pm6
-rw-r--r--perllib/FixMyStreet/Script/Questionnaires.pm9
-rw-r--r--perllib/FixMyStreet/Script/Reports.pm9
-rw-r--r--perllib/FixMyStreet/SendReport/Email.pm17
-rw-r--r--perllib/FixMyStreet/SendReport/Zurich.pm2
9 files changed, 79 insertions, 103 deletions
diff --git a/perllib/FixMyStreet.pm b/perllib/FixMyStreet.pm
index 1a9c8ff60..14f3f3607 100644
--- a/perllib/FixMyStreet.pm
+++ b/perllib/FixMyStreet.pm
@@ -190,23 +190,6 @@ sub configure_mysociety_dbhandle {
}
-=head2 get_email_template
-
-=cut
-
-sub get_email_template {
- # TODO further refactor this by just using Template path
- my ($class, $cobrand, $lang, $template) = @_;
-
- my $template_path = FixMyStreet->path_to( "templates", "email", $cobrand, $lang, $template )->stringify;
- $template_path = FixMyStreet->path_to( "templates", "email", $cobrand, $template )->stringify
- unless -e $template_path;
- $template_path = FixMyStreet->path_to( "templates", "email", "default", $template )->stringify
- unless -e $template_path;
- $template = Utils::read_file( $template_path );
- return $template;
-}
-
my $tz;
my $tz_f;
diff --git a/perllib/FixMyStreet/App.pm b/perllib/FixMyStreet/App.pm
index 79ca7f9ee..1a651d282 100644
--- a/perllib/FixMyStreet/App.pm
+++ b/perllib/FixMyStreet/App.pm
@@ -320,8 +320,7 @@ sub send_email {
my $email = mySociety::Locale::in_gb_locale { FixMyStreet::Email::construct_email(
{
- _template_ => $c->view('Email')->render( $c, $template, $vars ),
- _parameters_ => {},
+ _body_ => $c->view('Email')->render( $c, $template, $vars ),
_attachments_ => $extra_stash_values->{attachments},
From => $vars->{from},
To => $vars->{to},
diff --git a/perllib/FixMyStreet/Cobrand/Zurich.pm b/perllib/FixMyStreet/Cobrand/Zurich.pm
index d31b1c84e..987f0bb67 100644
--- a/perllib/FixMyStreet/Cobrand/Zurich.pm
+++ b/perllib/FixMyStreet/Cobrand/Zurich.pm
@@ -587,14 +587,6 @@ sub admin_report_edit {
# 2) setting $problem->whensent(undef) may make it eligible for generating an email
# to the body (internal or external). See DBRS::Problem->send_reports for Zurich-
# specific categories which are eligible for this.
- #
- # It looks like both of these will do:
- # a) TT processing of [% ... %] directives, in FMS::App->send_email(_cron)
- # b) pseudo-PHP substitution of <?=$values['name']?> which is done as
- # naive substitution
- # commonlib mySociety::Email
- #
- # So it makes sense to add new parameters as the more powerful TT (a).
my $redirect = 0;
my $new_cat = $c->get_param('category') || '';
diff --git a/perllib/FixMyStreet/Email.pm b/perllib/FixMyStreet/Email.pm
index 49f4632a8..d4bfee14e 100644
--- a/perllib/FixMyStreet/Email.pm
+++ b/perllib/FixMyStreet/Email.pm
@@ -1,3 +1,9 @@
+package FixMyStreet::Email::Error;
+
+use Error qw(:try);
+
+@FixMyStreet::Email::Error::ISA = qw(Error::Simple);
+
package FixMyStreet::Email;
use Email::MIME;
@@ -5,7 +11,7 @@ use Encode;
use POSIX qw();
use Template;
use Digest::HMAC_SHA1 qw(hmac_sha1_hex);
-use mySociety::Email;
+use Text::Wrap;
use mySociety::Locale;
use mySociety::Random qw(random_bytes);
use Utils::Email;
@@ -64,50 +70,42 @@ sub is_abuser {
return $schema->resultset('Abuse')->search( { email => [ $email, $domain ] } )->first;
}
+sub _render_template {
+ my ($tt, $template, $vars, %options) = @_;
+ my $var;
+ $tt->process($template, $vars, \$var);
+ return $var;
+}
+
sub send_cron {
- my ( $schema, $params, $env_from, $nomail, $cobrand, $lang_code ) = @_;
+ my ( $schema, $template, $vars, $hdrs, $env_from, $nomail, $cobrand, $lang_code ) = @_;
my $sender = FixMyStreet->config('DO_NOT_REPLY_EMAIL');
$env_from ||= $sender;
- if (!$params->{From}) {
+ if (!$hdrs->{From}) {
my $sender_name = $cobrand->contact_name;
- $params->{From} = [ $sender, _($sender_name) ];
+ $hdrs->{From} = [ $sender, _($sender_name) ];
}
- return 1 if is_abuser($schema, $params->{To});
+ return 1 if is_abuser($schema, $hdrs->{To});
- $params->{'Message-ID'} = sprintf('<fms-cron-%s-%s@%s>', time(),
+ $hdrs->{'Message-ID'} = sprintf('<fms-cron-%s-%s@%s>', time(),
unpack('h*', random_bytes(5, 1)), FixMyStreet->config('EMAIL_DOMAIN')
);
- # This is all to set the path for the templates processor so we can override
- # signature and site names in emails using templates in the old style emails.
- # It's a bit involved as not everywhere we use it knows about the cobrand so
- # we can't assume there will be one.
- my $include_path = FixMyStreet->path_to( 'templates', 'email', 'default' )->stringify;
- if ( $cobrand ) {
- $include_path =
- FixMyStreet->path_to( 'templates', 'email', $cobrand->moniker )->stringify . ':'
- . $include_path;
- if ( $lang_code ) {
- $include_path =
- FixMyStreet->path_to( 'templates', 'email', $cobrand->moniker, $lang_code )->stringify . ':'
- . $include_path;
- }
- }
my $tt = Template->new({
- INCLUDE_PATH => $include_path
+ ENCODING => 'utf8',
+ INCLUDE_PATH => [
+ FixMyStreet->path_to( 'templates', 'email', $cobrand->moniker, $lang_code )->stringify,
+ FixMyStreet->path_to( 'templates', 'email', $cobrand->moniker )->stringify,
+ FixMyStreet->path_to( 'templates', 'email', 'default' )->stringify,
+ ],
});
- my ($sig, $site_name);
- $tt->process( 'signature.txt', $params, \$sig );
- $sig = Encode::decode('utf8', $sig);
- $params->{_parameters_}->{signature} = $sig;
+ $vars->{signature} = _render_template($tt, 'signature.txt', $vars);
+ $vars->{site_name} = Utils::trim_text(_render_template($tt, 'site-name.txt', $vars));
+ $hdrs->{_body_} = _render_template($tt, $template, $vars);
- $tt->process( 'site-name.txt', $params, \$site_name );
- $site_name = Utils::trim_text(Encode::decode('utf8', $site_name));
- $params->{_parameters_}->{site_name} = $site_name;
-
- my $email = mySociety::Locale::in_gb_locale { construct_email($params) };
+ my $email = mySociety::Locale::in_gb_locale { construct_email($hdrs) };
if ($nomail) {
print $email->as_string;
@@ -125,16 +123,12 @@ containing elements as given below. Returns an Email::MIME email.
=over 4
-=item _template_, _parameters_
+=item _body_
-Templated body text and an associative array of template parameters. _template
-contains optional substititutions <?=$values['name']?>, each of which is
-replaced by the value of the corresponding named value in _parameters_. It is
-an error to use a substitution when the corresponding parameter is not present
-or undefined. The first line of the template will be interpreted as contents of
+Body text. The first line of the template will be interpreted as contents of
the Subject: header of the mail if it begins with the literal string 'Subject:
-' followed by a blank line. The templated text will be word-wrapped to produce
-lines of appropriate length.
+' followed by a blank line. The text will be word-wrapped to produce lines of
+appropriate length.
=item _attachments_
@@ -175,21 +169,42 @@ templated body, From or Subject (perhaps from the template).
sub construct_email ($) {
my $p = shift;
- throw mySociety::Email::Error("Must specify both '_template_' and '_parameters_'")
- if !exists($p->{_template_}) || !exists($p->{_parameters_});
- throw mySociety::Email::Error("Template parameters '_parameters_' must be an associative array")
- if (ref($p->{_parameters_}) ne 'HASH');
+ throw FixMyStreet::Email::Error("Must specify '_body_'") if !exists($p->{_body_});
+
+ my $body = $p->{_body_};
+ my $subject;
+ if ($body =~ m#^Subject: ([^\n]*)\n\n#s) {
+ $subject = $1;
+ $body =~ s#^Subject: ([^\n]*)\n\n##s;
+ }
+
+ $body =~ s/\r\n/\n/gs;
+ $body =~ s/^\s+$//mg; # Note this also reduces any gap between paragraphs of >1 blank line to 1
+ $body =~ s/\s+$//;
+
+ # Merge paragraphs into their own line. Two blank lines separate a
+ # paragraph. End a line with two spaces to force a linebreak.
+
+ # regex means, "replace any line ending that is neither preceded (?<!\n)
+ # nor followed (?!\n) by a blank line with a single space".
+ $body =~ s#(?<!\n)(?<! )\n(?!\n)# #gs;
+
+ # Wrap text to 72-column lines.
+ local($Text::Wrap::columns) = 69;
+ local($Text::Wrap::huge) = 'overflow';
+ local($Text::Wrap::unexpand) = 0;
+ $body = Text::Wrap::wrap('', '', $body);
+ $body =~ s/^\s+$//mg; # Do it again because of wordwrapping indented lines
- (my $subject, $body) = mySociety::Email::do_template_substitution($p->{_template_}, $p->{_parameters_}, '');
$p->{Subject} = $subject if defined($subject);
if (!exists($p->{Subject})) {
# XXX Try to find out what's causing this very occasionally
(my $error = $body) =~ s/\n/ | /g;
$error = "missing field 'Subject' in MESSAGE - $error";
- throw mySociety::Email::Error($error);
+ throw FixMyStreet::Email::Error($error);
}
- throw mySociety::Email::Error("missing field 'From' in MESSAGE") unless exists($p->{From});
+ throw FixMyStreet::Email::Error("missing field 'From' in MESSAGE") unless exists($p->{From});
# Construct email headers
my %hdr;
@@ -203,7 +218,7 @@ sub construct_email ($) {
# Array of addresses or [address, name] pairs.
$hdr{$h} = join(', ', map { mailbox($_, $h) } @{$p->{$h}});
} else {
- throw mySociety::Email::Error("Field '$h' in MESSAGE should be single value or an array");
+ throw FixMyStreet::Email::Error("Field '$h' in MESSAGE should be single value or an array");
}
}
@@ -251,7 +266,7 @@ sub mailbox {
if (ref($e) eq '') {
return $e;
} elsif (ref($e) ne 'ARRAY' || @$e != 2) {
- throw mySociety::Email::Error("'$header' field should be string or 2-element array");
+ throw FixMyStreet::Email::Error("'$header' field should be string or 2-element array");
} else {
return Email::Address->new($e->[1], $e->[0]);
}
diff --git a/perllib/FixMyStreet/Script/Alerts.pm b/perllib/FixMyStreet/Script/Alerts.pm
index fc5fef953..062601044 100644
--- a/perllib/FixMyStreet/Script/Alerts.pm
+++ b/perllib/FixMyStreet/Script/Alerts.pm
@@ -248,8 +248,6 @@ sub _send_aggregated_alert_email(%) {
} );
$data{unsubscribe_url} = $cobrand->base_url( $data{cobrand_data} ) . '/A/' . $token->token;
- my $template = FixMyStreet->get_email_template($cobrand->moniker, $data{lang}, "$data{template}.txt");
-
my $sender = sprintf('<fms-%s@%s>',
FixMyStreet::Email::generate_verp_token('alert', $data{alert_id}),
FixMyStreet->config('EMAIL_DOMAIN')
@@ -257,9 +255,9 @@ sub _send_aggregated_alert_email(%) {
my $result = FixMyStreet::Email::send_cron(
$data{schema},
+ "$data{template}.txt",
+ \%data,
{
- _template_ => $template,
- _parameters_ => \%data,
To => $data{alert_email},
},
$sender,
diff --git a/perllib/FixMyStreet/Script/Questionnaires.pm b/perllib/FixMyStreet/Script/Questionnaires.pm
index f72f59077..c5bc6bfe0 100644
--- a/perllib/FixMyStreet/Script/Questionnaires.pm
+++ b/perllib/FixMyStreet/Script/Questionnaires.pm
@@ -52,8 +52,6 @@ sub send_questionnaires_period {
# call checks if this is the host that sends mail for this cobrand.
next unless $cobrand->email_host;
- my $template = FixMyStreet->get_email_template($cobrand->moniker, $row->lang, 'questionnaire.txt');
-
my %h = map { $_ => $row->$_ } qw/name title detail category/;
$h{created} = Utils::prettify_duration( time() - $row->confirmed->epoch, 'week' );
@@ -78,14 +76,15 @@ sub send_questionnaires_period {
my $result = FixMyStreet::Email::send_cron(
$rs->result_source->schema,
+ 'questionnaire.txt',
+ \%h,
{
- _template_ => $template,
- _parameters_ => \%h,
To => [ [ $row->user->email, $row->name ] ],
},
undef,
$params->{nomail},
- $cobrand
+ $cobrand,
+ $row->lang,
);
unless ($result) {
print " ...success\n" if $params->{verbose};
diff --git a/perllib/FixMyStreet/Script/Reports.pm b/perllib/FixMyStreet/Script/Reports.pm
index 75111b852..278c58af1 100644
--- a/perllib/FixMyStreet/Script/Reports.pm
+++ b/perllib/FixMyStreet/Script/Reports.pm
@@ -289,19 +289,18 @@ sub _send_report_sent_email {
my $nomail = shift;
my $cobrand = shift;
- my $template = FixMyStreet->get_email_template($row->cobrand, $row->lang, 'confirm_report_sent.txt');
-
FixMyStreet::Email::send_cron(
$row->result_source->schema,
+ 'confirm_report_sent.txt',
+ $h,
{
- _template_ => $template,
- _parameters_ => $h,
To => $row->user->email,
From => [ FixMyStreet->config('CONTACT_EMAIL'), $cobrand->contact_name ],
},
FixMyStreet->config('CONTACT_EMAIL'),
$nomail,
- $cobrand
+ $cobrand,
+ $row->lang,
);
}
diff --git a/perllib/FixMyStreet/SendReport/Email.pm b/perllib/FixMyStreet/SendReport/Email.pm
index 7e5c10469..8582ebb3b 100644
--- a/perllib/FixMyStreet/SendReport/Email.pm
+++ b/perllib/FixMyStreet/SendReport/Email.pm
@@ -52,15 +52,8 @@ sub build_recipient_list {
sub get_template {
my ( $self, $row ) = @_;
-
- my $template = 'submit.txt';
-
- if ($row->cobrand eq 'fixmystreet') {
- $template = 'submit-oxfordshire.txt' if $row->bodies_str eq 2237;
- }
-
- $template = FixMyStreet->get_email_template($row->cobrand, $row->lang, $template);
- return $template;
+ return 'submit-oxfordshire.txt' if $row->cobrand eq 'fixmystreet' && $row->bodies_str eq 2237;
+ return 'submit.txt';
}
sub send_from {
@@ -88,8 +81,6 @@ sub send {
my ($verbose, $nomail) = CronFns::options();
my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($row->cobrand)->new();
my $params = {
- _template_ => $self->get_template( $row ),
- _parameters_ => $h,
To => $self->to,
From => $self->send_from( $row ),
};
@@ -108,7 +99,9 @@ sub send {
$params->{From} = [ $sender, $params->{From}[1] ];
}
- my $result = FixMyStreet::Email::send_cron($row->result_source->schema, $params, $sender, $nomail, $cobrand);
+ my $result = FixMyStreet::Email::send_cron($row->result_source->schema,
+ $self->get_template($row), $h,
+ $params, $sender, $nomail, $cobrand, $row->lang);
unless ($result) {
$self->success(1);
diff --git a/perllib/FixMyStreet/SendReport/Zurich.pm b/perllib/FixMyStreet/SendReport/Zurich.pm
index a8730bbe4..b38981d94 100644
--- a/perllib/FixMyStreet/SendReport/Zurich.pm
+++ b/perllib/FixMyStreet/SendReport/Zurich.pm
@@ -59,8 +59,6 @@ sub get_template {
}
}
- my $template_path = FixMyStreet->path_to( "templates", "email", "zurich", $template )->stringify;
- $template = Utils::read_file( $template_path );
return $template;
}