Merge branch 'patch-5' of https://github.com/gjones2/Freeside (#13854 as this bug...
[freeside.git] / rt / t / mail / gateway.t
1 #!/usr/bin/perl -w
2 # BEGIN BPS TAGGED BLOCK {{{
3
4 # COPYRIGHT:
5 #  
6 # This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC 
7 #                                          <jesse.com>
8
9 # (Except where explicitly superseded by other copyright notices)
10
11
12 # LICENSE:
13
14 # This work is made available to you under the terms of Version 2 of
15 # the GNU General Public License. A copy of that license should have
16 # been provided with this software, but in any event can be snarfed
17 # from www.gnu.org.
18
19 # This work is distributed in the hope that it will be useful, but
20 # WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22 # General Public License for more details.
23
24 # You should have received a copy of the GNU General Public License
25 # along with this program; if not, write to the Free Software
26 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27 # 02110-1301 or visit their web page on the internet at
28 # http://www.gnu.org/copyleft/gpl.html.
29
30
31 # CONTRIBUTION SUBMISSION POLICY:
32
33 # (The following paragraph is not intended to limit the rights granted
34 # to you to modify and distribute this software under the terms of
35 # the GNU General Public License and is only of importance to you if
36 # you choose to contribute your changes and enhancements to the
37 # community by submitting them to Best Practical Solutions, LLC.)
38
39 # By intentionally submitting any modifications, corrections or
40 # derivatives to this work, or any other work intended for use with
41 # Request Tracker, to Best Practical Solutions, LLC, you confirm that
42 # you are the copyright holder for those contributions and you grant
43 # Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
44 # royalty-free, perpetual, license to use, copy, create derivative
45 # works based on those contributions, and sublicense and distribute
46 # those contributions and any derivatives thereof.
47
48 # END BPS TAGGED BLOCK }}}
49
50 =head1 NAME
51
52 rt-mailgate - Mail interface to RT3.
53
54 =cut
55
56 use strict;
57 use warnings;
58
59
60 use RT::Test config => 'Set( $UnsafeEmailCommands, 1);', tests => 228, actual_server => 1;
61 my ($baseurl, $m) = RT::Test->started_ok;
62
63 use RT::Tickets;
64
65 use MIME::Entity;
66 use Digest::MD5 qw(md5_base64);
67 use LWP::UserAgent;
68
69 # TODO: --extension queue
70
71 my $url = $m->rt_base_url;
72
73 diag "Make sure that when we call the mailgate without URL, it fails";
74 {
75     my $text = <<EOF;
76 From: root\@localhost
77 To: rt\@@{[RT->Config->Get('rtname')]}
78 Subject: This is a test of new ticket creation
79
80 Foob!
81 EOF
82     my ($status, $id) = RT::Test->send_via_mailgate_and_http($text, url => undef);
83     is ($status >> 8, 1, "The mail gateway exited with a failure");
84     ok (!$id, "No ticket id") or diag "by mistake ticket #$id";
85     $m->no_warnings_ok;
86 }
87
88 diag "Make sure that when we call the mailgate with wrong URL, it tempfails";
89 {
90     my $text = <<EOF;
91 From: root\@localhost
92 To: rt\@@{[RT->Config->Get('rtname')]}
93 Subject: This is a test of new ticket creation
94
95 Foob!
96 EOF
97     my ($status, $id) = RT::Test->send_via_mailgate_and_http($text, url => 'http://this.test.for.non-connection.is.expected.to.generate.an.error');
98     is ($status >> 8, 75, "The mail gateway exited with a failure");
99     ok (!$id, "No ticket id");
100     $m->no_warnings_ok;
101 }
102
103 my $everyone_group;
104 diag "revoke rights tests depend on";
105 {
106     $everyone_group = RT::Group->new( RT->SystemUser );
107     $everyone_group->LoadSystemInternalGroup( 'Everyone' );
108     ok ($everyone_group->Id, "Found group 'everyone'");
109
110     foreach( qw(CreateTicket ReplyToTicket CommentOnTicket) ) {
111         $everyone_group->PrincipalObj->RevokeRight(Right => $_);
112     }
113 }
114
115 diag "Test new ticket creation by root who is privileged and superuser";
116 {
117     my $text = <<EOF;
118 From: root\@localhost
119 To: rt\@@{[RT->Config->Get('rtname')]}
120 Subject: This is a test of new ticket creation
121
122 Blah!
123 Foob!
124 EOF
125
126     my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
127     is ($status >> 8, 0, "The mail gateway exited normally");
128     ok ($id, "Created ticket");
129
130     my $tick = RT::Test->last_ticket;
131     isa_ok ($tick, 'RT::Ticket');
132     is ($tick->Id, $id, "correct ticket id");
133     is ($tick->Subject , 'This is a test of new ticket creation', "Created the ticket");
134     $m->no_warnings_ok;
135 }
136
137 diag "Test the 'X-RT-Mail-Extension' field in the header of a ticket";
138 {
139     my $text = <<EOF;
140 From: root\@localhost
141 To: rt\@@{[RT->Config->Get('rtname')]}
142 Subject: This is a test of the X-RT-Mail-Extension field
143 Blah!
144 Foob!
145 EOF
146     local $ENV{'EXTENSION'} = "bad value with\nnewlines\n";
147     my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
148     is ($status >> 8, 0, "The mail gateway exited normally");
149     ok ($id, "Created ticket #$id");
150
151     my $tick = RT::Test->last_ticket;
152     isa_ok ($tick, 'RT::Ticket');
153     is ($tick->Id, $id, "correct ticket id");
154     is ($tick->Subject, 'This is a test of the X-RT-Mail-Extension field', "Created the ticket");
155
156     my $transactions = $tick->Transactions;
157     $transactions->OrderByCols({ FIELD => 'id', ORDER => 'DESC' });
158     $transactions->Limit( FIELD => 'Type', OPERATOR => '!=', VALUE => 'EmailRecord');
159     my $txn = $transactions->First;
160     isa_ok ($txn, 'RT::Transaction');
161     is ($txn->Type, 'Create', "correct type");
162
163     my $attachment = $txn->Attachments->First;
164     isa_ok ($attachment, 'RT::Attachment');
165     # XXX: We eat all newlines in header, that's not what RFC's suggesting
166     is (
167         $attachment->GetHeader('X-RT-Mail-Extension'),
168         "bad value with newlines",
169         'header is in place, without trailing newline char'
170     );
171     $m->no_warnings_ok;
172 }
173
174 diag "Make sure that not standard --extension is passed";
175 {
176     my $text = <<EOF;
177 From: root\@localhost
178 To: rt\@@{[RT->Config->Get('rtname')]}
179 Subject: This is a test of new ticket creation
180
181 Foob!
182 EOF
183     my ($status, $id) = RT::Test->send_via_mailgate_and_http($text, extension => 'some-extension-arg' );
184     is ($status >> 8, 0, "The mail gateway exited normally");
185     ok ($id, "Created ticket #$id");
186
187     my $tick = RT::Test->last_ticket;
188     isa_ok ($tick, 'RT::Ticket');
189     is ($tick->Id, $id, "correct ticket id");
190
191     my $transactions = $tick->Transactions;
192     $transactions->OrderByCols({ FIELD => 'id', ORDER => 'DESC' });
193     $transactions->Limit( FIELD => 'Type', OPERATOR => '!=', VALUE => 'EmailRecord');
194     my $txn = $transactions->First;
195     isa_ok ($txn, 'RT::Transaction');
196     is ($txn->Type, 'Create', "correct type");
197
198     my $attachment = $txn->Attachments->First;
199     isa_ok ($attachment, 'RT::Attachment');
200     is (
201         $attachment->GetHeader('X-RT-Mail-Extension'),
202         'some-extension-arg',
203         'header is in place'
204     );
205     $m->no_warnings_ok;
206 }
207
208 diag "Test new ticket creation without --action argument";
209 {
210     my $text = <<EOF;
211 From: root\@localhost
212 To: rt\@$RT::rtname
213 Subject: using mailgate without --action arg
214
215 Blah!
216 Foob!
217 EOF
218     my ($status, $id) = RT::Test->send_via_mailgate_and_http($text, extension => 'some-extension-arg' );
219     is ($status >> 8, 0, "The mail gateway exited normally");
220     ok ($id, "Created ticket #$id");
221
222     my $tick = RT::Test->last_ticket;
223     isa_ok ($tick, 'RT::Ticket');
224     is ($tick->Id, $id, "correct ticket id");
225     is ($tick->Subject, 'using mailgate without --action arg', "using mailgate without --action arg");
226     $m->no_warnings_ok;
227 }
228
229 diag "This is a test of new ticket creation as an unknown user";
230 {
231     my $text = <<EOF;
232 From: doesnotexist\@@{[RT->Config->Get('rtname')]}
233 To: rt\@@{[RT->Config->Get('rtname')]}
234 Subject: This is a test of new ticket creation as an unknown user
235
236 Blah!
237 Foob!
238 EOF
239     my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
240     is ($status >> 8, 0, "The mail gateway exited normally");
241     ok (!$id, "no ticket created");
242
243     my $tick = RT::Test->last_ticket;
244     isa_ok ($tick, 'RT::Ticket');
245     ok ($tick->Id, "found ticket ".$tick->Id);
246     isnt ($tick->Subject , 'This is a test of new ticket creation as an unknown user', "failed to create the new ticket from an unprivileged account");
247
248     my $u = RT::User->new(RT->SystemUser);
249     $u->Load("doesnotexist\@@{[RT->Config->Get('rtname')]}");
250     ok( !$u->Id, "user does not exist and was not created by failed ticket submission");
251
252     $m->next_warning_like(qr/RT's configuration does not allow\s+for the creation of a new user for this email/);
253     $m->next_warning_like(qr/RT could not load a valid user/);
254     TODO: {
255         local $TODO = "we're a bit noisy for this warning case";
256         $m->no_leftover_warnings_ok;
257     }
258 }
259
260 diag "grant everybody with CreateTicket right";
261 {
262     ok( RT::Test->set_rights(
263         { Principal => $everyone_group->PrincipalObj,
264           Right => [qw(CreateTicket)],
265         },
266     ), "Granted everybody the right to create tickets");
267 }
268
269 my $ticket_id;
270 diag "now everybody can create tickets. can a random unkown user create tickets?";
271 {
272     my $text = <<EOF;
273 From: doesnotexist\@@{[RT->Config->Get('rtname')]}
274 To: rt\@@{[RT->Config->Get('rtname')]}
275 Subject: This is a test of new ticket creation as an unknown user
276
277 Blah!
278 Foob!
279 EOF
280     my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
281     is ($status >> 8, 0, "The mail gateway exited normally");
282     ok ($id, "ticket created");
283
284     my $tick = RT::Test->last_ticket;
285     isa_ok ($tick, 'RT::Ticket');
286     ok ($tick->Id, "found ticket ".$tick->Id);
287     is ($tick->Id, $id, "correct ticket id");
288     is ($tick->Subject , 'This is a test of new ticket creation as an unknown user', "failed to create the new ticket from an unprivileged account");
289
290     my $u = RT::User->new( RT->SystemUser );
291     $u->Load( "doesnotexist\@@{[RT->Config->Get('rtname')]}" );
292     ok ($u->Id, "user does not exist and was created by ticket submission");
293     $ticket_id = $id;
294     $m->no_warnings_ok;
295 }
296
297 diag "can another random reply to a ticket without being granted privs? answer should be no.";
298 {
299     my $text = <<EOF;
300 From: doesnotexist-2\@@{[RT->Config->Get('rtname')]}
301 To: rt\@@{[RT->Config->Get('rtname')]}
302 Subject: [@{[RT->Config->Get('rtname')]} #$ticket_id] This is a test of a reply as an unknown user
303
304 Blah!  (Should not work.)
305 Foob!
306 EOF
307     my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
308     is ($status >> 8, 0, "The mail gateway exited normally");
309     ok (!$id, "no way to reply to the ticket");
310
311     my $u = RT::User->new(RT->SystemUser);
312     $u->Load('doesnotexist-2@'.RT->Config->Get('rtname'));
313     ok( !$u->Id, " user does not exist and was not created by ticket correspondence submission");
314     $m->next_warning_like(qr/RT's configuration does not allow\s+for the creation of a new user for this email \(doesnotexist-2\@example\.com\)/);
315     TODO: {
316         local $TODO = "we're a bit noisy for this warning case";
317         $m->no_leftover_warnings_ok;
318     }
319 }
320
321 diag "grant everyone 'ReplyToTicket' right";
322 {
323     ok( RT::Test->set_rights(
324         { Principal => $everyone_group->PrincipalObj,
325           Right => [qw(CreateTicket ReplyToTicket)],
326         },
327     ), "Granted everybody the right to reply to tickets" );
328 }
329
330 diag "can another random reply to a ticket after being granted privs? answer should be yes";
331 {
332     my $text = <<EOF;
333 From: doesnotexist-2\@@{[RT->Config->Get('rtname')]}
334 To: rt\@@{[RT->Config->Get('rtname')]}
335 Subject: [@{[RT->Config->Get('rtname')]} #$ticket_id] This is a test of a reply as an unknown user
336
337 Blah!
338 Foob!
339 EOF
340     my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
341     is ($status >> 8, 0, "The mail gateway exited normally");
342     is ($id, $ticket_id, "replied to the ticket");
343
344     my $u = RT::User->new(RT->SystemUser);
345     $u->Load('doesnotexist-2@'.RT->Config->Get('rtname'));
346     ok ($u->Id, "user exists and was created by ticket correspondence submission");
347     $m->no_warnings_ok;
348 }
349
350 diag "add a reply to the ticket using '--extension ticket' feature";
351 {
352     my $text = <<EOF;
353 From: doesnotexist-2\@@{[RT->Config->Get('rtname')]}
354 To: rt\@@{[RT->Config->Get('rtname')]}
355 Subject: This is a test of a reply as an unknown user
356
357 Blah!
358 Foob!
359 EOF
360     local $ENV{'EXTENSION'} = $ticket_id;
361     my ($status, $id) = RT::Test->send_via_mailgate_and_http($text, extension => 'ticket');
362     is ($status >> 8, 0, "The mail gateway exited normally");
363     is ($id, $ticket_id, "replied to the ticket");
364
365     my $tick = RT::Test->last_ticket;
366     isa_ok ($tick, 'RT::Ticket');
367     ok ($tick->Id, "found ticket ".$tick->Id);
368     is ($tick->Id, $id, "correct ticket id");
369
370     my $transactions = $tick->Transactions;
371     $transactions->OrderByCols({ FIELD => 'id', ORDER => 'DESC' });
372     $transactions->Limit( FIELD => 'Type', OPERATOR => '!=', VALUE => 'EmailRecord');
373     my $txn = $transactions->First;
374     isa_ok ($txn, 'RT::Transaction');
375     is ($txn->Type, 'Correspond', "correct type");
376
377     my $attachment = $txn->Attachments->First;
378     isa_ok ($attachment, 'RT::Attachment');
379     is ($attachment->GetHeader('X-RT-Mail-Extension'), $id, 'header is in place');
380     $m->no_warnings_ok;
381 }
382
383 diag "can another random comment on a ticket without being granted privs? answer should be no";
384 {
385     my $text = <<EOF;
386 From: doesnotexist-3\@@{[RT->Config->Get('rtname')]}
387 To: rt\@@{[RT->Config->Get('rtname')]}
388 Subject: [@{[RT->Config->Get('rtname')]} #$ticket_id] This is a test of a comment as an unknown user
389
390 Blah!  (Should not work.)
391 Foob!
392 EOF
393     my ($status, $id) = RT::Test->send_via_mailgate_and_http($text, action => 'comment');
394     is ($status >> 8, 0, "The mail gateway exited normally");
395     ok (!$id, "no way to comment on the ticket");
396
397     my $u = RT::User->new(RT->SystemUser);
398     $u->Load('doesnotexist-3@'.RT->Config->Get('rtname'));
399     ok( !$u->Id, " user does not exist and was not created by ticket comment submission");
400     $m->next_warning_like(qr/RT's configuration does not allow\s+for the creation of a new user for this email \(doesnotexist-3\@example\.com\)/);
401     TODO: {
402         local $TODO = "we're a bit noisy for this warning case";
403         $m->no_leftover_warnings_ok;
404     }
405 }
406
407
408 diag "grant everyone 'CommentOnTicket' right";
409 {
410     ok( RT::Test->set_rights(
411         { Principal => $everyone_group->PrincipalObj,
412           Right => [qw(CreateTicket ReplyToTicket CommentOnTicket)],
413         },
414     ), "Granted everybody the right to comment on tickets");
415 }
416
417 diag "can another random reply to a ticket after being granted privs? answer should be yes";
418 {
419     my $text = <<EOF;
420 From: doesnotexist-3\@@{[RT->Config->Get('rtname')]}
421 To: rt\@@{[RT->Config->Get('rtname')]}
422 Subject: [@{[RT->Config->Get('rtname')]} #$ticket_id] This is a test of a comment as an unknown user
423
424 Blah!
425 Foob!
426 EOF
427     my ($status, $id) = RT::Test->send_via_mailgate_and_http($text, action => 'comment');
428     is ($status >> 8, 0, "The mail gateway exited normally");
429     is ($id, $ticket_id, "replied to the ticket");
430
431     my $u = RT::User->new(RT->SystemUser);
432     $u->Load('doesnotexist-3@'.RT->Config->Get('rtname'));
433     ok ($u->Id, " user exists and was created by ticket comment submission");
434     $m->no_warnings_ok;
435 }
436
437 diag "add comment to the ticket using '--extension action' feature";
438 {
439     my $text = <<EOF;
440 From: doesnotexist-3\@@{[RT->Config->Get('rtname')]}
441 To: rt\@@{[RT->Config->Get('rtname')]}
442 Subject: [@{[RT->Config->Get('rtname')]} #$ticket_id] This is a test of a comment via '--extension action'
443
444 Blah!
445 Foob!
446 EOF
447     local $ENV{'EXTENSION'} = 'comment';
448     my ($status, $id) = RT::Test->send_via_mailgate_and_http($text, extension => 'action');
449     is ($status >> 8, 0, "The mail gateway exited normally");
450     is ($id, $ticket_id, "added comment to the ticket");
451
452     my $tick = RT::Test->last_ticket;
453     isa_ok ($tick, 'RT::Ticket');
454     ok ($tick->Id, "found ticket ".$tick->Id);
455     is ($tick->Id, $id, "correct ticket id");
456
457     my $transactions = $tick->Transactions;
458     $transactions->OrderByCols({ FIELD => 'id', ORDER => 'DESC' });
459     $transactions->Limit(
460         FIELD => 'Type',
461         OPERATOR => 'NOT ENDSWITH',
462         VALUE => 'EmailRecord',
463         ENTRYAGGREGATOR => 'AND',
464     );
465     my $txn = $transactions->First;
466     isa_ok ($txn, 'RT::Transaction');
467     is ($txn->Type, 'Comment', "correct type");
468
469     my $attachment = $txn->Attachments->First;
470     isa_ok ($attachment, 'RT::Attachment');
471     is ($attachment->GetHeader('X-RT-Mail-Extension'), 'comment', 'header is in place');
472     $m->no_warnings_ok;
473 }
474
475 diag "Testing preservation of binary attachments";
476 {
477     # Get a binary blob (Best Practical logo) 
478     my $LOGO_FILE = $RT::MasonComponentRoot .'/NoAuth/images/bpslogo.png';
479
480     # Create a mime entity with an attachment
481     my $entity = MIME::Entity->build(
482         From    => 'root@localhost',
483         To      => 'rt@localhost',
484         Subject => 'binary attachment test',
485         Data    => ['This is a test of a binary attachment'],
486     );
487
488     $entity->attach(
489         Path     => $LOGO_FILE,
490         Type     => 'image/png',
491         Encoding => 'base64',
492     );
493     # Create a ticket with a binary attachment
494     my ($status, $id) = RT::Test->send_via_mailgate_and_http($entity);
495     is ($status >> 8, 0, "The mail gateway exited normally");
496     ok ($id, "created ticket");
497
498     my $tick = RT::Test->last_ticket;
499     isa_ok ($tick, 'RT::Ticket');
500     ok ($tick->Id, "found ticket ".$tick->Id);
501     is ($tick->Id, $id, "correct ticket id");
502     is ($tick->Subject , 'binary attachment test', "Created the ticket - ".$tick->Id);
503
504     my $file = `cat $LOGO_FILE`;
505     ok ($file, "Read in the logo image");
506     diag "for the raw file the md5 hex is ". Digest::MD5::md5_hex($file);
507
508     # Verify that the binary attachment is valid in the database
509     my $attachments = RT::Attachments->new(RT->SystemUser);
510     $attachments->Limit(FIELD => 'ContentType', VALUE => 'image/png');
511     my $txn_alias = $attachments->Join(
512         ALIAS1 => 'main',
513         FIELD1 => 'TransactionId',
514         TABLE2 => 'Transactions',
515         FIELD2 => 'id',
516     );
517     $attachments->Limit( ALIAS => $txn_alias, FIELD => 'ObjectType', VALUE => 'RT::Ticket' );
518     $attachments->Limit( ALIAS => $txn_alias, FIELD => 'ObjectId', VALUE => $id );
519     is ($attachments->Count, 1, 'Found only one png attached to the ticket');
520     my $attachment = $attachments->First;
521     ok ($attachment->Id, 'loaded attachment object');
522     my $acontent = $attachment->Content;
523
524     diag "coming from the database, md5 hex is ".Digest::MD5::md5_hex($acontent);
525     is ($acontent, $file, 'The attachment isn\'t screwed up in the database.');
526
527     # Grab the binary attachment via the web ui
528     my $ua = new LWP::UserAgent;
529     my $full_url = "$url/Ticket/Attachment/". $attachment->TransactionId
530         ."/". $attachment->id. "/bpslogo.png?&user=root&pass=password";
531     my $r = $ua->get( $full_url );
532
533     # Verify that the downloaded attachment is the same as what we uploaded.
534     is ($file, $r->content, 'The attachment isn\'t screwed up in download');
535
536     $m->no_warnings_ok;
537 }
538
539 diag "Simple I18N testing";
540 {
541     my $text = <<EOF;
542 From: root\@localhost
543 To: rtemail\@@{[RT->Config->Get('rtname')]}
544 Subject: This is a test of I18N ticket creation
545 Content-Type: text/plain; charset="utf-8"
546
547 2 accented lines
548 \303\242\303\252\303\256\303\264\303\273
549 \303\241\303\251\303\255\303\263\303\272
550 bye
551 EOF
552     my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
553     is ($status >> 8, 0, "The mail gateway exited normally");
554     ok ($id, "created ticket");
555
556     my $tick = RT::Test->last_ticket;
557     isa_ok ($tick, 'RT::Ticket');
558     ok ($tick->Id, "found ticket ". $tick->Id);
559     is ($tick->Id, $id, "correct ticket");
560     is ($tick->Subject , 'This is a test of I18N ticket creation', "Created the ticket - ". $tick->Subject);
561
562     my $unistring = "\303\241\303\251\303\255\303\263\303\272";
563     Encode::_utf8_on($unistring);
564     is (
565         $tick->Transactions->First->Content,
566         $tick->Transactions->First->Attachments->First->Content,
567         "Content is ". $tick->Transactions->First->Attachments->First->Content
568     );
569     ok (
570         $tick->Transactions->First->Content =~ /$unistring/i,
571         $tick->Id." appears to be unicode ". $tick->Transactions->First->Attachments->First->Id
572     );
573
574     $m->no_warnings_ok;
575 }
576
577 diag "supposedly I18N fails on the second message sent in.";
578 {
579     my $text = <<EOF;
580 From: root\@localhost
581 To: rtemail\@@{[RT->Config->Get('rtname')]}
582 Subject: This is a test of I18N ticket creation
583 Content-Type: text/plain; charset="utf-8"
584
585 2 accented lines
586 \303\242\303\252\303\256\303\264\303\273
587 \303\241\303\251\303\255\303\263\303\272
588 bye
589 EOF
590     my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
591     is ($status >> 8, 0, "The mail gateway exited normally");
592     ok ($id, "created ticket");
593
594     my $tick = RT::Test->last_ticket;
595     isa_ok ($tick, 'RT::Ticket');
596     ok ($tick->Id, "found ticket ". $tick->Id);
597     is ($tick->Id, $id, "correct ticket");
598     is ($tick->Subject , 'This is a test of I18N ticket creation', "Created the ticket");
599
600     my $unistring = "\303\241\303\251\303\255\303\263\303\272";
601     Encode::_utf8_on($unistring);
602
603     ok (
604         $tick->Transactions->First->Content =~ $unistring,
605         "It appears to be unicode - ". $tick->Transactions->First->Content
606     );
607
608     $m->no_warnings_ok;
609 }
610
611 diag "make sure we check that UTF-8 is really UTF-8";
612 {
613     my $text = <<EOF;
614 From: root\@localhost
615 To: rtemail\@@{[RT->Config->Get('rtname')]}
616 Subject: This is test wrong utf-8 chars
617 Content-Type: text/plain; charset="utf-8"
618
619 utf-8: informaci\303\263n confidencial
620 latin1: informaci\363n confidencial
621
622 bye
623 EOF
624     my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
625     is ($status >> 8, 0, "The mail gateway exited normally");
626     ok ($id, "created ticket");
627
628     my $tick = RT::Test->last_ticket;
629     is ($tick->Id, $id, "correct ticket");
630
631     my $content = $tick->Transactions->First->Content;
632     Encode::_utf8_off($content);
633
634     like $content, qr{informaci\303\263n confidencial};
635     like $content, qr{informaci\357\277\275n confidencial};
636
637     $m->no_warnings_ok;
638 }
639
640 diag "check that mailgate doesn't suffer from empty Reply-To:";
641 {
642     my $text = <<EOF;
643 From: root\@localhost
644 Reply-To: 
645 To: rtemail\@@{[RT->Config->Get('rtname')]}
646 Subject: test
647 Content-Type: text/plain; charset="utf-8"
648
649 test
650 EOF
651     my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
652     is ($status >> 8, 0, "The mail gateway exited normally");
653     ok ($id, "created ticket");
654
655     my $tick = RT::Test->last_ticket;
656     isa_ok ($tick, 'RT::Ticket');
657     ok ($tick->Id, "found ticket ". $tick->Id);
658     is ($tick->Id, $id, "correct ticket");
659
660     like $tick->RequestorAddresses, qr/root\@localhost/, 'correct requestor';
661
662     $m->no_warnings_ok;
663 }
664
665
666 my ($val,$msg) = $everyone_group->PrincipalObj->RevokeRight(Right => 'CreateTicket');
667 ok ($val, $msg);
668
669 SKIP: {
670 skip "Advanced mailgate actions require an unsafe configuration", 47
671     unless RT->Config->Get('UnsafeEmailCommands');
672
673 # create new queue to be shure we don't mess with rights
674 use RT::Queue;
675 my $queue = RT::Queue->new(RT->SystemUser);
676 my ($qid) = $queue->Create( Name => 'ext-mailgate');
677 ok( $qid, 'queue created for ext-mailgate tests' );
678
679
680 # create ticket that is owned by nobody
681 use RT::Ticket;
682 my $tick = RT::Ticket->new(RT->SystemUser);
683 my ($id) = $tick->Create( Queue => 'ext-mailgate', Subject => 'test');
684 ok( $id, 'new ticket created' );
685 is( $tick->Owner, RT->Nobody->Id, 'owner of the new ticket is nobody' );
686
687 $! = 0;
688 ok(open(MAIL, '|-', "$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action take"), "Opened the mailgate - $!");
689 print MAIL <<EOF;
690 From: root\@localhost
691 Subject: [@{[RT->Config->Get('rtname')]} \#$id] test
692
693 EOF
694 close (MAIL);
695 is ($? >> 8, 0, "The mail gateway exited normally");
696
697 $tick = RT::Ticket->new(RT->SystemUser);
698 $tick->Load( $id );
699 is( $tick->Id, $id, 'load correct ticket');
700 is( $tick->OwnerObj->EmailAddress, 'root@localhost', 'successfuly take ticket via email');
701
702 # check that there is no text transactions writen
703 is( $tick->Transactions->Count, 2, 'no superfluous transactions');
704
705 my $status;
706 ($status, $msg) = $tick->SetOwner( RT->Nobody->Id, 'Force' );
707 ok( $status, 'successfuly changed owner: '. ($msg||'') );
708 is( $tick->Owner, RT->Nobody->Id, 'set owner back to nobody');
709
710 $m->no_warnings_ok;
711
712
713 $! = 0;
714 ok(open(MAIL, '|-', "$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action take-correspond"), "Opened the mailgate - $@");
715 print MAIL <<EOF;
716 From: root\@localhost
717 Subject: [@{[RT->Config->Get('rtname')]} \#$id] correspondence
718
719 test
720 EOF
721 close (MAIL);
722 is ($? >> 8, 0, "The mail gateway exited normally");
723
724 DBIx::SearchBuilder::Record::Cachable->FlushCache;
725
726 $tick = RT::Ticket->new(RT->SystemUser);
727 $tick->Load( $id );
728 is( $tick->Id, $id, "load correct ticket #$id");
729 is( $tick->OwnerObj->EmailAddress, 'root@localhost', 'successfuly take ticket via email');
730 my $txns = $tick->Transactions;
731 $txns->Limit( FIELD => 'Type', VALUE => 'Correspond');
732 $txns->OrderBy( FIELD => 'id', ORDER => 'DESC' );
733 # +1 because of auto open
734 is( $tick->Transactions->Count, 6, 'no superfluous transactions');
735 is( $txns->First->Subject, "[$RT::rtname \#$id] correspondence", 'successfuly add correspond within take via email' );
736
737 $m->no_warnings_ok;
738
739
740 $! = 0;
741 ok(open(MAIL, '|-', "$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action resolve"), "Opened the mailgate - $!");
742 print MAIL <<EOF;
743 From: root\@localhost
744 Subject: [@{[RT->Config->Get('rtname')]} \#$id] test
745
746 EOF
747 close (MAIL);
748 is ($? >> 8, 0, "The mail gateway exited normally");
749
750 DBIx::SearchBuilder::Record::Cachable->FlushCache;
751
752 $tick = RT::Ticket->new(RT->SystemUser);
753 $tick->Load( $id );
754 is( $tick->Id, $id, 'load correct ticket');
755 is( $tick->Status, 'resolved', 'successfuly resolved ticket via email');
756 is( $tick->Transactions->Count, 7, 'no superfluous transactions');
757
758 use RT::User;
759 my $user = RT::User->new( RT->SystemUser );
760 my ($uid) = $user->Create( Name => 'ext-mailgate',
761                            EmailAddress => 'ext-mailgate@localhost',
762                            Privileged => 1,
763                            Password => 'qwe123',
764                          );
765 ok( $uid, 'user created for ext-mailgate tests' );
766 ok( !$user->HasRight( Right => 'OwnTicket', Object => $queue ), "User can't own ticket" );
767
768 $tick = RT::Ticket->new(RT->SystemUser);
769 ($id) = $tick->Create( Queue => $qid, Subject => 'test' );
770 ok( $id, 'create new ticket' );
771
772 my $rtname = RT->Config->Get('rtname');
773
774 $m->no_warnings_ok;
775
776 $! = 0;
777 ok(open(MAIL, '|-', "$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action take"), "Opened the mailgate - $!");
778 print MAIL <<EOF;
779 From: ext-mailgate\@localhost
780 Subject: [$rtname \#$id] test
781
782 EOF
783 close (MAIL);
784 is ( $? >> 8, 0, "mailgate exited normally" );
785 DBIx::SearchBuilder::Record::Cachable->FlushCache;
786
787 cmp_ok( $tick->Owner, '!=', $user->id, "we didn't change owner" );
788
789 ($status, $msg) = $user->PrincipalObj->GrantRight( Object => $queue, Right => 'ReplyToTicket' );
790 ok( $status, "successfuly granted right: $msg" );
791 my $ace_id = $status;
792 ok( $user->HasRight( Right => 'ReplyToTicket', Object => $tick ), "User can reply to ticket" );
793
794 $m->next_warning_like(qr/Permission Denied/);
795 $m->next_warning_like(qr/Could not record email: Ticket not taken/);
796 $m->no_leftover_warnings_ok;
797
798 $! = 0;
799 ok(open(MAIL, '|-', "$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action correspond-take"), "Opened the mailgate - $!");
800 print MAIL <<EOF;
801 From: ext-mailgate\@localhost
802 Subject: [$rtname \#$id] test
803
804 correspond-take
805 EOF
806 close (MAIL);
807 is ( $? >> 8, 0, "mailgate exited normally" );
808 DBIx::SearchBuilder::Record::Cachable->FlushCache;
809
810 cmp_ok( $tick->Owner, '!=', $user->id, "we didn't change owner" );
811 is( $tick->Transactions->Count, 3, "one transactions added" );
812
813 $m->next_warning_like(qr/Permission Denied/);
814 $m->next_warning_like(qr/Could not record email: Ticket not taken/);
815 $m->no_leftover_warnings_ok;
816
817 $! = 0;
818 ok(open(MAIL, '|-', "$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action take-correspond"), "Opened the mailgate - $!");
819 print MAIL <<EOF;
820 From: ext-mailgate\@localhost
821 Subject: [$rtname \#$id] test
822
823 correspond-take
824 EOF
825 close (MAIL);
826 is ( $? >> 8, 0, "mailgate exited normally" );
827 DBIx::SearchBuilder::Record::Cachable->FlushCache;
828
829 cmp_ok( $tick->Owner, '!=', $user->id, "we didn't change owner" );
830 is( $tick->Transactions->Count, 3, "no transactions added, user can't take ticket first" );
831
832 $m->next_warning_like(qr/Permission Denied/);
833 $m->next_warning_like(qr/Could not record email: Ticket not taken/);
834 $m->no_leftover_warnings_ok;
835
836 # revoke ReplyToTicket right
837 use RT::ACE;
838 my $ace = RT::ACE->new(RT->SystemUser);
839 $ace->Load( $ace_id );
840 $ace->Delete;
841 my $acl = RT::ACL->new(RT->SystemUser);
842 $acl->Limit( FIELD => 'RightName', VALUE => 'ReplyToTicket' );
843 $acl->LimitToObject( $RT::System );
844 while( my $ace = $acl->Next ) {
845         $ace->Delete;
846 }
847
848 ok( !$user->HasRight( Right => 'ReplyToTicket', Object => $tick ), "User can't reply to ticket any more" );
849
850
851 my $group = RT::Group->new( RT->SystemUser );
852 ok( $group->LoadQueueRoleGroup( Queue => $qid, Type=> 'Owner' ), "load queue owners role group" );
853 $ace = RT::ACE->new( RT->SystemUser );
854 ($ace_id, $msg) = $group->PrincipalObj->GrantRight( Right => 'ReplyToTicket', Object => $queue );
855 ok( $ace_id, "Granted queue owners role group with ReplyToTicket right" );
856
857 ($status, $msg) = $user->PrincipalObj->GrantRight( Object => $queue, Right => 'OwnTicket' );
858 ok( $status, "successfuly granted right: $msg" );
859 ($status, $msg) = $user->PrincipalObj->GrantRight( Object => $queue, Right => 'TakeTicket' );
860 ok( $status, "successfuly granted right: $msg" );
861
862 $! = 0;
863 ok(open(MAIL, '|-', "$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action take-correspond"), "Opened the mailgate - $!");
864 print MAIL <<EOF;
865 From: ext-mailgate\@localhost
866 Subject: [$rtname \#$id] test
867
868 take-correspond with reply right granted to owner role
869 EOF
870 close (MAIL);
871 is ( $? >> 8, 0, "mailgate exited normally" );
872 DBIx::SearchBuilder::Record::Cachable->FlushCache;
873
874 $tick->Load( $id );
875 is( $tick->Owner, $user->id, "we changed owner" );
876 ok( $user->HasRight( Right => 'ReplyToTicket', Object => $tick ), "owner can reply to ticket" );
877 is( $tick->Transactions->Count, 5, "transactions added" );
878
879 $m->no_warnings_ok;
880
881 };
882