summaryrefslogtreecommitdiff
path: root/rt/t/mail
diff options
context:
space:
mode:
Diffstat (limited to 'rt/t/mail')
-rw-r--r--rt/t/mail/autogenerated.t22
-rw-r--r--rt/t/mail/charsets-outgoing-plaintext.t315
-rw-r--r--rt/t/mail/charsets-outgoing.t6
-rw-r--r--rt/t/mail/crypt-gnupg.t94
-rw-r--r--rt/t/mail/dashboard-chart-with-utf8.t15
-rw-r--r--rt/t/mail/dashboards.t2
-rw-r--r--rt/t/mail/digest-attributes.t34
-rw-r--r--rt/t/mail/gateway.t38
-rw-r--r--rt/t/mail/gnupg-bad.t2
-rw-r--r--rt/t/mail/gnupg-incoming.t12
-rw-r--r--rt/t/mail/gnupg-outgoing-encrypted-plaintext.t27
-rw-r--r--rt/t/mail/gnupg-outgoing-plain-plaintext.t25
-rw-r--r--rt/t/mail/gnupg-outgoing-signed-plaintext.t27
-rw-r--r--rt/t/mail/gnupg-outgoing-signed_encrypted-plaintext.t28
-rw-r--r--rt/t/mail/gnupg-realmail.t2
-rw-r--r--rt/t/mail/gnupg-reverification.t9
-rw-r--r--rt/t/mail/header-characters.t40
-rw-r--r--rt/t/mail/html-outgoing.t187
-rw-r--r--rt/t/mail/mime_decoding.t177
-rw-r--r--rt/t/mail/multipart.t4
-rw-r--r--rt/t/mail/one-time-recipients.t312
-rw-r--r--rt/t/mail/outlook.t32
-rw-r--r--rt/t/mail/sendmail-plaintext.t150
-rw-r--r--rt/t/mail/sendmail.t41
-rw-r--r--rt/t/mail/smime/incoming.t202
-rw-r--r--rt/t/mail/smime/other-signed.t135
-rw-r--r--rt/t/mail/smime/outgoing.t80
-rw-r--r--rt/t/mail/smime/realmail.t125
-rw-r--r--rt/t/mail/smime/reject_on_unencrypted.t137
-rw-r--r--rt/t/mail/specials-in-encodedwords.t2
-rw-r--r--rt/t/mail/wrong_mime_charset.t9
31 files changed, 1919 insertions, 372 deletions
diff --git a/rt/t/mail/autogenerated.t b/rt/t/mail/autogenerated.t
new file mode 100644
index 000000000..a37c9b12d
--- /dev/null
+++ b/rt/t/mail/autogenerated.t
@@ -0,0 +1,22 @@
+use strict;
+use warnings;
+
+use RT::Test tests => undef;
+use Email::Abstract;
+
+my $msg = Email::Abstract->new(<<'MSG')->cast("MIME::Entity");
+From: somebody@example.com
+To: rt@example.com
+Precedence: never-bounce
+Precedence: bulk
+Subject: testing precedence
+
+I am bulk mail, hear me roar!
+MSG
+
+ok RT::Interface::Email::CheckForAutoGenerated($msg->head), "Is AutoGenerated";
+
+$msg->head->delete("Precedence", 1);
+ok !RT::Interface::Email::CheckForAutoGenerated($msg->head), "Isn't AutoGenerated";
+
+done_testing;
diff --git a/rt/t/mail/charsets-outgoing-plaintext.t b/rt/t/mail/charsets-outgoing-plaintext.t
new file mode 100644
index 000000000..be576e0bd
--- /dev/null
+++ b/rt/t/mail/charsets-outgoing-plaintext.t
@@ -0,0 +1,315 @@
+use strict;
+use warnings;
+
+use RT::Test tests => 79, text_templates => 1;
+
+my %string = (
+ ru => {
+ test => "\x{442}\x{435}\x{441}\x{442}",
+ autoreply => "\x{410}\x{432}\x{442}\x{43e}\x{43e}\x{442}\x{432}\x{435}\x{442}",
+ support => "\x{43f}\x{43e}\x{434}\x{434}\x{435}\x{440}\x{436}\x{43a}\x{430}",
+ },
+ latin1 => {
+ test => Encode::decode('latin1', "t\xE9st"),
+ autoreply => Encode::decode('latin1', "a\xFCtoreply"),
+ support => Encode::decode('latin1', "supp\xF5rt"),
+ },
+);
+
+my $queue = RT::Test->load_or_create_queue(
+ Name => 'Regression',
+ CorrespondAddress => 'rt-recipient@example.com',
+ CommentAddress => 'rt-recipient@example.com',
+);
+ok $queue && $queue->id, 'loaded or created queue';
+
+diag "make sure queue has no subject tag";
+{
+ my ($status, $msg) = $queue->SetSubjectTag( undef );
+ ok $status, "set subject tag for the queue" or diag "error: $msg";
+}
+
+diag "set intial simple autoreply template";
+{
+ my $template = RT::Template->new( RT->SystemUser );
+ $template->Load('Autoreply');
+ ok $template->id, "loaded autoreply tempalte";
+
+ my ($status, $msg) = $template->SetContent(
+ "Subject: Autreply { \$Ticket->Subject }\n"
+ ."\n"
+ ."hi there it's an autoreply.\n"
+ ."\n"
+ );
+ ok $status, "changed content of the template"
+ or diag "error: $msg";
+}
+
+diag "basic test of autoreply";
+{
+ my $ticket = RT::Ticket->new( RT->SystemUser );
+ $ticket->Create(
+ Queue => $queue->id,
+ Subject => 'test',
+ Requestor => 'root@localhost',
+ );
+ my @mails = RT::Test->fetch_caught_mails;
+ ok @mails, "got some outgoing emails";
+}
+
+diag "non-ascii Subject with ascii prefix set in the template";
+foreach my $set ( 'ru', 'latin1' ) {
+ my $ticket = RT::Ticket->new( RT->SystemUser );
+ $ticket->Create(
+ Queue => $queue->id,
+ Subject => $string{$set}{test},
+ Requestor => 'root@localhost',
+ );
+ my @mails = RT::Test->fetch_caught_mails;
+ ok @mails, "got some outgoing emails";
+
+ my $status = 1;
+ foreach my $mail ( @mails ) {
+ my $entity = parse_mail( $mail );
+ my $subject = Encode::decode( "UTF-8", $entity->head->get('Subject') );
+ $subject =~ /$string{$set}{test}/
+ or do { $status = 0; diag "wrong subject: $subject" };
+ }
+ ok $status, "all mails have correct data";
+}
+
+foreach my $tag_set ( 'ru', 'latin1' ) {
+
+diag "set non-ascii subject tag for the queue";
+{
+ my ($status, $msg) = $queue->SetSubjectTag( $string{$tag_set}{support} );
+ ok $status, "set subject tag for the queue" or diag "error: $msg";
+}
+
+diag "ascii subject with non-ascii subject tag";
+{
+ my $ticket = RT::Ticket->new( RT->SystemUser );
+ $ticket->Create(
+ Queue => $queue->id,
+ Subject => 'test',
+ Requestor => 'root@localhost',
+ );
+ my @mails = RT::Test->fetch_caught_mails;
+ ok @mails, "got some outgoing emails";
+
+ my $status = 1;
+ foreach my $mail ( @mails ) {
+ my $entity = parse_mail( $mail );
+ my $subject = Encode::decode( "UTF-8", $entity->head->get('Subject') );
+ $subject =~ /$string{$tag_set}{support}/
+ or do { $status = 0; diag "wrong subject: $subject" };
+ }
+ ok $status, "all mails have correct data";
+}
+
+diag "non-ascii subject with non-ascii subject tag";
+foreach my $set ( 'ru', 'latin1' ) {
+ my $ticket = RT::Ticket->new( RT->SystemUser );
+ $ticket->Create(
+ Queue => $queue->id,
+ Subject => $string{$set}{test},
+ Requestor => 'root@localhost',
+ );
+ my @mails = RT::Test->fetch_caught_mails;
+ ok @mails, "got some outgoing emails";
+
+ my $status = 1;
+ foreach my $mail ( @mails ) {
+ my $entity = parse_mail( $mail );
+ my $subject = Encode::decode( "UTF-8", $entity->head->get('Subject') );
+ $subject =~ /$string{$tag_set}{support}/
+ or do { $status = 0; diag "wrong subject: $subject" };
+ $subject =~ /$string{$set}{test}/
+ or do { $status = 0; diag "wrong subject: $subject" };
+ }
+ ok $status, "all mails have correct data";
+}
+
+} # subject tag
+
+diag "return back the empty subject tag";
+{
+ my ($status, $msg) = $queue->SetSubjectTag( undef );
+ ok $status, "set subject tag for the queue" or diag "error: $msg";
+}
+
+
+foreach my $prefix_set ( 'ru', 'latin1' ) {
+
+diag "add non-ascii subject prefix in the autoreply template";
+{
+ my $template = RT::Template->new( RT->SystemUser );
+ $template->Load('Autoreply');
+ ok $template->id, "loaded autoreply tempalte";
+
+ my ($status, $msg) = $template->SetContent(
+ "Subject: $string{$prefix_set}{autoreply} { \$Ticket->Subject }\n"
+ ."\n"
+ ."hi there it's an autoreply.\n"
+ ."\n"
+ );
+ ok $status, "changed content of the template" or diag "error: $msg";
+}
+
+diag "ascii subject with non-ascii subject prefix in template";
+{
+ my $ticket = RT::Ticket->new( RT->SystemUser );
+ $ticket->Create(
+ Queue => $queue->id,
+ Subject => 'test',
+ Requestor => 'root@localhost',
+ );
+ my @mails = RT::Test->fetch_caught_mails;
+ ok @mails, "got some outgoing emails";
+
+ my $status = 1;
+ foreach my $mail ( @mails ) {
+ my $entity = parse_mail( $mail );
+ my $subject = Encode::decode( "UTF-8", $entity->head->get('Subject') );
+ $subject =~ /$string{$prefix_set}{autoreply}/
+ or do { $status = 0; diag "wrong subject: $subject" };
+ }
+ ok $status, "all mails have correct data";
+}
+
+diag "non-ascii subject with non-ascii subject prefix in template";
+foreach my $set ( 'ru', 'latin1' ) {
+ my $ticket = RT::Ticket->new( RT->SystemUser );
+ $ticket->Create(
+ Queue => $queue->id,
+ Subject => $string{$set}{test},
+ Requestor => 'root@localhost',
+ );
+ my @mails = RT::Test->fetch_caught_mails;
+ ok @mails, "got some outgoing emails";
+
+ my $status = 1;
+ foreach my $mail ( @mails ) {
+ my $entity = parse_mail( $mail );
+ my $subject = Encode::decode( "UTF-8", $entity->head->get('Subject') );
+ $subject =~ /$string{$prefix_set}{autoreply}/
+ or do { $status = 0; diag "wrong subject: $subject" };
+ $subject =~ /$string{$set}{test}/
+ or do { $status = 0; diag "wrong subject: $subject" };
+ }
+ ok $status, "all mails have correct data";
+}
+
+foreach my $tag_set ( 'ru', 'latin1' ) {
+diag "set non-ascii subject tag for the queue";
+{
+ my ($status, $msg) = $queue->SetSubjectTag( $string{$tag_set}{support} );
+ ok $status, "set subject tag for the queue" or diag "error: $msg";
+}
+
+diag "non-ascii subject, non-ascii prefix in template and non-ascii tag";
+foreach my $set ( 'ru', 'latin1' ) {
+ my $ticket = RT::Ticket->new( RT->SystemUser );
+ $ticket->Create(
+ Queue => $queue->id,
+ Subject => $string{$set}{test},
+ Requestor => 'root@localhost',
+ );
+ my @mails = RT::Test->fetch_caught_mails;
+ ok @mails, "got some outgoing emails";
+
+ my $status = 1;
+ foreach my $mail ( @mails ) {
+ my $entity = parse_mail( $mail );
+ my $subject = Encode::decode( "UTF-8", $entity->head->get('Subject') );
+ $subject =~ /$string{$prefix_set}{autoreply}/
+ or do { $status = 0; diag "wrong subject: $subject" };
+ $subject =~ /$string{$tag_set}{support}/
+ or do { $status = 0; diag "wrong subject: $subject" };
+ $subject =~ /$string{$set}{test}/
+ or do { $status = 0; diag "wrong subject: $subject" };
+ }
+ ok $status, "all mails have correct data";
+}
+
+} # subject tag
+
+diag "flush subject tag of the queue";
+{
+ my ($status, $msg) = $queue->SetSubjectTag( undef );
+ ok $status, "set subject tag for the queue" or diag "error: $msg";
+}
+
+} # prefix set
+
+
+diag "don't change subject via template";
+# clean DB has autoreply that always changes subject in template,
+# we should test situation when subject is not changed from template
+{
+ my $template = RT::Template->new( RT->SystemUser );
+ $template->Load('Autoreply');
+ ok $template->id, "loaded autoreply tempalte";
+
+ my ($status, $msg) = $template->SetContent(
+ "\n"
+ ."\n"
+ ."hi there it's an autoreply.\n"
+ ."\n"
+ );
+ ok $status, "changed content of the template" or diag "error: $msg";
+}
+
+diag "non-ascii Subject without changes in template";
+foreach my $set ( 'ru', 'latin1' ) {
+ my $ticket = RT::Ticket->new( RT->SystemUser );
+ $ticket->Create(
+ Queue => $queue->id,
+ Subject => $string{$set}{test},
+ Requestor => 'root@localhost',
+ );
+ my @mails = RT::Test->fetch_caught_mails;
+ ok @mails, "got some outgoing emails";
+
+ my $status = 1;
+ foreach my $mail ( @mails ) {
+ my $entity = parse_mail( $mail );
+ my $subject = Encode::decode( "UTF-8", $entity->head->get('Subject') );
+ $subject =~ /$string{$set}{test}/
+ or do { $status = 0; diag "wrong subject: $subject" };
+ }
+ ok $status, "all mails have correct data";
+}
+
+foreach my $tag_set ( 'ru', 'latin1' ) {
+diag "set non-ascii subject tag for the queue";
+{
+ my ($status, $msg) = $queue->SetSubjectTag( $string{$tag_set}{support} );
+ ok $status, "set subject tag for the queue" or diag "error: $msg";
+}
+
+diag "non-ascii Subject without changes in template and with non-ascii subject tag";
+foreach my $set ( 'ru', 'latin1' ) {
+ my $ticket = RT::Ticket->new( RT->SystemUser );
+ $ticket->Create(
+ Queue => $queue->id,
+ Subject => $string{$set}{test},
+ Requestor => 'root@localhost',
+ );
+ my @mails = RT::Test->fetch_caught_mails;
+ ok @mails, "got some outgoing emails";
+
+ my $status = 1;
+ foreach my $mail ( @mails ) {
+ my $entity = parse_mail( $mail );
+ my $subject = Encode::decode( "UTF-8", $entity->head->get('Subject') );
+ $subject =~ /$string{$set}{test}/
+ or do { $status = 0; diag "wrong subject: $subject" };
+ $subject =~ /$string{$tag_set}{support}/
+ or do { $status = 0; diag "wrong subject: $subject" };
+ }
+ ok $status, "all mails have correct data";
+}
+
+} # subject tag set
+
diff --git a/rt/t/mail/charsets-outgoing.t b/rt/t/mail/charsets-outgoing.t
index 872721325..0f78f0a58 100644
--- a/rt/t/mail/charsets-outgoing.t
+++ b/rt/t/mail/charsets-outgoing.t
@@ -32,7 +32,7 @@ diag "make sure queue has no subject tag";
diag "set intial simple autoreply template";
{
my $template = RT::Template->new( RT->SystemUser );
- $template->Load('Autoreply');
+ $template->Load('Autoreply in HTML');
ok $template->id, "loaded autoreply tempalte";
my ($status, $msg) = $template->SetContent(
@@ -144,7 +144,7 @@ foreach my $prefix_set ( 'ru', 'latin1' ) {
diag "add non-ascii subject prefix in the autoreply template";
{
my $template = RT::Template->new( RT->SystemUser );
- $template->Load('Autoreply');
+ $template->Load('Autoreply in HTML');
ok $template->id, "loaded autoreply tempalte";
my ($status, $msg) = $template->SetContent(
@@ -248,7 +248,7 @@ diag "don't change subject via template";
# we should test situation when subject is not changed from template
{
my $template = RT::Template->new( RT->SystemUser );
- $template->Load('Autoreply');
+ $template->Load('Autoreply in HTML');
ok $template->id, "loaded autoreply tempalte";
my ($status, $msg) = $template->SetContent(
diff --git a/rt/t/mail/crypt-gnupg.t b/rt/t/mail/crypt-gnupg.t
index ffb059706..567573e93 100644
--- a/rt/t/mail/crypt-gnupg.t
+++ b/rt/t/mail/crypt-gnupg.t
@@ -10,9 +10,10 @@ BEGIN {
qw/data gnupg keyrings/ );
}
-use RT::Test::GnuPG tests => 96, gnupg_options => { homedir => $homedir };
+use RT::Test::GnuPG tests => 100, gnupg_options => { homedir => $homedir };
use Test::Warn;
+use_ok('RT::Crypt');
use_ok('MIME::Entity');
diag 'only signing. correct passphrase';
@@ -22,10 +23,12 @@ diag 'only signing. correct passphrase';
Subject => 'test',
Data => ['test'],
);
- my %res = RT::Crypt::GnuPG::SignEncrypt( Entity => $entity, Encrypt => 0, Passphrase => 'test' );
+ my %res = RT::Crypt->SignEncrypt( Entity => $entity, Encrypt => 0, Passphrase => 'test' );
ok( $entity, 'signed entity');
ok( !$res{'logger'}, "log is here as well" ) or diag $res{'logger'};
- my @status = RT::Crypt::GnuPG::ParseStatus( $res{'status'} );
+ my @status = RT::Crypt->ParseStatus(
+ Protocol => $res{'Protocol'}, Status => $res{'status'}
+ );
is( scalar @status, 2, 'two records: passphrase, signing');
is( $status[0]->{'Operation'}, 'PassphraseCheck', 'operation is correct');
is( $status[0]->{'Status'}, 'DONE', 'good passphrase');
@@ -36,15 +39,17 @@ diag 'only signing. correct passphrase';
ok( $entity->is_multipart, 'signed message is multipart' );
is( $entity->parts, 2, 'two parts' );
- my @parts = RT::Crypt::GnuPG::FindProtectedParts( Entity => $entity );
+ my @parts = RT::Crypt->FindProtectedParts( Entity => $entity );
is( scalar @parts, 1, 'one protected part' );
is( $parts[0]->{'Type'}, 'signed', "have signed part" );
is( $parts[0]->{'Format'}, 'RFC3156', "RFC3156 format" );
is( $parts[0]->{'Top'}, $entity, "it's the same entity" );
- my @res = RT::Crypt::GnuPG::VerifyDecrypt( Entity => $entity );
+ my @res = RT::Crypt->VerifyDecrypt( Entity => $entity );
is scalar @res, 1, 'one operation';
- @status = RT::Crypt::GnuPG::ParseStatus( $res[0]{'status'} );
+ @status = RT::Crypt->ParseStatus(
+ Protocol => $res[0]{'Protocol'}, Status => $res[0]{'status'}
+ );
is( scalar @status, 1, 'one record');
is( $status[0]->{'Operation'}, 'Verify', 'operation is correct');
is( $status[0]->{'Status'}, 'DONE', 'good passphrase');
@@ -60,7 +65,7 @@ diag 'only signing. missing passphrase';
);
my %res;
warning_like {
- %res = RT::Crypt::GnuPG::SignEncrypt(
+ %res = RT::Crypt->SignEncrypt(
Entity => $entity,
Encrypt => 0,
Passphrase => ''
@@ -69,7 +74,9 @@ diag 'only signing. missing passphrase';
ok( $res{'exit_code'}, "couldn't sign without passphrase");
ok( $res{'error'} || $res{'logger'}, "error is here" );
- my @status = RT::Crypt::GnuPG::ParseStatus( $res{'status'} );
+ my @status = RT::Crypt->ParseStatus(
+ Protocol => $res{'Protocol'}, Status => $res{'status'}
+ );
is( scalar @status, 1, 'one record');
is( $status[0]->{'Operation'}, 'PassphraseCheck', 'operation is correct');
is( $status[0]->{'Status'}, 'MISSING', 'missing passphrase');
@@ -85,7 +92,7 @@ diag 'only signing. wrong passphrase';
my %res;
warning_like {
- %res = RT::Crypt::GnuPG::SignEncrypt(
+ %res = RT::Crypt->SignEncrypt(
Entity => $entity,
Encrypt => 0,
Passphrase => 'wrong',
@@ -95,7 +102,9 @@ diag 'only signing. wrong passphrase';
ok( $res{'exit_code'}, "couldn't sign with bad passphrase");
ok( $res{'error'} || $res{'logger'}, "error is here" );
- my @status = RT::Crypt::GnuPG::ParseStatus( $res{'status'} );
+ my @status = RT::Crypt->ParseStatus(
+ Protocol => $res{'Protocol'}, Status => $res{'status'}
+ );
is( scalar @status, 1, 'one record');
is( $status[0]->{'Operation'}, 'PassphraseCheck', 'operation is correct');
is( $status[0]->{'Status'}, 'BAD', 'wrong passphrase');
@@ -109,18 +118,20 @@ diag 'encryption only';
Subject => 'test',
Data => ['test'],
);
- my %res = RT::Crypt::GnuPG::SignEncrypt( Entity => $entity, Sign => 0 );
+ my %res = RT::Crypt->SignEncrypt( Entity => $entity, Sign => 0 );
ok( !$res{'exit_code'}, "successful encryption" );
ok( !$res{'logger'}, "no records in logger" );
- my @status = RT::Crypt::GnuPG::ParseStatus( $res{'status'} );
+ my @status = RT::Crypt->ParseStatus(
+ Protocol => $res{'Protocol'}, Status => $res{'status'}
+ );
is( scalar @status, 1, 'one record');
is( $status[0]->{'Operation'}, 'Encrypt', 'operation is correct');
is( $status[0]->{'Status'}, 'DONE', 'done');
ok($entity, 'get an encrypted part');
- my @parts = RT::Crypt::GnuPG::FindProtectedParts( Entity => $entity );
+ my @parts = RT::Crypt->FindProtectedParts( Entity => $entity );
is( scalar @parts, 1, 'one protected part' );
is( $parts[0]->{'Type'}, 'encrypted', "have encrypted part" );
is( $parts[0]->{'Format'}, 'RFC3156', "RFC3156 format" );
@@ -138,7 +149,7 @@ diag 'encryption only, bad recipient';
my %res;
warning_like {
- %res = RT::Crypt::GnuPG::SignEncrypt(
+ %res = RT::Crypt->SignEncrypt(
Entity => $entity,
Sign => 0,
);
@@ -147,7 +158,9 @@ diag 'encryption only, bad recipient';
ok( $res{'exit_code'}, 'no way to encrypt without keys of recipients');
ok( $res{'logger'}, "errors are in logger" );
- my @status = RT::Crypt::GnuPG::ParseStatus( $res{'status'} );
+ my @status = RT::Crypt->ParseStatus(
+ Protocol => $res{'Protocol'}, Status => $res{'status'}
+ );
is( scalar @status, 1, 'one record');
is( $status[0]->{'Keyword'}, 'INV_RECP', 'invalid recipient');
}
@@ -160,11 +173,13 @@ diag 'encryption and signing with combined method';
Subject => 'test',
Data => ['test'],
);
- my %res = RT::Crypt::GnuPG::SignEncrypt( Entity => $entity, Passphrase => 'test' );
+ my %res = RT::Crypt->SignEncrypt( Entity => $entity, Passphrase => 'test' );
ok( !$res{'exit_code'}, "successful encryption with signing" );
ok( !$res{'logger'}, "no records in logger" );
- my @status = RT::Crypt::GnuPG::ParseStatus( $res{'status'} );
+ my @status = RT::Crypt->ParseStatus(
+ Protocol => $res{'Protocol'}, Status => $res{'status'}
+ );
is( scalar @status, 3, 'three records: passphrase, sign and encrypt');
is( $status[0]->{'Operation'}, 'PassphraseCheck', 'operation is correct');
is( $status[0]->{'Status'}, 'DONE', 'done');
@@ -175,7 +190,7 @@ diag 'encryption and signing with combined method';
ok($entity, 'get an encrypted and signed part');
- my @parts = RT::Crypt::GnuPG::FindProtectedParts( Entity => $entity );
+ my @parts = RT::Crypt->FindProtectedParts( Entity => $entity );
is( scalar @parts, 1, 'one protected part' );
is( $parts[0]->{'Type'}, 'encrypted', "have encrypted part" );
is( $parts[0]->{'Format'}, 'RFC3156', "RFC3156 format" );
@@ -190,14 +205,14 @@ diag 'encryption and signing with cascading, sign on encrypted';
Subject => 'test',
Data => ['test'],
);
- my %res = RT::Crypt::GnuPG::SignEncrypt( Entity => $entity, Sign => 0 );
+ my %res = RT::Crypt->SignEncrypt( Entity => $entity, Sign => 0 );
ok( !$res{'exit_code'}, 'successful encryption' );
ok( !$res{'logger'}, "no records in logger" );
- %res = RT::Crypt::GnuPG::SignEncrypt( Entity => $entity, Encrypt => 0, Passphrase => 'test' );
+ %res = RT::Crypt->SignEncrypt( Entity => $entity, Encrypt => 0, Passphrase => 'test' );
ok( !$res{'exit_code'}, 'successful signing' );
ok( !$res{'logger'}, "no records in logger" );
- my @parts = RT::Crypt::GnuPG::FindProtectedParts( Entity => $entity );
+ my @parts = RT::Crypt->FindProtectedParts( Entity => $entity );
is( scalar @parts, 1, 'one protected part, top most' );
is( $parts[0]->{'Type'}, 'signed', "have signed part" );
is( $parts[0]->{'Format'}, 'RFC3156', "RFC3156 format" );
@@ -212,7 +227,7 @@ diag 'find signed/encrypted part deep inside';
Subject => 'test',
Data => ['test'],
);
- my %res = RT::Crypt::GnuPG::SignEncrypt( Entity => $entity, Sign => 0 );
+ my %res = RT::Crypt->SignEncrypt( Entity => $entity, Sign => 0 );
ok( !$res{'exit_code'}, "success" );
$entity->make_multipart( 'mixed', Force => 1 );
$entity->attach(
@@ -220,7 +235,7 @@ diag 'find signed/encrypted part deep inside';
Data => ['-'x76, 'this is mailing list'],
);
- my @parts = RT::Crypt::GnuPG::FindProtectedParts( Entity => $entity );
+ my @parts = RT::Crypt->FindProtectedParts( Entity => $entity );
is( scalar @parts, 1, 'one protected part' );
is( $parts[0]->{'Type'}, 'encrypted', "have encrypted part" );
is( $parts[0]->{'Format'}, 'RFC3156', "RFC3156 format" );
@@ -236,7 +251,7 @@ diag 'wrong signed/encrypted parts: no protocol';
Data => ['test'],
);
- my %res = RT::Crypt::GnuPG::SignEncrypt(
+ my %res = RT::Crypt->SignEncrypt(
Entity => $entity,
Sign => 0,
);
@@ -245,11 +260,12 @@ diag 'wrong signed/encrypted parts: no protocol';
$entity->head->mime_attr( 'Content-Type.protocol' => undef );
my @parts;
- warning_like {
- @parts = RT::Crypt::GnuPG::FindProtectedParts( Entity => $entity );
- } qr{Entity is 'multipart/encrypted', but has no protocol defined. Skipped};
-
- is( scalar @parts, 0, 'no protected parts' );
+ warning_like { @parts = RT::Crypt->FindProtectedParts( Entity => $entity ) }
+ qr{Entity is 'multipart/encrypted', but has no protocol defined. Checking for PGP part};
+ is( scalar @parts, 1, 'one protected part' );
+ is( $parts[0]->{'Type'}, 'encrypted', "have encrypted part" );
+ is( $parts[0]->{'Format'}, 'RFC3156', "RFC3156 format" );
+ is( $parts[0]->{'Top'}, $entity, "it's the same entity" );
}
diag 'wrong signed/encrypted parts: not enought parts';
@@ -261,7 +277,7 @@ diag 'wrong signed/encrypted parts: not enought parts';
Data => ['test'],
);
- my %res = RT::Crypt::GnuPG::SignEncrypt(
+ my %res = RT::Crypt->SignEncrypt(
Entity => $entity,
Sign => 0,
);
@@ -271,7 +287,7 @@ diag 'wrong signed/encrypted parts: not enought parts';
my @parts;
warning_like {
- @parts = RT::Crypt::GnuPG::FindProtectedParts( Entity => $entity );
+ @parts = RT::Crypt->FindProtectedParts( Entity => $entity );
} qr/Encrypted or signed entity must has two subparts. Skipped/;
is( scalar @parts, 0, 'no protected parts' );
}
@@ -284,11 +300,11 @@ diag 'wrong signed/encrypted parts: wrong proto';
Subject => 'test',
Data => ['test'],
);
- my %res = RT::Crypt::GnuPG::SignEncrypt( Entity => $entity, Sign => 0 );
+ my %res = RT::Crypt->SignEncrypt( Entity => $entity, Sign => 0 );
ok( !$res{'exit_code'}, 'success' );
$entity->head->mime_attr( 'Content-Type.protocol' => 'application/bad-proto' );
- my @parts = RT::Crypt::GnuPG::FindProtectedParts( Entity => $entity );
+ my @parts = RT::Crypt->FindProtectedParts( Entity => $entity );
is( scalar @parts, 0, 'no protected parts' );
}
@@ -300,11 +316,11 @@ diag 'wrong signed/encrypted parts: wrong proto';
Subject => 'test',
Data => ['test'],
);
- my %res = RT::Crypt::GnuPG::SignEncrypt( Entity => $entity, Encrypt => 0, Passphrase => 'test' );
+ my %res = RT::Crypt->SignEncrypt( Entity => $entity, Encrypt => 0, Passphrase => 'test' );
ok( !$res{'exit_code'}, 'success' );
$entity->head->mime_attr( 'Content-Type.protocol' => 'application/bad-proto' );
- my @parts = RT::Crypt::GnuPG::FindProtectedParts( Entity => $entity );
+ my @parts = RT::Crypt->FindProtectedParts( Entity => $entity );
is( scalar @parts, 0, 'no protected parts' );
}
@@ -314,7 +330,7 @@ diag 'verify inline and in attachment signatures';
my $parser = new MIME::Parser;
my $entity = $parser->parse( $fh );
- my @parts = RT::Crypt::GnuPG::FindProtectedParts( Entity => $entity );
+ my @parts = RT::Crypt->FindProtectedParts( Entity => $entity );
is( scalar @parts, 2, 'two protected parts' );
is( $parts[1]->{'Type'}, 'signed', "have signed part" );
is( $parts[1]->{'Format'}, 'Inline', "inline format" );
@@ -325,8 +341,10 @@ diag 'verify inline and in attachment signatures';
is( $parts[0]->{'Data'}, $entity->parts(1), "data in second part" );
is( $parts[0]->{'Signature'}, $entity->parts(2), "file's signature in third part" );
- my @res = RT::Crypt::GnuPG::VerifyDecrypt( Entity => $entity );
- my @status = RT::Crypt::GnuPG::ParseStatus( $res[0]->{'status'} );
+ my @res = RT::Crypt->VerifyDecrypt( Entity => $entity );
+ my @status = RT::Crypt->ParseStatus(
+ Protocol => $res[0]{'Protocol'}, Status => $res[0]{'status'}
+ );
is( scalar @status, 1, 'one record');
is( $status[0]->{'Operation'}, 'Verify', 'operation is correct');
is( $status[0]->{'Status'}, 'DONE', 'good passphrase');
diff --git a/rt/t/mail/dashboard-chart-with-utf8.t b/rt/t/mail/dashboard-chart-with-utf8.t
index 37f8ce0c6..4fe483a1b 100644
--- a/rt/t/mail/dashboard-chart-with-utf8.t
+++ b/rt/t/mail/dashboard-chart-with-utf8.t
@@ -1,16 +1,10 @@
use strict;
use warnings;
-BEGIN {
- require RT::Test;
+use RT::Test tests => undef;
- if (eval { require GD }) {
- RT::Test->import(tests => 15);
- }
- else {
- RT::Test->import(skip_all => 'GD required.');
- }
-}
+plan skip_all => 'GD required'
+ unless GD->require;
my $root = RT::Test->load_or_create_user( Name => 'root' );
@@ -29,6 +23,7 @@ $m->submit_form(
fields => {
SavedSearchDescription => 'chart foo',
SavedSearchOwner => 'RT::User-' . $root->id,
+ ChartStyle => 'bar',
},
button => 'SavedSearchSave',
);
@@ -88,3 +83,5 @@ if ( my $io = $handle->open('r') ) {
}
is( $mail_image_data, $image, 'image in mail is the same one in web' );
+undef $m;
+done_testing;
diff --git a/rt/t/mail/dashboards.t b/rt/t/mail/dashboards.t
index 6bf4ba520..d7b1ccc7a 100644
--- a/rt/t/mail/dashboards.t
+++ b/rt/t/mail/dashboards.t
@@ -101,7 +101,7 @@ sub produces_dashboard_mail_ok { # {{{
my $mail = parse_mail( $mails[0] );
is($mail->head->get('Subject'), $subject);
- is($mail->head->get('From'), "root\n");
+ is($mail->head->get('From'), qq{"root" <root\@localhost>\n});
is($mail->head->get('Content-Transfer-Encoding'), "base64\n");
is($mail->head->get('X-RT-Dashboard-Id'), "$dashboard_id\n");
is($mail->head->get('X-RT-Dashboard-Subscription-Id'), "$subscription_id\n");
diff --git a/rt/t/mail/digest-attributes.t b/rt/t/mail/digest-attributes.t
index 54c1c803f..a0940dbb1 100644
--- a/rt/t/mail/digest-attributes.t
+++ b/rt/t/mail/digest-attributes.t
@@ -51,48 +51,48 @@ my $everyone = RT::Group->new( RT->SystemUser );
ok( $ret, "Loaded 'everyone' group: $msg" );
( $ret, $msg ) = $everyone->PrincipalObj->GrantRight( Right => 'CreateTicket',
- Object => $testq );
+ Object => $testq );
ok( $ret || $msg =~ /already has/, "Granted everyone CreateTicket on testq: $msg" );
# Make user_d an admincc for the queue.
( $ret, $msg ) = $user_d->PrincipalObj->GrantRight( Right => 'AdminQueue',
- Object => $testq );
+ Object => $testq );
ok( $ret || $msg =~ /already has/, "Granted dduser AdminQueue on testq: $msg" );
( $ret, $msg ) = $testq->AddWatcher( Type => 'AdminCc',
- PrincipalId => $user_d->PrincipalObj->id );
+ PrincipalId => $user_d->PrincipalObj->id );
ok( $ret || $msg =~ /already/, "dduser added as a queue watcher: $msg" );
# Give the others queue rights.
( $ret, $msg ) = $user_n->PrincipalObj->GrantRight( Right => 'AdminQueue',
- Object => $testq );
+ Object => $testq );
ok( $ret || $msg =~ /already has/, "Granted emailnormal right on testq: $msg" );
( $ret, $msg ) = $user_w->PrincipalObj->GrantRight( Right => 'AdminQueue',
- Object => $testq );
+ Object => $testq );
ok( $ret || $msg =~ /already has/, "Granted emailweekly right on testq: $msg" );
( $ret, $msg ) = $user_s->PrincipalObj->GrantRight( Right => 'AdminQueue',
- Object => $testq );
+ Object => $testq );
ok( $ret || $msg =~ /already has/, "Granted emailsusp right on testq: $msg" );
# Create a ticket with To: Cc: Bcc: fields using our four users.
my $id;
my $ticket = RT::Ticket->new( RT->SystemUser );
( $id, $ret, $msg ) = $ticket->Create( Queue => $testq->Name,
- Requestor => [ $user_w->Name ],
- Subject => 'Test ticket for RT::Extension::EmailDigest',
- );
+ Requestor => [ $user_w->Name ],
+ Subject => 'Test ticket for RT::Extension::EmailDigest',
+ );
ok( $ret, "Ticket $id created: $msg" );
# Make the other users ticket watchers.
( $ret, $msg ) = $ticket->AddWatcher( Type => 'Cc',
- PrincipalId => $user_n->PrincipalObj->id );
+ PrincipalId => $user_n->PrincipalObj->id );
ok( $ret, "Added user_n as a ticket watcher: $msg" );
( $ret, $msg ) = $ticket->AddWatcher( Type => 'Cc',
- PrincipalId => $user_s->PrincipalObj->id );
+ PrincipalId => $user_s->PrincipalObj->id );
ok( $ret, "Added user_s as a ticket watcher: $msg" );
my $obj;
($id, $msg, $obj ) = $ticket->Correspond(
- Content => "This is a ticket response for CC action" );
+ Content => "This is a ticket response for CC action" );
ok( $ret, "Transaction created: $msg" );
# Get the deferred notifications that should result. Should be two for
@@ -113,11 +113,11 @@ while( my $txn = $txns->Next ) {
# If the transaction has content...
if( $txn->ContentObj ) {
- # ...none of the deferred folk should be in the header.
- my $headerstr = $txn->ContentObj->Headers;
- foreach my $rcpt( @daily_rcpt, @weekly_rcpt, @susp_rcpt ) {
- ok( $headerstr !~ /$rcpt/, "Deferred recipient $rcpt not found in header" );
- }
+ # ...none of the deferred folk should be in the header.
+ my $headerstr = $txn->ContentObj->Headers;
+ foreach my $rcpt( @daily_rcpt, @weekly_rcpt, @susp_rcpt ) {
+ ok( $headerstr !~ /$rcpt/, "Deferred recipient $rcpt not found in header" );
+ }
}
}
diff --git a/rt/t/mail/gateway.t b/rt/t/mail/gateway.t
index 4f906c89c..89b1b60ab 100644
--- a/rt/t/mail/gateway.t
+++ b/rt/t/mail/gateway.t
@@ -420,7 +420,7 @@ EOF
diag "Testing preservation of binary attachments";
{
# Get a binary blob (Best Practical logo)
- my $LOGO_FILE = $RT::MasonComponentRoot .'/NoAuth/images/bpslogo.png';
+ my $LOGO_FILE = $RT::StaticPath .'/images/bpslogo.png';
# Create a mime entity with an attachment
my $entity = MIME::Entity->build(
@@ -636,13 +636,15 @@ EOF
close (MAIL);
is ($? >> 8, 0, "The mail gateway exited normally");
+DBIx::SearchBuilder::Record::Cachable->FlushCache;
+
$tick = RT::Ticket->new(RT->SystemUser);
$tick->Load( $id );
is( $tick->Id, $id, 'load correct ticket');
is( $tick->OwnerObj->EmailAddress, 'root@localhost', 'successfuly take ticket via email');
-# check that there is no text transactions writen
-is( $tick->Transactions->Count, 2, 'no superfluous transactions');
+# check that there is no text transactions writen (create + 2 for take)
+is( $tick->Transactions->Count, 3, 'no superfluous transactions');
my $status;
($status, $msg) = $tick->SetOwner( RT->Nobody->Id, 'Force' );
@@ -672,8 +674,8 @@ is( $tick->OwnerObj->EmailAddress, 'root@localhost', 'successfuly take ticket vi
my $txns = $tick->Transactions;
$txns->Limit( FIELD => 'Type', VALUE => 'Correspond');
$txns->OrderBy( FIELD => 'id', ORDER => 'DESC' );
-# +1 because of auto open
-is( $tick->Transactions->Count, 6, 'no superfluous transactions');
+# +2 from owner to nobody, +1 because of auto open, +2 from take, +1 from correspond
+is( $tick->Transactions->Count, 9, 'no superfluous transactions');
is( $txns->First->Subject, "[$RT::rtname \#$id] correspondence", 'successfuly add correspond within take via email' );
$m->no_warnings_ok;
@@ -695,15 +697,16 @@ $tick = RT::Ticket->new(RT->SystemUser);
$tick->Load( $id );
is( $tick->Id, $id, 'load correct ticket');
is( $tick->Status, 'resolved', 'successfuly resolved ticket via email');
-is( $tick->Transactions->Count, 7, 'no superfluous transactions');
+# +1 from resolve
+is( $tick->Transactions->Count, 10, 'no superfluous transactions');
use RT::User;
my $user = RT::User->new( RT->SystemUser );
my ($uid) = $user->Create( Name => 'ext-mailgate',
- EmailAddress => 'ext-mailgate@localhost',
- Privileged => 1,
- Password => 'qwe123',
- );
+ EmailAddress => 'ext-mailgate@localhost',
+ Privileged => 1,
+ Password => 'qwe123',
+ );
ok( $uid, 'user created for ext-mailgate tests' );
ok( !$user->HasRight( Right => 'OwnTicket', Object => $queue ), "User can't own ticket" );
@@ -733,7 +736,7 @@ ok( $status, "successfuly granted right: $msg" );
my $ace_id = $status;
ok( $user->HasRight( Right => 'ReplyToTicket', Object => $tick ), "User can reply to ticket" );
-$m->next_warning_like(qr/Permission Denied/);
+$m->next_warning_like(qr/That user may not own tickets in that queue/);
$m->next_warning_like(qr/Could not record email: Ticket not taken/);
$m->no_leftover_warnings_ok;
@@ -752,7 +755,7 @@ DBIx::SearchBuilder::Record::Cachable->FlushCache;
cmp_ok( $tick->Owner, '!=', $user->id, "we didn't change owner" );
is( $tick->Transactions->Count, 3, "one transactions added" );
-$m->next_warning_like(qr/Permission Denied/);
+$m->next_warning_like(qr/That user may not own tickets in that queue/);
$m->next_warning_like(qr/Could not record email: Ticket not taken/);
$m->no_leftover_warnings_ok;
@@ -771,7 +774,7 @@ DBIx::SearchBuilder::Record::Cachable->FlushCache;
cmp_ok( $tick->Owner, '!=', $user->id, "we didn't change owner" );
is( $tick->Transactions->Count, 3, "no transactions added, user can't take ticket first" );
-$m->next_warning_like(qr/Permission Denied/);
+$m->next_warning_like(qr/That user may not own tickets in that queue/);
$m->next_warning_like(qr/Could not record email: Ticket not taken/);
$m->no_leftover_warnings_ok;
@@ -784,14 +787,14 @@ my $acl = RT::ACL->new(RT->SystemUser);
$acl->Limit( FIELD => 'RightName', VALUE => 'ReplyToTicket' );
$acl->LimitToObject( $RT::System );
while( my $ace = $acl->Next ) {
- $ace->Delete;
+ $ace->Delete;
}
ok( !$user->HasRight( Right => 'ReplyToTicket', Object => $tick ), "User can't reply to ticket any more" );
-my $group = RT::Group->new( RT->SystemUser );
-ok( $group->LoadQueueRoleGroup( Queue => $qid, Type=> 'Owner' ), "load queue owners role group" );
+my $group = $queue->RoleGroup( 'Owner' );
+ok( $group->Id, "load queue owners role group" );
$ace = RT::ACE->new( RT->SystemUser );
($ace_id, $msg) = $group->PrincipalObj->GrantRight( Right => 'ReplyToTicket', Object => $queue );
ok( $ace_id, "Granted queue owners role group with ReplyToTicket right" );
@@ -816,7 +819,8 @@ DBIx::SearchBuilder::Record::Cachable->FlushCache;
$tick->Load( $id );
is( $tick->Owner, $user->id, "we changed owner" );
ok( $user->HasRight( Right => 'ReplyToTicket', Object => $tick ), "owner can reply to ticket" );
-is( $tick->Transactions->Count, 5, "transactions added" );
+# +2 from take, +1 from correspond
+is( $tick->Transactions->Count, 6, "transactions added" );
$m->no_warnings_ok;
diff --git a/rt/t/mail/gnupg-bad.t b/rt/t/mail/gnupg-bad.t
index a1c45be05..570501c30 100644
--- a/rt/t/mail/gnupg-bad.t
+++ b/rt/t/mail/gnupg-bad.t
@@ -10,7 +10,7 @@ use RT::Test::GnuPG
),
};
-RT->Config->Set( 'MailPlugins' => 'Auth::MailFrom', 'Auth::GnuPG' );
+RT->Config->Set( 'MailPlugins' => 'Auth::MailFrom', 'Auth::Crypt' );
my ($baseurl, $m) = RT::Test->started_ok;
diff --git a/rt/t/mail/gnupg-incoming.t b/rt/t/mail/gnupg-incoming.t
index 48d2d9b73..54b30d2a3 100644
--- a/rt/t/mail/gnupg-incoming.t
+++ b/rt/t/mail/gnupg-incoming.t
@@ -28,7 +28,7 @@ ok( $m->login, 'we did log in' );
$m->get( $baseurl.'/Admin/Queues/');
$m->follow_link_ok( {text => 'General'} );
$m->submit_form( form_number => 3,
- fields => { CorrespondAddress => 'general@example.com' } );
+ fields => { CorrespondAddress => 'general@example.com' } );
$m->content_like(qr/general\@example.com.* - never/, 'has key info.');
ok(my $user = RT::User->new(RT->SystemUser));
@@ -73,6 +73,7 @@ run3(
'--default-key' => 'recipient@example.com',
'--homedir' => $homedir,
'--passphrase' => 'recipient',
+ '--no-permission-warning',
),
\"fnord\r\n",
\$buf,
@@ -115,6 +116,7 @@ run3(
'--default-key' => 'recipient@example.com',
'--homedir' => $homedir,
'--passphrase' => 'recipient',
+ '--no-permission-warning',
),
\"clearfnord\r\n",
\$buf,
@@ -157,6 +159,7 @@ run3(
'--default-key' => 'recipient@example.com',
'--homedir' => $homedir,
'--passphrase' => 'recipient',
+ '--no-permission-warning',
),
\"orzzzzzz\r\n",
\$buf,
@@ -187,7 +190,7 @@ RT::Test->close_mailgate_ok($mail);
'recorded incoming mail that is encrypted'
);
is( $msg->GetHeader('X-RT-Privacy'),
- 'PGP',
+ 'GnuPG',
'recorded incoming mail that is encrypted'
);
like( $attach->Content, qr/orz/);
@@ -224,7 +227,7 @@ RT::Test->close_mailgate_ok($mail);
'recorded incoming mail that is encrypted'
);
is( $msg->GetHeader('X-RT-Privacy'),
- 'PGP',
+ 'GnuPG',
'recorded incoming mail that is encrypted'
);
like( $attach->Content, qr/orz/);
@@ -242,6 +245,7 @@ run3(
'--default-key' => 'rt@example.com',
'--homedir' => $homedir,
'--passphrase' => 'test',
+ '--no-permission-warning',
),
\"alright\r\n",
\$buf,
@@ -277,6 +281,7 @@ run3(
qw(gpg --batch --no-tty --armor --encrypt),
'--recipient' => 'random@localhost',
'--homedir' => $homedir,
+ '--no-permission-warning',
),
\"should not be there either\r\n",
\$buf,
@@ -314,6 +319,7 @@ run3(
qw(gpg --batch --no-tty --armor --encrypt),
'--recipient' => 'rt@example.com',
'--homedir' => $homedir,
+ '--no-permission-warning',
),
\"really should not be there either\r\n",
\$buf,
diff --git a/rt/t/mail/gnupg-outgoing-encrypted-plaintext.t b/rt/t/mail/gnupg-outgoing-encrypted-plaintext.t
new file mode 100644
index 000000000..35cfceddd
--- /dev/null
+++ b/rt/t/mail/gnupg-outgoing-encrypted-plaintext.t
@@ -0,0 +1,27 @@
+use strict;
+use warnings;
+
+use RT::Test::GnuPG
+ tests => 104,
+ text_templates => 1,
+ gnupg_options => {
+ passphrase => 'rt-test',
+ 'trust-model' => 'always',
+ };
+
+RT::Test->import_gnupg_key('rt-recipient@example.com');
+RT::Test->import_gnupg_key( 'rt-test@example.com', 'public' );
+
+my $queue = RT::Test->load_or_create_queue(
+ Name => 'Regression',
+ CorrespondAddress => 'rt-recipient@example.com',
+ CommentAddress => 'rt-recipient@example.com',
+ Encrypt => 1,
+);
+ok $queue && $queue->id, 'loaded or created queue';
+
+my ( $baseurl, $m ) = RT::Test->started_ok;
+ok $m->login, 'logged in';
+
+create_and_test_outgoing_emails( $queue, $m );
+
diff --git a/rt/t/mail/gnupg-outgoing-plain-plaintext.t b/rt/t/mail/gnupg-outgoing-plain-plaintext.t
new file mode 100644
index 000000000..32e7d5d8c
--- /dev/null
+++ b/rt/t/mail/gnupg-outgoing-plain-plaintext.t
@@ -0,0 +1,25 @@
+use strict;
+use warnings;
+
+use RT::Test::GnuPG
+ tests => 104,
+ text_templates => 1,
+ gnupg_options => {
+ passphrase => 'rt-test',
+ 'trust-model' => 'always',
+ };
+
+RT::Test->import_gnupg_key('rt-recipient@example.com');
+RT::Test->import_gnupg_key( 'rt-test@example.com', 'public' );
+
+my $queue = RT::Test->load_or_create_queue(
+ Name => 'Regression',
+ CorrespondAddress => 'rt-recipient@example.com',
+ CommentAddress => 'rt-recipient@example.com',
+);
+ok $queue && $queue->id, 'loaded or created queue';
+
+my ( $baseurl, $m ) = RT::Test->started_ok;
+ok $m->login, 'logged in';
+
+create_and_test_outgoing_emails( $queue, $m );
diff --git a/rt/t/mail/gnupg-outgoing-signed-plaintext.t b/rt/t/mail/gnupg-outgoing-signed-plaintext.t
new file mode 100644
index 000000000..cf46edd52
--- /dev/null
+++ b/rt/t/mail/gnupg-outgoing-signed-plaintext.t
@@ -0,0 +1,27 @@
+use strict;
+use warnings;
+
+use RT::Test::GnuPG
+ tests => 104,
+ text_templates => 1,
+ gnupg_options => {
+ passphrase => 'rt-test',
+ 'trust-model' => 'always',
+ };
+
+RT::Test->import_gnupg_key('rt-recipient@example.com');
+RT::Test->import_gnupg_key( 'rt-test@example.com', 'public' );
+
+my $queue = RT::Test->load_or_create_queue(
+ Name => 'Regression',
+ CorrespondAddress => 'rt-recipient@example.com',
+ CommentAddress => 'rt-recipient@example.com',
+ Sign => 1,
+);
+ok $queue && $queue->id, 'loaded or created queue';
+
+my ( $baseurl, $m ) = RT::Test->started_ok;
+ok $m->login, 'logged in';
+
+create_and_test_outgoing_emails( $queue, $m );
+
diff --git a/rt/t/mail/gnupg-outgoing-signed_encrypted-plaintext.t b/rt/t/mail/gnupg-outgoing-signed_encrypted-plaintext.t
new file mode 100644
index 000000000..c2753d00b
--- /dev/null
+++ b/rt/t/mail/gnupg-outgoing-signed_encrypted-plaintext.t
@@ -0,0 +1,28 @@
+use strict;
+use warnings;
+
+use RT::Test::GnuPG
+ tests => 104,
+ text_templates => 1,
+ gnupg_options => {
+ passphrase => 'rt-test',
+ 'trust-model' => 'always',
+ };
+
+RT::Test->import_gnupg_key('rt-recipient@example.com');
+RT::Test->import_gnupg_key( 'rt-test@example.com', 'public' );
+
+my $queue = RT::Test->load_or_create_queue(
+ Name => 'Regression',
+ CorrespondAddress => 'rt-recipient@example.com',
+ CommentAddress => 'rt-recipient@example.com',
+ Sign => 1,
+ Encrypt => 1,
+);
+ok $queue && $queue->id, 'loaded or created queue';
+
+my ( $baseurl, $m ) = RT::Test->started_ok;
+ok $m->login, 'logged in';
+
+create_and_test_outgoing_emails( $queue, $m );
+
diff --git a/rt/t/mail/gnupg-realmail.t b/rt/t/mail/gnupg-realmail.t
index 834014ccc..1609cffbb 100644
--- a/rt/t/mail/gnupg-realmail.t
+++ b/rt/t/mail/gnupg-realmail.t
@@ -62,7 +62,7 @@ sub email_ok {
my ($msg, @attachments) = @{$txn->Attachments->ItemsArrayRef};
is( $msg->GetHeader('X-RT-Privacy'),
- 'PGP',
+ 'GnuPG',
"$eid: recorded incoming mail that is encrypted"
);
diff --git a/rt/t/mail/gnupg-reverification.t b/rt/t/mail/gnupg-reverification.t
index deef1ec24..06c2e0d40 100644
--- a/rt/t/mail/gnupg-reverification.t
+++ b/rt/t/mail/gnupg-reverification.t
@@ -1,7 +1,7 @@
use strict;
use warnings;
-use RT::Test::GnuPG tests => 232, gnupg_options => { passphrase => 'rt-test' };
+use RT::Test::GnuPG tests => undef, gnupg_options => { passphrase => 'rt-test' };
diag "load Everyone group";
my $everyone;
@@ -46,8 +46,7 @@ foreach my $file ( @files ) {
is $status >> 8, 0, "$eid: the mail gateway exited normally";
ok $id, "$eid: got id of a newly created ticket - $id";
- like($warnings, qr/Had a problem during decrypting and verifying/);
- like($warnings, qr/public key not found/);
+ like($warnings, qr/Public key '0xD328035D84881F1B' is not available/);
my $ticket = RT::Ticket->new( RT->SystemUser );
$ticket->Load( $id );
@@ -62,12 +61,10 @@ foreach my $file ( @files ) {
$m->content_like(qr/This is .*ID:$eid/ims, "$eid: content is there and message is decrypted");
$m->next_warning_like(qr/public key not found/);
- $m->next_warning_like(qr/above error may result from an unconfigured RT\/GPG/);
# some mails contain multiple signatures
if ($eid == 5 || $eid == 17 || $eid == 18) {
$m->next_warning_like(qr/public key not found/);
- $m->next_warning_like(qr/above error may result from an unconfigured RT\/GPG/);
}
$m->no_leftover_warnings_ok;
@@ -90,3 +87,5 @@ foreach my $id ( @ticket_ids ) {
$m->no_warnings_ok;
}
+undef $m;
+done_testing;
diff --git a/rt/t/mail/header-characters.t b/rt/t/mail/header-characters.t
index 004ba8522..38a04b5df 100644
--- a/rt/t/mail/header-characters.t
+++ b/rt/t/mail/header-characters.t
@@ -6,14 +6,10 @@ use Test::Warn;
my ($baseurl, $m) = RT::Test->started_ok;
-diag "Testing non-ASCII in From: header";
-SKIP:{
- skip "Test requires Email::Address 1.893 or later, "
- . "you have $Email::Address::VERSION", 3,
- if $Email::Address::VERSION < 1.893;
-
+diag "Testing non-ASCII latin1 in From: header";
+{
my $mail = Encode::encode( 'iso-8859-1', Encode::decode( "UTF-8", <<'.') );
-From: René@example.com>
+From: <René@example.com>
Reply-To: =?iso-8859-1?Q?Ren=E9?= <René@example.com>
Subject: testing non-ASCII From
Content-Type: text/plain; charset=iso-8859-1
@@ -23,24 +19,20 @@ here's some content
my ($status, $id);
warnings_like { ( $status, $id ) = RT::Test->send_via_mailgate($mail) }
- [qr/Failed to parse Reply-To:.*, From:/,
+ [(qr/Unable to parse an email address from/) x 2,
qr/Couldn't parse or find sender's address/
],
'Got parse error for non-ASCII in From';
- is( $status >> 8, 0, "The mail gateway exited normally" );
TODO: {
- local $TODO = "Currently don't handle non-ASCII for sender";
- ok( $id, "Created ticket" );
- }
+ local $TODO = "Currently don't handle non-ASCII for sender";
+ is( $status >> 8, 0, "The mail gateway exited normally" );
+ ok( $id, "Created ticket" );
+ }
}
-diag "Testing iso-8859-1 encoded non-ASCII in From: header";
-SKIP:{
- skip "Test requires Email::Address 1.893 or later, "
- . "you have $Email::Address::VERSION", 3,
- if $Email::Address::VERSION < 1.893;
-
- my $mail = Encode::encode( 'iso-8859-1', Encode::decode( "UTF-8", <<'.' ) );
+diag "Testing non-ASCII latin1 in From: header with MIME-word-encoded phrase";
+{
+ my $mail = Encode::encode( 'iso-8859-1', Encode::decode( "UTF-8", <<'.') );
From: =?iso-8859-1?Q?Ren=E9?= <René@example.com>
Reply-To: =?iso-8859-1?Q?Ren=E9?= <René@example.com>
Subject: testing non-ASCII From
@@ -51,14 +43,14 @@ here's some content
my ($status, $id);
warnings_like { ( $status, $id ) = RT::Test->send_via_mailgate($mail) }
- [qr/Failed to parse Reply-To:.*, From:/,
+ [(qr/Unable to parse an email address from/) x 2,
qr/Couldn't parse or find sender's address/
],
'Got parse error for iso-8859-1 in From';
- is( $status >> 8, 0, "The mail gateway exited normally" );
TODO: {
- local $TODO = "Currently don't handle non-ASCII in sender";
- ok( $id, "Created ticket" );
+ local $TODO = "Currently don't handle non-ASCII in sender";
+ is( $status >> 8, 0, "The mail gateway exited normally" );
+ ok( $id, "Created ticket" );
}
}
@@ -76,6 +68,6 @@ here's some content
warnings_like { ( $status, $id ) = RT::Test->send_via_mailgate($mail) }
[qr/Couldn't parse or find sender's address/],
'Got parse error with no sender fields';
- is( $status >> 8, 0, "The mail gateway exited normally" );
+ is( $status >> 8, 1, "The mail gateway failed" );
ok( !$id, "No ticket created" );
}
diff --git a/rt/t/mail/html-outgoing.t b/rt/t/mail/html-outgoing.t
new file mode 100644
index 000000000..a37f52cdd
--- /dev/null
+++ b/rt/t/mail/html-outgoing.t
@@ -0,0 +1,187 @@
+use strict;
+use warnings;
+use RT::Test tests => undef;
+
+use RT::Test::Email;
+use Test::Warn;
+
+my $root = RT::User->new(RT->SystemUser);
+$root->Load('root');
+
+# Set root as admincc
+my $q = RT::Queue->new(RT->SystemUser);
+$q->Load('General');
+my ($ok, $msg) = $q->AddWatcher( Type => 'AdminCc', PrincipalId => $root->Id );
+ok($ok, "Added root as a watcher on the General queue");
+
+# Create a couple users to test notifications
+my %users;
+for my $user_name (qw(enduser tech)) {
+ my $user = $users{$user_name} = RT::User->new(RT->SystemUser);
+ $user->Create( Name => ucfirst($user_name),
+ Privileged => 1,
+ EmailAddress => $user_name.'@example.com');
+ my ($val, $msg);
+ ($val, $msg) = $user->PrincipalObj->GrantRight(Object =>$q, Right => $_)
+ for qw(ModifyTicket OwnTicket ShowTicket);
+}
+
+my $t = RT::Ticket->new(RT->SystemUser);
+my ($tid, $ttrans, $tmsg);
+
+diag "Autoreply and AdminCc (Transaction)";
+mail_ok {
+ ($tid, $ttrans, $tmsg) =
+ $t->Create(Subject => "The internet is broken",
+ Owner => 'Tech', Requestor => 'Enduser',
+ Queue => 'General');
+} { from => qr/The default queue/,
+ to => 'enduser@example.com',
+ subject => qr/\Q[example.com #1] AutoReply: The internet is broken\E/,
+ body => parts_regex(
+ 'trouble ticket regarding \*?The internet is broken\*?',
+ 'trouble ticket regarding <b>The internet is broken</b>'
+ ),
+ 'Content-Type' => qr{multipart},
+},{ from => qr/RT System/,
+ bcc => 'root@localhost',
+ subject => qr/\Q[example.com #1] The internet is broken\E/,
+ body => parts_regex(
+ 'Request (\[\d+\])?1(\s*[(<]http://localhost:\d+/Ticket/Display\.html\?id=1[)>])?\s*was acted upon by RT_System',
+ 'Request <a href="http://localhost:\d+/Ticket/Display\.html\?id=1">1</a> was acted upon by RT_System\.</b>'
+ ),
+ 'Content-Type' => qr{multipart},
+};
+
+diag "Admin Correspondence and Correspondence";
+mail_ok {
+ ($ok, $tmsg) = $t->Correspond(
+ MIMEObj => HTML::Mason::Commands::MakeMIMEEntity(
+ Body => '<p>This is a test of <b>HTML</b> correspondence.</p>',
+ Type => 'text/html',
+ ),
+ );
+} { from => qr/RT System/,
+ bcc => 'root@localhost',
+ subject => qr/\Q[example.com #1] The internet is broken\E/,
+ body => parts_regex(
+ 'Ticket URL: (?:\[\d+\])?http://localhost:\d+/Ticket/Display\.html\?id=1.+?'.
+ 'This is a test of \*?HTML\*? correspondence\.',
+ 'Ticket URL: <a href="(http://localhost:\d+/Ticket/Display\.html\?id=1)">\1</a>.+?'.
+ '<p>This is a test of <b>HTML</b> correspondence\.</p>'
+ ),
+ 'Content-Type' => qr{multipart},
+},{ from => qr/RT System/,
+ to => 'enduser@example.com',
+ subject => qr/\Q[example.com #1] The internet is broken\E/,
+ body => parts_regex(
+ 'This is a test of \*?HTML\*? correspondence\.',
+ '<p>This is a test of <b>HTML</b> correspondence\.</p>'
+ ),
+ 'Content-Type' => qr{multipart},
+};
+
+SKIP: {
+ skip "Only fails on core HTMLFormatter", 9
+ unless RT->Config->Get("HTMLFormatter") eq "core";
+ diag "Failing HTML -> Text conversion";
+ warnings_like {
+ my $body = '<table><tr><td><table><tr><td>Foo</td></tr></table></td></tr></table>';
+ mail_ok {
+ ($ok, $tmsg) = $t->Correspond(
+ MIMEObj => HTML::Mason::Commands::MakeMIMEEntity(
+ Body => $body,
+ Type => 'text/html',
+ ),
+ );
+ } { from => qr/RT System/,
+ bcc => 'root@localhost',
+ subject => qr/\Q[example.com #1] The internet is broken\E/,
+ body => qr{Ticket URL: <a href="(http://localhost:\d+/Ticket/Display\.html\?id=1)">\1</a>.+?$body}s,
+ 'Content-Type' => qr{text/html}, # TODO
+ },{ from => qr/RT System/,
+ to => 'enduser@example.com',
+ subject => qr/\Q[example.com #1] The internet is broken\E/,
+ body => qr{$body},
+ 'Content-Type' => qr{text/html}, # TODO
+ };
+ } [(qr/uninitialized value/, qr/Failed to downgrade HTML/)x3];
+}
+
+
+diag "Admin Comment in HTML";
+mail_ok {
+ ($ok, $tmsg) = $t->Comment(
+ MIMEObj => HTML::Mason::Commands::MakeMIMEEntity(
+ Body => '<p>Comment test, <em>please!</em></p>',
+ Type => 'text/html',
+ ),
+ );
+} { from => qr/RT System/,
+ bcc => 'root@localhost',
+ subject => qr/\Q[example.com #1] [Comment] The internet is broken\E/,
+ body => parts_regex(
+ 'This is a comment about (\[\d+\])?ticket.1(\s*[(<]http://localhost:\d+/Ticket/Display\.html\?id=1[)>])?\..+?'.
+ 'It is not sent to the Requestor\(s\):.+?'.
+ 'Comment test, _?please!_?',
+
+ '<p>This is a comment about <a href="http://localhost:\d+/Ticket/Display\.html\?id=1">ticket 1</a>\. '.
+ 'It is not sent to the Requestor\(s\):</p>.+?'.
+ '<p>Comment test, <em>please!</em></p>',
+ ),
+ 'Content-Type' => qr{multipart},
+};
+
+
+diag "Resolved in HTML templates";
+mail_ok {
+ ($ok, $tmsg) = $t->SetStatus('resolved');
+} { from => qr/RT System/,
+ to => 'enduser@example.com',
+ subject => qr/\Q[example.com #1] Resolved: The internet is broken\E/,
+ body => parts_regex(
+ 'According to our records, your request has been resolved\.',
+ '<p>According to our records, your request has been resolved\.',
+ ),
+ 'Content-Type' => qr{multipart},
+};
+
+
+diag "Status changes in HTML";
+my $scrip = RT::Scrip->new(RT->SystemUser);
+my ($sval, $smsg) =$scrip->Create(
+ ScripCondition => 'On Status Change',
+ ScripAction => 'Notify Requestors',
+ Template => 'Status Change in HTML',
+ Queue => $q->Id,
+ Description => 'Tell requestors about status changes'
+);
+ok ($sval, $smsg);
+ok ($scrip->Id, "Created the scrip");
+ok ($scrip->TemplateObj->Id, "Created the scrip template");
+ok ($scrip->ConditionObj->Id, "Created the scrip condition");
+ok ($scrip->ActionObj->Id, "Created the scrip action");
+
+mail_ok {
+ ($ok, $tmsg) = $t->SetStatus('stalled');
+} { from => qr/RT System/,
+ to => 'enduser@example.com',
+ subject => qr/\Q[example.com #1] Status Changed to: stalled\E/,
+ body => parts_regex(
+ 'http://localhost:\d+/Ticket/Display\.html\?id=1.+?',
+ '<a href="(http://localhost:\d+/Ticket/Display\.html\?id=1)">\1</a>'
+ ),
+ 'Content-Type' => qr{multipart},
+};
+
+done_testing;
+
+sub parts_regex {
+ my ($text, $html) = @_;
+
+ my $pattern = 'Content-Type: text/plain.+?' . $text . '.+?' .
+ 'Content-Type: text/html.+?' . $html;
+
+ return qr/$pattern/s;
+}
+
diff --git a/rt/t/mail/mime_decoding.t b/rt/t/mail/mime_decoding.t
index fbf884932..1126f1f84 100644
--- a/rt/t/mail/mime_decoding.t
+++ b/rt/t/mail/mime_decoding.t
@@ -1,14 +1,23 @@
use strict;
use warnings;
-use RT::Test nodb => 1, tests => 14;
+use RT::Test nodb => 1, tests => undef;
+use Test::LongString;
+use Test::Warn;
use_ok('RT::I18N');
diag q{'=' char in a leading part before an encoded part};
{
my $str = 'key="plain"; key="=?UTF-8?B?0LzQvtC5X9GE0LDQudC7LmJpbg==?="';
+ warnings_like {
+ is(
+ RT::I18N::DecodeMIMEWordsToUTF8($str),
+ 'key="plain"; key="мой_файл.bin"',
+ "right decoding"
+ );
+ } [qr/DecodeMIMEWordsTo.*?called without field name/i];
is(
- RT::I18N::DecodeMIMEWordsToUTF8($str),
+ RT::I18N::DecodeMIMEWordsToUTF8($str, 'content-disposition'),
'key="plain"; key="мой_файл.bin"',
"right decoding"
);
@@ -17,8 +26,15 @@ diag q{'=' char in a leading part before an encoded part};
diag q{not compliant with standards, but MUAs send such field when attachment has non-ascii in name};
{
my $str = 'attachment; filename="=?UTF-8?B?0LzQvtC5X9GE0LDQudC7LmJpbg==?="';
+ warnings_like {
+ is(
+ RT::I18N::DecodeMIMEWordsToUTF8($str),
+ 'attachment; filename="мой_файл.bin"',
+ "right decoding"
+ );
+ } [qr/DecodeMIMEWordsTo.*?called without field name/i];
is(
- RT::I18N::DecodeMIMEWordsToUTF8($str),
+ RT::I18N::DecodeMIMEWordsToUTF8($str, 'content-disposition'),
'attachment; filename="мой_файл.bin"',
"right decoding"
);
@@ -27,8 +43,15 @@ diag q{not compliant with standards, but MUAs send such field when attachment ha
diag q{'=' char in a trailing part after an encoded part};
{
my $str = 'attachment; filename="=?UTF-8?B?0LzQvtC5X9GE0LDQudC7LmJpbg==?="; some_prop="value"';
+ warnings_like {
+ is(
+ RT::I18N::DecodeMIMEWordsToUTF8($str),
+ 'attachment; filename="мой_файл.bin"; some_prop="value"',
+ "right decoding"
+ );
+ } [qr/DecodeMIMEWordsTo.*?called without field name/i];
is(
- RT::I18N::DecodeMIMEWordsToUTF8($str),
+ RT::I18N::DecodeMIMEWordsToUTF8($str, 'content-disposition'),
'attachment; filename="мой_файл.bin"; some_prop="value"',
"right decoding"
);
@@ -36,12 +59,9 @@ diag q{'=' char in a trailing part after an encoded part};
diag q{adding quotes around mime words containing specials when word is already quoted};
{
- my $str = <<"END";
-Content-Disposition: attachment; filename="=?iso-8859-1?Q?foobar,_?=
- =?iso-8859-1?Q?barfoo.docx?="
-END
- my $decoded = 'Content-Disposition: attachment; filename="foobar, barfoo.docx"';
- is( RT::I18N::DecodeMIMEWordsToUTF8($str), $decoded, "No added quotes" );
+ my $str = 'attachment; filename="=?iso-8859-1?Q?foobar,_?=' . "\n" . '=?iso-8859-1?Q?barfoo.docx?="';
+ my $decoded = 'attachment; filename="foobar, barfoo.docx"';
+ is( RT::I18N::DecodeMIMEWordsToUTF8($str, 'content-disposition'), $decoded, "No added quotes" );
}
diag q{regression test for #5248 from rt3.fsck.com};
@@ -49,7 +69,7 @@ diag q{regression test for #5248 from rt3.fsck.com};
my $str = qq{Subject: =?ISO-8859-1?Q?Re=3A_=5BXXXXXX=23269=5D_=5BComment=5D_Frag?=}
. qq{\n =?ISO-8859-1?Q?e_zu_XXXXXX--xxxxxx_/_Xxxxx=FCxxxxxxxxxx?=};
is(
- RT::I18N::DecodeMIMEWordsToUTF8($str),
+ RT::I18N::DecodeMIMEWordsToUTF8($str, 'Subject'),
qq{Subject: Re: [XXXXXX#269] [Comment] Frage zu XXXXXX--xxxxxx / Xxxxxüxxxxxxxxxx},
"right decoding"
);
@@ -58,9 +78,16 @@ diag q{regression test for #5248 from rt3.fsck.com};
diag q{newline and encoded file name};
{
my $str = qq{application/vnd.ms-powerpoint;\n\tname="=?ISO-8859-1?Q?Main_presentation.ppt?="};
+ warnings_like {
+ is(
+ RT::I18N::DecodeMIMEWordsToUTF8($str),
+ qq{application/vnd.ms-powerpoint;\tname="Main presentation.ppt"},
+ "right decoding"
+ );
+ } [qr/DecodeMIMEWordsTo.*?called without field name/i];
is(
- RT::I18N::DecodeMIMEWordsToUTF8($str),
- qq{application/vnd.ms-powerpoint;\tname="Main presentation.ppt"},
+ RT::I18N::DecodeMIMEWordsToUTF8($str,'content-type'),
+ qq{application/vnd.ms-powerpoint; name="Main presentation.ppt"},
"right decoding"
);
}
@@ -97,54 +124,116 @@ inline;
diag q{canonicalize mime word encodings like gb2312};
{
my $str = qq{Subject: =?gb2312?B?1NrKwL3nuPe12Lmy09CzrN9eX1NpbXBsaWZpZWRfQ05fR0IyMzEyYQ==?=
- =?gb2312?B?dHRhY2hlbWVudCB0ZXN0IGluIENOIHNpbXBsaWZpZWQ=?=};
+\t=?gb2312?B?dHRhY2hlbWVudCB0ZXN0IGluIENOIHNpbXBsaWZpZWQ=?=};
is(
- RT::I18N::DecodeMIMEWordsToUTF8($str),
+ RT::I18N::DecodeMIMEWordsToUTF8($str, "Subject"),
qq{Subject: 在世界各地共有超過_Simplified_CN_GB2312attachement test in CN simplified},
"right decoding"
);
}
-
diag q{Whitespace between encoded words should be removed};
{
- my $str = "=?utf-8?Q?=E3=82=AD?= =?utf-8?Q?=E3=83=A3?=";
- is(
- RT::I18N::DecodeMIMEWordsToUTF8($str),
- "キャ",
- "whitespace between encoded words is removed",
- );
-
- $str = "=?utf-8?Q?=E3=82=AD?= \n =?utf-8?Q?=E3=83=A3?=";
- is(
- RT::I18N::DecodeMIMEWordsToUTF8($str),
- "キャ",
- "newlines between encoded words also removed",
- );
+ warnings_like {
+ my $str = "=?utf-8?Q?=E3=82=AD?= =?utf-8?Q?=E3=83=A3?=";
+ is(
+ RT::I18N::DecodeMIMEWordsToUTF8($str),
+ "キャ",
+ "whitespace between encoded words is removed",
+ );
+
+ $str = "=?utf-8?Q?=E3=82=AD?= \n =?utf-8?Q?=E3=83=A3?=";
+ is(
+ RT::I18N::DecodeMIMEWordsToUTF8($str),
+ "キャ",
+ "newlines between encoded words also removed",
+ );
+ } [(qr/DecodeMIMEWordsTo.*?called without field name/i) x 2];
}
diag q{Multiple octets split across QP hunks are correctly reassembled};
{
- # This passes even without explicit code to handle it because utf8
- # is perl's internal string encoding.
- my $str = "=?utf-8?Q?=E3?= =?utf-8?Q?=82?= =?utf-8?Q?=AD?=";
- is(
- RT::I18N::DecodeMIMEWordsToUTF8($str),
- "キ",
- "UTF8 character split in three is successfully reassembled",
- );
-
- # Non-utf8 encodings thus also must be checked
- $str = <<EOT; chomp $str;
+ warnings_like {
+ # This passes even without explicit code to handle it because utf8
+ # is perl's internal string encoding.
+ my $str = "=?utf-8?Q?=E3?= =?utf-8?Q?=82?= =?utf-8?Q?=AD?=";
+ is(
+ RT::I18N::DecodeMIMEWordsToUTF8($str),
+ "キ",
+ "UTF8 character split in three is successfully reassembled",
+ );
+
+ # Non-utf8 encodings thus also must be checked
+ $str = <<EOT; chomp $str;
=?gb2312?q?Chinese(gb2312)=20=20=C3=C0=B9=FA=C7=B0=CB=BE=B7=A8=B2=BF=B3?=
=?gb2312?q?=A4=C3=E6=BC=FB=C8=F8=B4=EF=C4=B7=BA=F3=B3=C6=C6=E4=D7=B4=CC=AC?=
=?gb2312?q?=BA=DC=BA=C3=20=20Chinese=20(gb2312)?=
EOT
- is(
- RT::I18N::DecodeMIMEWordsToUTF8($str),
- "Chinese(gb2312) 美国前司法部长面见萨达姆后称其状态很好 Chinese (gb2312)",
- "gb2312 character is successfully reassembled",
+ is(
+ RT::I18N::DecodeMIMEWordsToUTF8($str),
+ "Chinese(gb2312) 美国前司法部长面见萨达姆后称其状态很好 Chinese (gb2312)",
+ "gb2312 character is successfully reassembled",
+ );
+ } [(qr/DecodeMIMEWordsTo.*?called without field name/i) x 2];
+}
+
+diag "multiple mime words containing special chars already in quotes";
+{
+ my $str = q{attachment; filename="=?ISO-2022-JP?B?Mi4bJEIlSyVlITwlOSVqJWohPCU5GyhC?= =?ISO-2022-JP?B?LnBkZg==?="};
+ is_string(
+ RT::I18N::DecodeMIMEWordsToUTF8($str, 'Content-Disposition'),
+ q{attachment; filename="2.ニュースリリース.pdf"},
+ "base64"
);
+ $str = q{attachment; filename="=?UTF-8?Q?2=2E=E3=83=8B=E3=83=A5=E3=83=BC=E3=82=B9=E3=83=AA=E3=83=AA?= =?UTF-8?Q?=E3=83=BC=E3=82=B9=2Epdf?="};
+ is_string(
+ RT::I18N::DecodeMIMEWordsToUTF8($str, 'Content-Disposition'),
+ q{attachment; filename="2.ニュースリリース.pdf"},
+ "QP"
+ );
}
+
+diag "mime word combined with text in quoted filename property";
+{
+ my $str = q{attachment; filename="=?UTF-8?B?Q2VjaSBuJ2VzdCBwYXMgdW5l?= pipe.pdf"};
+ is_string(
+ RT::I18N::DecodeMIMEWordsToUTF8($str, 'Content-Disposition'),
+ q{attachment; filename="Ceci n'est pas une pipe.pdf"},
+ "base64"
+ );
+
+ $str = q{attachment; filename="=?UTF-8?B?Q2VjaSBuJ2VzdCBwYXMgdW5lLi4u?= pipe.pdf"};
+ is_string(
+ RT::I18N::DecodeMIMEWordsToUTF8($str, 'Content-Disposition'),
+ q{attachment; filename="Ceci n'est pas une... pipe.pdf"},
+ "base64"
+ );
+
+ $str = q{attachment; filename="=?UTF-8?Q?Ceci n'est pas une?= pipe.pdf"};
+ is_string(
+ RT::I18N::DecodeMIMEWordsToUTF8($str, 'Content-Disposition'),
+ q{attachment; filename="Ceci n'est pas une pipe.pdf"},
+ "QP"
+ );
+
+ $str = q{attachment; filename="=?UTF-8?Q?Ceci n'est pas une...?= pipe.pdf"};
+ is_string(
+ RT::I18N::DecodeMIMEWordsToUTF8($str, 'Content-Disposition'),
+ q{attachment; filename="Ceci n'est pas une... pipe.pdf"},
+ "QP"
+ );
+}
+
+diag "quotes in filename";
+{
+ my $str = q{attachment; filename="=?UTF-8?B?YSAicXVvdGVkIiBmaWxl?="};
+ is_string(
+ RT::I18N::DecodeMIMEWordsToUTF8($str, 'Content-Disposition'),
+ q{attachment; filename="a \"quoted\" file"},
+ "quoted filename correctly decoded"
+ );
+}
+
+done_testing;
diff --git a/rt/t/mail/multipart.t b/rt/t/mail/multipart.t
index 1c1106421..644305ebd 100644
--- a/rt/t/mail/multipart.t
+++ b/rt/t/mail/multipart.t
@@ -1,7 +1,7 @@
use strict;
use warnings;
-use RT::Test tests => 4;
+use RT::Test tests => 4, config => q{Set($CorrespondAddress, 'rt@example.com');};
use RT::Test::Email;
my $queue = RT::Test->load_or_create_queue( Name => 'General' );
@@ -37,4 +37,4 @@ is(@msgs,2,"sent 2 emails");
diag("We're skipping any testing of the autoreply");
my $entity = parse_mail($msgs[1]);
-is($entity->parts, 0, "only one entity");
+is($entity->parts, 2, "only two parts");
diff --git a/rt/t/mail/one-time-recipients.t b/rt/t/mail/one-time-recipients.t
index a9881cded..1bc172d71 100644
--- a/rt/t/mail/one-time-recipients.t
+++ b/rt/t/mail/one-time-recipients.t
@@ -1,7 +1,9 @@
use strict;
use warnings;
-use RT::Test tests => 38;
+use RT::Test tests => undef;
+use RT::Test::Email;
+use Test::Warn;
my $queue = RT::Test->load_or_create_queue(
Name => 'General',
@@ -17,191 +19,149 @@ my $user = RT::Test->load_or_create_user(
ok $user && $user->id, 'loaded or created user';
diag "Reply to ticket with actor as one time cc";
-{
+warnings_are {
my $ticket = RT::Ticket->new( RT::CurrentUser->new( $user ) );
- my ($status, undef, $msg) = $ticket->Create(
- Queue => $queue->id,
- Subject => 'test',
- Requestor => 'root@localhost',
- );
- ok $status, "created ticket";
-
- my @mails = RT::Test->fetch_caught_mails;
- ok @mails, "got some outgoing emails";
- foreach my $mail ( @mails ) {
- my $entity = parse_mail( $mail );
- my $to = $entity->head->get('To');
- $to =~ s/^\s+|\s+$//;
- is $to, 'root@localhost', 'got mail'
- }
+ mail_ok {
+ my ($status, undef, $msg) = $ticket->Create(
+ Queue => $queue->id,
+ Subject => 'test',
+ Requestor => 'root@localhost',
+ );
+ ok $status, "created ticket";
+ } { To => 'root@localhost' };
RT->Config->Set( NotifyActor => 1 );
- ($status, $msg) = $ticket->Correspond(
- Content => 'test mail',
- );
- ok $status, "replied to a ticket";
-
- @mails = RT::Test->fetch_caught_mails;
- ok @mails, "got some outgoing emails";
- foreach my $mail ( @mails ) {
- my $entity = parse_mail( $mail );
- my $to = $entity->head->get('To');
- $to =~ s/^\s+|\s+$//;
- is $to, 'root@localhost', 'got mail'
- }
+ mail_ok {
+ my ($status, $msg) = $ticket->Correspond(
+ Content => 'test mail',
+ );
+ ok $status, "replied to a ticket";
+ } { To => 'root@localhost' };
RT->Config->Set( NotifyActor => 0 );
- ($status, $msg) = $ticket->Correspond(
- Content => 'test mail',
- );
- ok $status, "replied to a ticket";
-
- @mails = RT::Test->fetch_caught_mails;
- ok !@mails, "no mail - don't notify actor";
-
- ($status, $msg) = $ticket->Correspond(
- Content => 'test mail',
- CcMessageTo => 'root@localhost',
- );
- ok $status, "replied to a ticket";
-
- @mails = RT::Test->fetch_caught_mails;
- ok @mails, "got some outgoing emails";
- foreach my $mail ( @mails ) {
- my $entity = parse_mail( $mail );
- my $to = $entity->head->get('Cc');
- $to =~ s/^\s+|\s+$//;
- is $to, 'root@localhost', 'got mail'
- }
-}
+ mail_ok {
+ my ($status, $msg) = $ticket->Correspond(
+ Content => 'test mail',
+ );
+ ok $status, "replied to a ticket";
+ };
+
+ mail_ok {
+ my ($status, $msg) = $ticket->Correspond(
+ Content => 'test mail',
+ CcMessageTo => 'root@localhost',
+ );
+ ok $status, "replied to a ticket";
+ } { Cc => 'root@localhost' };
+} [];
diag "Reply to ticket with requestor squelched";
-{
+warnings_are {
my $ticket = RT::Ticket->new( RT::CurrentUser->new( $user ) );
- my ($status, undef, $msg) = $ticket->Create(
- Queue => $queue->id,
- Subject => 'test',
- Requestor => 'test@localhost',
- );
- ok $status, "created ticket";
-
- my @mails = RT::Test->fetch_caught_mails;
- ok @mails, "got some outgoing emails";
- foreach my $mail ( @mails ) {
- my $entity = parse_mail( $mail );
- my $to = $entity->head->get('To');
- $to =~ s/^\s+|\s+$//;
- is $to, 'test@localhost', 'got mail'
- }
-
- ($status, $msg) = $ticket->Correspond(
- Content => 'test mail',
- );
- ok $status, "replied to a ticket";
-
- @mails = RT::Test->fetch_caught_mails;
- ok @mails, "got some outgoing emails";
- foreach my $mail ( @mails ) {
- my $entity = parse_mail( $mail );
- my $to = $entity->head->get('To');
- $to =~ s/^\s+|\s+$//;
- is $to, 'test@localhost', 'got mail'
- }
+ mail_ok {
+ my ($status, undef, $msg) = $ticket->Create(
+ Queue => $queue->id,
+ Subject => 'test',
+ Requestor => 'test@localhost',
+ );
+ ok $status, "created ticket";
+ } { To => 'test@localhost' };
+
+ mail_ok {
+ my ($status, $msg) = $ticket->Correspond(
+ Content => 'test mail',
+ );
+ ok $status, "replied to a ticket";
+ } { To => 'test@localhost' };
$ticket->SquelchMailTo('test@localhost');
- ($status, $msg) = $ticket->Correspond(
- Content => 'test mail',
- );
- ok $status, "replied to a ticket";
-
- @mails = RT::Test->fetch_caught_mails;
- ok !@mails, "no mail - squelched";
-
- ($status, $msg) = $ticket->Correspond(
- Content => 'test mail',
- CcMessageTo => 'test@localhost',
- );
- ok $status, "replied to a ticket";
-
- @mails = RT::Test->fetch_caught_mails;
- ok @mails, "got some outgoing emails";
- foreach my $mail ( @mails ) {
- my $entity = parse_mail( $mail );
- my $to = $entity->head->get('Cc');
- $to =~ s/^\s+|\s+$//;
- is $to, 'test@localhost', 'got mail'
- }
-}
+ mail_ok {
+ my ($status, $msg) = $ticket->Correspond(
+ Content => 'test mail',
+ );
+ ok $status, "replied to a ticket";
+ };
+
+ mail_ok {
+ my ($status, $msg) = $ticket->Correspond(
+ Content => 'test mail',
+ CcMessageTo => 'test@localhost',
+ );
+ ok $status, "replied to a ticket";
+ } { Cc => 'test@localhost' };
+} [];
diag "Reply to ticket with requestor squelched";
-{
+warnings_are {
my $ticket = RT::Ticket->new( RT::CurrentUser->new( $user ) );
- my ($status, undef, $msg) = $ticket->Create(
- Queue => $queue->id,
- Subject => 'test',
- Requestor => 'test@localhost',
- );
- ok $status, "created ticket";
-
- my @mails = RT::Test->fetch_caught_mails;
- ok @mails, "got some outgoing emails";
- foreach my $mail ( @mails ) {
- my $entity = parse_mail( $mail );
- my $to = $entity->head->get('To');
- $to =~ s/^\s+|\s+$//;
- is $to, 'test@localhost', 'got mail'
- }
-
- ($status, $msg) = $ticket->Correspond(
- Content => 'test mail',
- );
- ok $status, "replied to a ticket";
-
- @mails = RT::Test->fetch_caught_mails;
- ok @mails, "got some outgoing emails";
- foreach my $mail ( @mails ) {
- my $entity = parse_mail( $mail );
- my $to = $entity->head->get('To');
- $to =~ s/^\s+|\s+$//;
- is $to, 'test@localhost', 'got mail'
- }
-
- ($status, $msg) = $ticket->Correspond(
- Content => 'test mail',
- SquelchMailTo => ['test@localhost'],
- );
- ok $status, "replied to a ticket";
-
- @mails = RT::Test->fetch_caught_mails;
- ok !@mails, "no mail - squelched";
-
- ($status, $msg) = $ticket->Correspond(
- Content => 'test mail',
- );
- ok $status, "replied to a ticket";
-
- @mails = RT::Test->fetch_caught_mails;
- ok @mails, "got some outgoing emails";
- foreach my $mail ( @mails ) {
- my $entity = parse_mail( $mail );
- my $to = $entity->head->get('To');
- $to =~ s/^\s+|\s+$//;
- is $to, 'test@localhost', 'got mail'
- }
-
- ($status, $msg) = $ticket->Correspond(
- Content => 'test mail',
- CcMessageTo => 'test@localhost',
- SquelchMailTo => ['test@localhost'],
- );
- ok $status, "replied to a ticket";
-
- @mails = RT::Test->fetch_caught_mails;
- ok @mails, "got some outgoing emails";
- foreach my $mail ( @mails ) {
- my $entity = parse_mail( $mail );
- my $to = $entity->head->get('Cc');
- $to =~ s/^\s+|\s+$//;
- is $to, 'test@localhost', 'got mail'
- }
-}
+ mail_ok {
+ my ($status, undef, $msg) = $ticket->Create(
+ Queue => $queue->id,
+ Subject => 'test',
+ Requestor => 'test@localhost',
+ );
+ ok $status, "created ticket";
+ } { To => 'test@localhost' };
+
+ mail_ok {
+ my ($status, $msg) = $ticket->Correspond(
+ Content => 'test mail',
+ );
+ ok $status, "replied to a ticket";
+ } { To => 'test@localhost' };
+
+ mail_ok {
+ my ($status, $msg) = $ticket->Correspond(
+ Content => 'test mail',
+ SquelchMailTo => ['test@localhost'],
+ );
+ ok $status, "replied to a ticket";
+ };
+
+ mail_ok {
+ my ($status, $msg) = $ticket->Correspond(
+ Content => 'test mail',
+ );
+ ok $status, "replied to a ticket";
+ } { To => 'test@localhost' };
+
+ mail_ok {
+ my ($status, $msg) = $ticket->Correspond(
+ Content => 'test mail',
+ CcMessageTo => 'test@localhost',
+ SquelchMailTo => ['test@localhost'],
+ );
+ ok $status, "replied to a ticket";
+ } { Cc => 'test@localhost' };
+} [];
+
+diag "Requestor is an RT address";
+warnings_are {
+ my $ticket = RT::Ticket->new( RT::CurrentUser->new( $user ) );
+ mail_ok {
+ my ($status, undef, $msg) = $ticket->Create(
+ Queue => $queue->id,
+ Subject => 'test',
+ Requestor => 'rt-address@example.com',
+ );
+ ok $status, "created ticket";
+ } { To => 'rt-address@example.com' };
+
+ RT->Config->Set( RTAddressRegexp => qr/^rt-address\@example\.com$/i );
+ mail_ok {
+ my ($status, $msg) = $ticket->Correspond(
+ Content => 'test mail',
+ );
+ ok $status, "replied to a ticket";
+ };
+
+ mail_ok {
+ my ($status, $msg) = $ticket->Correspond(
+ Content => 'test mail',
+ CcMessageTo => 'rt-address@example.com',
+ );
+ ok $status, "replied to a ticket";
+ };
+} [];
+
+done_testing;
diff --git a/rt/t/mail/outlook.t b/rt/t/mail/outlook.t
index 752a91fae..8f3b71bc8 100644
--- a/rt/t/mail/outlook.t
+++ b/rt/t/mail/outlook.t
@@ -15,11 +15,11 @@ X-Mailer: $mailer
To: rt\@@{[RT->Config->Get('rtname')]}
Subject: outlook basic test
Content-Type: multipart/alternative;
- boundary="----=_NextPart_000_0004_01CB045C.A5A075D0"
+\tboundary="----=_NextPart_000_0004_01CB045C.A5A075D0"
------=_NextPart_000_0004_01CB045C.A5A075D0
Content-Type: text/plain;
- charset="us-ascii"
+\tcharset="us-ascii"
Content-Transfer-Encoding: 7bit
here is the content
@@ -33,7 +33,7 @@ another line
------=_NextPart_000_0004_01CB045C.A5A075D0
Content-Type: text/html;
- charset="us-ascii"
+\tcharset="us-ascii"
Content-Transfer-Encoding: quoted-printable
<html>this is fake</html>
@@ -61,16 +61,16 @@ X-Mailer: $mailer
To: rt\@@{[RT->Config->Get('rtname')]}
Subject: outlook basic test
Content-Type: multipart/mixed;
- boundary="----=_NextPart_000_000F_01CB045E.5222CB40"
+\tboundary="----=_NextPart_000_000F_01CB045E.5222CB40"
------=_NextPart_000_000F_01CB045E.5222CB40
Content-Type: multipart/alternative;
- boundary="----=_NextPart_001_0010_01CB045E.5222CB40"
+\tboundary="----=_NextPart_001_0010_01CB045E.5222CB40"
------=_NextPart_001_0010_01CB045E.5222CB40
Content-Type: text/plain;
- charset="us-ascii"
+\tcharset="us-ascii"
Content-Transfer-Encoding: 7bit
foo
@@ -84,7 +84,7 @@ baz
------=_NextPart_001_0010_01CB045E.5222CB40
Content-Type: text/html;
- charset="us-ascii"
+\tcharset="us-ascii"
Content-Transfer-Encoding: quoted-printable
<html>this is fake</html>
@@ -93,10 +93,10 @@ Content-Transfer-Encoding: quoted-printable
------=_NextPart_000_000F_01CB045E.5222CB40
Content-Type: text/plain;
- name="att.txt"
+\tname="att.txt"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
- filename="att.txt"
+\tfilename="att.txt"
this is the attachment! :)=0A=
@@ -210,8 +210,8 @@ John Smith
Some Company
email\@someco.com
EOF
- test_email( $text, $content,
- ' with base64, no X-Mailer, \n\n are replaced' );
+ test_email( $text, $content,
+ ' with base64, no X-Mailer, \n\n are replaced' );
}
@@ -223,11 +223,11 @@ X-Mailer: Mutt
To: rt\@@{[RT->Config->Get('rtname')]}
Subject: outlook basic test
Content-Type: multipart/alternative;
- boundary="----=_NextPart_000_0004_01CB045C.A5A075D0"
+\tboundary="----=_NextPart_000_0004_01CB045C.A5A075D0"
------=_NextPart_000_0004_01CB045C.A5A075D0
Content-Type: text/plain;
- charset="us-ascii"
+\tcharset="us-ascii"
Content-Transfer-Encoding: 7bit
foo
@@ -241,7 +241,7 @@ baz
------=_NextPart_000_0004_01CB045C.A5A075D0
Content-Type: text/html;
- charset="us-ascii"
+\tcharset="us-ascii"
Content-Transfer-Encoding: quoted-printable
<html>this is fake</html>
@@ -382,8 +382,8 @@ This isthesig
EOF
- test_email( $text, $content,
- 'Another sample multipart message with Exchange headers' );
+ test_email( $text, $content,
+ 'Another sample multipart message with Exchange headers' );
}
sub test_email {
diff --git a/rt/t/mail/sendmail-plaintext.t b/rt/t/mail/sendmail-plaintext.t
new file mode 100644
index 000000000..b9eb71951
--- /dev/null
+++ b/rt/t/mail/sendmail-plaintext.t
@@ -0,0 +1,150 @@
+use strict;
+use warnings;
+
+use RT::Test tests => undef, text_templates => 1;
+
+use File::Spec ();
+use Email::Abstract;
+
+# We're not testing acls here.
+my $everyone = RT::Group->new(RT->SystemUser);
+$everyone->LoadSystemInternalGroup('Everyone');
+$everyone->PrincipalObj->GrantRight( Right =>'SuperUser' );
+
+# some utils
+sub first_txn { return $_[0]->Transactions->First }
+sub first_attach { return first_txn($_[0])->Attachments->First }
+sub count_attachs { return first_txn($_[0])->Attachments->Count }
+
+sub mail_in_ticket {
+ my ($filename) = @_;
+ my $path = RT::Test::get_relocatable_file($filename,
+ (File::Spec->updir(), 'data', 'emails'));
+ my $content = RT::Test->file_content($path);
+
+ RT::Test->clean_caught_mails;
+ my ($status, $id) = RT::Test->send_via_mailgate( $content );
+ ok( !$status, "Fed $filename into mailgate");
+
+ my $ticket = RT::Ticket->new(RT->SystemUser);
+ $ticket->Load($id);
+ ok( $ticket->Id, "Successfully created ticket ".$ticket->Id);
+
+ my @mail = map {Email::Abstract->new($_)->cast('MIME::Entity')}
+ RT::Test->fetch_caught_mails;
+ return ($ticket, @mail);
+}
+
+{
+ my ($ticket) = mail_in_ticket('multipart-report');
+ like( first_txn($ticket)->Content , qr/The original message was received/, "It's the bounce");
+}
+
+for my $encoding ('ISO-8859-1', 'UTF-8') {
+ RT->Config->Set( EmailOutputEncoding => $encoding );
+
+ my ($ticket, @mail) = mail_in_ticket('new-ticket-from-iso-8859-1');
+ like (first_txn($ticket)->Content , qr/H\x{e5}vard/, "It's signed by havard. yay");
+
+ is(@mail, 1);
+ like( $mail[0]->head->get('Content-Type') , qr/$encoding/,
+ "Its content type is $encoding" );
+ my $message_as_string = $mail[0]->bodyhandle->as_string();
+ $message_as_string = Encode::decode($encoding, $message_as_string);
+ like( $message_as_string , qr/H\x{e5}vard/,
+ "The message's content contains havard's name in $encoding");
+}
+
+{
+ my ($ticket) = mail_in_ticket('multipart-alternative-with-umlaut');
+ like( first_txn($ticket)->Content, qr/causes Error/,
+ "We recorded the content as containing 'causes error'");
+ is( count_attachs($ticket), 3,
+ "Has three attachments, presumably a text-plain, a text-html and a multipart alternative");
+}
+
+{
+ my ($ticket, @mail) = mail_in_ticket('text-html-with-umlaut');
+ like( first_attach($ticket)->Content, qr/causes Error/,
+ "We recorded the content as containing 'causes error'");
+ like( first_attach($ticket)->ContentType , qr/text\/html/,
+ "We recorded the content as text/html");
+ is (count_attachs($ticket), 1,
+ "Has one attachment, just a text-html");
+
+ is(@mail, 1);
+ is( $mail[0]->parts, 0, "generated correspondence mime entity does not have parts");
+ is( $mail[0]->head->mime_type , "text/plain", "The mime type is a plain");
+}
+
+{
+ my @InputEncodings = RT->Config->Get('EmailInputEncodings');
+ RT->Config->Set( EmailInputEncodings => 'koi8-r', @InputEncodings );
+ RT->Config->Set( EmailOutputEncoding => 'koi8-r' );
+
+ my ($ticket, @mail) = mail_in_ticket('russian-subject-no-content-type');
+ like( first_attach($ticket)->ContentType, qr/text\/plain/,
+ "We recorded the content type right");
+ is( count_attachs($ticket), 1,
+ "Has one attachment, presumably a text-plain");
+ is( $ticket->Subject, Encode::decode("UTF-8","тест тест"),
+ "Recorded the subject right");
+
+ is(@mail, 1);
+ is( $mail[0]->head->mime_type , "text/plain", "The only part is text/plain ");
+ like( $mail[0]->head->get("subject"), qr/\Q=?KOI8-R?B?W2V4YW1wbGUuY29tICM2XSBBdXRvUmVwbHk6INTF09Qg1MXT1A==?=\E/,
+ "The subject is encoded correctly");
+
+ RT->Config->Set(EmailInputEncodings => @InputEncodings );
+ RT->Config->Set(EmailOutputEncoding => 'utf-8');
+}
+
+{
+ my ($ticket, @mail) = mail_in_ticket('nested-rfc-822');
+ is( $ticket->Subject, "[Jonas Liljegren] Re: [Para] Niv\x{e5}er?");
+ like( first_attach($ticket)->ContentType, qr/multipart\/mixed/,
+ "We recorded the content type right");
+ is( count_attachs($ticket), 5,
+ "Has five attachments, presumably a text-plain and a message RFC 822 and another plain");
+
+ is(@mail, 1);
+ is( $mail[0]->head->mime_type , "text/plain", "The outgoing mail is plain text");
+
+ my $encoded_subject = $mail[0]->head->get("Subject");
+ chomp $encoded_subject;
+ my $subject = Encode::decode('MIME-Header',$encoded_subject);
+ like($subject, qr/Niv\x{e5}er/, "The subject matches the word - $subject");
+}
+
+{
+ my ($ticket) = mail_in_ticket('notes-uuencoded');
+ like( first_txn($ticket)->Content, qr/from Lotus Notes/,
+ "We recorded the content right");
+ is( count_attachs($ticket), 3, "Has three attachments");
+}
+
+{
+ my ($ticket) = mail_in_ticket('crashes-file-based-parser');
+ like( first_txn($ticket)->Content, qr/FYI/, "We recorded the content right");
+ is( count_attachs($ticket), 5, "Has five attachments");
+}
+
+{
+ my ($ticket) = mail_in_ticket('rt-send-cc');
+ my $cc = first_attach($ticket)->GetHeader('RT-Send-Cc');
+ like ($cc, qr/test$_/, "Found test $_") for 1..5;
+}
+
+{
+ diag "Regression test for #5248 from rt3.fsck.com";
+ my ($ticket) = mail_in_ticket('subject-with-folding-ws');
+ is ($ticket->Subject, 'test', 'correct subject');
+}
+
+{
+ diag "Regression test for #5248 from rt3.fsck.com";
+ my ($ticket) = mail_in_ticket('very-long-subject');
+ is ($ticket->Subject, '0123456789'x20, 'correct subject');
+}
+
+done_testing;
diff --git a/rt/t/mail/sendmail.t b/rt/t/mail/sendmail.t
index 56202ad5d..4ef320611 100644
--- a/rt/t/mail/sendmail.t
+++ b/rt/t/mail/sendmail.t
@@ -24,7 +24,7 @@ sub mail_in_ticket {
RT::Test->clean_caught_mails;
my ($status, $id) = RT::Test->send_via_mailgate( $content );
- ok( $status, "Fed $filename into mailgate");
+ ok( !$status, "Fed $filename into mailgate");
my $ticket = RT::Ticket->new(RT->SystemUser);
$ticket->Load($id);
@@ -47,12 +47,30 @@ for my $encoding ('ISO-8859-1', 'UTF-8') {
like (first_txn($ticket)->Content , qr/H\x{e5}vard/, "It's signed by havard. yay");
is(@mail, 1);
- like( $mail[0]->head->get('Content-Type') , qr/$encoding/,
- "Its content type is $encoding" );
- my $message_as_string = $mail[0]->bodyhandle->as_string();
+ like( $mail[0]->head->get('Content-Type'), qr/multipart\/alternative/,
+ "Its content type is multipart/alternative" );
+
+ # The text/html part is guaranteed to not have had non-latin-1
+ # characters introduced by the HTML-to-text conversion, so it is
+ # guaranteed to be able to be represented in latin-1
+ like( $mail[0]->parts(1)->head->get('Content-Type'), qr/text\/html.+?$encoding/,
+ "Second part's content type is text/html $encoding" );
+ my $message_as_string = $mail[0]->parts(1)->bodyhandle->as_string();
$message_as_string = Encode::decode($encoding, $message_as_string);
like( $message_as_string , qr/H\x{e5}vard/,
"The message's content contains havard's name in $encoding");
+
+ # The text/plain part may have utf-8 characters in it. Accept either encoding.
+ like( $mail[0]->parts(0)->head->get('Content-Type'), qr/text\/plain.+?(ISO-8859-1|UTF-8)/i,
+ "First part's content type is text/plain (ISO-8859-1 or UTF-8)" );
+
+ # Make sure it checks out in whatever encoding it ended up in
+ $mail[0]->parts(0)->head->get('Content-Type') =~ /text\/plain.+?(ISO-8859-1|UTF-8)/i;
+ my $found = $1 || $encoding;
+ $message_as_string = $mail[0]->parts(0)->bodyhandle->as_string();
+ $message_as_string = Encode::decode($found, $message_as_string);
+ like( $message_as_string , qr/H\x{e5}vard/,
+ "The message's content contains havard's name in $encoding");
}
{
@@ -73,8 +91,9 @@ for my $encoding ('ISO-8859-1', 'UTF-8') {
"Has one attachment, just a text-html");
is(@mail, 1);
- is( $mail[0]->parts, 0, "generated correspondence mime entity does not have parts");
- is( $mail[0]->head->mime_type , "text/plain", "The mime type is a plain");
+ is( $mail[0]->parts, 2, "generated correspondence mime entity has parts");
+ is( $mail[0]->parts(0)->head->mime_type , "text/plain", "The first part mime type is a plain");
+ is( $mail[0]->parts(1)->head->mime_type , "text/html", "The second part mime type is an html");
}
{
@@ -91,7 +110,10 @@ for my $encoding ('ISO-8859-1', 'UTF-8') {
"Recorded the subject right");
is(@mail, 1);
- is( $mail[0]->head->mime_type , "text/plain", "The only part is text/plain ");
+ is( $mail[0]->head->mime_type , "multipart/alternative", "The top part is multipart/alternative");
+ is( $mail[0]->parts, 2, "generated correspondnece mime entity has parts");
+ is( $mail[0]->parts(0)->head->mime_type , "text/plain", "The first part is a plain");
+ is( $mail[0]->parts(1)->head->mime_type , "text/html", "The second part is an html");
like( $mail[0]->head->get("subject"), qr/\Q=?KOI8-R?B?W2V4YW1wbGUuY29tICM2XSBBdXRvUmVwbHk6INTF09Qg1MXT1A==?=\E/,
"The subject is encoded correctly");
@@ -108,7 +130,10 @@ for my $encoding ('ISO-8859-1', 'UTF-8') {
"Has five attachments, presumably a text-plain and a message RFC 822 and another plain");
is(@mail, 1);
- is( $mail[0]->head->mime_type , "text/plain", "The outgoing mail is plain text");
+ is( $mail[0]->head->mime_type , "multipart/alternative", "The top part is multipart/alternative");
+ is( $mail[0]->parts, 2, "generated correspondnece mime entity has parts");
+ is( $mail[0]->parts(0)->head->mime_type , "text/plain", "The first part is a plain");
+ is( $mail[0]->parts(1)->head->mime_type , "text/html", "The second part is an html");
my $encoded_subject = $mail[0]->head->get("Subject");
chomp $encoded_subject;
diff --git a/rt/t/mail/smime/incoming.t b/rt/t/mail/smime/incoming.t
new file mode 100644
index 000000000..918844a88
--- /dev/null
+++ b/rt/t/mail/smime/incoming.t
@@ -0,0 +1,202 @@
+use strict;
+use warnings;
+
+use RT::Test::SMIME tests => undef, actual_server => 1;
+my $test = 'RT::Test::SMIME';
+
+use IPC::Run3 'run3';
+use String::ShellQuote 'shell_quote';
+use RT::Tickets;
+use Test::Warn;
+
+my ($url, $m) = RT::Test->started_ok;
+ok $m->login, "logged in";
+
+# configure key for General queue
+RT::Test::SMIME->import_key('sender@example.com');
+my $queue = RT::Test->load_or_create_queue(
+ Name => 'General',
+ CorrespondAddress => 'sender@example.com',
+ CommentAddress => 'sender@example.com',
+);
+ok $queue && $queue->id, 'loaded or created queue';
+
+my $user = RT::Test->load_or_create_user(
+ Name => 'root@example.com',
+ EmailAddress => 'root@example.com',
+);
+RT::Test::SMIME->import_key('root@example.com.crt', $user);
+RT::Test->add_rights( Principal => $user, Right => 'SuperUser', Object => RT->System );
+
+my $mail = RT::Test->open_mailgate_ok($url);
+print $mail <<EOF;
+From: root\@localhost
+To: rt\@$RT::rtname
+Subject: This is a test of new ticket creation as root
+
+Blah!
+Foob!
+EOF
+RT::Test->close_mailgate_ok($mail);
+
+{
+ my $tick = RT::Test->last_ticket;
+ is( $tick->Subject,
+ 'This is a test of new ticket creation as root',
+ "Created the ticket"
+ );
+ my $txn = $tick->Transactions->First;
+ like(
+ $txn->Attachments->First->Headers,
+ qr/^X-RT-Incoming-Encryption: Not encrypted/m,
+ 'recorded incoming mail that is not encrypted'
+ );
+ like( $txn->Attachments->First->Content, qr'Blah');
+}
+
+{
+ # test for encrypted mail
+ my $buf = '';
+ run3(
+ shell_quote(
+ qw(openssl smime -encrypt -des3),
+ -from => 'root@example.com',
+ -to => 'sender@example.com',
+ -subject => "Encrypted message for queue",
+ $test->key_path('sender@example.com.crt'),
+ ),
+ \"Subject: test\n\norzzzzzz",
+ \$buf,
+ \*STDERR
+ );
+
+ my ($status, $tid) = RT::Test->send_via_mailgate( $buf );
+ is ($status >> 8, 0, "The mail gateway exited normally");
+
+ my $tick = RT::Ticket->new( $RT::SystemUser );
+ $tick->Load( $tid );
+ is( $tick->Subject, 'Encrypted message for queue',
+ "Created the ticket"
+ );
+
+ my $txn = $tick->Transactions->First;
+ my ($msg, $attach, $orig) = @{$txn->Attachments->ItemsArrayRef};
+ is( $msg->GetHeader('X-RT-Incoming-Encryption'),
+ 'Success',
+ 'recorded incoming mail that is encrypted'
+ );
+ is( $msg->GetHeader('X-RT-Privacy'),
+ 'SMIME',
+ 'recorded incoming mail that is encrypted'
+ );
+ like( $attach->Content, qr'orz');
+
+ is( $orig->GetHeader('Content-Type'), 'application/x-rt-original-message');
+}
+
+{
+ my $buf = '';
+
+ run3(
+ join(
+ ' ',
+ shell_quote(
+ RT->Config->Get('SMIME')->{'OpenSSL'},
+ qw( smime -sign -nodetach -passin pass:123456),
+ -signer => $test->key_path('root@example.com.crt'),
+ -inkey => $test->key_path('root@example.com.key'),
+ ),
+ '|',
+ shell_quote(
+ qw(openssl smime -encrypt -des3),
+ -from => 'root@example.com',
+ -to => 'sender@example.com',
+ -subject => "Encrypted and signed message for queue",
+ $test->key_path('sender@example.com.crt'),
+ )),
+ \"Subject: test\n\norzzzzzz",
+ \$buf,
+ \*STDERR
+ );
+
+ my ($status, $tid) = RT::Test->send_via_mailgate( $buf );
+
+ my $tick = RT::Ticket->new( $RT::SystemUser );
+ $tick->Load( $tid );
+ ok( $tick->Id, "found ticket " . $tick->Id );
+ is( $tick->Subject, 'Encrypted and signed message for queue',
+ "Created the ticket"
+ );
+
+ my $txn = $tick->Transactions->First;
+ my ($msg, $attach, $orig) = @{$txn->Attachments->ItemsArrayRef};
+ is( $msg->GetHeader('X-RT-Incoming-Encryption'),
+ 'Success',
+ 'recorded incoming mail that is encrypted'
+ );
+ like( $attach->Content, qr'orzzzz');
+}
+
+{
+ my $buf = '';
+
+ run3(
+ shell_quote(
+ RT->Config->Get('SMIME')->{'OpenSSL'},
+ qw( smime -sign -passin pass:123456),
+ -signer => $test->key_path('root@example.com.crt'),
+ -inkey => $test->key_path('root@example.com.key'),
+ ),
+ \"Content-type: text/plain\n\nThis is the body",
+ \$buf,
+ \*STDERR
+ );
+ $buf = "Subject: Signed email\n"
+ . "From: root\@example.com\n"
+ . $buf;
+
+ {
+ my ($status, $tid) = RT::Test->send_via_mailgate( $buf );
+
+ my $tick = RT::Ticket->new( $RT::SystemUser );
+ $tick->Load( $tid );
+ ok( $tick->Id, "found ticket " . $tick->Id );
+ is( $tick->Subject, 'Signed email',
+ "Created the ticket"
+ );
+
+ my $txn = $tick->Transactions->First;
+ my ($msg, $attach, $orig) = @{$txn->Attachments->ItemsArrayRef};
+ is( $msg->GetHeader('X-RT-Incoming-Signature'),
+ '"Enoch Root" <root@example.com>',
+ "Message was signed"
+ );
+ like( $attach->Content, qr/This is the body/ );
+ }
+
+ # Make the signature not match
+ $buf =~ s/This is the body/This is not the body/;
+
+ warning_like {
+ my ($status, $tid) = RT::Test->send_via_mailgate( $buf );
+
+ my $tick = RT::Ticket->new( $RT::SystemUser );
+ $tick->Load( $tid );
+ ok( $tick->Id, "found ticket " . $tick->Id );
+ is( $tick->Subject, 'Signed email',
+ "Created the ticket"
+ );
+
+ my $txn = $tick->Transactions->First;
+ my ($msg, $attach, $orig) = @{$txn->Attachments->ItemsArrayRef};
+ isnt( $msg->GetHeader('X-RT-Incoming-Signature'),
+ '"Enoch Root" <root@example.com>',
+ "Message was not marked signed"
+ );
+ like( $attach->Content, qr/This is not the body/ );
+ } qr/Failure during SMIME verify: The signature did not verify/;
+
+}
+
+undef $m;
+done_testing;
diff --git a/rt/t/mail/smime/other-signed.t b/rt/t/mail/smime/other-signed.t
new file mode 100644
index 000000000..4e97e711f
--- /dev/null
+++ b/rt/t/mail/smime/other-signed.t
@@ -0,0 +1,135 @@
+use strict;
+use warnings;
+
+use RT::Test::SMIME tests => undef;
+my $test = 'RT::Test::SMIME';
+
+use IPC::Run3 'run3';
+use String::ShellQuote 'shell_quote';
+use RT::Tickets;
+use Test::Warn;
+
+# configure key for General queue
+RT::Test::SMIME->import_key('sender@example.com');
+my $queue = RT::Test->load_or_create_queue(
+ Name => 'General',
+ CorrespondAddress => 'sender@example.com',
+ CommentAddress => 'sender@example.com',
+);
+ok $queue && $queue->id, 'loaded or created queue';
+
+my $user = RT::Test->load_or_create_user(
+ Name => 'root@example.com',
+ EmailAddress => 'root@example.com',
+);
+RT::Test::SMIME->import_key('root@example.com.crt', $user);
+RT::Test->add_rights( Principal => $user, Right => 'SuperUser', Object => RT->System );
+
+my $buf = '';
+
+run3(
+ shell_quote(
+ RT->Config->Get('SMIME')->{'OpenSSL'},
+ qw( smime -sign -passin pass:123456),
+ -signer => $test->key_path('root@example.com.crt'),
+ -inkey => $test->key_path('root@example.com.key'),
+ ),
+ \"Content-type: text/plain\n\nThis is the body",
+ \$buf,
+ \*STDERR
+);
+$buf = "Subject: Signed email\n"
+ . "From: root\@example.com\n"
+ . $buf;
+
+my $send_mail = sub {
+ my %args = ( CAPath => undef, AcceptUntrustedCAs => undef, @_ );
+
+ RT->Config->Get('SMIME')->{$_} = $args{$_} for keys %args;
+
+ my ($status, $tid) = RT::Test->send_via_mailgate( $buf );
+
+ my $tick = RT::Ticket->new( $RT::SystemUser );
+ $tick->Load( $tid );
+ ok( $tick->Id, "found ticket " . $tick->Id );
+ is( $tick->Subject, 'Signed email',
+ "Created the ticket"
+ );
+
+ my $txn = $tick->Transactions->First;
+ my ($msg, $attach, $orig) = @{$txn->Attachments->ItemsArrayRef};
+
+ ($status) = RT::Crypt->ParseStatus(
+ Protocol => 'SMIME',
+ Status => $msg->GetHeader('X-RT-SMIME-Status')
+ );
+
+ return ($msg, $status);
+};
+
+# Test with no CA path; should not be marked as signed
+warning_like {
+ my ($msg, $status) = $send_mail->( CAPath => undef );
+ is( $msg->GetHeader('X-RT-Incoming-Signature'),
+ undef,
+ "Message was not marked as signed"
+ );
+
+ is($status->{Operation}, "Verify", "Found the Verify operation");
+ is($status->{Status}, "BAD", "Verify was a failure");
+ is($status->{Trust}, "NONE", "Noted the no trust level");
+ like($status->{Message}, qr/not trusted/, "Verify was a failure");
+} qr/Failure during SMIME verify: The signing CA was not trusted/;
+
+# Test with the correct CA path; marked as signed, trusted
+{
+ my ($msg, $status) = $send_mail->( CAPath => $test->key_path . "/demoCA/cacert.pem" );
+ is( $msg->GetHeader('X-RT-Incoming-Signature'),
+ '"Enoch Root" <root@example.com>', "Message is signed" );
+
+ is($status->{Operation}, "Verify", "Found the Verify operation");
+ is($status->{Status}, "DONE", "Verify was a success");
+ is($status->{Trust}, "FULL", "Noted the full trust level");
+}
+
+# Test with the other CA
+warning_like {
+ my ($msg, $status) = $send_mail->( CAPath => $test->key_path . "/otherCA/cacert.pem" );
+ is( $msg->GetHeader('X-RT-Incoming-Signature'),
+ undef,
+ "Message was not marked as signed"
+ );
+
+ is($status->{Operation}, "Verify", "Found the Verify operation");
+ is($status->{Status}, "BAD", "Verify was a failure");
+ is($status->{Trust}, "NONE", "Noted the no trust level");
+ like($status->{Message}, qr/not trusted/, "Verify was a failure");
+} qr/Failure during SMIME verify: The signing CA was not trusted/;
+
+# Other CA, but allow all CAs
+{
+ my ($msg, $status) = $send_mail->( CAPath => $test->key_path . "/otherCA/cacert.pem", AcceptUntrustedCAs => 1 );
+ is( $msg->GetHeader('X-RT-Incoming-Signature'),
+ '"Enoch Root" <root@example.com>',
+ "Message was marked as signed"
+ );
+
+ is($status->{Operation}, "Verify", "Found the Verify operation");
+ is($status->{Status}, "DONE", "Verify was a success");
+ is($status->{Trust}, "NONE", "Noted the no trust level");
+}
+
+# No CA path, but allow all CAs
+{
+ my ($msg, $status) = $send_mail->( CAPath => undef, AcceptUntrustedCAs => 1 );
+ is( $msg->GetHeader('X-RT-Incoming-Signature'),
+ '"Enoch Root" <root@example.com>',
+ "Message was marked as signed"
+ );
+
+ is($status->{Operation}, "Verify", "Found the Verify operation");
+ is($status->{Status}, "DONE", "Verify was a success");
+ is($status->{Trust}, "UNKNOWN", "Noted the no trust level");
+}
+
+done_testing;
diff --git a/rt/t/mail/smime/outgoing.t b/rt/t/mail/smime/outgoing.t
new file mode 100644
index 000000000..6f6b00d68
--- /dev/null
+++ b/rt/t/mail/smime/outgoing.t
@@ -0,0 +1,80 @@
+use strict;
+use warnings;
+
+use RT::Test::SMIME tests => undef;
+my $test = 'RT::Test::SMIME';
+
+use IPC::Run3 'run3';
+use RT::Interface::Email;
+
+my ($url, $m) = RT::Test->started_ok;
+ok $m->login, "logged in";
+
+my $queue = RT::Test->load_or_create_queue(
+ Name => 'General',
+ CorrespondAddress => 'sender@example.com',
+ CommentAddress => 'sender@example.com',
+);
+ok $queue && $queue->id, 'loaded or created queue';
+
+{
+ my ($status, $msg) = $queue->SetEncrypt(1);
+ ok $status, "turn on encyption by default"
+ or diag "error: $msg";
+}
+
+my $user;
+{
+ $user = RT::User->new($RT::SystemUser);
+ ok($user->LoadByEmail('root@localhost'), "Loaded user 'root'");
+ ok($user->Load('root'), "Loaded user 'root'");
+ is($user->EmailAddress, 'root@localhost');
+
+ RT::Test::SMIME->import_key( 'root@example.com.crt' => $user );
+}
+
+RT::Test->clean_caught_mails;
+
+{
+ my $mail = <<END;
+From: root\@localhost
+To: rt\@example.com
+Subject: This is a test of new ticket creation as an unknown user
+
+Blah!
+Foob!
+
+END
+
+ my ($status, $id) = RT::Test->send_via_mailgate(
+ $mail, queue => $queue->Name,
+ );
+ is $status >> 8, 0, "successfuly executed mailgate";
+
+ my $ticket = RT::Ticket->new($RT::SystemUser);
+ $ticket->Load( $id );
+ ok ($ticket->id, "found ticket ". $ticket->id);
+}
+
+{
+ my @mails = RT::Test->fetch_caught_mails;
+ is scalar @mails, 1, "autoreply";
+
+ my ($buf, $err);
+ local $@;
+ ok(eval {
+ run3([
+ qw(openssl smime -decrypt -passin pass:123456),
+ '-inkey', $test->key_path('root@example.com.key'),
+ '-recip', $test->key_path('root@example.com.crt')
+ ], \$mails[0], \$buf, \$err )
+ }, 'can decrypt'
+ );
+ diag $@ if $@;
+ diag $err if $err;
+ diag "Error code: $?" if $?;
+ like($buf, qr'This message has been automatically generated in response');
+}
+
+undef $m;
+done_testing;
diff --git a/rt/t/mail/smime/realmail.t b/rt/t/mail/smime/realmail.t
new file mode 100644
index 000000000..be157aaee
--- /dev/null
+++ b/rt/t/mail/smime/realmail.t
@@ -0,0 +1,125 @@
+use strict;
+use warnings;
+
+use RT::Test::SMIME tests => undef;
+use Digest::MD5 qw(md5_hex);
+
+my $test = 'RT::Test::SMIME';
+my $mails = $test->mail_set_path;
+
+RT->Config->Get('SMIME')->{AcceptUntrustedCAs} = 1;
+
+RT::Test::SMIME->import_key('root@example.com');
+RT::Test::SMIME->import_key('sender@example.com');
+
+my ($baseurl, $m) = RT::Test->started_ok;
+ok $m->login, 'we did log in';
+$m->get_ok( '/Admin/Queues/');
+$m->follow_link_ok( {text => 'General'} );
+$m->submit_form( form_number => 3,
+ fields => { CorrespondAddress => 'root@example.com' } );
+
+diag "load Everyone group" if $ENV{'TEST_VERBOSE'};
+my $everyone;
+{
+ $everyone = RT::Group->new( $RT::SystemUser );
+ $everyone->LoadSystemInternalGroup('Everyone');
+ ok $everyone->id, "loaded 'everyone' group";
+}
+
+RT::Test->set_rights(
+ Principal => $everyone,
+ Right => ['CreateTicket'],
+);
+
+
+my $eid = 0;
+for my $usage (qw/signed encrypted signed&encrypted/) {
+ for my $attachment (qw/plain text-attachment binary-attachment/) {
+ ++$eid;
+ diag "Email $eid: $usage, $attachment email" if $ENV{TEST_VERBOSE};
+ eval { email_ok($eid, $usage, $attachment) };
+ }
+}
+
+undef $m;
+done_testing;
+
+sub email_ok {
+ my ($eid, $usage, $attachment) = @_;
+ diag "email_ok $eid: $usage, $attachment" if $ENV{'TEST_VERBOSE'};
+
+ my ($file) = glob("$mails/$eid-*");
+ my $mail = RT::Test->file_content($file);
+
+ my ($status, $id) = RT::Test->send_via_mailgate($mail);
+ is ($status >> 8, 0, "$eid: The mail gateway exited normally");
+ ok ($id, "$eid: got id of a newly created ticket - $id");
+
+ my $tick = RT::Ticket->new( $RT::SystemUser );
+ $tick->Load( $id );
+ ok ($tick->id, "$eid: loaded ticket #$id");
+
+ is ($tick->Subject,
+ "Test Email ID:$eid",
+ "$eid: Created the ticket"
+ );
+
+ my $txn = $tick->Transactions->First;
+ my ($msg, @attachments) = @{$txn->Attachments->ItemsArrayRef};
+
+ is( $msg->GetHeader('X-RT-Privacy'),
+ 'SMIME',
+ "$eid: recorded incoming mail that is secured"
+ );
+
+ if ($usage =~ /encrypted/) {
+ is( $msg->GetHeader('X-RT-Incoming-Encryption'),
+ 'Success',
+ "$eid: recorded incoming mail that is encrypted"
+ );
+ like( $attachments[0]->Content, qr/ID:$eid/,
+ "$eid: incoming mail did NOT have original body"
+ );
+ }
+ else {
+ is( $msg->GetHeader('X-RT-Incoming-Encryption'),
+ 'Not encrypted',
+ "$eid: recorded incoming mail that is not encrypted"
+ );
+ like( $msg->Content || $attachments[0]->Content, qr/ID:$eid/,
+ "$eid: got original content"
+ );
+ }
+
+ if ($usage =~ /signed/) {
+ is( $msg->GetHeader('X-RT-Incoming-Signature'),
+ '"sender" <sender@example.com>',
+ "$eid: recorded incoming mail that is signed"
+ );
+ }
+ else {
+ is( $msg->GetHeader('X-RT-Incoming-Signature'),
+ undef,
+ "$eid: recorded incoming mail that is not signed"
+ );
+ }
+
+ if ($attachment =~ /attachment/) {
+ my ($a) = grep $_->Filename, @attachments;
+ ok ($a && $a->Id, "$eid: found attachment with filename");
+
+ my $acontent = $a->Content;
+ if ($attachment =~ /binary/)
+ {
+ is(md5_hex($acontent), '1e35f1aa90c98ca2bab85c26ae3e1ba7', "$eid: The binary attachment's md5sum matches");
+ }
+ else
+ {
+ like($acontent, qr/zanzibar/, "$eid: The attachment isn't screwed up in the database.");
+ }
+ }
+
+ return 0;
+}
+
diff --git a/rt/t/mail/smime/reject_on_unencrypted.t b/rt/t/mail/smime/reject_on_unencrypted.t
new file mode 100644
index 000000000..ab62d83fc
--- /dev/null
+++ b/rt/t/mail/smime/reject_on_unencrypted.t
@@ -0,0 +1,137 @@
+use strict;
+use warnings;
+
+use RT::Test::SMIME tests => undef, actual_server => 1, config => 'Set( %Crypt, RejectOnUnencrypted => 1 );';
+my $test = 'RT::Test::SMIME';
+
+use IPC::Run3 'run3';
+use String::ShellQuote 'shell_quote';
+use RT::Tickets;
+
+my ($url, $m) = RT::Test->started_ok;
+ok $m->login, "logged in";
+
+# configure key for General queue
+RT::Test::SMIME->import_key('sender@example.com');
+my $queue = RT::Test->load_or_create_queue(
+ Name => 'General',
+ CorrespondAddress => 'sender@example.com',
+ CommentAddress => 'sender@example.com',
+);
+ok $queue && $queue->id, 'loaded or created queue';
+
+my $user = RT::Test->load_or_create_user(
+ Name => 'root@example.com',
+ EmailAddress => 'root@example.com',
+);
+RT::Test::SMIME->import_key('root@example.com.crt', $user);
+RT::Test->add_rights( Principal => $user, Right => 'SuperUser', Object => RT->System );
+
+my $mail = RT::Test->open_mailgate_ok($url);
+print $mail <<EOF;
+From: root\@localhost
+To: rt\@$RT::rtname
+Subject: This is a test of new ticket creation as root
+
+Blah!
+Foob!
+EOF
+RT::Test->close_mailgate_ok($mail);
+
+{
+ ok(!RT::Test->last_ticket, 'A ticket was not created');
+ my ($mail) = RT::Test->fetch_caught_mails;
+ like(
+ $mail,
+ qr/^Subject: RT requires that all incoming mail be encrypted/m,
+ 'rejected mail that is not encrypted'
+ );
+ my ($warning) = $m->get_warnings;
+ like($warning, qr/rejected because the message is unencrypted/);
+}
+
+{
+ # test for encrypted mail
+ my $buf = '';
+ run3(
+ shell_quote(
+ qw(openssl smime -encrypt -des3),
+ -from => 'root@example.com',
+ -to => 'sender@example.com',
+ -subject => "Encrypted message for queue",
+ $test->key_path('sender@example.com.crt' ),
+ ),
+ \"Subject: test\n\norzzzzzz",
+ \$buf,
+ \*STDERR
+ );
+
+ my ($status, $tid) = RT::Test->send_via_mailgate( $buf );
+ is ($status >> 8, 0, "The mail gateway exited normally");
+
+ my $tick = RT::Ticket->new( $RT::SystemUser );
+ $tick->Load( $tid );
+ is( $tick->Subject, 'Encrypted message for queue',
+ "Created the ticket"
+ );
+
+ my $txn = $tick->Transactions->First;
+ my ($msg, $attach, $orig) = @{$txn->Attachments->ItemsArrayRef};
+ is( $msg->GetHeader('X-RT-Incoming-Encryption'),
+ 'Success',
+ 'recorded incoming mail that is encrypted'
+ );
+ is( $msg->GetHeader('X-RT-Privacy'),
+ 'SMIME',
+ 'recorded incoming mail that is encrypted'
+ );
+ like( $attach->Content, qr'orz');
+
+ is( $orig->GetHeader('Content-Type'), 'application/x-rt-original-message');
+}
+
+{
+ my $buf = '';
+
+ run3(
+ join(
+ ' ',
+ shell_quote(
+ RT->Config->Get('SMIME')->{'OpenSSL'},
+ qw( smime -sign -nodetach -passin pass:123456),
+ -signer => $test->key_path('root@example.com.crt' ),
+ -inkey => $test->key_path('root@example.com.key' ),
+ ),
+ '|',
+ shell_quote(
+ qw(openssl smime -encrypt -des3),
+ -from => 'root@example.com',
+ -to => 'sender@example.com',
+ -subject => "Encrypted and signed message for queue",
+ $test->key_path('sender@example.com.crt' ),
+ )),
+ \"Subject: test\n\norzzzzzz",
+ \$buf,
+ \*STDERR
+ );
+
+ my ($status, $tid) = RT::Test->send_via_mailgate( $buf );
+
+ my $tick = RT::Ticket->new( $RT::SystemUser );
+ $tick->Load( $tid );
+ ok( $tick->Id, "found ticket " . $tick->Id );
+ is( $tick->Subject, 'Encrypted and signed message for queue',
+ "Created the ticket"
+ );
+
+ my $txn = $tick->Transactions->First;
+ my ($msg, $attach, $orig) = @{$txn->Attachments->ItemsArrayRef};
+ is( $msg->GetHeader('X-RT-Incoming-Encryption'),
+ 'Success',
+ 'recorded incoming mail that is encrypted'
+ );
+ like( $attach->Content, qr'orzzzz');
+}
+
+undef $m;
+done_testing;
diff --git a/rt/t/mail/specials-in-encodedwords.t b/rt/t/mail/specials-in-encodedwords.t
index f9da9c6e9..36efcd5e7 100644
--- a/rt/t/mail/specials-in-encodedwords.t
+++ b/rt/t/mail/specials-in-encodedwords.t
@@ -14,7 +14,7 @@ diag "specials (, and ;) in MIME encoded-words aren't treated as specials";
From: root@localhost
Subject: testing mime encoded specials
Cc: a@example.com, =?utf8?q?d=40example.com=2ce=40example.com=3b?=
- <b@example.com>; c@example.com
+ <b@example.com>, c@example.com
Content-Type: text/plain; charset=utf8
here's some content
diff --git a/rt/t/mail/wrong_mime_charset.t b/rt/t/mail/wrong_mime_charset.t
index 6bbaca1bb..a3986d72f 100644
--- a/rt/t/mail/wrong_mime_charset.t
+++ b/rt/t/mail/wrong_mime_charset.t
@@ -1,6 +1,6 @@
use strict;
use warnings;
-use RT::Test nodb => 1, tests => 6;
+use RT::Test nodb => 1, tests => undef;
use_ok('RT::I18N');
my $test_string = Encode::decode("UTF-8", 'À');
@@ -20,10 +20,6 @@ local $SIG{__WARN__} = sub {
RT::I18N::SetMIMEEntityToEncoding( $mime, 'iso-8859-1' );
-TODO: {
- local $TODO =
-'need a better approach of encoding converter, should be fixed in 4.2';
-
# this is a weird behavior for different perl versions, 5.12 warns twice,
# which is correct since we do the encoding thing twice, for Subject
# and Data respectively.
@@ -44,4 +40,5 @@ is( $subject, $test_string, 'subject is set to iso-8859-1' );
my $body = Encode::decode( 'iso-8859-1', $mime->stringify_body );
chomp $body;
is( $body, $test_string, 'body is set to iso-8859-1' );
-}
+
+done_testing;