aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Somerville <matthew-github@dracos.co.uk>2016-07-15 18:31:52 +0100
committerDave Arter <davea@mysociety.org>2016-08-01 11:52:22 +0100
commit1820db45188fd62699223f63167c5f7250d1b7a6 (patch)
tree116814d9bb6ebd7f6fa015d3e492993b620ac6b1
parent0271c3fa016178f8c72b1192f1d0ed57437ec4c4 (diff)
Add HTML email templates.
Design is all Zarino. This adds the ability to send HTML emails, including attached inline images. When included, this is done as a multipart/related email containing a multipart/alternative (of plain and HTML) and any attached images, so that the images are available even if HTML mail is not. The alert emails list data has been improved so it can be constructed in the templates rather than the code. Various templates have been tidied. Various workarounds for email clients have been made, including: * <th> is used so that the Android 4.x mail client can give them `block` styling in the small screen media query. * Font settings defined on every table cell (<th>) so that sans-serif fonts are used in Outlook, rather than Times New Roman. * A three-column wrapper table to create a 620px centred content area that also shrinks down on narrow screens. (Outlook doesn’t like max-width, so this is the simplest alternative.) * Enforcing a sensible (500px) min-width for the main content area, on clients that don’t support media queries (eg: native Gmail app). * Giant borders on buttons so Outlook displays them * Image alignment with align rather than float.
-rw-r--r--perllib/FixMyStreet/App.pm40
-rw-r--r--perllib/FixMyStreet/App/Controller/Contact.pm20
-rw-r--r--perllib/FixMyStreet/App/View/Email.pm7
-rw-r--r--perllib/FixMyStreet/Cobrand/Default.pm2
-rw-r--r--perllib/FixMyStreet/Email.pm126
-rw-r--r--perllib/FixMyStreet/Script/Alerts.pm89
-rw-r--r--perllib/FixMyStreet/Script/Questionnaires.pm3
-rw-r--r--perllib/FixMyStreet/Script/Reports.pm3
-rw-r--r--perllib/FixMyStreet/SendReport/Email.pm1
-rw-r--r--perllib/FixMyStreet/TestMech.pm42
-rw-r--r--t/app/controller/alert_new.t75
-rw-r--r--t/app/controller/auth.t19
-rw-r--r--t/app/controller/auth_social.t12
-rw-r--r--t/app/controller/contact.t8
-rw-r--r--t/app/controller/moderate.t3
-rw-r--r--t/app/controller/questionnaire.t28
-rw-r--r--t/app/controller/report_import.t15
-rw-r--r--t/app/controller/report_new.t38
-rw-r--r--t/app/controller/report_updates.t27
-rw-r--r--t/app/helpers/emails/html_test.html15
-rw-r--r--t/app/helpers/emails/html_test.txt14
-rw-r--r--t/app/helpers/emails/test.txt (renamed from templates/email/default/test.txt)0
-rw-r--r--t/app/helpers/send_email.t32
-rw-r--r--t/app/model/alert_type.t18
-rw-r--r--t/app/model/problem.t27
-rw-r--r--t/cobrand/bromley.t7
-rw-r--r--t/cobrand/fixamingata.t11
-rw-r--r--templates/email/bromley/questionnaire.txt8
-rw-r--r--templates/email/default/_email_bottom.html17
-rw-r--r--templates/email/default/_email_comment_list.html14
-rw-r--r--templates/email/default/_email_comment_list.txt8
-rw-r--r--templates/email/default/_email_report_list.html19
-rw-r--r--templates/email/default/_email_report_list.txt8
-rw-r--r--templates/email/default/_email_settings.html108
-rw-r--r--templates/email/default/_email_top.html64
-rw-r--r--templates/email/default/alert-confirm.html21
-rw-r--r--templates/email/default/alert-problem-area.html19
-rw-r--r--templates/email/default/alert-problem-area.txt2
-rw-r--r--templates/email/default/alert-problem-council.html19
-rw-r--r--templates/email/default/alert-problem-council.txt2
-rw-r--r--templates/email/default/alert-problem-nearby.html19
-rw-r--r--templates/email/default/alert-problem-nearby.txt2
-rw-r--r--templates/email/default/alert-problem-ward.html19
-rw-r--r--templates/email/default/alert-problem-ward.txt2
-rw-r--r--templates/email/default/alert-problem.html19
-rw-r--r--templates/email/default/alert-problem.txt2
-rw-r--r--templates/email/default/alert-update.html31
-rw-r--r--templates/email/default/alert-update.txt3
-rw-r--r--templates/email/default/change_email.html22
-rw-r--r--templates/email/default/change_email.txt4
-rw-r--r--templates/email/default/contact.html45
-rw-r--r--templates/email/default/contact.txt4
-rw-r--r--templates/email/default/login.html22
-rw-r--r--templates/email/default/login.txt4
-rw-r--r--templates/email/default/problem-confirm-not-sending.html36
-rw-r--r--templates/email/default/problem-confirm-not-sending.txt7
-rw-r--r--templates/email/default/problem-confirm.html39
-rw-r--r--templates/email/default/problem-confirm.txt6
-rw-r--r--templates/email/default/problem-moderated.html38
-rw-r--r--templates/email/default/problem-moderated.txt7
-rw-r--r--templates/email/default/questionnaire.html36
-rw-r--r--templates/email/default/questionnaire.txt8
-rw-r--r--templates/email/default/submit.html63
-rw-r--r--templates/email/default/update-confirm-donotsend.txt2
-rw-r--r--templates/email/default/update-confirm.html33
-rw-r--r--templates/email/fiksgatami/alert-problem-area.txt2
-rw-r--r--templates/email/fiksgatami/alert-problem-council.txt2
-rw-r--r--templates/email/fiksgatami/alert-problem-nearby.txt2
-rw-r--r--templates/email/fiksgatami/alert-problem-ward.txt2
-rw-r--r--templates/email/fiksgatami/alert-problem.txt2
-rw-r--r--templates/email/fiksgatami/alert-update.txt2
-rw-r--r--templates/email/fiksgatami/contact.txt4
-rw-r--r--templates/email/fiksgatami/nn/alert-problem-area.txt2
-rw-r--r--templates/email/fiksgatami/nn/alert-problem-council.txt2
-rw-r--r--templates/email/fiksgatami/nn/alert-problem-nearby.txt2
-rw-r--r--templates/email/fiksgatami/nn/alert-problem-ward.txt2
-rw-r--r--templates/email/fiksgatami/nn/alert-problem.txt2
-rw-r--r--templates/email/fiksgatami/nn/alert-update.txt2
-rw-r--r--templates/email/fiksgatami/questionnaire.txt6
-rw-r--r--templates/email/fixamingata/alert-problem-area.txt2
-rw-r--r--templates/email/fixamingata/alert-problem-council.txt2
-rw-r--r--templates/email/fixamingata/alert-problem-nearby.txt2
-rw-r--r--templates/email/fixamingata/alert-problem-ward.txt2
-rw-r--r--templates/email/fixamingata/alert-problem.txt2
-rw-r--r--templates/email/fixamingata/alert-update.txt2
-rw-r--r--templates/email/fixamingata/contact.txt4
-rw-r--r--templates/email/fixamingata/questionnaire.txt8
-rw-r--r--templates/email/fixmystreet.com/_submit_footer.html9
-rw-r--r--templates/email/fixmystreet.com/submit-oxfordshire.txt47
-rw-r--r--templates/email/fixmystreet.com/submit.html69
-rw-r--r--templates/email/fixmystreet.com/submit.txt4
-rw-r--r--templates/email/fixmystreet.com/update-confirm-donotsend.txt4
-rw-r--r--templates/email/harrogate/submit.txt47
-rw-r--r--templates/email/oxfordshire/submit.txt47
-rw-r--r--templates/email/zurich/alert-moderation-overdue.txt2
-rw-r--r--templates/email/zurich/alert-overdue.txt2
-rw-r--r--templates/email/zurich/alert-update.txt2
-rw-r--r--web/cobrands/fixmystreet.com/images/email-logo.gifbin0 -> 2521 bytes
98 files changed, 1322 insertions, 433 deletions
diff --git a/perllib/FixMyStreet/App.pm b/perllib/FixMyStreet/App.pm
index be0e91101..ea7d43512 100644
--- a/perllib/FixMyStreet/App.pm
+++ b/perllib/FixMyStreet/App.pm
@@ -306,30 +306,38 @@ sub send_email {
my $sender_name = $c->cobrand->contact_name;
# create the vars to pass to the email template
+ my @include_path = @{ $c->cobrand->path_to_email_templates($c->stash->{lang_code}) };
my $vars = {
from => [ $sender, _($sender_name) ],
%{ $c->stash },
%$extra_stash_values,
- additional_template_paths => $c->cobrand->path_to_email_templates($c->stash->{lang_code}),
+ additional_template_paths => \@include_path,
};
return if FixMyStreet::Email::is_abuser($c->model('DB')->schema, $vars->{to});
- my $email = mySociety::Locale::in_gb_locale { FixMyStreet::Email::construct_email(
- {
- _body_ => $c->view('Email')->render( $c, $template, $vars ),
- _attachments_ => $extra_stash_values->{attachments},
- From => $vars->{from},
- To => $vars->{to},
- 'Message-ID' => sprintf('<fms-%s-%s@%s>',
- time(), unpack('h*', random_bytes(5, 1)), $c->config->{EMAIL_DOMAIN}
- ),
- $vars->{subject} ? (Subject => $vars->{subject}) : (),
- $vars->{'Reply-To'} ? ('Reply-To' => $vars->{'Reply-To'}) : (),
- }
- ) };
-
- # send the email
+ my @inline_images;
+ $vars->{inline_image} = sub { FixMyStreet::Email::add_inline_image(\@inline_images, @_); },
+
+ my $html_template = FixMyStreet::Email::get_html_template($template, @include_path);
+ my $html_compiled = eval {
+ $c->view('Email')->render($c, $html_template, $vars) if $html_template;
+ };
+ $c->log->debug("Error compiling HTML $template: $@") if $@;
+
+ my $data = {
+ _body_ => $c->view('Email')->render( $c, $template, $vars ),
+ _attachments_ => $extra_stash_values->{attachments},
+ From => $vars->{from},
+ To => $vars->{to},
+ 'Message-ID' => FixMyStreet::Email::message_id(),
+ };
+ $data->{Subject} = $vars->{subject} if $vars->{subject};
+ $data->{'Reply-To'} = $vars->{'Reply-To'} if $vars->{'Reply-To'};
+ $data->{_html_} = $html_compiled if $html_compiled;
+ $data->{_html_images_} = \@inline_images if @inline_images;
+
+ my $email = mySociety::Locale::in_gb_locale { FixMyStreet::Email::construct_email($data) };
$c->model('EmailSend')->send($email);
return $email;
diff --git a/perllib/FixMyStreet/App/Controller/Contact.pm b/perllib/FixMyStreet/App/Controller/Contact.pm
index e20011471..5527256a6 100644
--- a/perllib/FixMyStreet/App/Controller/Contact.pm
+++ b/perllib/FixMyStreet/App/Controller/Contact.pm
@@ -168,26 +168,22 @@ sub prepare_params_for_email : Private {
if ( $c->stash->{update} ) {
- my $problem_url = $base_url . '/report/' . $c->stash->{update}->problem_id
+ $c->stash->{problem_url} = $base_url . '/report/' . $c->stash->{update}->problem_id
. '#update_' . $c->stash->{update}->id;
- my $admin_url = " - $admin_url" . '/update_edit/' . $c->stash->{update}->id
- if $admin_url;
- $c->stash->{message} .= sprintf(
- " \n\n[ Complaint about update %d on report %d - %s%s ]",
+ $c->stash->{admin_url} = $admin_url . '/update_edit/' . $c->stash->{update}->id;
+ $c->stash->{complaint} = sprintf(
+ "Complaint about update %d on report %d",
$c->stash->{update}->id,
$c->stash->{update}->problem_id,
- $problem_url, $admin_url
);
}
elsif ( $c->stash->{problem} ) {
- my $problem_url = $base_url . '/report/' . $c->stash->{problem}->id;
- $admin_url = " - $admin_url" . '/report_edit/' . $c->stash->{problem}->id
- if $admin_url;
- $c->stash->{message} .= sprintf(
- " \n\n[ Complaint about report %d - %s%s ]",
+ $c->stash->{problem_url} = $base_url . '/report/' . $c->stash->{problem}->id;
+ $c->stash->{admin_url} = $admin_url . '/report_edit/' . $c->stash->{problem}->id;
+ $c->stash->{complaint} = sprintf(
+ "Complaint about report %d",
$c->stash->{problem}->id,
- $problem_url, $admin_url
);
# flag this so it's automatically listed in the admin interface
diff --git a/perllib/FixMyStreet/App/View/Email.pm b/perllib/FixMyStreet/App/View/Email.pm
index 86d5c1d60..6073ee814 100644
--- a/perllib/FixMyStreet/App/View/Email.pm
+++ b/perllib/FixMyStreet/App/View/Email.pm
@@ -14,7 +14,7 @@ __PACKAGE__->config(
],
ENCODING => 'utf8',
render_die => 1,
- expose_methods => ['loc'],
+ expose_methods => ['loc', 'file_exists'],
);
=head1 NAME
@@ -40,5 +40,10 @@ sub loc {
return _(@args);
}
+sub file_exists {
+ my ( $self, $c, @args ) = @_;
+ -e FixMyStreet->path_to(@args);
+}
+
1;
diff --git a/perllib/FixMyStreet/Cobrand/Default.pm b/perllib/FixMyStreet/Cobrand/Default.pm
index e5ec0c13a..686684a05 100644
--- a/perllib/FixMyStreet/Cobrand/Default.pm
+++ b/perllib/FixMyStreet/Cobrand/Default.pm
@@ -395,7 +395,7 @@ Return an override type of map if necessary.
=cut
sub map_type {
my $self = shift;
- return 'OSM' if $self->{c}->req->uri->host =~ /^osm\./;
+ return 'OSM' if $self->{c} && $self->{c}->req->uri->host =~ /^osm\./;
return;
}
diff --git a/perllib/FixMyStreet/Email.pm b/perllib/FixMyStreet/Email.pm
index d955f6f72..34ac1514c 100644
--- a/perllib/FixMyStreet/Email.pm
+++ b/perllib/FixMyStreet/Email.pm
@@ -8,6 +8,7 @@ package FixMyStreet::Email;
use Email::MIME;
use Encode;
+use File::Spec;
use POSIX qw();
use Template;
use Digest::HMAC_SHA1 qw(hmac_sha1_hex);
@@ -72,10 +73,77 @@ sub is_abuser {
sub _render_template {
my ($tt, $template, $vars, %options) = @_;
my $var;
- $tt->process($template, $vars, \$var);
+ $tt->process($template, $vars, \$var) || print "Template processing error: " . $tt->error() . "\n";
return $var;
}
+sub _unique_id {
+ sprintf('fms-%s-%s@%s',
+ time(), unpack('h*', random_bytes(5, 1)),
+ FixMyStreet->config('EMAIL_DOMAIN'));
+}
+
+sub message_id {
+ '<' . _unique_id() . '>'
+}
+
+sub add_inline_image {
+ my ($inline_images, $obj, $name) = @_;
+ if (ref $obj eq 'HASH') {
+ return _add_inline($inline_images, $name, $obj->{data}, $obj->{content_type});
+ } else {
+ my $file = FixMyStreet->path_to($obj);
+ return _add_inline($inline_images, $file->basename, scalar $file->slurp);
+ }
+}
+
+sub _add_inline {
+ my ($inline_images, $name, $data, $type) = @_;
+
+ return unless $data;
+
+ $name ||= 'photo';
+ if ($type) {
+ if ($name !~ /\./) {
+ my ($suffix) = $type =~ m{image/(.*)};
+ $name .= ".$suffix";
+ }
+ } else {
+ my ($b, $t) = split /\./, $name;
+ $type = "image/$t";
+ }
+
+ my $cid = _unique_id();
+ push @$inline_images, {
+ body => $data,
+ attributes => {
+ id => $cid,
+ filename => $name,
+ content_type => $type,
+ encoding => 'base64',
+ name => $name,
+ },
+ };
+ return "cid:$cid";
+}
+
+# We only want an HTML template from the same directory as the .txt
+sub get_html_template {
+ my ($template, @include_path) = @_;
+ push @include_path, FixMyStreet->path_to( 'templates', 'email', 'default' );
+ (my $html_template = $template) =~ s/\.txt$/\.html/;
+ my $template_dir = find_template_dir($template, @include_path);
+ my $html_template_dir = find_template_dir($html_template, @include_path);
+ return $html_template if $template_dir eq $html_template_dir;
+}
+
+sub find_template_dir {
+ my ($template, @include_path) = @_;
+ foreach (@include_path) {
+ return $_ if -e File::Spec->catfile($_, $template);
+ }
+}
+
sub send_cron {
my ( $schema, $template, $vars, $hdrs, $env_from, $nomail, $cobrand, $lang_code ) = @_;
@@ -88,11 +156,11 @@ sub send_cron {
return 1 if is_abuser($schema, $hdrs->{To});
- $hdrs->{'Message-ID'} = sprintf('<fms-cron-%s-%s@%s>', time(),
- unpack('h*', random_bytes(5, 1)), FixMyStreet->config('EMAIL_DOMAIN')
- );
+ $hdrs->{'Message-ID'} = message_id();
my @include_path = @{ $cobrand->path_to_email_templates($lang_code) };
+ my $html_template = get_html_template($template, @include_path);
+
push @include_path, FixMyStreet->path_to( 'templates', 'email', 'default' );
my $tt = Template->new({
ENCODING => 'utf8',
@@ -102,6 +170,14 @@ sub send_cron {
$vars->{site_name} = Utils::trim_text(_render_template($tt, 'site-name.txt', $vars));
$hdrs->{_body_} = _render_template($tt, $template, $vars);
+ if ($html_template) {
+ my @inline_images;
+ $vars->{inline_image} = sub { add_inline_image(\@inline_images, @_) };
+ $vars->{file_exists} = sub { -e FixMyStreet->path_to(@_) };
+ $hdrs->{_html_} = _render_template($tt, $html_template, $vars);
+ $hdrs->{_html_images_} = \@inline_images;
+ }
+
my $email = mySociety::Locale::in_gb_locale { construct_email($hdrs) };
if ($nomail) {
@@ -236,6 +312,47 @@ sub construct_email ($) {
),
];
+ my $overall_type;
+ if ($p->{_html_}) {
+ my $html = _mime_create(
+ body_str => $p->{_html_},
+ attributes => {
+ charset => 'utf-8',
+ encoding => 'quoted-printable',
+ content_type => 'text/html',
+ },
+ );
+ if ($p->{_html_images_} || $p->{_attachments_}) {
+ $parts = [ _mime_create(
+ attributes => { content_type => 'multipart/alternative' },
+ parts => [ $parts->[0], $html ]
+ ) ];
+ } else {
+ # The top level will be the alternative multipart if there are
+ # no images and no other attachments
+ push @$parts, $html;
+ $overall_type = 'multipart/alternative';
+ }
+ if ($p->{_html_images_}) {
+ foreach (@{$p->{_html_images_}}) {
+ my $cid = delete $_->{attributes}->{id};
+ my $part = _mime_create(%$_);
+ $part->header_set('Content-ID' => "<$cid>");
+ push @$parts, $part;
+ }
+ if ($p->{_attachments_}) {
+ $parts = [ _mime_create(
+ attributes => { content_type => 'multipart/related' },
+ parts => $parts,
+ ) ];
+ } else {
+ # The top level will be the related multipart if there are
+ # images but no other attachments
+ $overall_type = 'multipart/related';
+ }
+ }
+ }
+
if ($p->{_attachments_}) {
push @$parts, map { _mime_create(%$_) } @{$p->{_attachments_}};
}
@@ -245,6 +362,7 @@ sub construct_email ($) {
parts => $parts,
attributes => {
charset => 'utf-8',
+ $overall_type ? (content_type => $overall_type) : (),
},
);
diff --git a/perllib/FixMyStreet/Script/Alerts.pm b/perllib/FixMyStreet/Script/Alerts.pm
index 062601044..91f5cd6ef 100644
--- a/perllib/FixMyStreet/Script/Alerts.pm
+++ b/perllib/FixMyStreet/Script/Alerts.pm
@@ -15,9 +15,13 @@ use RABX;
use FixMyStreet::Cobrand;
use FixMyStreet::DB;
use FixMyStreet::Email;
+use FixMyStreet::Map;
+use FixMyStreet::App::Model::PhotoSet;
FixMyStreet->configure_mysociety_dbhandle;
+my $parser = DateTime::Format::Pg->new();
+
# Child must have confirmed, id, email, state(!) columns
# If parent/child, child table must also have name and text
# and foreign key to parent must be PARENT_id
@@ -37,6 +41,7 @@ sub send() {
$item_table.id as item_id, $item_table.text as item_text,
$item_table.name as item_name, $item_table.anonymous as item_anonymous,
$item_table.confirmed as item_confirmed,
+ $item_table.photo as item_photo,
$head_table.*
from alert, $item_table, $head_table
where alert.parameter::integer = $head_table.id
@@ -63,7 +68,7 @@ sub send() {
$query = dbh()->prepare($query);
$query->execute();
my $last_alert_id;
- my %data = ( template => $alert_type->template, data => '', schema => $schema );
+ my %data = ( template => $alert_type->template, data => [], schema => $schema );
while (my $row = $query->fetchrow_hashref) {
my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($row->{alert_cobrand})->new();
@@ -84,7 +89,7 @@ sub send() {
} );
if ($last_alert_id && $last_alert_id != $row->{alert_id}) {
_send_aggregated_alert_email(%data);
- %data = ( template => $alert_type->template, data => '', schema => $schema );
+ %data = ( template => $alert_type->template, data => [], schema => $schema );
}
# create problem status message for the templates
@@ -116,30 +121,50 @@ sub send() {
} else {
$data{problem_url} = $url . "/report/" . $row->{id};
}
- $data{data} .= $row->{item_name} . ' : ' if $row->{item_name} && !$row->{item_anonymous};
- if ( $cobrand->include_time_in_update_alerts ) {
- my $parser = DateTime::Format::Pg->new();
- my $dt = $parser->parse_timestamp( $row->{item_confirmed} );
- # We need to always set this otherwise we end up with the DateTime
- # object being in the floating timezone in which case applying a
- # subsequent timezone set will have no effect.
- # this is basically recreating the code from the inflate wrapper
- # in the database model.
- FixMyStreet->set_time_zone($dt);
- $data{data} .= $cobrand->prettify_dt( $dt, 'alert' ) . "\n\n";
- }
- $data{data} .= $row->{item_text} . "\n\n------\n\n";
+
+ my $dt = $parser->parse_timestamp( $row->{item_confirmed} );
+ # We need to always set this otherwise we end up with the DateTime
+ # object being in the floating timezone in which case applying a
+ # subsequent timezone set will have no effect.
+ # this is basically recreating the code from the inflate wrapper
+ # in the database model.
+ FixMyStreet->set_time_zone($dt);
+ $row->{confirmed} = $dt;
+
+ # Hack in the image for the non-object updates
+ $row->{get_first_image_fp} = sub {
+ return FixMyStreet::App::Model::PhotoSet->new({
+ db_data => $row->{item_photo},
+ })->get_image_data( num => 0, size => 'fp' );
+ };
+
# this is ward and council problems
} else {
- $data{data} .= $url . "/report/" . $row->{id} . " - $row->{title}\n\n";
if ( exists $row->{geocode} && $row->{geocode} && $ref =~ /ward|council/ ) {
my $nearest_st = _get_address_from_gecode( $row->{geocode} );
- $data{data} .= $nearest_st if $nearest_st;
+ $row->{nearest} = $nearest_st;
}
- $data{data} .= "\n\n------\n\n";
+
+ my $dt = $parser->parse_timestamp( $row->{confirmed} );
+ FixMyStreet->set_time_zone($dt);
+ $row->{confirmed} = $dt;
+
+ # Hack in the image for the non-object reports
+ $row->{get_first_image_fp} = sub {
+ return FixMyStreet::App::Model::PhotoSet->new({
+ db_data => $row->{photo},
+ })->get_image_data( num => 0, size => 'fp' );
+ };
}
+
+ push @{$data{data}}, $row;
+
if (!$data{alert_user_id}) {
%data = (%data, %$row);
+ if ($ref eq 'new_updates') {
+ # Get a report object for its photo and static map
+ $data{report} = $schema->resultset('Problem')->find({ id => $row->{id} });
+ }
if ($ref eq 'area_problems' || $ref eq 'council_problems' || $ref eq 'ward_problems') {
my $va_info = mySociety::MaPit::call('area', $row->{alert_parameter});
$data{area_name} = $va_info->{name};
@@ -149,7 +174,7 @@ sub send() {
$data{ward_name} = $va_info->{name};
}
}
- $data{cobrand} = $row->{alert_cobrand};
+ $data{cobrand} = $cobrand;
$data{cobrand_data} = $row->{alert_cobrand_data};
$data{lang} = $row->{alert_lang};
$last_alert_id = $row->{alert_id};
@@ -183,15 +208,16 @@ sub send() {
my $states = "'" . join( "', '", FixMyStreet::DB::Result::Problem::visible_states() ) . "'";
my %data = (
template => $template,
- data => '',
+ data => [],
alert_id => $alert->id,
alert_email => $alert->user->email,
lang => $alert->lang,
- cobrand => $alert->cobrand,
+ cobrand => $cobrand,
cobrand_data => $alert->cobrand_data,
schema => $schema,
);
- my $q = "select problem.id, problem.bodies_str, problem.postcode, problem.geocode, problem.title from problem_find_nearby(?, ?, ?) as nearby, problem, users
+ my $q = "select problem.id, problem.bodies_str, problem.postcode, problem.geocode, problem.confirmed,
+ problem.title, problem.detail, problem.photo from problem_find_nearby(?, ?, ?) as nearby, problem, users
where nearby.problem_id = problem.id
and problem.user_id = users.id
and problem.state in ($states)
@@ -207,24 +233,31 @@ sub send() {
alert_id => $alert->id,
parameter => $row->{id},
} );
- my $url = $cobrand->base_url_for_report($row);
- $data{data} .= $url . "/report/" . $row->{id} . " - $row->{title}\n\n";
if ( exists $row->{geocode} && $row->{geocode} ) {
my $nearest_st = _get_address_from_gecode( $row->{geocode} );
- $data{data} .= $nearest_st if $nearest_st;
+ $row->{nearest} = $nearest_st;
}
- $data{data} .= "\n\n------\n\n";
+ my $dt = $parser->parse_timestamp( $row->{confirmed} );
+ FixMyStreet->set_time_zone($dt);
+ $row->{confirmed} = $dt;
+ $row->{get_first_image_fp} = sub {
+ return FixMyStreet::App::Model::PhotoSet->new({
+ db_data => $row->{photo},
+ })->get_image_data( num => 0, size => 'fp' );
+ };
+ push @{$data{data}}, $row;
}
- _send_aggregated_alert_email(%data) if $data{data};
+ _send_aggregated_alert_email(%data) if @{$data{data}};
}
}
sub _send_aggregated_alert_email(%) {
my %data = @_;
- my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($data{cobrand})->new();
+ my $cobrand = $data{cobrand};
$cobrand->set_lang_and_domain( $data{lang}, 1, FixMyStreet->path_to('locale')->stringify );
+ FixMyStreet::Map::set_map_class($cobrand->map_type);
if (!$data{alert_email}) {
my $user = $data{schema}->resultset('User')->find( {
diff --git a/perllib/FixMyStreet/Script/Questionnaires.pm b/perllib/FixMyStreet/Script/Questionnaires.pm
index c5bc6bfe0..3f22eb150 100644
--- a/perllib/FixMyStreet/Script/Questionnaires.pm
+++ b/perllib/FixMyStreet/Script/Questionnaires.pm
@@ -5,6 +5,7 @@ use warnings;
use Utils;
use FixMyStreet::DB;
use FixMyStreet::Email;
+use FixMyStreet::Map;
use FixMyStreet::Cobrand;
sub send {
@@ -41,6 +42,7 @@ sub send_questionnaires_period {
my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($row->cobrand)->new();
$cobrand->set_lang_and_domain($row->lang, 1);
+ FixMyStreet::Map::set_map_class($cobrand->map_type);
# Not all cobrands send questionnaires
next unless $cobrand->send_questionnaires;
@@ -53,6 +55,7 @@ sub send_questionnaires_period {
next unless $cobrand->email_host;
my %h = map { $_ => $row->$_ } qw/name title detail category/;
+ $h{report} = $row;
$h{created} = Utils::prettify_duration( time() - $row->confirmed->epoch, 'week' );
my $questionnaire = $rs->create( {
diff --git a/perllib/FixMyStreet/Script/Reports.pm b/perllib/FixMyStreet/Script/Reports.pm
index 30d24f640..311d8fec4 100644
--- a/perllib/FixMyStreet/Script/Reports.pm
+++ b/perllib/FixMyStreet/Script/Reports.pm
@@ -14,6 +14,7 @@ use FixMyStreet;
use FixMyStreet::Cobrand;
use FixMyStreet::DB;
use FixMyStreet::Email;
+use FixMyStreet::Map;
use FixMyStreet::SendReport;
sub send(;$) {
@@ -60,6 +61,7 @@ sub send(;$) {
}
$cobrand->set_lang_and_domain($row->lang, 1);
+ FixMyStreet::Map::set_map_class($cobrand->map_type);
if ( $row->is_from_abuser) {
$row->update( { state => 'hidden' } );
debug_print("hiding because its sender is flagged as an abuser", $row->id) if $debug_mode;
@@ -73,6 +75,7 @@ sub send(;$) {
# Template variables for the email
my $email_base_url = $cobrand->base_url_for_report($row);
my %h = map { $_ => $row->$_ } qw/id title detail name category latitude longitude used_map/;
+ $h{report} = $row;
map { $h{$_} = $row->user->$_ || '' } qw/email phone/;
$h{confirmed} = DateTime::Format::Pg->format_datetime( $row->confirmed->truncate (to => 'second' ) )
if $row->confirmed;
diff --git a/perllib/FixMyStreet/SendReport/Email.pm b/perllib/FixMyStreet/SendReport/Email.pm
index 8582ebb3b..2eab1c754 100644
--- a/perllib/FixMyStreet/SendReport/Email.pm
+++ b/perllib/FixMyStreet/SendReport/Email.pm
@@ -52,7 +52,6 @@ sub build_recipient_list {
sub get_template {
my ( $self, $row ) = @_;
- return 'submit-oxfordshire.txt' if $row->cobrand eq 'fixmystreet' && $row->bodies_str eq 2237;
return 'submit.txt';
}
diff --git a/perllib/FixMyStreet/TestMech.pm b/perllib/FixMyStreet/TestMech.pm
index 937780a31..5f4a6ceed 100644
--- a/perllib/FixMyStreet/TestMech.pm
+++ b/perllib/FixMyStreet/TestMech.pm
@@ -221,6 +221,48 @@ sub get_email {
return $emails[0];
}
+sub get_text_body_from_email {
+ my ($mech, $email, $obj) = @_;
+ unless ($email) {
+ $email = $mech->get_email;
+ $mech->clear_emails_ok;
+ }
+
+ my $body;
+ $email->walk_parts(sub {
+ my $part = shift;
+ return if $part->subparts;
+ return if $part->content_type !~ m{text/plain};
+ $body = $obj ? $part : $part->body;
+ ok $body, "Found text body";
+ });
+ return $body;
+}
+
+sub get_link_from_email {
+ my ($mech, $email, $multiple) = @_;
+ unless ($email) {
+ $email = $mech->get_email;
+ $mech->clear_emails_ok;
+ }
+
+ my @links;
+ $email->walk_parts(sub {
+ my $part = shift;
+ return if $part->subparts;
+ return if $part->content_type !~ m{text/};
+ if (@links) {
+ # Must be an HTML part now, first two links are in header
+ my @html_links = $part->body =~ m{https?://[^"]+}g;
+ is $links[0], $html_links[2], 'HTML link matches text link';
+ } else {
+ @links = $part->body =~ m{https?://\S+}g;
+ ok @links, "Found links in email '@links'";
+ }
+ });
+ return $multiple ? @links : $links[0];
+}
+
=head2 get_first_email
$email = $mech->get_first_email(@emails);
diff --git a/t/app/controller/alert_new.t b/t/app/controller/alert_new.t
index 2c20daf9d..1b85adf7e 100644
--- a/t/app/controller/alert_new.t
+++ b/t/app/controller/alert_new.t
@@ -98,9 +98,10 @@ foreach my $test (
my $email = $mech->get_email;
ok $email, "got an email";
- like $email->body, qr/$test->{email_text}/i, "Correct email text";
+ like $mech->get_text_body_from_email($email), qr/$test->{email_text}/i, "Correct email text";
- my ( $url, $url_token ) = $email->body =~ m{(http://\S+/A/)(\S+)};
+ my $url = $mech->get_link_from_email($email);
+ my ($url_token) = $url =~ m{/A/(\S+)};
ok $url, "extracted confirm url '$url'";
my $token = FixMyStreet::App->model('DB::Token')->find(
@@ -119,10 +120,8 @@ foreach my $test (
$mech->get_ok( $test->{uri} . "&token=$csrf" );
- $email = $mech->get_email;
- ok $email, 'got a second email';
-
- ($url_token) = $email->body =~ m{http://\S+/A/(\S+)};
+ $url = $mech->get_link_from_email;
+ ($url_token) = $url =~ m{/A/(\S+)};
ok $url_token ne $existing_token, 'sent out a new token';
$token = FixMyStreet::App->model('DB::Token')->find(
@@ -361,9 +360,9 @@ subtest "Test normal alert signups and that alerts are sent" => sub {
} );
};
if ( $alert->{email_confirm} ) {
- my $email = $mech->get_email;
+ my $url = $mech->get_link_from_email;
+ my ($url_token) = $url =~ m{/A/(\S+)};
$mech->clear_emails_ok;
- my ( $url, $url_token ) = $email->body =~ m{http://\S+(/A/(\S+))};
my $token = FixMyStreet::App->model('DB::Token')->find( { token => $url_token, scope => 'alert' } );
$mech->get_ok( $url );
$mech->content_contains('alert created');
@@ -446,30 +445,32 @@ subtest "Test normal alert signups and that alerts are sent" => sub {
my @emails = $mech->get_email;
my $count;
for (@emails) {
- $count++ if $_->body =~ /The following updates have been left on this report:/;
- $count++ if $_->body =~ /The following new FixMyStreet reports have been added in the City of\s+Edinburgh\s+Council area:/;
- $count++ if $_->body =~ /The following FixMyStreet reports have been made within the area you\s+specified:/;
- $count++ if $_->body =~ /\s+-\s+Testing/;
+ my $body = $mech->get_text_body_from_email($_);
+ $count++ if $body =~ /The following updates have been left on this report:/;
+ $count++ if $body =~ /The following new FixMyStreet reports have been added in the City of\s+Edinburgh\s+Council area:/;
+ $count++ if $body =~ /The following FixMyStreet reports have been made within the area you\s+specified:/;
+ $count++ if $body =~ /\s+-\s+Testing/;
}
is $count, 5, 'Three emails, with five matching lines in them';
my $email = $emails[0];
- like $email->body, qr/Other User/, 'Update name given';
- unlike $email->body, qr/Anonymous User/, 'Update name not given';
+ my $body = $mech->get_text_body_from_email($email);
+ like $body, qr/Other User/, 'Update name given';
+ unlike $body, qr/Anonymous User/, 'Update name not given';
# The update alert was to the problem reporter, so has a special update URL
$mech->log_out_ok;
$mech->get_ok( "/report/$report_id" );
$mech->content_lacks( 'has not been fixed' );
- my ($url) = $email->body =~ m{(http://\S+/R/\S+)};
- ok $url, "extracted update url '$url'";
- $mech->get_ok( $url );
+ my @urls = $mech->get_link_from_email($email, 1);
+ ok $urls[0] =~ m{/R/\S+}, "extracted update url '$urls[0]'";
+ $mech->get_ok( $urls[0] );
is $mech->uri->path, "/report/" . $report_id, "redirected to report page";
$mech->content_contains( 'has not been fixed' );
$mech->not_logged_in_ok;
- ($url) = $emails[0]->body =~ m{http://\S+(/A/\S+)};
- $mech->get_ok( $url );
+ ok $urls[-1] =~ m{/A/\S+}, "unsubscribe URL '$urls[-1]'";
+ $mech->get_ok( $urls[-1] );
$mech->content_contains('alert deleted');
$mech->not_logged_in_ok;
@@ -546,13 +547,10 @@ subtest "Test signature template is used from cobrand" => sub {
}, sub {
FixMyStreet::App->model('DB::AlertType')->email_alerts();
};
- # TODO Note the below will fail if the db has an existing alert that matches
- $mech->email_count_is(1);
- my @emails = $mech->get_email;
- my $email = $emails[0];
- like $email->body, qr/All the best/, 'default signature used';
- unlike $email->body, qr/twitter.com/, 'nothing from fixmystreet signature';
+ my $email = $mech->get_text_body_from_email;
+ like $email, qr/All the best/, 'default signature used';
+ unlike $email, qr/twitter.com/, 'nothing from fixmystreet signature';
$update = FixMyStreet::App->model('DB::Comment')->create( {
problem_id => $report_id,
@@ -577,12 +575,9 @@ subtest "Test signature template is used from cobrand" => sub {
}, sub {
FixMyStreet::App->model('DB::AlertType')->email_alerts();
};
- # TODO Note the below will fail if the db has an existing alert that matches
- $mech->email_count_is(1);
- @emails = $mech->get_email;
- $email = $emails[0];
- like $email->body, qr/twitter.com/, 'fixmystreet signature used';
+ $email = $mech->get_text_body_from_email;
+ like $email, qr/twitter.com/, 'fixmystreet signature used';
$mech->delete_user($user1);
$mech->delete_user($user2);
@@ -682,9 +677,8 @@ for my $test (
}, sub {
FixMyStreet::App->model('DB::AlertType')->email_alerts();
};
- $mech->email_count_is(1);
- my $email = $mech->get_email;
- like $email->body, qr/Alert\s+test\s+for\s+non\s+public\s+reports/, 'alert contains public report';
+ my $email = $mech->get_text_body_from_email;
+ like $email, qr/Alert\s+test\s+for\s+non\s+public\s+reports/, 'alert contains public report';
$mech->delete_user( $user1 );
$mech->delete_user( $user2 );
@@ -766,16 +760,14 @@ subtest 'check new updates alerts for non public reports only go to report owner
ok $alert_user2, "alert created";
FixMyStreet::App->model('DB::AlertType')->email_alerts();
- $mech->email_count_is(1);
- my $email = $mech->get_email;
- like $email->body, qr/This is some more update text/, 'alert contains update text';
+ my $email = $mech->get_text_body_from_email;
+ like $email, qr/This is some more update text/, 'alert contains update text';
$mech->clear_emails_ok;
$report->update( { non_public => 0 } );
FixMyStreet::App->model('DB::AlertType')->email_alerts();
- $mech->email_count_is(1);
- $email = $mech->get_email;
- like $email->body, qr/This is some more update text/, 'alert contains update text';
+ $email = $mech->get_text_body_from_email;
+ like $email, qr/This is some more update text/, 'alert contains update text';
$mech->delete_user( $user1 );
$mech->delete_user( $user2 );
@@ -848,7 +840,6 @@ subtest 'check setting inlude dates in new updates cobrand option' => sub {
$mech->clear_emails_ok;
FixMyStreet::App->model('DB::AlertType')->email_alerts();
- $mech->email_count_is(1);
# if we don't do this then we're applying the date inflation code and
# it's timezone munging to the DateTime object above and not the DateTime
@@ -858,8 +849,8 @@ subtest 'check setting inlude dates in new updates cobrand option' => sub {
$update->discard_changes();
my $date_in_alert = Utils::prettify_dt( $update->confirmed );
- my $email = $mech->get_email;
- like $email->body, qr/$date_in_alert/, 'alert contains date';
+ my $email = $mech->get_text_body_from_email;
+ like $email, qr/$date_in_alert/, 'alert contains date';
$mech->delete_user( $user1 );
$mech->delete_user( $user2 );
diff --git a/t/app/controller/auth.t b/t/app/controller/auth.t
index 60f22acfb..251aa2977 100644
--- a/t/app/controller/auth.t
+++ b/t/app/controller/auth.t
@@ -72,8 +72,7 @@ $mech->not_logged_in_ok;
is $email->header('To'), $test_email, "to is correct";
# extract the link
- my ($link) = $email->body =~ m{(http://\S+)};
- ok $link, "Found a link in email '$link'";
+ my $link = $mech->get_link_from_email($email);
# check that the user does not exist
sub get_user {
@@ -117,9 +116,7 @@ $mech->not_logged_in_ok;
# follow link and change password - check not prompted for old password
$mech->not_logged_in_ok;
- my $email = $mech->get_email;
- $mech->clear_emails_ok;
- my ($link) = $email->body =~ m{(http://\S+)};
+ my $link = $mech->get_link_from_email;
$mech->get_ok($link);
is $mech->uri->path, '/faq', "redirected to the Help page";
@@ -187,9 +184,7 @@ subtest "Test change email page" => sub {
$mech->submit_form_ok({ with_fields => { email => $test_email2 } }, "change_email to $test_email2");
is $mech->uri->path, '/auth/change_email', "still on change email page";
$mech->content_contains( 'Now check your email', "found check your email" );
- my $email = $mech->get_email;
- $mech->clear_emails_ok;
- my ($link) = $email->body =~ m{(http://\S+)};
+ my $link = $mech->get_link_from_email;
$mech->get_ok($link);
is $mech->uri->path, '/auth/change_email/success', "redirected to the change_email page";
$mech->content_contains('successfully confirmed');
@@ -201,9 +196,7 @@ subtest "Test change email page" => sub {
);
is $mech->uri->path, '/auth/change_email', "still on change email page";
$mech->content_contains( 'Now check your email', "found check your email" );
- $email = $mech->get_email;
- $mech->clear_emails_ok;
- ($link) = $email->body =~ m{(http://\S+)};
+ $link = $mech->get_link_from_email;
$mech->get_ok($link);
is $mech->uri->path, '/auth/change_email/success', "redirected to the change_email page";
$mech->content_contains('successfully confirmed');
@@ -214,9 +207,7 @@ subtest "Test change email page" => sub {
);
is $mech->uri->path, '/auth/change_email', "still on change email page";
$mech->content_contains( 'Now check your email', "found check your email" );
- $email = $mech->get_email;
- $mech->clear_emails_ok;
- ($link) = $email->body =~ m{(http://\S+)};
+ $link = $mech->get_link_from_email;
$mech->log_out_ok;
$mech->get_ok($link);
isnt $mech->uri->path, '/auth/change_email/success', "not redirected to the change_email page";
diff --git a/t/app/controller/auth_social.t b/t/app/controller/auth_social.t
index 6929c0ddc..f3eae32a7 100644
--- a/t/app/controller/auth_social.t
+++ b/t/app/controller/auth_social.t
@@ -113,10 +113,8 @@ for my $fb_state ( 'refused', 'no email', 'existing UID', 'okay' ) {
$mech->submit_form(with_fields => $fields);
$mech->content_contains('Nearly done! Now check your email');
- my $email = $mech->get_email;
- ok $email, "got an email";
+ my $url = $mech->get_link_from_email;
$mech->clear_emails_ok;
- my ( $url, $url_token ) = $email->body =~ m{(https?://\S+/[CMP]/)(\S+)};
ok $url, "extracted confirm url '$url'";
my $user = FixMyStreet::App->model( 'DB::User' )->find( { email => $fb_email } );
@@ -125,7 +123,7 @@ for my $fb_state ( 'refused', 'no email', 'existing UID', 'okay' ) {
} else {
is $user->facebook_id, undef, 'User has no facebook ID';
}
- $mech->get_ok( $url . $url_token );
+ $mech->get_ok( $url );
$user = FixMyStreet::App->model( 'DB::User' )->find( { email => $fb_email } );
is $user->facebook_id, $fb_uid, 'User now has correct facebook ID';
@@ -225,10 +223,8 @@ for my $tw_state ( 'refused', 'existing UID', 'no email' ) {
$mech->submit_form(with_fields => $fields);
$mech->content_contains('Nearly done! Now check your email');
- my $email = $mech->get_email;
- ok $email, "got an email";
+ my $url = $mech->get_link_from_email;
$mech->clear_emails_ok;
- my ( $url, $url_token ) = $email->body =~ m{(https?://\S+/[CMP]/)(\S+)};
ok $url, "extracted confirm url '$url'";
my $user = FixMyStreet::App->model( 'DB::User' )->find( { email => $tw_email } );
@@ -237,7 +233,7 @@ for my $tw_state ( 'refused', 'existing UID', 'no email' ) {
} else {
is $user->twitter_id, undef, 'User has no twitter ID';
}
- $mech->get_ok( $url . $url_token );
+ $mech->get_ok( $url );
$user = FixMyStreet::App->model( 'DB::User' )->find( { email => $tw_email } );
is $user->twitter_id, $tw_uid, 'User now has correct twitter ID';
diff --git a/t/app/controller/contact.t b/t/app/controller/contact.t
index 1b0f09a85..dd94fc431 100644
--- a/t/app/controller/contact.t
+++ b/t/app/controller/contact.t
@@ -251,16 +251,16 @@ for my $test (
}
$mech->submit_form_ok( { with_fields => $test->{fields} } );
$mech->content_contains('Thank you for your feedback');
- $mech->email_count_is(1);
my $email = $mech->get_email;
is $email->header('Subject'), 'FMS message: ' . $test->{fields}->{subject}, 'subject';
is $email->header('From'), "\"$test->{fields}->{name}\" <$test->{fields}->{em}>", 'from';
- like $email->body, qr/$test->{fields}->{message}/, 'body';
- like $email->body, qr/Sent by contact.cgi on \S+. IP address (?:\d{1,3}\.){3,}\d{1,3}/, 'body footer';
+ my $body = $mech->get_text_body_from_email($email);
+ like $body, qr/$test->{fields}->{message}/, 'body';
+ like $body, qr/Sent by contact.cgi on \S+. IP address (?:\d{1,3}\.){3,}\d{1,3}/, 'body footer';
my $problem_id = $test->{fields}{id};
- like $email->body, qr/Complaint about report $problem_id/, 'reporting a report'
+ like $body, qr/Complaint about report $problem_id/, 'reporting a report'
if $test->{fields}{id};
$problem_main->discard_changes;
diff --git a/t/app/controller/moderate.t b/t/app/controller/moderate.t
index 14c751115..e3e8bf2cf 100644
--- a/t/app/controller/moderate.t
+++ b/t/app/controller/moderate.t
@@ -169,8 +169,7 @@ subtest 'Problem moderation' => sub {
$report->discard_changes;
is $report->state, 'hidden', 'Is hidden';
- my $email = $mech->get_email;
- my ($url) = $email->body =~ m{(http://\S+)};
+ my $url = $mech->get_link_from_email;
ok $url, "extracted complain url '$url'";
$mech->get_ok($url);
diff --git a/t/app/controller/questionnaire.t b/t/app/controller/questionnaire.t
index 7a46e48bd..b05f74225 100644
--- a/t/app/controller/questionnaire.t
+++ b/t/app/controller/questionnaire.t
@@ -58,12 +58,14 @@ FixMyStreet::App->model('DB::Questionnaire')->send_questionnaires( {
} );
my $email = $mech->get_email;
ok $email, "got an email";
-like $email->body, qr/fill in our short questionnaire/i, "got questionnaire email";
+my $plain = $mech->get_text_body_from_email($email, 1);
+like $plain->body, qr/fill in our short questionnaire/i, "got questionnaire email";
-like $email->body_str, qr/Testing \x{2013} Detail/, 'email contains encoded character';
-is $email->header('Content-Type'), 'text/plain; charset="utf-8"', 'in the right character set';
+like $plain->body_str, qr/Testing \x{2013} Detail/, 'email contains encoded character';
+is $plain->header('Content-Type'), 'text/plain; charset="utf-8"', 'in the right character set';
-my ($token) = $email->body =~ m{http://.*?/Q/(\S+)};
+my $url = $mech->get_link_from_email($email);
+my ($token) = $url =~ m{/Q/(\S+)};
ok $token, "extracted questionnaire token '$token'";
$mech->clear_emails_ok;
@@ -399,13 +401,14 @@ FixMyStreet::override_config {
$questionnaire->delete;
FixMyStreet::App->model('DB::Questionnaire')->send_questionnaires();
- $email = $mech->get_email;
- ok $email, "got an email";
- $mech->clear_emails_ok;
- (my $body = $email->body) =~ s/\s+/ /g;
+ my $email = $mech->get_email;
+ my $body = $mech->get_text_body_from_email($email);
+ $mech->clear_emails_ok;
+ $body =~ s/\s+/ /g;
like $body, qr/fill in our short questionnaire/i, "got questionnaire email";
- ($token) = $email->body =~ m{http://.*?/Q/(\S+)};
+ my $url = $mech->get_link_from_email($email);
+ ($token) = $url =~ m{/Q/(\S+)};
ok $token, "extracted questionnaire token '$token'";
# Test already answered the ever reported question, so not shown again
@@ -445,9 +448,10 @@ FixMyStreet::override_config {
ok $email, "got an email";
$mech->clear_emails_ok;
- like $email->body_str, qr/Testing \x{2013} Detail/, 'email contains encoded character from user';
- like $email->body_str, qr/sak p\xe5 FiksGataMi/, 'email contains encoded character from template';
- is $email->header('Content-Type'), 'text/plain; charset="utf-8"', 'email is in right encoding';
+ my $plain = $mech->get_text_body_from_email($email, 1);
+ like $plain->body_str, qr/Testing \x{2013} Detail/, 'email contains encoded character from user';
+ like $plain->body_str, qr/sak p\xe5 FiksGataMi/, 'email contains encoded character from template';
+ is $plain->header('Content-Type'), 'text/plain; charset="utf-8"', 'email is in right encoding';
};
$mech->delete_user('test@example.com');
diff --git a/t/app/controller/report_import.t b/t/app/controller/report_import.t
index 26acf7790..c8cbcf412 100644
--- a/t/app/controller/report_import.t
+++ b/t/app/controller/report_import.t
@@ -114,11 +114,8 @@ subtest "Submit a correct entry" => sub {
is $mech->content, 'SUCCESS', "Got success response";
# check that we have received the email
- $mech->email_count_is(1);
- my $email = $mech->get_email;
+ my $token_url = $mech->get_link_from_email;
$mech->clear_emails_ok;
-
- my ($token_url) = $email->body =~ m{(http://\S+)};
ok $token_url, "Found a token url $token_url";
# go to the token url
@@ -257,11 +254,8 @@ subtest "Submit a correct entry (with location)" => sub {
is $mech->content, 'SUCCESS', "Got success response";
# check that we have received the email
- $mech->email_count_is(1);
- my $email = $mech->get_email;
+ my $token_url = $mech->get_link_from_email;
$mech->clear_emails_ok;
-
- my ($token_url) = $email->body =~ m{(http://\S+)};
ok $token_url, "Found a token url $token_url";
# go to the token url
@@ -356,11 +350,8 @@ subtest "Submit a correct entry (with location) to cobrand" => sub {
is $mech->content, 'SUCCESS', "Got success response";
# check that we have received the email
- $mech->email_count_is(1);
- my $email = $mech->get_email;
+ my $token_url = $mech->get_link_from_email;
$mech->clear_emails_ok;
-
- my ($token_url) = $email->body =~ m{(http://\S+)};
ok $token_url, "Found a token url $token_url";
# go to the token url
diff --git a/t/app/controller/report_new.t b/t/app/controller/report_new.t
index 2aebfa00b..6b4f40172 100644
--- a/t/app/controller/report_new.t
+++ b/t/app/controller/report_new.t
@@ -607,10 +607,9 @@ foreach my $test (
# receive token
my $email = $mech->get_email;
ok $email, "got an email";
- like $email->body, qr/confirm that you want to send your\s+report/i, "confirm the problem";
+ like $mech->get_text_body_from_email($email), qr/confirm that you want to send your\s+report/i, "confirm the problem";
- my ($url) = $email->body =~ m{(http://\S+)};
- ok $url, "extracted confirm url '$url'";
+ my $url = $mech->get_link_from_email($email);
# confirm token
$mech->get_ok($url);
@@ -949,10 +948,9 @@ subtest "test report creation for a category that is non public" => sub {
my $email = $mech->get_email;
ok $email, "got an email";
- like $email->body, qr/confirm that you want to send your\s+report/i, "confirm the problem";
+ like $mech->get_text_body_from_email($email), qr/confirm that you want to send your\s+report/i, "confirm the problem";
- my ($url) = $email->body =~ m{(http://\S+)};
- ok $url, "extracted confirm url '$url'";
+ my $url = $mech->get_link_from_email($email);
# confirm token
$mech->get_ok($url);
@@ -1145,10 +1143,9 @@ for my $test (
my $email = $mech->get_email;
ok $email, "got an email";
- like $email->body, qr/confirm that you want to send your\s+report/i, "confirm the problem";
+ like $mech->get_text_body_from_email($email), qr/confirm that you want to send your\s+report/i, "confirm the problem";
- my ($url) = $email->body =~ m{(https?://\S+)};
- ok $url, "extracted confirm url '$url'";
+ my $url = $mech->get_link_from_email($email);
# confirm token in order to update the user details
$mech->get_ok($url);
@@ -1315,17 +1312,17 @@ subtest "test Hart" => sub {
# receive token
my $email = $mech->get_email;
ok $email, "got an email";
- like $email->body, qr/to confirm that you want to send your/i, "confirm the problem";
+ my $body = $mech->get_text_body_from_email($email);
+ like $body, qr/to confirm that you want to send your/i, "confirm the problem";
# does it reference the fact that this report hasn't been sent to Hart?
if ( $test->{national} ) {
- like $email->body, qr/Hart Council is not responsible for this type/i, "mentions report hasn't gone to Hart";
+ like $body, qr/Hart Council is not responsible for this type/i, "mentions report hasn't gone to Hart";
} else {
- unlike $email->body, qr/Hart Council is not responsible for this type/i, "doesn't mention report hasn't gone to Hart";
+ unlike $body, qr/Hart Council is not responsible for this type/i, "doesn't mention report hasn't gone to Hart";
}
- my ($url) = $email->body =~ m{(http://\S+)};
- ok $url, "extracted confirm url '$url'";
+ my $url = $mech->get_link_from_email($email);
# confirm token
FixMyStreet::override_config {
@@ -1541,9 +1538,7 @@ subtest "unresponsive body handling works" => sub {
ok $report, "Found the report";
is $report->bodies_str, undef, "Report not going anywhere";
- my $email = $mech->get_email;
- ok $email, "got an email";
- like $email->body, qr/despite not being sent/i, "correct email sent";
+ like $mech->get_text_body_from_email, qr/despite not being sent/i, "correct email sent";
$user->problems->delete;
$mech->clear_emails_ok;
@@ -1577,9 +1572,7 @@ subtest "unresponsive body handling works" => sub {
ok $report, "Found the report";
is $report->bodies_str, undef, "Report not going anywhere";
- $email = $mech->get_email;
- ok $email, "got an email";
- like $email->body, qr/despite not being sent/i, "correct email sent";
+ like $mech->get_text_body_from_email, qr/despite not being sent/i, "correct email sent";
$user->problems->delete;
$mech->clear_emails_ok;
@@ -1737,10 +1730,9 @@ subtest "extra google analytics code displayed on email confirmation problem cre
my $email = $mech->get_email;
ok $email, "got an email";
- like $email->body, qr/confirm that you want to/i, "confirm the problem";
+ like $mech->get_text_body_from_email($email), qr/confirm that you want to/i, "confirm the problem";
- my ($url) = $email->body =~ m{(https?://\S+)};
- ok $url, "extracted confirm url '$url'";
+ my $url = $mech->get_link_from_email($email);
# confirm token in order to update the user details
$mech->get_ok($url);
diff --git a/t/app/controller/report_updates.t b/t/app/controller/report_updates.t
index e077a07c9..e1cd0da71 100644
--- a/t/app/controller/report_updates.t
+++ b/t/app/controller/report_updates.t
@@ -362,10 +362,11 @@ for my $test (
$mech->content_contains('Nearly done! Now check your email');
my $email = $mech->get_email;
- ok $email, "got an email";
- like $email->body, qr/confirm your update on/i, "Correct email text";
+ my $body = $mech->get_text_body_from_email($email);
+ like $body, qr/confirm your update on/i, "Correct email text";
- my ( $url, $url_token ) = $email->body =~ m{(http://\S+/C/)(\S+)};
+ my $url = $mech->get_link_from_email($email);
+ my ($url_token) = $url =~ m{/C/(\S+)};
ok $url, "extracted confirm url '$url'";
my $token = FixMyStreet::App->model('DB::Token')->find(
@@ -392,7 +393,7 @@ for my $test (
is $update->text, $details->{update}, 'update text';
is $add_alerts, $details->{add_alert} ? 1 : 0, 'do not sign up for alerts';
- $mech->get_ok( $url . $url_token );
+ $mech->get_ok( $url );
$mech->content_contains("/report/$report_id#update_$update_id");
my $unreg_user = FixMyStreet::App->model( 'DB::User' )->find( { email => $details->{rznvy} } );
@@ -1000,10 +1001,11 @@ subtest 'submit an update for a registered user, creating update by email' => su
is $user->name, 'Mr Reg', 'name unchanged';
my $email = $mech->get_email;
- ok $email, "got an email";
- like $email->body, qr/confirm your update on/i, "Correct email text";
+ my $body = $mech->get_text_body_from_email($email);
+ like $body, qr/confirm your update on/i, "Correct email text";
- my ( $url, $url_token ) = $email->body =~ m{(http://\S+/C/)(\S+)};
+ my $url = $mech->get_link_from_email($email);
+ my ($url_token) = $url =~ m{/C/(\S+)};
ok $url, "extracted confirm url '$url'";
my $token = FixMyStreet::App->model('DB::Token')->find( {
@@ -1021,7 +1023,7 @@ subtest 'submit an update for a registered user, creating update by email' => su
is $update->user->email, 'registered@example.com', 'update email';
is $update->text, 'Update from a user', 'update text';
- $mech->get_ok( $url . $url_token );
+ $mech->get_ok( $url );
$mech->content_contains("/report/$report_id#update_$update_id");
# User should have new name and password
@@ -1514,8 +1516,6 @@ for my $test (
$mech->content_contains( 'Now check your email' );
- $mech->email_count_is(1);
-
my $results = { %{ $test->{fields} }, %{ $test->{changed} }, };
my $update = $report->comments->first;
@@ -1526,10 +1526,11 @@ for my $test (
is $update->anonymous, $test->{anonymous}, 'user anonymous';
my $email = $mech->get_email;
- ok $email, "got an email";
- like $email->body, qr/confirm your update on/i, "Correct email text";
+ my $body = $mech->get_text_body_from_email($email);
+ like $body, qr/confirm your update on/i, "Correct email text";
- my ( $url, $url_token ) = $email->body =~ m{(http://\S+/C/)(\S+)};
+ my $url = $mech->get_link_from_email($email);
+ my ($url_token) = $url =~ m{/C/(\S+)};
ok $url, "extracted confirm url '$url'";
my $token = FixMyStreet::App->model('DB::Token')->find(
diff --git a/t/app/helpers/emails/html_test.html b/t/app/helpers/emails/html_test.html
new file mode 100644
index 000000000..49f7b38d3
--- /dev/null
+++ b/t/app/helpers/emails/html_test.html
@@ -0,0 +1,15 @@
+Subject: test email ☺
+
+Hello,
+
+This is a test email where foo: [% foo %].
+
+utf8: 我们应该能够无缝处理UTF8编码
+
+ indented_text
+
+It additionally has an inline image!
+<img src="[% inline_image('t/app/helpers/grey.gif') %]">
+
+Yours,
+FixMyStreet.
diff --git a/t/app/helpers/emails/html_test.txt b/t/app/helpers/emails/html_test.txt
new file mode 100644
index 000000000..692d25ccf
--- /dev/null
+++ b/t/app/helpers/emails/html_test.txt
@@ -0,0 +1,14 @@
+Subject: test email ☺
+
+Hello,
+
+This is a test email where foo: [% foo %].
+
+utf8: 我们应该能够无缝处理UTF8编码
+
+ indented_text
+
+It additionally has an inline image!
+
+Yours,
+FixMyStreet.
diff --git a/templates/email/default/test.txt b/t/app/helpers/emails/test.txt
index 1acd4b6ca..1acd4b6ca 100644
--- a/templates/email/default/test.txt
+++ b/t/app/helpers/emails/test.txt
diff --git a/t/app/helpers/send_email.t b/t/app/helpers/send_email.t
index e2c8688a8..3975002fa 100644
--- a/t/app/helpers/send_email.t
+++ b/t/app/helpers/send_email.t
@@ -2,6 +2,12 @@ use strict;
use warnings;
use utf8;
+package FixMyStreet::Cobrand::Tester;
+use parent 'FixMyStreet::Cobrand::Default';
+sub path_to_email_templates { [ FixMyStreet->path_to( 't', 'app', 'helpers', 'emails') ] }
+
+package main;
+
BEGIN {
use FixMyStreet;
FixMyStreet->test_mode(1);
@@ -28,8 +34,12 @@ $c->stash->{foo} = 'bar';
Email::Send::Test->clear;
# send the test email
-ok $c->send_email( 'test.txt', { to => 'test@recipient.com' } ),
- "sent an email";
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'tester' ],
+}, sub {
+ ok $c->send_email( 'test.txt', { to => 'test@recipient.com' } ),
+ "sent an email";
+};
# check it got templated and sent correctly
my @emails = Email::Send::Test->emails;
@@ -51,9 +61,7 @@ is_string $email->body, $expected_email->body, 'email is as expected';
subtest 'MIME attachments' => sub {
my $data = path(__FILE__)->parent->child('grey.gif')->slurp_raw;
- Email::Send::Test->clear;
- my @emails = Email::Send::Test->emails;
- is scalar(@emails), 0, "reset";
+ $mech->clear_emails_ok;
ok $c->send_email( 'test.txt',
{ to => 'test@recipient.com',
@@ -108,6 +116,20 @@ subtest 'MIME attachments' => sub {
$path->spew($email_as_string);
diag "Saved output in $path";
};
+ $mech->clear_emails_ok;
+};
+
+subtest 'Inline emails!' => sub {
+ ok $c->send_email( 'html_test.txt', { to => 'test@recipient.com' } ), "sent an email with email attachments";
+
+ my $email = $mech->get_email;
+ like $email->debug_structure, qr[
+ \+\ multipart/related.*\n
+ \ {5}\+\ multipart/alternative.*\n
+ \ {10}\+\ text/plain.*\n
+ \ {10}\+\ text/html.*\n
+ \ {5}\+\ image/gif]x;
+ $mech->clear_emails_ok;
};
done_testing;
diff --git a/t/app/model/alert_type.t b/t/app/model/alert_type.t
index e94ee8ce1..4e8817225 100644
--- a/t/app/model/alert_type.t
+++ b/t/app/model/alert_type.t
@@ -145,7 +145,7 @@ for my $test (
my @emails = $mech->get_email;
my $msg = $test->{msg};
for my $email (@emails) {
- my $body = $email->body;
+ my $body = $mech->get_text_body_from_email($email);
my $to = $email->header('To');
like $body, qr/$msg/, 'email says problem is ' . $test->{state};
@@ -193,9 +193,8 @@ subtest "correct text for title after URL" => sub {
FixMyStreet::DB->resultset('AlertType')->email_alerts();
};
- my $email = $mech->get_email;
(my $title = $report->title) =~ s/ /\\s+/;
- my $body = $email->body;
+ my $body = $mech->get_text_body_from_email;
like $body, qr#report/$report_id\s+-\s+$title#, 'email contains expected title';
};
@@ -330,8 +329,7 @@ foreach my $test (
FixMyStreet::DB->resultset('AlertType')->email_alerts();
};
- my $email = $mech->get_email;
- my $body = $email->body;
+ my $body = $mech->get_text_body_from_email;
if ( $test->{nearest} ) {
like $body, $test->{nearest}, 'correct nearest line';
@@ -439,8 +437,7 @@ subtest "check alerts from cobrand send main site url for alerts for different c
FixMyStreet::DB->resultset('AlertType')->email_alerts();
};
- my $email = $mech->get_email;
- my $body = $email->body;
+ my $body = $mech->get_text_body_from_email;
my $expected1 = FixMyStreet->config('BASE_URL') . '/report/' . $report_to_county_council->id;
my $expected3 = FixMyStreet->config('BASE_URL') . '/report/' . $report_outside_district->id;
@@ -476,8 +473,7 @@ subtest "check local alerts from cobrand send main site url for alerts for diffe
FixMyStreet::DB->resultset('AlertType')->email_alerts();
- my $email = $mech->get_email;
- my $body = $email->body;
+ my $body = $mech->get_text_body_from_email;
my $expected1 = FixMyStreet->config('BASE_URL') . '/report/' . $report_to_county_council->id;
my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker('hart')->new();
@@ -505,9 +501,7 @@ subtest "correct i18n-ed summary for state of closed" => sub {
FixMyStreet::DB->resultset('AlertType')->email_alerts();
};
- $mech->email_count_is( 1 );
- my $email = $mech->get_email;
- my $body = $email->body;
+ my $body = $mech->get_text_body_from_email;
my $msg = 'Denne rapporten er for tiden markert som lukket';
like $body, qr/$msg/, 'email says problem is closed, in Norwegian';
};
diff --git a/t/app/model/problem.t b/t/app/model/problem.t
index ea45f7356..836e8a047 100644
--- a/t/app/model/problem.t
+++ b/t/app/model/problem.t
@@ -548,24 +548,25 @@ foreach my $test ( {
like $email->header('To'), $test->{ to }, 'to line looks correct';
is $email->header('From'), sprintf('"%s" <%s>', $test->{ name }, $test->{ email } ), 'from line looks correct';
like $email->header('Subject'), qr/A Title/, 'subject line looks correct';
- like $email->body, qr/A user of FixMyStreet/, 'email body looks a bit like a report';
- like $email->body, qr/Subject: A Title/, 'more email body checking';
- like $email->body, $test->{ dear }, 'Salutation looks correct';
+ my $body = $mech->get_text_body_from_email($email);
+ like $body, qr/A user of FixMyStreet/, 'email body looks a bit like a report';
+ like $body, qr/Subject: A Title/, 'more email body checking';
+ like $body, $test->{ dear }, 'Salutation looks correct';
if ($test->{longitude}) {
- like $email->body, qr{Easting/Northing \(IE\): 297279/362371};
+ like $body, qr{Easting/Northing \(IE\): 297279/362371};
} else {
- like $email->body, qr{Easting/Northing: };
+ like $body, qr{Easting/Northing: };
}
if ( $test->{multiple} ) {
- like $email->body, qr/This email has been sent to several councils /, 'multiple body text correct';
+ like $body, qr/This email has been sent to several councils /, 'multiple body text correct';
} elsif ( $test->{ missing } ) {
- like $email->body, $test->{ missing }, 'missing body information correct';
+ like $body, $test->{ missing }, 'missing body information correct';
}
if ( $test->{url} ) {
my $id = $problem->id;
- like $email->body, qr[$test->{url}fixmystreet.com/report/$id], 'URL present is correct';
+ like $body, qr[$test->{url}fixmystreet.com/report/$id], 'URL present is correct';
}
$problem->discard_changes;
@@ -655,16 +656,18 @@ subtest 'check can turn on report sent email alerts' => sub {
like $email->header('To'),qr/City of Edinburgh Council/, 'to line looks correct';
is $email->header('From'), '"Test User" <system_user@example.com>', 'from line looks correct';
like $email->header('Subject'), qr/A Title/, 'subject line looks correct';
- like $email->body, qr/A user of FixMyStreet/, 'email body looks a bit like a report';
- like $email->body, qr/Subject: A Title/, 'more email body checking';
- like $email->body, qr/Dear City of Edinburgh Council/, 'Salutation looks correct';
+ my $body = $mech->get_text_body_from_email($email);
+ like $body, qr/A user of FixMyStreet/, 'email body looks a bit like a report';
+ like $body, qr/Subject: A Title/, 'more email body checking';
+ like $body, qr/Dear City of Edinburgh Council/, 'Salutation looks correct';
$problem->discard_changes;
ok defined( $problem->whensent ), 'whensent set';
$email = $emails[1];
like $email->header('Subject'), qr/FixMyStreet Report Sent/, 'report sent email title correct';
- like $email->body, qr/to submit your report/, 'report sent body correct';
+ $body = $mech->get_text_body_from_email($email);
+ like $body, qr/to submit your report/, 'report sent body correct';
$send_confirmation_mail_override->restore();
};
diff --git a/t/cobrand/bromley.t b/t/cobrand/bromley.t
index 6066c66b6..e39bcbe4c 100644
--- a/t/cobrand/bromley.t
+++ b/t/cobrand/bromley.t
@@ -103,10 +103,9 @@ for my $test (
};
$mech->content_contains('Nearly done! Now check your email');
- my $email = $mech->get_email;
- ok $email, "got an email";
- like $email->body, qr/This update will be sent to Bromley Council/i, "Email indicates problem will be sent to Bromley";
- unlike $email->body, qr/Note that we do not send updates to/i, "Email does not say updates aren't sent to Bromley";
+ my $body = $mech->get_text_body_from_email;
+ like $body, qr/This update will be sent to Bromley Council/i, "Email indicates problem will be sent to Bromley";
+ unlike $body, qr/Note that we do not send updates to/i, "Email does not say updates aren't sent to Bromley";
my $unreg_user = FixMyStreet::App->model( 'DB::User' )->find( { email => 'unregistered@example.com' } );
diff --git a/t/cobrand/fixamingata.t b/t/cobrand/fixamingata.t
index 0cf7a31fe..2ef3c09b4 100644
--- a/t/cobrand/fixamingata.t
+++ b/t/cobrand/fixamingata.t
@@ -46,10 +46,11 @@ FixMyStreet::override_config {
FixMyStreet::DB->resultset('Problem')->send_reports();
};
my $email = $mech->get_email;
-like $email->header('Content-Type'), qr/utf-8/, 'encoding looks okay';
+my $plain = $mech->get_text_body_from_email($email, 1);
+like $plain->header('Content-Type'), qr/utf-8/, 'encoding looks okay';
like $email->header('Subject'), qr/Ny rapport: Test Test/, 'subject looks okay';
like $email->header('To'), qr/other\@example.org/, 'to line looks correct';
-like $email->body_str, qr/V\xe4nligen,/, 'signature looks correct';
+like $plain->body_str, qr/V\xe4nligen,/, 'signature looks correct';
$mech->clear_emails_ok;
my $user =
@@ -89,10 +90,10 @@ FixMyStreet::override_config {
FixMyStreet::DB->resultset('AlertType')->email_alerts();
};
-$mech->email_count_is(1);
$email = $mech->get_email;
-like $email->header('Content-Type'), qr/utf-8/, 'encoding looks okay';
-like $email->body_str, qr/V\xe4nligen,/, 'signature looks correct';
+$plain = $mech->get_text_body_from_email($email, 1);
+like $plain->header('Content-Type'), qr/utf-8/, 'encoding looks okay';
+like $plain->body_str, qr/V\xe4nligen,/, 'signature looks correct';
$mech->clear_emails_ok;
subtest "Test ajax decimal points" => sub {
diff --git a/templates/email/bromley/questionnaire.txt b/templates/email/bromley/questionnaire.txt
index 5c0bd2957..fa80ab105 100644
--- a/templates/email/bromley/questionnaire.txt
+++ b/templates/email/bromley/questionnaire.txt
@@ -1,6 +1,6 @@
-Subject: Questionnaire about your report: '[% title %]'
+Subject: Questionnaire about your report: '[% report.title %]'
-Hello [% name %],
+Hello [% report.name %],
[% created %] ago, you reported a problem, the details of
which are at the end of this email. To keep the site
@@ -16,7 +16,7 @@ mailbox, please do not reply.
Your report was as follows:
-[% title %]
+[% report.title %]
-[% detail %]
+[% report.detail %]
diff --git a/templates/email/default/_email_bottom.html b/templates/email/default/_email_bottom.html
new file mode 100644
index 000000000..5f5fdd2b0
--- /dev/null
+++ b/templates/email/default/_email_bottom.html
@@ -0,0 +1,17 @@
+ </tr>
+ <tr>
+ <th colspan="[% email_columns %]" style="[% td_style %][% hint_style %]" class="hint">
+ [% IF email_footer %]
+ [% email_footer %]
+ [% ELSE %]
+ This email was sent automatically, from an unmonitored email account. Please do not reply to it.
+ [% END %]
+ </th>
+ </tr>
+ </table>
+ </th>
+ <th></th>
+ </tr>
+ </table>
+</body>
+</html>
diff --git a/templates/email/default/_email_comment_list.html b/templates/email/default/_email_comment_list.html
new file mode 100644
index 000000000..4fc469b6d
--- /dev/null
+++ b/templates/email/default/_email_comment_list.html
@@ -0,0 +1,14 @@
+[% FOR update IN data %]
+ <div style="[% list_item_style %]">
+ [% IF update.item_photo %]
+ <a href="[% problem_url %]">
+ <img style="[% list_item_photo_style %]" src="[% inline_image(update.get_first_image_fp) %]" alt="">
+ </a>
+ [% END %]
+ <p style="[% list_item_p_style %]">&ldquo;[% update.item_text | html %]&rdquo;</p>
+ <p style="[% list_item_date_style %]">
+ [% update.item_name | html IF update.item_name AND NOT update.item_anonymous -%]
+ [% '(' _ cobrand.prettify_dt(update.confirmed) _ ') ' IF cobrand.include_time_in_update_alerts -%]
+ </p>
+ </div>
+[% END %]
diff --git a/templates/email/default/_email_comment_list.txt b/templates/email/default/_email_comment_list.txt
new file mode 100644
index 000000000..dbf00640f
--- /dev/null
+++ b/templates/email/default/_email_comment_list.txt
@@ -0,0 +1,8 @@
+[% FOR row IN data -%]
+[% row.item_name _ ' : ' IF row.item_name AND NOT row.item_anonymous -%]
+[% '(' _ cobrand.prettify_dt(row.confirmed) _ ') ' IF cobrand.include_time_in_update_alerts -%]
+[% row.item_text %]
+
+------
+
+[% END %]
diff --git a/templates/email/default/_email_report_list.html b/templates/email/default/_email_report_list.html
new file mode 100644
index 000000000..5f7f67864
--- /dev/null
+++ b/templates/email/default/_email_report_list.html
@@ -0,0 +1,19 @@
+[% FOR report IN data %]
+<div style="[% list_item_style %]">
+[% IF report.photo %]
+ <a href="[% cobrand.base_url_for_report( report ) %]/report/[% report.id %]">
+ <img style="[% list_item_photo_style %]" src="[% inline_image(report.get_first_image_fp) %]" alt="">
+ </a>
+[% END %]
+ <h2 style="[% list_item_h2_style %]">
+ <a href="[% cobrand.base_url_for_report( report ) %]/report/[% report.id %]">
+ [%~ report.title | html ~%]
+ </a>
+ </h2>
+ <p style="[% list_item_p_style %]">[% report.detail | html %]</p>
+ <p style="[% list_item_date_style %]">
+ [% cobrand.prettify_dt( report.confirmed ) %].
+ [% report.nearest %]
+ </p>
+</div>
+[% END %]
diff --git a/templates/email/default/_email_report_list.txt b/templates/email/default/_email_report_list.txt
new file mode 100644
index 000000000..3128e2f06
--- /dev/null
+++ b/templates/email/default/_email_report_list.txt
@@ -0,0 +1,8 @@
+[% FOR report IN data -%]
+[% cobrand.base_url_for_report(report) %]/report/[% report.id %] - [% report.title %]
+
+[% report.nearest ~%]
+
+------
+
+[% END %]
diff --git a/templates/email/default/_email_settings.html b/templates/email/default/_email_settings.html
new file mode 100644
index 000000000..73f140743
--- /dev/null
+++ b/templates/email/default/_email_settings.html
@@ -0,0 +1,108 @@
+[%
+
+# The default colours.
+
+color_blue = "#0F87C5"
+color_blue_darker = "#00527C"
+color_blue_pale = "#D6E2EB"
+color_grey = "#D2D2D2"
+color_gunmetal = "#42494C"
+color_gunmetal_light = "#81959D"
+color_yellow = "#FDD008"
+color_red_dark = "#ce2626"
+color_green_dark = "#39a515"
+color_black = "#000000"
+color_white = "#ffffff"
+
+link_text_color = color_blue
+link_hover_text_color = color_blue_darker
+
+body_background_color = color_gunmetal
+body_font_family = "Helvetica, Arial, sans-serif"
+body_text_color = color_gunmetal_light
+
+header_background_color = color_yellow
+header_text_color = color_black
+header_padding = "15px 20px" # a full CSS padding property (eg: top/right/bottom/left)
+
+logo_width = "192" # pixel measurement, but without 'px' suffix
+logo_height = "35" # pixel measurement, but without 'px' suffix
+logo_font_size = "24px"
+
+primary_column_background_color = color_white
+primary_column_text_color = color_black
+secondary_column_background_color = color_blue_pale
+secondary_column_text_color = color_black
+column_divider_color = color_grey
+column_padding = "20" # a single CSS pixel measurement without the "px" suffix
+
+preview_photo_border = "1px solid rgba(0,0,0,0.1)"
+list_item_border_bottom = "1px solid $color_grey"
+
+button_border_radius = "4px" # a full CSS border-radius property
+button_background_color = color_yellow
+button_background_color_fixed = color_green_dark
+button_background_color_notfixed = color_red_dark
+button_text_color = color_black
+button_text_color_fixed = color_white
+button_text_color_notfixed = color_white
+button_font_weight = "bold"
+
+%]
+
+[% # Handy point at which your cobrand can override any of those default colours before the rest of the settings are constructed. %]
+[% TRY %][% PROCESS '_email_color_overrides.html' %][% CATCH file %][% END %]
+
+[%
+
+# Variables used inside the email templates.
+
+table_reset = 'cellspacing="0" cellpadding="0" border="0" width="100%"'
+wrapper_table = 'cellspacing="0" cellpadding="5" border="0" width="100%"'
+
+link_style = "color: $link_text_color;"
+link_hover_style = "text-decoration: none; color: $link_hover_text_color;"
+
+td_style = "font-family: $body_font_family; font-size: 16px; line-height: 21px; font-weight: normal; text-align: left;"
+
+body_style = "margin: 0; background: $body_background_color;"
+wrapper_style = "$td_style background: $body_background_color;"
+
+hint_style = "padding: ${ column_padding }px 0; color: $body_text_color; font-size: 12px; line-height: 18px;"
+header_style = "padding: $header_padding; background: $header_background_color; color: $header_text_color;"
+
+only_column_style = "padding: ${ column_padding }px; vertical-align: top; background-color: $primary_column_background_color; color: $primary_column_text_color;"
+primary_column_style = "vertical-align: top; width: 50%; background-color: $primary_column_background_color; color: $primary_column_text_color;"
+secondary_column_style = "vertical-align: top; width: 50%; background-color: $secondary_column_background_color; color: $secondary_column_text_color; border-left: 1px solid $column_divider_color;"
+
+# Use these to add padding inside primary and secondary columns.
+start_padded_box = '<table cellspacing="0" cellpadding="' _ column_padding _ '" border="0" width="100%"><tr><th style="' _ td_style _ '">'
+end_padded_box = '</th></tr></table>'
+
+logo_style = "font-size: $logo_font_size; line-height: ${ logo_height }px; vertical-align: middle;"
+h1_style = "margin: 0 0 20px 0; font-size: 28px; line-height: 30px;"
+h2_style = "margin: 0 0 20px 0; font-size: 21px; line-height: 24px;"
+p_style = "margin: 0 0 0.8em 0;"
+secondary_p_style = "font-size: 14px; line-height: 20px; $p_style"
+preview_photo_style = "display: block; margin: 0 0 1em 1em; border: $preview_photo_border;"
+map_image_style = "display: block; width: 100%; height: auto;"
+
+list_item_style = "padding-bottom: 20px; margin-bottom: 20px; border-bottom: $list_item_border_bottom;"
+list_item_h2_style = "margin: 0 0 16px 0; font-size: 21px; line-height: 24px;"
+list_item_p_style = "margin: 0 0 16px 0;"
+list_item_date_style = "font-size: 14px; line-height: 20px; margin: 0; color: $color_gunmetal_light;"
+list_item_photo_style = "float: right; margin: 0 0 1em 1em; border: none;"
+
+contact_meta_style = "padding: 15px ${ column_padding }px; vertical-align: top; background-color: $secondary_column_background_color; border-bottom: 1px solid $column_divider_color;"
+contact_th_style = "vertical-align: top; padding: 0.4em 1em 0 0; white-space: nowrap; text-align: left;"
+contact_td_style = "vertical-align: top; padding: 0.4em 0 0.4em 0; width: 100%;"
+
+# The below is so the buttons work okay in Outlook: https://litmus.com/blog/a-guide-to-bulletproof-buttons-in-email-design
+button_style = "display: inline-block; border: 10px solid $button_background_color; border-width: 10px 15px; border-radius: $button_border_radius; background-color: $button_background_color; color: $button_text_color; font-size: 18px; line-height: 21px; font-weight: $button_font_weight; text-decoration: underline;"
+fixed_button_style = "$button_style border-color: $button_background_color_fixed; background-color: $button_background_color_fixed; color: $button_text_color_fixed; margin: 0 0.2em;"
+notfixed_button_style = "$button_style border-color: $button_background_color_notfixed; background-color: $button_background_color_notfixed; color: $button_text_color_notfixed; margin: 0 0.2em;"
+
+%]
+
+[% # Handy point at which your cobrand can override any of the constructed variables before they are sent to the templates. %]
+[% TRY %][% PROCESS '_email_setting_overrides.html' %][% CATCH file %][% END %]
diff --git a/templates/email/default/_email_top.html b/templates/email/default/_email_top.html
new file mode 100644
index 000000000..c599142b7
--- /dev/null
+++ b/templates/email/default/_email_top.html
@@ -0,0 +1,64 @@
+[%
+ # The cobrand might come to us a variety of ways
+ # Alert sets cobrand directly, questionnaire/submit have it in report, otherwise web
+ cobrand = cobrand.moniker OR report.cobrand OR c.cobrand.moniker;
+
+ IF cobrand == 'fixmystreet';
+ SET img_dir = 'fixmystreet.com';
+ ELSE;
+ SET img_dir = cobrand;
+ END -%]
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <style type="text/css">
+ [% # Styles here will be applied by everything except Gmail.com %]
+ a { [% link_style %] }
+ a:hover { [% link_hover_style %] }
+
+ body, table, td, th {
+ font-family: [% body_font_family %] !important;
+ }
+
+ [% # 550px = 5+5+5+520+5+5+5 %]
+ @media only screen and (max-width: 549px) {
+ #main {
+ min-width: 0 !important;
+ }
+ }
+
+ @media only screen and (max-width: 500px) {
+ #main table, #main tr, #main th {
+ display: block !important;
+ }
+
+ #primary_column,
+ #secondary_column {
+ width: auto !important;
+ }
+ }
+ </style>
+</head>
+<body style="[% body_style %]">
+ <table [% wrapper_table %] style="[% wrapper_style %]">
+ <tr>
+ <th></th>
+ <th width="620" style="[% td_style %] min-width: 520px;" id="main">
+ <table [% table_reset %]>
+ <tr>
+ <th colspan="[% email_columns %]" style="[% td_style %][% hint_style %]" class="hint">
+ [% email_summary %]
+ </th>
+ </tr>
+ <tr>
+ <th colspan="[% email_columns %]" style="[% td_style %][% header_style %]">
+ [%~ IF file_exists("web/cobrands/${ img_dir }/images/email-logo.gif") ~%]
+ <img src="[% inline_image('web/cobrands/' _ img_dir _ '/images/email-logo.gif') %]" width="[% logo_width %]" height="[% logo_height %]" alt="[% site_name %]" style="[% logo_style %]"/>
+ [%~ ELSE ~%]
+ <span style="[% logo_style %]">[% site_name %]</span>
+ [% END %]
+ </th>
+ </tr>
+ <tr>
diff --git a/templates/email/default/alert-confirm.html b/templates/email/default/alert-confirm.html
new file mode 100644
index 000000000..9abfea644
--- /dev/null
+++ b/templates/email/default/alert-confirm.html
@@ -0,0 +1,21 @@
+[%
+
+email_summary = "You need to confirm your " _ site_name _ " alert settings before we can send you alerts.";
+email_columns = 1;
+
+PROCESS '_email_settings.html';
+
+INCLUDE '_email_top.html';
+
+%]
+
+<th style="[% td_style %][% only_column_style %]">
+ <h1 style="[% h1_style %]">Please confirm your email alert&nbsp;settings</h1>
+ <p style="[% p_style %]">Please click on the link below to confirm that you want to receive email alerts within your chosen area.</p>
+ <p style="margin: 20px auto; text-align: center">
+ <a style="[% button_style %]" href="[% token_url %]">Yes, send me alerts</a>
+ </p>
+ <p style="[% p_style %]">If you no longer wish to subscribe to alerts in this area, just ignore this email.</p>
+</th>
+
+[% INCLUDE '_email_bottom.html' %]
diff --git a/templates/email/default/alert-problem-area.html b/templates/email/default/alert-problem-area.html
new file mode 100644
index 000000000..a18933519
--- /dev/null
+++ b/templates/email/default/alert-problem-area.html
@@ -0,0 +1,19 @@
+[%
+
+email_summary = "New reports in " _ area_name;
+email_columns = 1;
+
+PROCESS '_email_settings.html';
+
+INCLUDE '_email_top.html';
+
+%]
+
+<th style="[% td_style %][% only_column_style %]">
+ <h1 style="[% h1_style %]">New reports in [% area_name %]</h1>
+ [% INCLUDE '_email_report_list.html' %]
+
+ <p style="[% p_style %]"><a href="[% unsubscribe_url %]">Unsubscribe from alerts about new reports in this area</a></p>
+</th>
+
+[% INCLUDE '_email_bottom.html' %]
diff --git a/templates/email/default/alert-problem-area.txt b/templates/email/default/alert-problem-area.txt
index 548befe2f..7bf013cda 100644
--- a/templates/email/default/alert-problem-area.txt
+++ b/templates/email/default/alert-problem-area.txt
@@ -3,7 +3,7 @@ Subject: New [% site_name %] reports in [% area_name %]
The following new [% site_name %] reports have been added in
the [% area_name %] area:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
[% signature %]
diff --git a/templates/email/default/alert-problem-council.html b/templates/email/default/alert-problem-council.html
new file mode 100644
index 000000000..867182e09
--- /dev/null
+++ b/templates/email/default/alert-problem-council.html
@@ -0,0 +1,19 @@
+[%
+
+email_summary = "New reports to ${ area_name }";
+email_columns = 1;
+
+PROCESS '_email_settings.html';
+
+INCLUDE '_email_top.html';
+
+%]
+
+<th style="[% td_style %][% only_column_style %]">
+ <h1 style="[% h1_style %]">New reports to [% area_name %]</h1>
+ [% INCLUDE '_email_report_list.html' %]
+
+ <p style="[% p_style %]"><a href="[% unsubscribe_url %]">Unsubscribe from alerts about new reports to this area</a></p>
+</th>
+
+[% INCLUDE '_email_bottom.html' %]
diff --git a/templates/email/default/alert-problem-council.txt b/templates/email/default/alert-problem-council.txt
index abb704870..ecf671e69 100644
--- a/templates/email/default/alert-problem-council.txt
+++ b/templates/email/default/alert-problem-council.txt
@@ -3,7 +3,7 @@ Subject: New [% site_name %] reports to [% area_name %]
The following new [% site_name %] reports have been sent to
[% area_name %]:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
[% signature %]
diff --git a/templates/email/default/alert-problem-nearby.html b/templates/email/default/alert-problem-nearby.html
new file mode 100644
index 000000000..78af4cd84
--- /dev/null
+++ b/templates/email/default/alert-problem-nearby.html
@@ -0,0 +1,19 @@
+[%
+
+email_summary = "New reports within your area";
+email_columns = 1;
+
+PROCESS '_email_settings.html';
+
+INCLUDE '_email_top.html';
+
+%]
+
+<th style="[% td_style %][% only_column_style %]">
+ <h1 style="[% h1_style %]">New reports within your area</h1>
+ [% INCLUDE '_email_report_list.html' %]
+
+ <p style="[% p_style %]"><a href="[% unsubscribe_url %]">Unsubscribe from alerts about new reports in this area</a></p>
+</th>
+
+[% INCLUDE '_email_bottom.html' %]
diff --git a/templates/email/default/alert-problem-nearby.txt b/templates/email/default/alert-problem-nearby.txt
index 1a4f713e8..fdffca5b5 100644
--- a/templates/email/default/alert-problem-nearby.txt
+++ b/templates/email/default/alert-problem-nearby.txt
@@ -3,7 +3,7 @@ Subject: New reports on [% site_name %]
The following [% site_name %] reports have been made within the area
you specified:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
[% signature %]
diff --git a/templates/email/default/alert-problem-ward.html b/templates/email/default/alert-problem-ward.html
new file mode 100644
index 000000000..459bd173c
--- /dev/null
+++ b/templates/email/default/alert-problem-ward.html
@@ -0,0 +1,19 @@
+[%
+
+email_summary = "New reports to " _ area_name _ " within " _ ward_name;
+email_columns = 1;
+
+PROCESS '_email_settings.html';
+
+INCLUDE '_email_top.html';
+
+%]
+
+<th style="[% td_style %][% only_column_style %]">
+ <h1 style="[% h1_style %]">New reports to [% area_name %] within [% ward_name %]</h1>
+ [% INCLUDE '_email_report_list.html' %]
+
+ <p style="[% p_style %]"><a href="[% unsubscribe_url %]">Unsubscribe from alerts about new reports in this area</a></p>
+</th>
+
+[% INCLUDE '_email_bottom.html' %]
diff --git a/templates/email/default/alert-problem-ward.txt b/templates/email/default/alert-problem-ward.txt
index e757a2963..edbed6087 100644
--- a/templates/email/default/alert-problem-ward.txt
+++ b/templates/email/default/alert-problem-ward.txt
@@ -3,7 +3,7 @@ Subject: New [% site_name %] reports to [% area_name %] within [% ward_name %]
The following new [% site_name %] reports have been sent to [% area_name %]
within [% ward_name %]:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
[% signature %]
diff --git a/templates/email/default/alert-problem.html b/templates/email/default/alert-problem.html
new file mode 100644
index 000000000..bff65e57a
--- /dev/null
+++ b/templates/email/default/alert-problem.html
@@ -0,0 +1,19 @@
+[%
+
+email_summary = "New reports on " _ site_name;
+email_columns = 1;
+
+PROCESS '_email_settings.html';
+
+INCLUDE '_email_top.html';
+
+%]
+
+<th style="[% td_style %][% only_column_style %]">
+ <h1 style="[% h1_style %]">New reports on [% site_name %]</h1>
+ [% INCLUDE '_email_report_list.html' %]
+
+ <p style="[% p_style %]"><a href="[% unsubscribe_url %]">Unsubscribe from alerts about new [% site_name %] reports</a></p>
+</th>
+
+[% INCLUDE '_email_bottom.html' %]
diff --git a/templates/email/default/alert-problem.txt b/templates/email/default/alert-problem.txt
index 7163ee7bf..87ae1f037 100644
--- a/templates/email/default/alert-problem.txt
+++ b/templates/email/default/alert-problem.txt
@@ -2,7 +2,7 @@ Subject: New reports on [% site_name %]
The following new reports have been added to [% site_name %]:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
[% signature %]
diff --git a/templates/email/default/alert-update.html b/templates/email/default/alert-update.html
new file mode 100644
index 000000000..0a8aadab7
--- /dev/null
+++ b/templates/email/default/alert-update.html
@@ -0,0 +1,31 @@
+[%
+
+title = title | html;
+email_summary = "New updates on &ldquo;" _ title _ "&rdquo;";
+email_columns = 2;
+
+PROCESS '_email_settings.html';
+
+INCLUDE '_email_top.html';
+
+%]
+
+<th style="[% td_style %][% primary_column_style %]" id="primary_column">
+ [% start_padded_box %]
+ <h1 style="[% h1_style %]">New updates on <a href="[% problem_url %]">[% title %]</a></h1>
+ [% INCLUDE '_email_comment_list.html' %]
+ <p style="[% p_style %]"><a href="[% unsubscribe_url %]">Unsubscribe from alerts about this report</a></p>
+ [% end_padded_box %]
+</th>
+<th style="[% td_style %][% secondary_column_style %]" id="secondary_column">
+ <img style="[% map_image_style %]" src="[% inline_image(report.static_map, 'map.jpeg') %]" width="310" height="200" alt="">
+ [% start_padded_box %]
+ [% IF photo %]
+ <img style="[% preview_photo_style %]" src="[% inline_image(report.get_first_image_fp) %]" alt="" align="right">
+ [% END %]
+ <h2 style="[% h2_style %]">[% title | html %]</h2>
+ <p style="[% secondary_p_style %]">[% detail | html %]</p>
+ [% end_padded_box %]
+</th>
+
+[% INCLUDE '_email_bottom.html' %]
diff --git a/templates/email/default/alert-update.txt b/templates/email/default/alert-update.txt
index 7722d2c1f..3bf9e4377 100644
--- a/templates/email/default/alert-update.txt
+++ b/templates/email/default/alert-update.txt
@@ -5,11 +5,12 @@ You asked us to send you an email every time an update was made to the
The following updates have been left on this report:
-[% data %]
+[% INCLUDE '_email_comment_list.txt' %]
[% state_message %]
If you would like to view or reply to these updates, please visit the following URL:
+
[% problem_url %]
This email was sent automatically, from an unmonitored email account - so
diff --git a/templates/email/default/change_email.html b/templates/email/default/change_email.html
new file mode 100644
index 000000000..965741eed
--- /dev/null
+++ b/templates/email/default/change_email.html
@@ -0,0 +1,22 @@
+[%
+
+email_summary = "Click this link to change your " _ site_name _ " email address";
+email_columns = 1;
+
+PROCESS '_email_settings.html';
+
+INCLUDE '_email_top.html';
+
+%]
+
+<th style="[% td_style %][% only_column_style %]">
+ <h1 style="[% h1_style %]">Change your [% site_name %] email&nbsp;address</h1>
+ <p style="[% p_style %]">Please click on the link below to confirm you wish to update your
+email address on [% site_name %].</p>
+ <p style="margin: 20px auto; text-align: center">
+ <a style="[% button_style %]" href="[% c.uri_for_action( 'auth/token', token ) %]">Change my email address</a>
+ </p>
+ <p style="[% p_style %]">If you no longer wish to change your email address, just ignore this email.</p>
+</th>
+
+[% INCLUDE '_email_bottom.html' %]
diff --git a/templates/email/default/change_email.txt b/templates/email/default/change_email.txt
index 0c5aeac14..8db6b105e 100644
--- a/templates/email/default/change_email.txt
+++ b/templates/email/default/change_email.txt
@@ -1,7 +1,7 @@
-Subject: Updating your [% INCLUDE 'site-name.txt' | trim %] email address
+Subject: Updating your [% site_name %] email address
Please click on the link below to confirm you wish to update your
-email address on [% INCLUDE 'site-name.txt' | trim %].
+email address on [% site_name %].
[% c.uri_for_action( 'auth/token', token ) %]
diff --git a/templates/email/default/contact.html b/templates/email/default/contact.html
new file mode 100644
index 000000000..81f9cb080
--- /dev/null
+++ b/templates/email/default/contact.html
@@ -0,0 +1,45 @@
+[%
+
+subject_html = subject | html;
+name = form_name | html;
+email_summary = "&ldquo;" _ subject_html _ "&rdquo; &ndash; Message from " _ name _ " on " _ host;
+email_columns = 1;
+
+PROCESS '_email_settings.html';
+
+INCLUDE '_email_top.html';
+
+%]
+
+<th style="[% td_style %][% contact_meta_style %]">
+ <table [% table_reset %]>
+ <tr>
+ <th style="[% contact_th_style %]">From</th>
+ <td style="[% contact_td_style %]">[% name %] &lt;<a href="mailto:[% em | html %]">[% em | html %]</a>&gt;</td>
+ </tr>
+ <tr>
+ <th style="[% contact_th_style %]">IP address</th>
+ <td style="[% contact_td_style %]">[% ip %]</td>
+ </tr>
+ <tr>
+ <th style="[% contact_th_style %]">To</th>
+ <td style="[% contact_td_style %]">[% host %] administrators</td>
+ </tr>
+ </table>
+</th>
+</tr>
+
+<tr>
+<th style="[% td_style %][% only_column_style %]">
+ <h1 style="[% h1_style %]">[% subject | html %]</h1>
+ <p style="[% p_style %]">[% message | html %]</p>
+ [% IF complaint %]
+ <p style="[% secondary_p_style %]">
+ [% complaint | html %]
+ - <a href="[% problem_url %]">Report</a>
+ - <a href="[% admin_url %]">Admin</a>
+ </p>
+ [% END %]
+</th>
+
+[% INCLUDE '_email_bottom.html' %]
diff --git a/templates/email/default/contact.txt b/templates/email/default/contact.txt
index 59a778ad5..6e1fd5ac9 100644
--- a/templates/email/default/contact.txt
+++ b/templates/email/default/contact.txt
@@ -2,4 +2,8 @@ Subject: FMS message: [% subject %]
[% message %]
+[% IF complaint %]
+[ [% complaint %] - [% problem_url %] - [% admin_url %] ]
+[% END %]
+
[ Sent by contact.cgi on [% host %]. IP address [% ip %] ]
diff --git a/templates/email/default/login.html b/templates/email/default/login.html
new file mode 100644
index 000000000..b22838d4e
--- /dev/null
+++ b/templates/email/default/login.html
@@ -0,0 +1,22 @@
+[%
+
+email_summary = "Click this link to confirm your email address and log into " _ site_name;
+email_columns = 1;
+
+PROCESS '_email_settings.html';
+
+INCLUDE '_email_top.html';
+
+%]
+
+<th style="[% td_style %][% only_column_style %]">
+ <h1 style="[% h1_style %]">Thanks for using [% site_name %]</h1>
+ <p style="[% p_style %]">Please click on the link below to confirm your email address and log into [% site_name %].</p>
+ <p style="margin: 20px auto; text-align: center">
+ <a style="[% button_style %]" href="[% c.uri_for_action( 'auth/token', token ) %]">Yes, this is my address</a>
+ </p>
+ <p style="[% p_style %]">Once you&rsquo;ve done this, you&rsquo;ll be able to view and manage all reports and
+updates you&rsquo;ve made from the &ldquo;Your account&rdquo; menu on [% site_name %].</p>
+</th>
+
+[% INCLUDE '_email_bottom.html' %]
diff --git a/templates/email/default/login.txt b/templates/email/default/login.txt
index 360eb8512..9a57c4fd9 100644
--- a/templates/email/default/login.txt
+++ b/templates/email/default/login.txt
@@ -1,11 +1,11 @@
-Subject: Your [% INCLUDE 'site-name.txt' | trim %] account details
+Subject: Your [% site_name %] account details
Please click on the link below to confirm your email address.
[% c.uri_for_action( 'auth/token', token ) %]
Once you've done this, you'll be able to view and manage all reports and
-updates you've made on [% INCLUDE 'site-name.txt' | trim %].
+updates you've made on [% site_name %].
[% INCLUDE 'signature.txt' %]
diff --git a/templates/email/default/problem-confirm-not-sending.html b/templates/email/default/problem-confirm-not-sending.html
new file mode 100644
index 000000000..6b60afbcf
--- /dev/null
+++ b/templates/email/default/problem-confirm-not-sending.html
@@ -0,0 +1,36 @@
+[%
+
+email_summary = "You need to confirm your " _ site_name _ " report before it can be made public.";
+email_columns = 2;
+
+PROCESS '_email_settings.html';
+
+INCLUDE '_email_top.html';
+
+%]
+
+<th style="[% td_style %][% primary_column_style %]" id="primary_column">
+ [% start_padded_box %]
+ <h1 style="[% h1_style %]">Please confirm your&nbsp;report</h1>
+ <p style="[% p_style %]">Please click on the link below to confirm that you want your report to appear
+on [% site_name %], despite not being sent to the
+council.</p>
+ <p style="[% p_style %]">Your report will also appear on the [% site_name %] website.</p>
+ <p style="margin: 20px auto; text-align: center">
+ <a style="[% button_style %]" href="[% token_url %]">Yes, publish my report</a>
+ </p>
+ <p style="[% p_style %]">If you no longer wish to publish this report, please take no further action.</p>
+ [% end_padded_box %]
+</th>
+<th style="[% td_style %][% secondary_column_style %]" id="secondary_column">
+ <img style="[% map_image_style %]" src="[% inline_image(report.static_map, 'map.jpeg') %]" width="310" height="200" alt="">
+ [% start_padded_box %]
+ [% IF report.photo %]
+ <img style="[% preview_photo_style %]" src="[% inline_image(report.get_first_image_fp) %]" alt="" align="right">
+ [% END %]
+ <h2 style="[% h2_style %]">[% report.title | html %]</h2>
+ <p style="[% secondary_p_style %]">[% report.detail | html %]</p>
+ [% end_padded_box %]
+</th>
+
+[% INCLUDE '_email_bottom.html' %]
diff --git a/templates/email/default/problem-confirm-not-sending.txt b/templates/email/default/problem-confirm-not-sending.txt
index 2443805bb..d27b47677 100644
--- a/templates/email/default/problem-confirm-not-sending.txt
+++ b/templates/email/default/problem-confirm-not-sending.txt
@@ -1,10 +1,9 @@
-Subject: Confirm your report on [% INCLUDE 'site-name.txt' | trim %]
+Subject: Confirm your report on [% site_name %]
Hello [% report.name %],
Please click on the link below to confirm that you want your report to appear
-on [% INCLUDE 'site-name.txt' | trim %], despite not being sent to the
-council:
+on [% site_name %], despite not being sent to the council:
[% token_url %]
@@ -22,7 +21,7 @@ And details:
If you no longer wish your report to be displayed on the site, please take no
further action.
-Thank you for supporting [% INCLUDE 'site-name.txt' | trim %].
+Thank you for supporting [% site_name %].
diff --git a/templates/email/default/problem-confirm.html b/templates/email/default/problem-confirm.html
new file mode 100644
index 000000000..cfb199df6
--- /dev/null
+++ b/templates/email/default/problem-confirm.html
@@ -0,0 +1,39 @@
+[%
+
+email_summary = "You need to confirm your " _ site_name _ " report before it can be sent to ${ report.body }.";
+email_columns = 2;
+
+PROCESS '_email_settings.html';
+
+INCLUDE '_email_top.html';
+
+%]
+
+<th style="[% td_style %][% primary_column_style %]" id="primary_column">
+ [% start_padded_box %]
+ <h1 style="[% h1_style %]">Please confirm your&nbsp;report</h1>
+ <p style="[% p_style %]">Please click on the link below to confirm that you want to send your report to [% report.body %].
+[% IF c.cobrand.is_council && !c.cobrand.owns_problem( report ) %]
+Please note that [% c.cobrand.council_name %] is not responsible for this type
+of problem, so it will instead be sent to [% report.body %].
+[% END %]
+ </p>
+ <p style="[% p_style %]">Your report will also appear on the [% site_name %] website.</p>
+ <p style="margin: 20px auto; text-align: center">
+ <a style="[% button_style %]" href="[% token_url %]">Yes, send my report</a>
+ </p>
+ <p style="[% p_style %]">If you no longer wish to send this report, please take no further action.</p>
+ [% end_padded_box %]
+</th>
+<th style="[% td_style %][% secondary_column_style %]" id="secondary_column">
+ <img style="[% map_image_style %]" src="[% inline_image(report.static_map, 'map.jpeg') %]" width="310" height="200" alt="">
+ [% start_padded_box %]
+ [% IF report.photo %]
+ <img style="[% preview_photo_style %]" src="[% inline_image(report.get_first_image_fp) %]" alt="" align="right">
+ [% END %]
+ <h2 style="[% h2_style %]">[% report.title | html %]</h2>
+ <p style="[% secondary_p_style %]">[% report.detail | html %]</p>
+ [% end_padded_box %]
+</th>
+
+[% INCLUDE '_email_bottom.html' %]
diff --git a/templates/email/default/problem-confirm.txt b/templates/email/default/problem-confirm.txt
index de671a284..9d0767671 100644
--- a/templates/email/default/problem-confirm.txt
+++ b/templates/email/default/problem-confirm.txt
@@ -1,9 +1,9 @@
-Subject: Confirm your report on [% INCLUDE 'site-name.txt' | trim %]
+Subject: Confirm your report on [% site_name %]
Hello [% report.name %],
Please click on the link below to confirm that you want to send your report to
-[% report.body %]. Note that your report will also appear on the [% INCLUDE 'site-name.txt' | trim %]
+[% report.body %]. Note that your report will also appear on the [% site_name %]
website:
[% token_url %]
@@ -24,7 +24,7 @@ And details:
If you no longer wish to send this report, please take no further action.
-Thank you for submitting a report through [% INCLUDE 'site-name.txt' | trim %].
+Thank you for submitting a report through [% site_name %].
diff --git a/templates/email/default/problem-moderated.html b/templates/email/default/problem-moderated.html
new file mode 100644
index 000000000..b3dd2d353
--- /dev/null
+++ b/templates/email/default/problem-moderated.html
@@ -0,0 +1,38 @@
+[%
+
+email_summary = "Your report on " _ site_name _ " has been moderated.";
+email_columns = 2;
+
+PROCESS '_email_settings.html';
+
+INCLUDE '_email_top.html';
+
+%]
+
+<th style="[% td_style %][% primary_column_style %]" id="primary_column">
+ [% start_padded_box %]
+ <h1 style="[% h1_style %]">Your report has been&nbsp;moderated</h1>
+[% IF types == 'hide' -%]
+ <p style="[% p_style %]">The report has been hidden from the site.</p>
+[% ELSE %]
+ <p style="[% p_style %]">The following data has been changed: <strong>[% types %]</strong></p>
+ <p style="margin: 20px auto; text-align: center">
+ <a style="[% button_style %]" href="[% report_uri %]">View my report</a>
+ </p>
+[% END -%]
+ <p style="[% p_style %]">If you do not think that this report should have been moderated, you may contact
+the team at <a href="[% report_complain_uri %]">[% report_complain_uri %]</a></p>
+ [% end_padded_box %]
+</th>
+<th style="[% td_style %][% secondary_column_style %]" id="secondary_column">
+ <img style="[% map_image_style %]" src="[% inline_image(problem.static_map, 'map.jpeg') %]" width="310" height="200" alt="">
+ [% start_padded_box %]
+ [% IF problem.photo %]
+ <img style="[% preview_photo_style %]" src="[% inline_image(problem.get_first_image_fp) %]" alt="" align="right">
+ [% END %]
+ <h2 style="[% h2_style %]">[% problem.moderation_original_data.title | html %]</h2>
+ <p style="[% secondary_p_style %]">[% problem.moderation_original_data.detail | html %]</p>
+ [% end_padded_box %]
+</th>
+
+[% INCLUDE '_email_bottom.html' %]
diff --git a/templates/email/default/problem-moderated.txt b/templates/email/default/problem-moderated.txt
index 70dc5ad11..f69004be2 100644
--- a/templates/email/default/problem-moderated.txt
+++ b/templates/email/default/problem-moderated.txt
@@ -1,8 +1,8 @@
-Subject: Your report on [% INCLUDE 'site-name.txt' | trim %] has been moderated
+Subject: Your report on [% site_name %] has been moderated
Hello [% user.name %],
-Your report on [% INCLUDE 'site-name.txt' | trim %] has been moderated.
+Your report on [% site_name %] has been moderated.
[% IF types == 'hide' -%]
The report has been hidden from the site.
@@ -28,8 +28,7 @@ You can see the report at [% report_uri %]
If you do not think that this report should have been moderated, you may contact
the team at [% report_complain_uri %]
-Thank you for submitting a report through [% INCLUDE 'site-name.txt' | trim %].
-
+Thank you for submitting a report through [% site_name %].
[% INCLUDE 'signature.txt' %]
diff --git a/templates/email/default/questionnaire.html b/templates/email/default/questionnaire.html
new file mode 100644
index 000000000..814e5a658
--- /dev/null
+++ b/templates/email/default/questionnaire.html
@@ -0,0 +1,36 @@
+[%
+
+title = report.title | html;
+email_summary = "Got a minute spare? Let us know what happened to your " _ site_name _ " report about ${ title }.";
+email_columns = 2;
+
+PROCESS '_email_settings.html';
+
+INCLUDE '_email_top.html';
+
+%]
+
+<th style="[% td_style %][% primary_column_style %]" id="primary_column">
+ [% start_padded_box %]
+ <h1 style="[% h1_style %]">Has your problem been&nbsp;fixed?</h1>
+ <p style="[% p_style %]">[% created %] ago, you reported a problem using [% site_name %].</p>
+ <p style="[% p_style %]">Help us keep [% site_name %] up to date by letting us know whether the problem has been fixed yet:</p>
+ <p style="margin: 20px auto; text-align: center">
+ <a style="[% fixed_button_style %]" href="[% url %]">Fixed</a>
+ <a style="[% notfixed_button_style %]" href="[% url %]">Not fixed</a>
+ </p>
+ <p style="[% p_style %]">Thank you! Your feedback is really valuable.</p>
+ [% end_padded_box %]
+</th>
+<th style="[% td_style %][% secondary_column_style %]" id="secondary_column">
+ <img style="[% map_image_style %]" src="[% inline_image(report.static_map, 'map.jpeg') %]" width="310" height="200" alt="">
+ [% start_padded_box %]
+ [% IF report.photo %]
+ <img style="[% preview_photo_style %]" src="[% inline_image(report.get_first_image_fp) %]" alt="" align="right">
+ [% END %]
+ <h2 style="[% h2_style %]">[% title %]</h2>
+ <p style="[% secondary_p_style %]">[% report.detail | html %]</p>
+ [% end_padded_box %]
+</th>
+
+[% INCLUDE '_email_bottom.html' %]
diff --git a/templates/email/default/questionnaire.txt b/templates/email/default/questionnaire.txt
index 80b556c41..95acca6ee 100644
--- a/templates/email/default/questionnaire.txt
+++ b/templates/email/default/questionnaire.txt
@@ -1,6 +1,6 @@
-Subject: Questionnaire about your [% site_name %] report: '[% title %]'
+Subject: Questionnaire about your [% site_name %] report: '[% report.title %]'
-Hello [% name %],
+Hello [% report.name %],
[% created %] ago, you reported a problem using [% site_name %].
@@ -16,9 +16,9 @@ updating the status of your problem:
Your report was as follows:
-[% title %]
+[% report.title %]
-[% detail %]
+[% report.detail %]
This email was sent automatically, from an unmonitored email account - so
please do not reply to it.
diff --git a/templates/email/default/submit.html b/templates/email/default/submit.html
new file mode 100644
index 000000000..e5cd8f203
--- /dev/null
+++ b/templates/email/default/submit.html
@@ -0,0 +1,63 @@
+[%
+
+email_summary = "A new problem in your area has been reported by a " _ site_name _ " user.";
+email_footer = "If there is a more appropriate email address for messages about " _ category_footer _ ", please let us know. This will help improve the service for local people. We also welcome any other feedback you may have.";
+email_columns = 2;
+
+PROCESS '_email_settings.html';
+
+INCLUDE '_email_top.html';
+
+%]
+
+<th style="[% td_style %][% primary_column_style %]" id="primary_column">
+ [% start_padded_box %]
+ <h1 style="[% h1_style %]">New problem in your&nbsp;area</h1>
+ <p style="[% p_style %]">[% missing %][% multiple %]A user of [% site_name %] has submitted the following report
+of a local problem that they believe might require your attention.</p>
+
+ <p style="margin: 20px auto; text-align: center">
+ <a style="[% button_style %]" href="[% url %]">Show full report</a>
+ </p>
+ <h2 style="[% h2_style %] margin: 30px 0 10px 0">Reported by:</h2>
+ <table [% table_reset %]>
+ <tr>
+ <th style="[% contact_th_style %]">Name</th>
+ <td style="[% contact_td_style %]">[% name | html %]</td>
+ </tr>
+ <tr>
+ <th style="[% contact_th_style %]">Email</th>
+ <td style="[% contact_td_style %]"><a href="mailto:[% email | html %]">[% email | html %]</a></td>
+ </tr>
+ [% IF phone %]
+ <tr>
+ <th style="[% contact_th_style %]">Phone</th>
+ <td style="[% contact_td_style %]"><a href="tel:[% phone | html %]">[% phone | html %]</a></td>
+ </tr>
+ [% END %]
+ </table>
+ <p style="[% p_style %] margin-top: 0.5em;">Replies to this message will go directly to [% name | html %], the user who reported the problem.</p>
+ [% end_padded_box %]
+</th>
+<th style="[% td_style %][% secondary_column_style %]" id="secondary_column">
+ <img style="[% map_image_style %]" src="[% inline_image(report.static_map, 'map.jpeg') %]" width="310" height="200" alt="">
+ [% start_padded_box %]
+ [% IF has_photo %]
+ <img style="[% preview_photo_style %]" src="[% inline_image(report.get_first_image_fp) %]" alt="" align="right">
+ [% END %]
+ <h2 style="[% h2_style %]">[% title | html %]</h2>
+ [% IF category_line %]
+ <p style="[% secondary_p_style %]">[% category | html %]</p>
+ [% END %]
+ <p style="[% secondary_p_style %]">[% detail | html %]</p>
+ <p style="[% secondary_p_style %]">
+ <strong>Location:</strong>
+ <a href="[% osm_url %]" title="View OpenStreetMap of this location">
+ [%~ latitude %], [% longitude ~%]
+ </a>
+ [% IF closest_address %]<br>[% closest_address | trim | replace("\n\n", "<br>") %][% END %]
+ </p>
+ [% end_padded_box %]
+</th>
+
+[% INCLUDE '_email_bottom.html' %]
diff --git a/templates/email/default/update-confirm-donotsend.txt b/templates/email/default/update-confirm-donotsend.txt
index bbeffef6e..c9fdef5ea 100644
--- a/templates/email/default/update-confirm-donotsend.txt
+++ b/templates/email/default/update-confirm-donotsend.txt
@@ -1,3 +1,3 @@
Note that we do not send updates to [% update.problem.body %] - they are
-intended as a place for [% INCLUDE 'site-name.txt' | trim %] users to
+intended as a place for [% site_name %] users to
discuss, support, and offer advice.
diff --git a/templates/email/default/update-confirm.html b/templates/email/default/update-confirm.html
new file mode 100644
index 000000000..40841bd82
--- /dev/null
+++ b/templates/email/default/update-confirm.html
@@ -0,0 +1,33 @@
+[%
+
+email_summary = "Confirm your update on " _ site_name;
+email_columns = 2;
+
+PROCESS '_email_settings.html';
+
+INCLUDE '_email_top.html';
+
+%]
+
+<th style="[% td_style %][% primary_column_style %]" id="primary_column">
+ [% start_padded_box %]
+ <h1 style="[% h1_style %]">Please confirm your&nbsp;update</h1>
+ <p style="[% p_style %]">Please click on the link below to confirm your update on [% site_name %].</p>
+ <p style="margin: 20px auto; text-align: center">
+ <a style="[% button_style %]" href="[% token_url %]">Yes, confirm my update</a>
+ </p>
+ <p style="[% p_style %]">[% INCLUDE 'update-confirm-donotsend.txt' %]</p>
+ <p style="[% p_style %]">If you no longer wish to confirm this update, please take no further action.</p>
+ [% end_padded_box %]
+</th>
+<th style="[% td_style %][% secondary_column_style %]" id="secondary_column">
+ <img style="[% map_image_style %]" src="[% inline_image(problem.static_map, 'map.jpeg') %]" width="310" height="200" alt="">
+ [% start_padded_box %]
+ [% IF update.photo %]
+ <img style="[% preview_photo_style %]" src="[% inline_image(update.get_first_image_fp) %]" alt="" align="right">
+ [% END %]
+ <p style="[% secondary_p_style %]">[% update.text | html %]</p>
+ [% end_padded_box %]
+</th>
+
+[% INCLUDE '_email_bottom.html' %]
diff --git a/templates/email/fiksgatami/alert-problem-area.txt b/templates/email/fiksgatami/alert-problem-area.txt
index 950e9574b..086ea9a4a 100644
--- a/templates/email/fiksgatami/alert-problem-area.txt
+++ b/templates/email/fiksgatami/alert-problem-area.txt
@@ -3,7 +3,7 @@ Subject: Nye saker i [% area_name %] hos FiksGataMi.no
Følgende saker er sendt til
[% area_name %]:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
Vennlig hilsen,
FiksGataMi-gruppen
diff --git a/templates/email/fiksgatami/alert-problem-council.txt b/templates/email/fiksgatami/alert-problem-council.txt
index 24aa02bc6..e0b0209c8 100644
--- a/templates/email/fiksgatami/alert-problem-council.txt
+++ b/templates/email/fiksgatami/alert-problem-council.txt
@@ -2,7 +2,7 @@ Subject: Nye saker sendt til [% area_name %] via FiksGataMi.no
Følgende saker er sendt til [% area_name %]:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
Vennlig hilsen,
FiksGataMi-gruppen
diff --git a/templates/email/fiksgatami/alert-problem-nearby.txt b/templates/email/fiksgatami/alert-problem-nearby.txt
index b19b08bea..8ba22709a 100644
--- a/templates/email/fiksgatami/alert-problem-nearby.txt
+++ b/templates/email/fiksgatami/alert-problem-nearby.txt
@@ -2,7 +2,7 @@ Subject: Nye saker i nærheten på FiksGataMi.no
Følgende saker i nærheten er lagt inn på FiksGataMi.no:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
Vennlig hilsen,
FiksGataMi-gruppen
diff --git a/templates/email/fiksgatami/alert-problem-ward.txt b/templates/email/fiksgatami/alert-problem-ward.txt
index c7109d5c1..c2e45e7d3 100644
--- a/templates/email/fiksgatami/alert-problem-ward.txt
+++ b/templates/email/fiksgatami/alert-problem-ward.txt
@@ -3,7 +3,7 @@ Subject: Nye saker sendt til [% area_name %] innenfor [% ward_name %] via FiksGa
Følgende saker er sendt til [% area_name %]
innenfor [% ward_name %]:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
Vennlig hilsen,
FiksGataMi-gruppen
diff --git a/templates/email/fiksgatami/alert-problem.txt b/templates/email/fiksgatami/alert-problem.txt
index ffdcedc2c..f6a962612 100644
--- a/templates/email/fiksgatami/alert-problem.txt
+++ b/templates/email/fiksgatami/alert-problem.txt
@@ -2,7 +2,7 @@ Subject: Nye saker på FiksGataMi.no
Følgende nye saker er lagt til:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
Vennlig hilsen,
FiksGataMi-gruppen
diff --git a/templates/email/fiksgatami/alert-update.txt b/templates/email/fiksgatami/alert-update.txt
index 950e33082..c075006aa 100644
--- a/templates/email/fiksgatami/alert-update.txt
+++ b/templates/email/fiksgatami/alert-update.txt
@@ -2,7 +2,7 @@ Subject: Nye oppdateringer for problem - '[% title %]'
Følgende oppdateringer har blitt lagt inn for dette problemet:
-[% data %]
+[% INCLUDE '_email_comment_list.txt' %]
[% state_message %]
diff --git a/templates/email/fiksgatami/contact.txt b/templates/email/fiksgatami/contact.txt
index 59a778ad5..6e1fd5ac9 100644
--- a/templates/email/fiksgatami/contact.txt
+++ b/templates/email/fiksgatami/contact.txt
@@ -2,4 +2,8 @@ Subject: FMS message: [% subject %]
[% message %]
+[% IF complaint %]
+[ [% complaint %] - [% problem_url %] - [% admin_url %] ]
+[% END %]
+
[ Sent by contact.cgi on [% host %]. IP address [% ip %] ]
diff --git a/templates/email/fiksgatami/nn/alert-problem-area.txt b/templates/email/fiksgatami/nn/alert-problem-area.txt
index 24b22b777..37fdc376f 100644
--- a/templates/email/fiksgatami/nn/alert-problem-area.txt
+++ b/templates/email/fiksgatami/nn/alert-problem-area.txt
@@ -3,7 +3,7 @@ Subject: Nye saker i [% area_name %] hos FiksGataMi.no
Følgjande saker er sendt til
[% area_name %]:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
Venleg helsing,
FiksGataMi-gruppa
diff --git a/templates/email/fiksgatami/nn/alert-problem-council.txt b/templates/email/fiksgatami/nn/alert-problem-council.txt
index 308115de5..36d42d891 100644
--- a/templates/email/fiksgatami/nn/alert-problem-council.txt
+++ b/templates/email/fiksgatami/nn/alert-problem-council.txt
@@ -2,7 +2,7 @@ Subject: Nye saker sendt til [% area_name %] via FiksGataMi.no
Følgjande saker er sendt til [% area_name %]:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
Venleg helsing,
FiksGataMi-gruppa
diff --git a/templates/email/fiksgatami/nn/alert-problem-nearby.txt b/templates/email/fiksgatami/nn/alert-problem-nearby.txt
index 1d356f938..c67d7a37b 100644
--- a/templates/email/fiksgatami/nn/alert-problem-nearby.txt
+++ b/templates/email/fiksgatami/nn/alert-problem-nearby.txt
@@ -2,7 +2,7 @@ Subject: Nye saker i nærleiken på FiksGataMi.no
Følgjande saker i nærleiken er lagd inn på FiksGataMi.no:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
Venleg helsing,
FiksGataMi-gruppa
diff --git a/templates/email/fiksgatami/nn/alert-problem-ward.txt b/templates/email/fiksgatami/nn/alert-problem-ward.txt
index 81896e856..57c95deba 100644
--- a/templates/email/fiksgatami/nn/alert-problem-ward.txt
+++ b/templates/email/fiksgatami/nn/alert-problem-ward.txt
@@ -3,7 +3,7 @@ Subject: Nye saker sendt til [% area_name %] innanfor [% ward_name %] via FiksGa
Følgjande saker er sendt til [% area_name %]
innanfor [% ward_name %]:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
Venleg helsing,
FiksGataMi-gruppa
diff --git a/templates/email/fiksgatami/nn/alert-problem.txt b/templates/email/fiksgatami/nn/alert-problem.txt
index 0f11f1048..4d788b3ea 100644
--- a/templates/email/fiksgatami/nn/alert-problem.txt
+++ b/templates/email/fiksgatami/nn/alert-problem.txt
@@ -2,7 +2,7 @@ Subject: Nye saker på FiksGataMi.no
Følgjande nye saker er lagt til:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
Venleg helsing,
FiksGataMi-gruppa
diff --git a/templates/email/fiksgatami/nn/alert-update.txt b/templates/email/fiksgatami/nn/alert-update.txt
index 1c0422bb7..19b31b7ca 100644
--- a/templates/email/fiksgatami/nn/alert-update.txt
+++ b/templates/email/fiksgatami/nn/alert-update.txt
@@ -2,7 +2,7 @@ Subject: Nye oppdateringar for problem – '[% title %]'
Følgjande oppdateringar har vorte lagt inn for dette problemet:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
[% state_message %]
diff --git a/templates/email/fiksgatami/questionnaire.txt b/templates/email/fiksgatami/questionnaire.txt
index 202ac4ba5..0ee5f9f08 100644
--- a/templates/email/fiksgatami/questionnaire.txt
+++ b/templates/email/fiksgatami/questionnaire.txt
@@ -1,6 +1,6 @@
Subject: Spørreskjema for din sak på FiksGataMi
-Hei [% name %],
+Hei [% report.name %],
for [% created %] siden, la du til en sak på FiksGataMi.no
med detaljene som vist i denne e-posten. For å holde vår nettside oppdatert
@@ -16,8 +16,8 @@ FiksGataMi-gruppen
Saken du la til var som følger:
-[% title %]
+[% report.title %]
-[% detail %]
+[% report.detail %]
diff --git a/templates/email/fixamingata/alert-problem-area.txt b/templates/email/fixamingata/alert-problem-area.txt
index 29e3bb83f..09ded3c46 100644
--- a/templates/email/fixamingata/alert-problem-area.txt
+++ b/templates/email/fixamingata/alert-problem-area.txt
@@ -2,7 +2,7 @@ Subject: Nya rapporter i [% area_name %] på FixaMinGata
Följande nya rapporter har lagts till inom [% area_name %]:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
[% signature %]
diff --git a/templates/email/fixamingata/alert-problem-council.txt b/templates/email/fixamingata/alert-problem-council.txt
index 29e3bb83f..09ded3c46 100644
--- a/templates/email/fixamingata/alert-problem-council.txt
+++ b/templates/email/fixamingata/alert-problem-council.txt
@@ -2,7 +2,7 @@ Subject: Nya rapporter i [% area_name %] på FixaMinGata
Följande nya rapporter har lagts till inom [% area_name %]:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
[% signature %]
diff --git a/templates/email/fixamingata/alert-problem-nearby.txt b/templates/email/fixamingata/alert-problem-nearby.txt
index 0462568ac..657ef820a 100644
--- a/templates/email/fixamingata/alert-problem-nearby.txt
+++ b/templates/email/fixamingata/alert-problem-nearby.txt
@@ -2,7 +2,7 @@ Subject: Nya rapporter på FixMyStreet
Följande rapporter har nyligen lagts till på:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
[% signature %]
diff --git a/templates/email/fixamingata/alert-problem-ward.txt b/templates/email/fixamingata/alert-problem-ward.txt
index 29e3bb83f..09ded3c46 100644
--- a/templates/email/fixamingata/alert-problem-ward.txt
+++ b/templates/email/fixamingata/alert-problem-ward.txt
@@ -2,7 +2,7 @@ Subject: Nya rapporter i [% area_name %] på FixaMinGata
Följande nya rapporter har lagts till inom [% area_name %]:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
[% signature %]
diff --git a/templates/email/fixamingata/alert-problem.txt b/templates/email/fixamingata/alert-problem.txt
index 0462568ac..657ef820a 100644
--- a/templates/email/fixamingata/alert-problem.txt
+++ b/templates/email/fixamingata/alert-problem.txt
@@ -2,7 +2,7 @@ Subject: Nya rapporter på FixMyStreet
Följande rapporter har nyligen lagts till på:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
[% signature %]
diff --git a/templates/email/fixamingata/alert-update.txt b/templates/email/fixamingata/alert-update.txt
index 89a9681a8..c5facfca7 100644
--- a/templates/email/fixamingata/alert-update.txt
+++ b/templates/email/fixamingata/alert-update.txt
@@ -8,7 +8,7 @@ uppdateringar, klicka på följande länk:
Följande uppdatering har lämnats för rapporten
[% title %]:
-[% data %]
+[% INCLUDE '_email_comment_list.txt' %]
[% state_message %]
diff --git a/templates/email/fixamingata/contact.txt b/templates/email/fixamingata/contact.txt
index aab7f400f..e08612778 100644
--- a/templates/email/fixamingata/contact.txt
+++ b/templates/email/fixamingata/contact.txt
@@ -1,3 +1,7 @@
Subject: [% subject %] (via FixaMinGata)
[% message %]
+
+[% IF complaint %]
+[ [% complaint %] - [% problem_url %] - [% admin_url %] ]
+[% END %]
diff --git a/templates/email/fixamingata/questionnaire.txt b/templates/email/fixamingata/questionnaire.txt
index cd065d1f1..b59bb8415 100644
--- a/templates/email/fixamingata/questionnaire.txt
+++ b/templates/email/fixamingata/questionnaire.txt
@@ -1,6 +1,6 @@
-Subject: Frågeformulär om '[% title %]'
+Subject: Frågeformulär om '[% report.title %]'
-Hej [% name %],
+Hej [% report.name %],
OBS! Du kan inte svara på detta brev. För att se eller svara på dessa
uppdateringar, klicka på följande länk:
@@ -19,6 +19,6 @@ kommentarsfältet i frågeformuläret.
Ditt rapporterade problem var enligt nedan:
-[% title %]
+[% report.title %]
-[% detail %]
+[% report.detail %]
diff --git a/templates/email/fixmystreet.com/_submit_footer.html b/templates/email/fixmystreet.com/_submit_footer.html
new file mode 100644
index 000000000..b76f128a5
--- /dev/null
+++ b/templates/email/fixmystreet.com/_submit_footer.html
@@ -0,0 +1,9 @@
+This message was sent via FixMyStreet, a project of UKCOD, registered charity
+number 1076346. If there is a more appropriate email address for messages about
+[% category_footer %], please <a href="https://www.fixmystreet.com/contact">let
+us know</a>. This will help improve the service for local people. We also
+welcome any other feedback you may have.
+<br><br>
+FixMyStreet is now available for full integration into council websites, making
+life easier for both you and your residents.
+<a href="https://www.fixmystreet.com/council">Read more</a>
diff --git a/templates/email/fixmystreet.com/submit-oxfordshire.txt b/templates/email/fixmystreet.com/submit-oxfordshire.txt
deleted file mode 100644
index 547f7ce7f..000000000
--- a/templates/email/fixmystreet.com/submit-oxfordshire.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-Subject: FMS Problem Report: [% title %]
-
-Dear [% bodies_name %],
-
-[% missing %][% multiple %]A user of
-FixMyStreet has submitted the following report
-of a local problem that they believe might require your attention.
-
-[% fuzzy %], or to provide an update on the problem,
-please visit the following link:
-
- [% url %]
-
-[% has_photo %]----------
-
-Name: [% name %]
-
-Email: [% email %]
-
-[% phone_line %][% category_line %]Subject: [% title %]
-
-Details: [% detail %]
-
-Easting/Northing: [% easting %]/[% northing %]
-
-Latitude: [% latitude %]
-
-Longitude: [% longitude %]
-
-View OpenStreetMap of this location: [% osm_url %]
-
-[% closest_address %]----------
-
-Replies to this email will go to the user who submitted the problem.
-
-[% signature %]
-
-This message was sent via FixMyStreet, a project of UKCOD, registered charity
-number 1076346. If there is a more appropriate email address for messages about
-[% category_footer %], please let us know by visiting <https://www.fixmystreet.com/contact>.
-This will help improve the service for local people. We
-also welcome any other feedback you may have.
-
-FixMyStreet is now available for full integration into council
-websites, making life easier for both you and your residents.
-Read more here: https://www.fixmystreet.com/council
-
diff --git a/templates/email/fixmystreet.com/submit.html b/templates/email/fixmystreet.com/submit.html
new file mode 100644
index 000000000..e90862ee9
--- /dev/null
+++ b/templates/email/fixmystreet.com/submit.html
@@ -0,0 +1,69 @@
+[%
+
+email_summary = "A new problem in your area has been reported by a " _ site_name _ " user.";
+email_footer = PROCESS '_submit_footer.html';
+email_columns = 2;
+
+PROCESS '_email_settings.html';
+
+INCLUDE '_email_top.html';
+
+%]
+
+<th style="[% td_style %][% primary_column_style %]" id="primary_column">
+ [% start_padded_box %]
+ <h1 style="[% h1_style %]">New problem in your&nbsp;area</h1>
+ <p style="[% p_style %]">[% missing %][% multiple %]A user of [% site_name %] has submitted the following report
+of a local problem that they believe might require your attention.</p>
+
+ <p style="margin: 20px auto; text-align: center">
+ <a style="[% button_style %]" href="[% url %]">Show full report</a>
+ </p>
+ <h2 style="[% h2_style %] margin: 30px 0 10px 0">Reported by:</h2>
+ <table [% table_reset %]>
+ <tr>
+ <th style="[% contact_th_style %]">Name</th>
+ <td style="[% contact_td_style %]">[% name | html %]</td>
+ </tr>
+ <tr>
+ <th style="[% contact_th_style %]">Email</th>
+ <td style="[% contact_td_style %]"><a href="mailto:[% email | html %]">[% email | html %]</a></td>
+ </tr>
+ [% IF phone %]
+ <tr>
+ <th style="[% contact_th_style %]">Phone</th>
+ <td style="[% contact_td_style %]"><a href="tel:[% phone | html %]">[% phone | html %]</a></td>
+ </tr>
+ [% END %]
+ </table>
+ <p style="[% p_style %] margin-top: 0.5em;">Replies to this message will go directly to [% name | html %], the user who reported the problem.</p>
+ [% end_padded_box %]
+</th>
+<th style="[% td_style %][% secondary_column_style %]" id="secondary_column">
+ <img style="[% map_image_style %]" src="[% inline_image(report.static_map, 'map.jpeg') %]" width="310" height="200" alt="">
+ [% start_padded_box %]
+ [% IF has_photo %]
+ <img style="[% preview_photo_style %]" src="[% inline_image(report.get_first_image_fp) %]" alt="" align="right">
+ [% END %]
+ <h2 style="[% h2_style %]">[% title | html %]</h2>
+ [% IF category_line %]
+ <p style="[% secondary_p_style %]">[% category | html %]</p>
+ [% END %]
+ <p style="[% secondary_p_style %]">[% detail | html %]</p>
+ [% IF additional_information %]
+ <p style="[% secondary_p_style %]">[% additional_information %]</p>
+ [% END %]
+ <p style="[% secondary_p_style %]">
+ <strong>Location:</strong>
+ <br>Easting/Northing
+ [%~ " (IE)" IF coordsyst == "I" ~%]
+ : [% easting %]/[% northing %]
+ (<a href="[% osm_url %]" title="View OpenStreetMap of this location">
+ [%~ latitude %], [% longitude ~%]
+ </a>)
+ [% IF closest_address %]<br>[% closest_address | trim | replace("\n\n", "<br>") %][% END %]
+ </p>
+ [% end_padded_box %]
+</th>
+
+[% INCLUDE '_email_bottom.html' %]
diff --git a/templates/email/fixmystreet.com/submit.txt b/templates/email/fixmystreet.com/submit.txt
index 735fdf37d..c30244db9 100644
--- a/templates/email/fixmystreet.com/submit.txt
+++ b/templates/email/fixmystreet.com/submit.txt
@@ -3,7 +3,7 @@ Subject: Problem Report: [% title %]
Dear [% bodies_name %],
[% missing %][% multiple %]A user of
-FixMyStreet has submitted the following report
+[% site_name %] has submitted the following report
of a local problem that they believe might require your attention.
[% fuzzy %], or to provide an update on the problem,
@@ -21,6 +21,8 @@ Email: [% email %]
Details: [% detail %]
+[% additional_information %]
+
Easting/Northing
[%- " (IE)" IF coordsyst == "I" -%]
: [% easting %]/[% northing %]
diff --git a/templates/email/fixmystreet.com/update-confirm-donotsend.txt b/templates/email/fixmystreet.com/update-confirm-donotsend.txt
index 2e04dc0bf..43be8fe26 100644
--- a/templates/email/fixmystreet.com/update-confirm-donotsend.txt
+++ b/templates/email/fixmystreet.com/update-confirm-donotsend.txt
@@ -1,8 +1,8 @@
[% IF update.problem.bodies_str != 2482 AND update.problem.bodies_str != 2347 %]
Note that we do not send updates to [% update.problem.body %] - they are
-intended as a place for [% INCLUDE 'site-name.txt' | trim %] users to
+intended as a place for [% site_name %] users to
discuss, support, and offer advice.
[% ELSE %]
This update will be sent to [% update.problem.body %] and will
-also be displayed on the [% INCLUDE 'site-name.txt' | trim %] website.
+also be displayed on the [% site_name %] website.
[% END %]
diff --git a/templates/email/harrogate/submit.txt b/templates/email/harrogate/submit.txt
deleted file mode 100644
index a4dcd5220..000000000
--- a/templates/email/harrogate/submit.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-Subject: Problem Report: [% title %]
-
-Dear [% bodies_name %],
-
-[% missing %][% multiple %]A user of
-FixMyStreet has submitted the following report
-of a local problem that they believe might require your attention.
-
-[% fuzzy %], or to provide an update on the problem,
-please visit the following link:
-
- [% url %]
-
-[% has_photo %]----------
-
-Name: [% name %]
-
-Email: [% email %]
-
-[% phone_line %][% category_line %]Subject: [% title %]
-
-[% detail %] [% additional_information %]
-
-Easting/Northing: [% easting %]/[% northing %]
-
-Latitude: [% latitude %]
-
-Longitude: [% longitude %]
-
-View OpenStreetMap of this location: [% osm_url %]
-
-[% closest_address %]----------
-
-Replies to this email will go to the user who submitted the problem.
-
-[% signature %]
-
-This message was sent via FixMyStreet, a project of UKCOD, registered charity
-number 1076346. If there is a more appropriate email address for messages about
-[% category_footer %], please let us know by visiting <https://www.fixmystreet.com/contact>.
-This will help improve the service for local people. We
-also welcome any other feedback you may have.
-
-FixMyStreet is now available for full integration into council
-websites, making life easier for both you and your residents.
-Read more here: https://www.fixmystreet.com/council
-
diff --git a/templates/email/oxfordshire/submit.txt b/templates/email/oxfordshire/submit.txt
deleted file mode 100644
index 547f7ce7f..000000000
--- a/templates/email/oxfordshire/submit.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-Subject: FMS Problem Report: [% title %]
-
-Dear [% bodies_name %],
-
-[% missing %][% multiple %]A user of
-FixMyStreet has submitted the following report
-of a local problem that they believe might require your attention.
-
-[% fuzzy %], or to provide an update on the problem,
-please visit the following link:
-
- [% url %]
-
-[% has_photo %]----------
-
-Name: [% name %]
-
-Email: [% email %]
-
-[% phone_line %][% category_line %]Subject: [% title %]
-
-Details: [% detail %]
-
-Easting/Northing: [% easting %]/[% northing %]
-
-Latitude: [% latitude %]
-
-Longitude: [% longitude %]
-
-View OpenStreetMap of this location: [% osm_url %]
-
-[% closest_address %]----------
-
-Replies to this email will go to the user who submitted the problem.
-
-[% signature %]
-
-This message was sent via FixMyStreet, a project of UKCOD, registered charity
-number 1076346. If there is a more appropriate email address for messages about
-[% category_footer %], please let us know by visiting <https://www.fixmystreet.com/contact>.
-This will help improve the service for local people. We
-also welcome any other feedback you may have.
-
-FixMyStreet is now available for full integration into council
-websites, making life easier for both you and your residents.
-Read more here: https://www.fixmystreet.com/council
-
diff --git a/templates/email/zurich/alert-moderation-overdue.txt b/templates/email/zurich/alert-moderation-overdue.txt
index 869f379e5..914f4607c 100644
--- a/templates/email/zurich/alert-moderation-overdue.txt
+++ b/templates/email/zurich/alert-moderation-overdue.txt
@@ -2,7 +2,7 @@ Subject: eskalierte Meldungen auf Züri wie neu
Die folgenden Meldungen auf <<Züri wie neu>> sind älter als einen Tag und müssen dringend bearbeitet werden:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
Um diese Meldungen zu moderieren, klicken Sie auf folgende URL:
diff --git a/templates/email/zurich/alert-overdue.txt b/templates/email/zurich/alert-overdue.txt
index 7e7914b46..fa5457cd7 100644
--- a/templates/email/zurich/alert-overdue.txt
+++ b/templates/email/zurich/alert-overdue.txt
@@ -2,7 +2,7 @@ Subject: Rückmeldung erforderlich auf Züri wie neu
Die folgenden Meldungen wurden eskaliert, da sie nicht innerhalb von fünf Tagen beantwortet worden sind:
-[% data %]
+[% INCLUDE '_email_report_list.txt' %]
Um diese Meldungen zu bearbeiten, klicken Sie auf folgende URL:
diff --git a/templates/email/zurich/alert-update.txt b/templates/email/zurich/alert-update.txt
index 144047599..30b822f9d 100644
--- a/templates/email/zurich/alert-update.txt
+++ b/templates/email/zurich/alert-update.txt
@@ -2,7 +2,7 @@ Subject: New update on report - '[% title %]'
The following update has been left on this report:
-[% data %]
+[% INCLUDE '_email_comment_list.txt' %]
To view this report on the site, please visit the following URL:
[% problem_url %]
diff --git a/web/cobrands/fixmystreet.com/images/email-logo.gif b/web/cobrands/fixmystreet.com/images/email-logo.gif
new file mode 100644
index 000000000..8b954a81a
--- /dev/null
+++ b/web/cobrands/fixmystreet.com/images/email-logo.gif
Binary files differ