-# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
+# Copyright (C) 2013-2015 all contributors <meta@public-inbox.org>
# License: AGPLv3 or later (https://www.gnu.org/licenses/agpl-3.0.txt)
use strict;
use warnings;
use Test::More;
use Email::MIME;
-use Email::Filter;
use PublicInbox::Filter;
sub count_body_parts {
$bodies->{$body}++;
}
+# multipart/alternative: HTML and quoted-printable, keep the plain-text
+{
+ my $html_body = "<html><body>hi</body></html>";
+ my $parts = [
+ Email::MIME->create(
+ attributes => {
+ content_type => 'text/html; charset=UTF-8',
+ encoding => 'base64',
+ },
+ body => $html_body,
+ ),
+ Email::MIME->create(
+ attributes => {
+ content_type => 'text/plain',
+ encoding => 'quoted-printable',
+ },
+ body => 'hi = "bye"',
+ )
+ ];
+ my $email = Email::MIME->create(
+ header_str => [
+ From => 'a@example.com',
+ Subject => 'blah',
+ 'Content-Type' => 'multipart/alternative'
+ ],
+ parts => $parts,
+ );
+ is(1, PublicInbox::Filter->run($email), "run was a success");
+ my $parsed = Email::MIME->new($email->as_string);
+ is("text/plain", $parsed->header("Content-Type"));
+ is(scalar $parsed->parts, 1, "HTML part removed");
+ my %bodies;
+ $parsed->walk_parts(sub {
+ my ($part) = @_;
+ return if $part->subparts; # walk_parts already recurses
+ count_body_parts(\%bodies, $part);
+ });
+ is(scalar keys %bodies, 1, "one bodies");
+ is($bodies{"hi =3D \"bye\"="}, 1, "QP text part unchanged");
+ $parsed->walk_parts(sub {
+ my ($part) = @_;
+ my $b = $part->body;
+ $b =~ s/\s*\z//;
+ is($b, "hi = \"bye\"", "decoded body matches");
+ });
+}
+
# plain-text email is passed through unchanged
{
- my $s = Email::Simple->create(
+ my $s = Email::MIME->create(
header => [
From => 'a@example.com',
To => 'b@example.com',
],
body => "hello world\n",
);
- my $f = Email::Filter->new(data => $s->as_string);
- is(1, PublicInbox::Filter->run($f->simple), "run was a success");
- is($s->as_string, $f->simple->as_string, "plain email unchanged");
+ is(1, PublicInbox::Filter->run($s), "run was a success");
}
# convert single-part HTML to plain-text
{
- my $s = Email::Simple->create(
+ my $s = Email::MIME->create(
header => [
From => 'a@example.com',
To => 'b@example.com',
'Content-Type' => 'text/html',
Subject => 'HTML only badness',
],
- body => "<html><body>bad body</body></html>\n",
+ body => "<html><body>bad body\r\n</body></html>\n",
);
- my $f = Email::Filter->new(data => $s->as_string);
- is(1, PublicInbox::Filter->run($f->simple), "run was a success");
- unlike($f->simple->as_string, qr/<html>/, "HTML removed");
- is("text/plain", $f->simple->header("Content-Type"),
+ is(1, PublicInbox::Filter->run($s), "run was a success");
+ unlike($s->as_string, qr/<html>/, "HTML removed");
+ is("text/plain", $s->header("Content-Type"),
"content-type changed");
- like($f->simple->body, qr/\A\s*bad body\s*\z/, "body");
- like($f->simple->header("X-Content-Filtered-By"),
+ like($s->body, qr/\A\s*bad body\s*\z/, "body");
+ unlike($s->body, qr/\r/, "body has no cr");
+ like($s->header("X-Content-Filtered-By"),
qr/PublicInbox::Filter/, "XCFB header added");
}
],
parts => $parts,
);
- my $f = Email::Filter->new(data => $email->as_string);
- is(1, PublicInbox::Filter->run($f->simple), "run was a success");
- my $parsed = Email::MIME->new($f->simple->as_string);
+ is(1, PublicInbox::Filter->run($email), "run was a success");
+ my $parsed = Email::MIME->new($email->as_string);
is("text/plain", $parsed->header("Content-Type"));
is(scalar $parsed->parts, 1, "HTML part removed");
my %bodies;
header_str => [ From => 'a@example.com', Subject => 'blah' ],
parts => $parts,
);
- my $f = Email::Filter->new(data => $email->as_string);
- is(1, PublicInbox::Filter->run($f->simple), "run was a success");
- my $parsed = Email::MIME->new($f->simple->as_string);
+ is(1, PublicInbox::Filter->run($email), "run was a success");
+ my $parsed = Email::MIME->new($email->as_string);
is(scalar $parsed->parts, 2, "still 2 parts");
my %bodies;
$parsed->walk_parts(sub {
header_str => [ From => 'a@example.com', Subject => 'blah' ],
parts => $parts,
);
- my $f = Email::Filter->new(data => $email->as_string);
- is(1, PublicInbox::Filter->run($f->simple), "run was a success");
- my $parsed = Email::MIME->new($f->simple->as_string);
+ is(1, PublicInbox::Filter->run($email), "run was a success");
+ my $parsed = Email::MIME->new($email->as_string);
is(scalar $parsed->parts, 2, "still 2 parts");
my %bodies;
$parsed->walk_parts(sub {
header_str => [ From => 'a@example.com', Subject => 'blah' ],
parts => $parts,
);
- my $f = Email::Filter->new(data => $email->as_string);
- is(1, PublicInbox::Filter->run($f->simple), "run was a success");
- my $parsed = Email::MIME->new($f->simple->as_string);
+ is(1, PublicInbox::Filter->run($email), "run was a success");
+ my $parsed = Email::MIME->new($email->as_string);
is(scalar $parsed->parts, 1, "image part removed");
my %bodies;
$parsed->walk_parts(sub {
header_str => [ From => 'a@example.com', Subject => 'blah' ],
parts => $parts,
);
- my $f = Email::Filter->new(data => $email->as_string);
- is(0, PublicInbox::Filter->run($f->simple),
+ is(0, PublicInbox::Filter->run($email),
"run signaled to stop delivery");
- my $parsed = Email::MIME->new($f->simple->as_string);
+ my $parsed = Email::MIME->new($email->as_string);
is(scalar $parsed->parts, 1, "bad parts removed");
my %bodies;
$parsed->walk_parts(sub {
}
{
- my $s = Email::Simple->create(
+ my $s = Email::MIME->create(
header => [
From => 'a@example.com',
To => 'b@example.com',
],
body => "hello world\n",
);
- my $f = Email::Filter->new(data => $s->as_string);
- is(0, PublicInbox::Filter->run($f->simple), "run was a failure");
- like($f->simple->as_string, qr/scrubbed/, "scrubbed message");
-}
-
-{
- my $s = Email::Simple->create(
- header => [
- From => 'a@example.com',
- To => 'b@example.com',
- 'Content-Type' => 'text/plain',
- 'Mail-Followup-To' => 'c@example.com',
- Subject => 'mfttest',
- ],
- body => "mft\n",
- );
-
- is('c@example.com', $s->header("Mail-Followup-To"),
- "mft set correctly");
- my $f = Email::Filter->new(data => $s->as_string);
- is(1, PublicInbox::Filter->run($f->simple), "run succeeded for mft");
- is(undef, $f->simple->header("Mail-Followup-To"), "mft stripped");
+ is(0, PublicInbox::Filter->run($s), "run was a failure");
+ like($s->as_string, qr/scrubbed/, "scrubbed message");
}
# multi-part with application/octet-stream
printf("Hello world\\n");
return 0;
}
+\f
+/* some folks like ^L */
EOF
),
Email::MIME->create(
header_str => [ From => 'a@example.com', Subject => 'blah' ],
parts => $parts,
);
- my $f = Email::Filter->new(data => $email->as_string);
- is(1, PublicInbox::Filter->run($f->simple), "run was a success");
- my $parsed = Email::MIME->new($f->simple->as_string);
+ is(1, PublicInbox::Filter->run($email), "run was a success");
+ my $parsed = Email::MIME->new($email->as_string);
is(scalar $parsed->parts, 1, "only one remaining part");
- like($f->simple->header("X-Content-Filtered-By"),
+ like($parsed->header("X-Content-Filtered-By"),
qr/PublicInbox::Filter/, "XCFB header added");
}