aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/handlemail6
-rw-r--r--cpanfile1
-rw-r--r--perllib/FixMyStreet/App.pm33
-rw-r--r--perllib/FixMyStreet/App/Controller/Contact.pm3
-rw-r--r--perllib/FixMyStreet/Cobrand/Zurich.pm2
-rw-r--r--perllib/FixMyStreet/Email.pm192
-rw-r--r--t/app/01app.t4
-rw-r--r--t/app/controller/questionnaire.t10
-rw-r--r--t/app/helpers/send_email.t3
-rw-r--r--t/app/helpers/send_email_sample.txt4
-rw-r--r--t/app/helpers/send_email_sample_mime.txt106
-rw-r--r--t/app/model/alert_type.t2
-rw-r--r--t/cobrand/fixamingata.t8
-rw-r--r--t/cobrand/zurich.t7
-rw-r--r--t/cobrand/zurich_attachments.txt73
-rw-r--r--t/i18n.t12
16 files changed, 276 insertions, 190 deletions
diff --git a/bin/handlemail b/bin/handlemail
index e91a8a3a0..55a053963 100755
--- a/bin/handlemail
+++ b/bin/handlemail
@@ -22,7 +22,6 @@ BEGIN {
use FixMyStreet;
use FixMyStreet::DB;
use FixMyStreet::Email;
-use mySociety::Email;
use mySociety::EmailUtil;
use mySociety::HandleMail;
use mySociety::SystemMisc qw(print_log);
@@ -168,14 +167,13 @@ sub handle_non_bounce_to_null_address {
$fp->close;
# We generate this as a bounce.
- my $mail = mySociety::Email::construct_email({
+ my $mail = FixMyStreet::Email::construct_email({
From => [ FixMyStreet->config('CONTACT_EMAIL'), 'FixMyStreet' ],
To => $data{return_path},
_template_ => $template,
_parameters_ => { },
- _line_indent => '',
});
- send_mail($mail, '<>', $data{return_path});
+ send_mail($mail->as_string, '<>', $data{return_path});
}
sub forward_on_to {
diff --git a/cpanfile b/cpanfile
index 5df6cb0dc..c8ed8a771 100644
--- a/cpanfile
+++ b/cpanfile
@@ -51,7 +51,6 @@ requires 'Digest::SHA';
requires 'Email::MIME';
requires 'Email::Send';
requires 'Email::Send::SMTP';
-requires 'Email::Simple';
requires 'Email::Valid';
requires 'Error';
requires 'FCGI';
diff --git a/perllib/FixMyStreet/App.pm b/perllib/FixMyStreet/App.pm
index b8ce2e051..af9dc1f9d 100644
--- a/perllib/FixMyStreet/App.pm
+++ b/perllib/FixMyStreet/App.pm
@@ -6,7 +6,6 @@ use Catalyst::Runtime 5.80;
use FixMyStreet;
use FixMyStreet::Cobrand;
use Memcached;
-use mySociety::Email;
use mySociety::Random qw(random_bytes);
use FixMyStreet::Map;
use FixMyStreet::Email;
@@ -319,37 +318,23 @@ sub send_email {
return if FixMyStreet::Email::is_abuser($c->model('DB')->schema, $vars->{to});
- # render the template
- my $content = $c->view('Email')->render( $c, $template, $vars );
-
- # create an email - will parse headers out of content
- my $email = Email::Simple->new($content);
- $email->header_set( 'Subject', $vars->{subject} ) if $vars->{subject};
- $email->header_set( 'Reply-To', $vars->{'Reply-To'} ) if $vars->{'Reply-To'};
-
- $email->header_set( 'Message-ID', sprintf('<fms-%s-%s@%s>',
- time(), unpack('h*', random_bytes(5, 1)), $c->config->{EMAIL_DOMAIN}
- ) );
-
- # pass the email into mySociety::Email to construct the on the wire 7bit
- # format - this should probably happen in the transport instead but hohum.
- my $email_text = mySociety::Locale::in_gb_locale { mySociety::Email::construct_email(
+ my $email = mySociety::Locale::in_gb_locale { FixMyStreet::Email::construct_email(
{
- _template_ => $email->body, # will get line wrapped
+ _template_ => $c->view('Email')->render( $c, $template, $vars ),
_parameters_ => {},
- _line_indent => '',
+ _attachments_ => $extra_stash_values->{attachments},
From => $vars->{from},
To => $vars->{to},
- $email->header_pairs
+ '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'}) : (),
}
) };
- if (my $attachments = $extra_stash_values->{attachments}) {
- $email_text = FixMyStreet::Email::munge_attachments($email_text, $attachments);
- }
-
# send the email
- $c->model('EmailSend')->send($email_text);
+ $c->model('EmailSend')->send($email);
return $email;
}
diff --git a/perllib/FixMyStreet/App/Controller/Contact.pm b/perllib/FixMyStreet/App/Controller/Contact.pm
index 115f4e3d2..e20011471 100644
--- a/perllib/FixMyStreet/App/Controller/Contact.pm
+++ b/perllib/FixMyStreet/App/Controller/Contact.pm
@@ -242,8 +242,7 @@ sub send_email : Private {
my $from = [ $c->stash->{em}, $c->stash->{form_name} ];
my $params = {
- to => [ [ $recipient, _($recipient_name) ] ],
- subject => 'FMS message: ' . $c->stash->{subject},
+ to => [ [ $recipient, _($recipient_name) ] ],
};
if (FixMyStreet::Email::test_dmarc($c->stash->{em})) {
$params->{'Reply-To'} = [ $from ];
diff --git a/perllib/FixMyStreet/Cobrand/Zurich.pm b/perllib/FixMyStreet/Cobrand/Zurich.pm
index c7e3c4d45..596ef2dc6 100644
--- a/perllib/FixMyStreet/Cobrand/Zurich.pm
+++ b/perllib/FixMyStreet/Cobrand/Zurich.pm
@@ -1029,7 +1029,7 @@ sub munge_sendreport_params {
},
}
} (0..$num-1);
- $params->{attachments} = \@attachments;
+ $params->{_attachments_} = \@attachments;
}
}
diff --git a/perllib/FixMyStreet/Email.pm b/perllib/FixMyStreet/Email.pm
index 1787c32da..49f4632a8 100644
--- a/perllib/FixMyStreet/Email.pm
+++ b/perllib/FixMyStreet/Email.pm
@@ -1,6 +1,8 @@
package FixMyStreet::Email;
+use Email::MIME;
use Encode;
+use POSIX qw();
use Template;
use Digest::HMAC_SHA1 qw(hmac_sha1_hex);
use mySociety::Email;
@@ -105,15 +107,10 @@ sub send_cron {
$site_name = Utils::trim_text(Encode::decode('utf8', $site_name));
$params->{_parameters_}->{site_name} = $site_name;
- $params->{_line_indent} = '';
- my $attachments = delete $params->{attachments};
-
- my $email = mySociety::Locale::in_gb_locale { mySociety::Email::construct_email($params) };
-
- $email = munge_attachments($email, $attachments) if $attachments;
+ my $email = mySociety::Locale::in_gb_locale { construct_email($params) };
if ($nomail) {
- print $email;
+ print $email->as_string;
return 1; # Failure
} else {
my $result = FixMyStreet::EmailSend->new({ env_from => $env_from })->send($email);
@@ -121,41 +118,152 @@ sub send_cron {
}
}
-sub munge_attachments {
- my ($message, $attachments) = @_;
- # $attachments should be an array_ref of things that can be parsed to Email::MIME,
- # for example
- # [
- # body => $binary_data,
- # attributes => {
- # content_type => 'image/jpeg',
- # encoding => 'base64',
- # filename => '1234.1.jpeg',
- # name => '1234.1.jpeg',
- # },
- # ...
- # ]
- #
- # XXX: mySociety::Email::construct_email isn't using a MIME library and
- # requires more analysis to refactor, so for now, we'll simply parse the
- # generated MIME and add attachments.
- #
- # (Yes, this means that the email is constructed by Email::Simple, munged
- # manually by custom code, turned back into Email::Simple, and then munged
- # with Email::MIME. What's your point?)
-
- require Email::MIME;
- my $mime = Email::MIME->new($message);
- $mime->parts_add([ map { Email::MIME->create(%$_)} @$attachments ]);
- my $data = $mime->as_string;
-
- # unsure why Email::MIME adds \r\n. Possibly mail client should handle
- # gracefully, BUT perhaps as the segment constructed by
- # mySociety::Email::construct_email strips to \n, they seem not to.
- # So we re-run the same regexp here to the added part.
- $data =~ s/\r\n/\n/gs;
-
- return $data;
+=item construct_email SPEC
+
+Construct an email message according to SPEC, which is an associative array
+containing elements as given below. Returns an Email::MIME email.
+
+=over 4
+
+=item _template_, _parameters_
+
+Templated body text and an associative array of template parameters. _template
+contains optional substititutions <?=$values['name']?>, each of which is
+replaced by the value of the corresponding named value in _parameters_. It is
+an error to use a substitution when the corresponding parameter is not present
+or undefined. The first line of the template will be interpreted as contents of
+the Subject: header of the mail if it begins with the literal string 'Subject:
+' followed by a blank line. The templated text will be word-wrapped to produce
+lines of appropriate length.
+
+=item _attachments_
+
+An arrayref of hashrefs that can be passed to Email::MIME.
+
+=item To
+
+Contents of the To: header, as a literal UTF-8 string or an array of addresses
+or [address, name] pairs.
+
+=item From
+
+Contents of the From: header, as an email address or an [address, name] pair.
+
+=item Cc
+
+Contents of the Cc: header, as for To.
+
+=item Reply-To
+
+Contents of the Reply-To: header, as for To.
+
+=item Subject
+
+Contents of the Subject: header, as a UTF-8 string.
+
+=item I<any other element>
+
+interpreted as the literal value of a header with the same name.
+
+=back
+
+If no Date is given, the current date is used. If no To is given, then the
+string "Undisclosed-Recipients: ;" is used. It is an error to fail to give a
+templated body, From or Subject (perhaps from the template).
+
+=cut
+sub construct_email ($) {
+ my $p = shift;
+
+ throw mySociety::Email::Error("Must specify both '_template_' and '_parameters_'")
+ if !exists($p->{_template_}) || !exists($p->{_parameters_});
+ throw mySociety::Email::Error("Template parameters '_parameters_' must be an associative array")
+ if (ref($p->{_parameters_}) ne 'HASH');
+
+ (my $subject, $body) = mySociety::Email::do_template_substitution($p->{_template_}, $p->{_parameters_}, '');
+ $p->{Subject} = $subject if defined($subject);
+
+ if (!exists($p->{Subject})) {
+ # XXX Try to find out what's causing this very occasionally
+ (my $error = $body) =~ s/\n/ | /g;
+ $error = "missing field 'Subject' in MESSAGE - $error";
+ throw mySociety::Email::Error($error);
+ }
+ throw mySociety::Email::Error("missing field 'From' in MESSAGE") unless exists($p->{From});
+
+ # Construct email headers
+ my %hdr;
+
+ foreach my $h (grep { exists($p->{$_}) } qw(To Cc Reply-To)) {
+ if (ref($p->{$h}) eq '') {
+ # Interpret as a literal string in UTF-8, so all we need to do is
+ # escape it.
+ $hdr{$h} = $p->{$h};
+ } elsif (ref($p->{$h}) eq 'ARRAY') {
+ # Array of addresses or [address, name] pairs.
+ $hdr{$h} = join(', ', map { mailbox($_, $h) } @{$p->{$h}});
+ } else {
+ throw mySociety::Email::Error("Field '$h' in MESSAGE should be single value or an array");
+ }
+ }
+
+ foreach my $h (grep { exists($p->{$_}) } qw(From Sender)) {
+ $hdr{$h} = mailbox($p->{$h}, $h);
+ }
+
+ # Some defaults
+ $hdr{To} ||= 'Undisclosed-recipients: ;';
+ $hdr{Date} ||= POSIX::strftime("%a, %d %h %Y %T %z", localtime(time()));
+
+ # Other headers, including Subject
+ foreach (keys(%$p)) {
+ $hdr{$_} = $p->{$_} if ($_ !~ /^_/ && !exists($hdr{$_}));
+ }
+
+ my $parts = [
+ _mime_create(
+ body_str => $body,
+ attributes => {
+ charset => 'utf-8',
+ encoding => 'quoted-printable',
+ },
+ ),
+ ];
+
+ if ($p->{_attachments_}) {
+ push @$parts, map { _mime_create(%$_) } @{$p->{_attachments_}};
+ }
+
+ my $email = Email::MIME->create(
+ header_str => [ %hdr ],
+ parts => $parts,
+ attributes => {
+ charset => 'utf-8',
+ },
+ );
+
+ return $email;
+}
+
+# Handle being given a string, or an arrayref of [ name, email ]
+sub mailbox {
+ my ($e, $header) = @_;
+ if (ref($e) eq '') {
+ return $e;
+ } elsif (ref($e) ne 'ARRAY' || @$e != 2) {
+ throw mySociety::Email::Error("'$header' field should be string or 2-element array");
+ } else {
+ return Email::Address->new($e->[1], $e->[0]);
+ }
+}
+
+# Don't want Date/MIME-Version headers that Email::MIME adds to all parts
+sub _mime_create {
+ my %h = @_;
+ my $e = Email::MIME->create(%h);
+ $e->header_set('Date');
+ $e->header_set('MIME-Version');
+ return $e;
}
1;
diff --git a/t/app/01app.t b/t/app/01app.t
index eb98b6319..df562b829 100644
--- a/t/app/01app.t
+++ b/t/app/01app.t
@@ -16,12 +16,16 @@ use Encode qw(encode);
ok( request('/')->is_success, 'Request should succeed' );
+SKIP: {
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'tester' ],
}, sub {
+ skip 'Test will not pass on Mac OS', 1 if $^O eq 'darwin';
+
my $page = get('/');
my $num = encode('UTF-8', "12\N{NO-BREAK SPACE}345");
like $page, qr/$num/;
};
+}
done_testing();
diff --git a/t/app/controller/questionnaire.t b/t/app/controller/questionnaire.t
index 7718d5034..cad86a40d 100644
--- a/t/app/controller/questionnaire.t
+++ b/t/app/controller/questionnaire.t
@@ -63,8 +63,8 @@ my $email = $mech->get_email;
ok $email, "got an email";
like $email->body, qr/fill in our short questionnaire/i, "got questionnaire email";
-like $email->body, qr/Testing =96 Detail/, 'email contains encoded character';
-is $email->header('Content-Type'), 'text/plain; charset="windows-1252"', 'in the right character set';
+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';
my ($token) = $email->body =~ m{http://.*?/Q/(\S+)};
ok $token, "extracted questionnaire token '$token'";
@@ -461,9 +461,9 @@ FixMyStreet::override_config {
ok $email, "got an email";
$mech->clear_emails_ok;
- like $email->body, qr/Testing =96 Detail/, 'email contains encoded character from user';
- like $email->body, qr/sak p=E5 FiksGataMi/, 'email contains encoded character from template';
- is $email->header('Content-Type'), 'text/plain; charset="windows-1252"', 'email is in right encoding';
+ 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';
};
$mech->delete_user('test@example.com');
diff --git a/t/app/helpers/send_email.t b/t/app/helpers/send_email.t
index f60f7fa5a..e2c8688a8 100644
--- a/t/app/helpers/send_email.t
+++ b/t/app/helpers/send_email.t
@@ -41,8 +41,7 @@ my $email = Email::MIME->new($email_as_string);
my $expected_email_content = path(__FILE__)->parent->child('send_email_sample.txt')->slurp;
my $name = FixMyStreet->config('CONTACT_NAME');
-$name = "\"$name\"" if $name =~ / /;
-my $sender = $name . ' <' . FixMyStreet->config('DO_NOT_REPLY_EMAIL') . '>';
+my $sender = '"' . $name . '" <' . FixMyStreet->config('DO_NOT_REPLY_EMAIL') . '>';
$expected_email_content =~ s{CONTACT_EMAIL}{$sender};
my $expected_email = Email::MIME->new($expected_email_content);
diff --git a/t/app/helpers/send_email_sample.txt b/t/app/helpers/send_email_sample.txt
index 1ccce6a23..0f7406172 100644
--- a/t/app/helpers/send_email_sample.txt
+++ b/t/app/helpers/send_email_sample.txt
@@ -1,5 +1,5 @@
MIME-Version: 1.0
-Subject: test email =?utf-8?Q?=E2=98=BA?=
+Subject: =?UTF-8?B?dGVzdCBlbWFpbCDimLo=?=
Content-Type: text/plain; charset="utf-8"
To: test@recipient.com
Content-Transfer-Encoding: quoted-printable
@@ -24,5 +24,3 @@ culpa qui officia deserunt mollit anim id est laborum.
Yours,=20=20
FixMyStreet.=20=
-
-
diff --git a/t/app/helpers/send_email_sample_mime.txt b/t/app/helpers/send_email_sample_mime.txt
index c4ca97bcc..0649d1ceb 100644
--- a/t/app/helpers/send_email_sample_mime.txt
+++ b/t/app/helpers/send_email_sample_mime.txt
@@ -1,57 +1,49 @@
-MIME-Version: 1.0
-Subject: test email =?utf-8?Q?=E2=98=BA?=
-Content-Type: multipart/mixed; boundary="BOUNDARY"
-To: test@recipient.com
-Content-Transfer-Encoding: 7bit
-From: CONTACT_EMAIL
-
-
---BOUNDARY
-MIME-Version: 1.0
-Subject: test email =?utf-8?Q?=E2=98=BA?=
-Content-Type: text/plain; charset="utf-8"
-To: test@recipient.com
-Content-Transfer-Encoding: quoted-printable
-From: CONTACT_EMAIL
-
-Hello,
-
-This is a test email where foo: bar.
-
-utf8: =E6=88=91=E4=BB=AC=E5=BA=94=E8=AF=A5=E8=83=BD=E5=A4=9F=E6=97=A0=E7=BC=
-=9D=E5=A4=84=E7=90=86UTF8=E7=BC=96=E7=A0=81
-
- indented_text
-
-long line: Lorem ipsum dolor sit amet, consectetur adipisicing elit,
-sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
-Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
-nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
-reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
-pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
-culpa qui officia deserunt mollit anim id est laborum.
-
-Yours,=20=20
-FixMyStreet.=20=
-
-
-
---BOUNDARY
-MIME-Version: 1.0
-Content-Type: image/gif; name="foo.gif"
-Content-Disposition: inline; filename="foo.gif"
-Content-Transfer-Encoding: quoted-printable
-
-GIF89a=01=00=01=00=80=00=00=00=00=00=CC=CC=CC,=00=00=00=00=01=00=01=00=00=
-=02=01L=00;=
-
---BOUNDARY
-MIME-Version: 1.0
-Content-Type: image/gif; name="bar.gif"
-Content-Disposition: inline; filename="bar.gif"
-Content-Transfer-Encoding: quoted-printable
-
-GIF89a=01=00=01=00=80=00=00=00=00=00=CC=CC=CC,=00=00=00=00=01=00=01=00=00=
-=02=01L=00;=
-
---BOUNDARY--
+MIME-Version: 1.0
+Subject: =?UTF-8?B?dGVzdCBlbWFpbCDimLo=?=
+Content-Type: multipart/mixed; boundary="BOUNDARY"
+To: test@recipient.com
+Content-Transfer-Encoding: 7bit
+From: CONTACT_EMAIL
+
+
+--BOUNDARY
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: quoted-printable
+
+Hello,
+
+This is a test email where foo: bar.
+
+utf8: =E6=88=91=E4=BB=AC=E5=BA=94=E8=AF=A5=E8=83=BD=E5=A4=9F=E6=97=A0=E7=BC=
+=9D=E5=A4=84=E7=90=86UTF8=E7=BC=96=E7=A0=81
+
+ indented_text
+
+long line: Lorem ipsum dolor sit amet, consectetur adipisicing elit,
+sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
+nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
+reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
+pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
+culpa qui officia deserunt mollit anim id est laborum.
+
+Yours,=20=20
+FixMyStreet.=20=
+
+--BOUNDARY
+Content-Type: image/gif; name="foo.gif"
+Content-Disposition: inline; filename="foo.gif"
+Content-Transfer-Encoding: quoted-printable
+
+GIF89a=01=00=01=00=80=00=00=00=00=00=CC=CC=CC,=00=00=00=00=01=00=01=00=00=
+=02=01L=00;=
+
+--BOUNDARY
+Content-Type: image/gif; name="bar.gif"
+Content-Disposition: inline; filename="bar.gif"
+Content-Transfer-Encoding: quoted-printable
+
+GIF89a=01=00=01=00=80=00=00=00=00=00=CC=CC=CC,=00=00=00=00=01=00=01=00=00=
+=02=01L=00;=
+
+--BOUNDARY--
diff --git a/t/app/model/alert_type.t b/t/app/model/alert_type.t
index 0130f404e..e94ee8ce1 100644
--- a/t/app/model/alert_type.t
+++ b/t/app/model/alert_type.t
@@ -287,7 +287,7 @@ foreach my $test (
desc => 'address only',
addressLine => '18 North Bridge',
locality => undef,
- nearest => qr/: 18 North Bridge\n/,
+ nearest => qr/: 18 North Bridge\r?\n/,
},
{
desc => 'no fields',
diff --git a/t/cobrand/fixamingata.t b/t/cobrand/fixamingata.t
index 50b7713d1..0cf7a31fe 100644
--- a/t/cobrand/fixamingata.t
+++ b/t/cobrand/fixamingata.t
@@ -46,10 +46,10 @@ FixMyStreet::override_config {
FixMyStreet::DB->resultset('Problem')->send_reports();
};
my $email = $mech->get_email;
-like $email->header('Content-Type'), qr/iso-8859-1/, 'encoding looks okay';
+like $email->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, qr/V=E4nligen,/, 'signature looks correct';
+like $email->body_str, qr/V\xe4nligen,/, 'signature looks correct';
$mech->clear_emails_ok;
my $user =
@@ -91,8 +91,8 @@ FixMyStreet::override_config {
$mech->email_count_is(1);
$email = $mech->get_email;
-like $email->header('Content-Type'), qr/iso-8859-1/, 'encoding looks okay';
-like $email->body, qr/V=E4nligen,/, 'signature looks correct';
+like $email->header('Content-Type'), qr/utf-8/, 'encoding looks okay';
+like $email->body_str, qr/V\xe4nligen,/, 'signature looks correct';
$mech->clear_emails_ok;
subtest "Test ajax decimal points" => sub {
diff --git a/t/cobrand/zurich.t b/t/cobrand/zurich.t
index 4734dc837..cf66136e5 100644
--- a/t/cobrand/zurich.t
+++ b/t/cobrand/zurich.t
@@ -661,7 +661,7 @@ subtest "external report triggers email" => sub {
};
$email = $mech->get_email;
my $report_id = $report->id;
- like $email->header('Subject'), qr/Meldung #$report_id/, 'subject looks okay';
+ like Encode::decode('MIME-Header', $email->header('Subject')), qr/Meldung #$report_id/, 'subject looks okay';
like $email->header('To'), qr/test\@example.com/, 'to line looks correct';
like $email->body, qr/$PUBLIC_RESPONSE/, 'public_response was passed on' or die $email->body;
$mech->clear_emails_ok;
@@ -894,6 +894,11 @@ subtest 'email images to external partners' => sub {
my $expected_email_content = path(__FILE__)->parent->child('zurich_attachments.txt')->slurp;
my $REPORT_ID = $report->id;
+ $expected_email_content =~ s{Subject: (.*?)\r?\n}{
+ my $subj = Encode::decode('MIME-Header', $1);
+ $subj =~ s{REPORT_ID}{$REPORT_ID}g;
+ 'Subject: ' . Email::MIME::Encode::mime_encode($subj, "utf-8") . "\n";
+ }eg;
$expected_email_content =~ s{REPORT_ID}{$REPORT_ID}g;
$expected_email_content =~ s{BOUNDARY}{$boundary}g;
my $expected_email = Email::MIME->new($expected_email_content);
diff --git a/t/cobrand/zurich_attachments.txt b/t/cobrand/zurich_attachments.txt
index 4ccc90205..bdc4333bf 100644
--- a/t/cobrand/zurich_attachments.txt
+++ b/t/cobrand/zurich_attachments.txt
@@ -1,40 +1,33 @@
-MIME-Version: 1.0
-Subject: =?iso-8859-1?Q?Z=FCri?= wie neu: Weitergeleitete Meldung #REPORT_ID
-Content-Type: multipart/mixed; boundary="BOUNDARY"
-To: "External Body" <external_body@example.org>
-Content-Transfer-Encoding: 7bit
-From: FixMyStreet <division@example.org>
-
-
---BOUNDARY
-MIME-Version: 1.0
-Subject: =?iso-8859-1?Q?Z=FCri?= wie neu: Weitergeleitete Meldung #REPORT_ID
-Content-Type: text/plain; charset="iso-8859-1"
-To: "External Body" <external_body@example.org>
-Content-Transfer-Encoding: quoted-printable
-From: FixMyStreet <division@example.org>
-
-Gr=FCezi External Body,
-
-=D6ffentliche URL: http://www.example.org/report/REPORT_ID
-
-Bei Fragen zu "Z=FCri wie neu" wenden Sie sich bitte an
-gis-zentrum@zuerich.ch.=
-
-
-
---BOUNDARY
-MIME-Version: 1.0
-Content-Type: image/jpeg; name="REPORT_ID.0.jpeg"
-Content-Disposition: inline; filename="REPORT_ID.0.jpeg"
-Content-Transfer-Encoding: base64
-
-/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEP
-ERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4e
-Hh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCABTAAEDAREA
-AhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIIB//EAB8QAQAABAcAAAAAAAAAAAAAAAADBAbT
-BxcYVVaUpf/EABcBAQEBAQAAAAAAAAAAAAAAAAAFBgT/xAAgEQEAAAQHAQAAAAAAAAAAAAAAAwQV
-UgECFlNhodGx/9oADAMBAAIRAxEAPwCywAIozyxS5R58tbbujSW33j6zFRj3fGbKbjAGAgAACs9N
-FCbtUfYg2mO1BM25e/V+lQeW3ISo/9k=
-
---BOUNDARY--
+MIME-Version: 1.0
+Subject: =?iso-8859-1?Q?Z=FCri?= wie neu: Weitergeleitete Meldung #REPORT_ID
+Content-Type: multipart/mixed; boundary="BOUNDARY"
+To: "External Body" <external_body@example.org>
+Content-Transfer-Encoding: 7bit
+From: "FixMyStreet" <division@example.org>
+
+
+--BOUNDARY
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: quoted-printable
+
+Gr=C3=BCezi External Body,
+
+=C3=96ffentliche URL: http://www.example.org/report/REPORT_ID
+
+Bei Fragen zu "Z=C3=BCri wie neu" wenden Sie sich bitte an
+gis-zentrum@zuerich.ch.=
+
+--BOUNDARY
+Content-Type: image/jpeg; name="REPORT_ID.0.jpeg"
+Content-Disposition: inline; filename="REPORT_ID.0.jpeg"
+Content-Transfer-Encoding: base64
+
+/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEP
+ERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4e
+Hh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCABTAAEDAREA
+AhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIIB//EAB8QAQAABAcAAAAAAAAAAAAAAAADBAbT
+BxcYVVaUpf/EABcBAQEBAQAAAAAAAAAAAAAAAAAFBgT/xAAgEQEAAAQHAQAAAAAAAAAAAAAAAwQV
+UgECFlNhodGx/9oADAMBAAIRAxEAPwCywAIozyxS5R58tbbujSW33j6zFRj3fGbKbjAGAgAACs9N
+FCbtUfYg2mO1BM25e/V+lQeW3ISo/9k=
+
+--BOUNDARY--
diff --git a/t/i18n.t b/t/i18n.t
index 3337f1a7f..550bc2358 100644
--- a/t/i18n.t
+++ b/t/i18n.t
@@ -56,7 +56,7 @@ my @EN_sorted = qw( A Å Ø Z );
my @NO_sorted = qw( A Z Ø Å );
my @default_sorted = qw( A Z Å Ø );
-{
+SKIP: {
mySociety::Locale::negotiate_language( #
'en-gb,English,en_GB|cy,Cymraeg,cy_GB', 'en_GB'
@@ -71,12 +71,16 @@ my @default_sorted = qw( A Z Å Ø );
is_deeply( [ keysort { $_ } @random_sorted ],
\@default_sorted, "keysort correctly with no locale" );
+ skip 'Will not pass on Mac', 1 if $^O eq 'darwin';
+
# Note - this obeys the locale
is_deeply( [ sort { strcoll( $a, $b ) } @random_sorted ],
\@EN_sorted, "sort strcoll correctly with no locale (to 'en_GB')" );
}
-{
+SKIP: {
+ skip 'Will not pass on Mac', 2 if $^O eq 'darwin';
+
mySociety::Locale::negotiate_language( #
'en-gb,English,en_GB|cy,Cymraeg,cy_GB', 'en_GB'
);
@@ -93,7 +97,9 @@ my @default_sorted = qw( A Z Å Ø );
\@EN_sorted, "sort strcoll correctly with use locale 'en_GB'" );
}
-{
+SKIP: {
+ skip 'Will not pass on Mac', 2 if $^O eq 'darwin';
+
mySociety::Locale::negotiate_language( #
'nb-no,Norwegian,nb_NO', 'nb_NO'
);