first pass RT4 merge, RT#13852
[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 => 221, 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 "check that mailgate doesn't suffer from empty Reply-To:";
612 {
613     my $text = <<EOF;
614 From: root\@localhost
615 Reply-To: 
616 To: rtemail\@@{[RT->Config->Get('rtname')]}
617 Subject: test
618 Content-Type: text/plain; charset="utf-8"
619
620 test
621 EOF
622     my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
623     is ($status >> 8, 0, "The mail gateway exited normally");
624     ok ($id, "created ticket");
625
626     my $tick = RT::Test->last_ticket;
627     isa_ok ($tick, 'RT::Ticket');
628     ok ($tick->Id, "found ticket ". $tick->Id);
629     is ($tick->Id, $id, "correct ticket");
630
631     like $tick->RequestorAddresses, qr/root\@localhost/, 'correct requestor';
632
633     $m->no_warnings_ok;
634 }
635
636
637 my ($val,$msg) = $everyone_group->PrincipalObj->RevokeRight(Right => 'CreateTicket');
638 ok ($val, $msg);
639
640 SKIP: {
641 skip "Advanced mailgate actions require an unsafe configuration", 47
642     unless RT->Config->Get('UnsafeEmailCommands');
643
644 # create new queue to be shure we don't mess with rights
645 use RT::Queue;
646 my $queue = RT::Queue->new(RT->SystemUser);
647 my ($qid) = $queue->Create( Name => 'ext-mailgate');
648 ok( $qid, 'queue created for ext-mailgate tests' );
649
650
651 # create ticket that is owned by nobody
652 use RT::Ticket;
653 my $tick = RT::Ticket->new(RT->SystemUser);
654 my ($id) = $tick->Create( Queue => 'ext-mailgate', Subject => 'test');
655 ok( $id, 'new ticket created' );
656 is( $tick->Owner, RT->Nobody->Id, 'owner of the new ticket is nobody' );
657
658 $! = 0;
659 ok(open(MAIL, '|-', "$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action take"), "Opened the mailgate - $!");
660 print MAIL <<EOF;
661 From: root\@localhost
662 Subject: [@{[RT->Config->Get('rtname')]} \#$id] test
663
664 EOF
665 close (MAIL);
666 is ($? >> 8, 0, "The mail gateway exited normally");
667
668 $tick = RT::Ticket->new(RT->SystemUser);
669 $tick->Load( $id );
670 is( $tick->Id, $id, 'load correct ticket');
671 is( $tick->OwnerObj->EmailAddress, 'root@localhost', 'successfuly take ticket via email');
672
673 # check that there is no text transactions writen
674 is( $tick->Transactions->Count, 2, 'no superfluous transactions');
675
676 my $status;
677 ($status, $msg) = $tick->SetOwner( RT->Nobody->Id, 'Force' );
678 ok( $status, 'successfuly changed owner: '. ($msg||'') );
679 is( $tick->Owner, RT->Nobody->Id, 'set owner back to nobody');
680
681 $m->no_warnings_ok;
682
683
684 $! = 0;
685 ok(open(MAIL, '|-', "$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action take-correspond"), "Opened the mailgate - $@");
686 print MAIL <<EOF;
687 From: root\@localhost
688 Subject: [@{[RT->Config->Get('rtname')]} \#$id] correspondence
689
690 test
691 EOF
692 close (MAIL);
693 is ($? >> 8, 0, "The mail gateway exited normally");
694
695 DBIx::SearchBuilder::Record::Cachable->FlushCache;
696
697 $tick = RT::Ticket->new(RT->SystemUser);
698 $tick->Load( $id );
699 is( $tick->Id, $id, "load correct ticket #$id");
700 is( $tick->OwnerObj->EmailAddress, 'root@localhost', 'successfuly take ticket via email');
701 my $txns = $tick->Transactions;
702 $txns->Limit( FIELD => 'Type', VALUE => 'Correspond');
703 $txns->OrderBy( FIELD => 'id', ORDER => 'DESC' );
704 # +1 because of auto open
705 is( $tick->Transactions->Count, 6, 'no superfluous transactions');
706 is( $txns->First->Subject, "[$RT::rtname \#$id] correspondence", 'successfuly add correspond within take via email' );
707
708 $m->no_warnings_ok;
709
710
711 $! = 0;
712 ok(open(MAIL, '|-', "$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action resolve"), "Opened the mailgate - $!");
713 print MAIL <<EOF;
714 From: root\@localhost
715 Subject: [@{[RT->Config->Get('rtname')]} \#$id] test
716
717 EOF
718 close (MAIL);
719 is ($? >> 8, 0, "The mail gateway exited normally");
720
721 DBIx::SearchBuilder::Record::Cachable->FlushCache;
722
723 $tick = RT::Ticket->new(RT->SystemUser);
724 $tick->Load( $id );
725 is( $tick->Id, $id, 'load correct ticket');
726 is( $tick->Status, 'resolved', 'successfuly resolved ticket via email');
727 is( $tick->Transactions->Count, 7, 'no superfluous transactions');
728
729 use RT::User;
730 my $user = RT::User->new( RT->SystemUser );
731 my ($uid) = $user->Create( Name => 'ext-mailgate',
732                            EmailAddress => 'ext-mailgate@localhost',
733                            Privileged => 1,
734                            Password => 'qwe123',
735                          );
736 ok( $uid, 'user created for ext-mailgate tests' );
737 ok( !$user->HasRight( Right => 'OwnTicket', Object => $queue ), "User can't own ticket" );
738
739 $tick = RT::Ticket->new(RT->SystemUser);
740 ($id) = $tick->Create( Queue => $qid, Subject => 'test' );
741 ok( $id, 'create new ticket' );
742
743 my $rtname = RT->Config->Get('rtname');
744
745 $m->no_warnings_ok;
746
747 $! = 0;
748 ok(open(MAIL, '|-', "$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action take"), "Opened the mailgate - $!");
749 print MAIL <<EOF;
750 From: ext-mailgate\@localhost
751 Subject: [$rtname \#$id] test
752
753 EOF
754 close (MAIL);
755 is ( $? >> 8, 0, "mailgate exited normally" );
756 DBIx::SearchBuilder::Record::Cachable->FlushCache;
757
758 cmp_ok( $tick->Owner, '!=', $user->id, "we didn't change owner" );
759
760 ($status, $msg) = $user->PrincipalObj->GrantRight( Object => $queue, Right => 'ReplyToTicket' );
761 ok( $status, "successfuly granted right: $msg" );
762 my $ace_id = $status;
763 ok( $user->HasRight( Right => 'ReplyToTicket', Object => $tick ), "User can reply to ticket" );
764
765 $m->next_warning_like(qr/Permission Denied/);
766 $m->next_warning_like(qr/Could not record email: Ticket not taken/);
767 $m->no_leftover_warnings_ok;
768
769 $! = 0;
770 ok(open(MAIL, '|-', "$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action correspond-take"), "Opened the mailgate - $!");
771 print MAIL <<EOF;
772 From: ext-mailgate\@localhost
773 Subject: [$rtname \#$id] test
774
775 correspond-take
776 EOF
777 close (MAIL);
778 is ( $? >> 8, 0, "mailgate exited normally" );
779 DBIx::SearchBuilder::Record::Cachable->FlushCache;
780
781 cmp_ok( $tick->Owner, '!=', $user->id, "we didn't change owner" );
782 is( $tick->Transactions->Count, 3, "one transactions added" );
783
784 $m->next_warning_like(qr/Permission Denied/);
785 $m->next_warning_like(qr/Could not record email: Ticket not taken/);
786 $m->no_leftover_warnings_ok;
787
788 $! = 0;
789 ok(open(MAIL, '|-', "$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action take-correspond"), "Opened the mailgate - $!");
790 print MAIL <<EOF;
791 From: ext-mailgate\@localhost
792 Subject: [$rtname \#$id] test
793
794 correspond-take
795 EOF
796 close (MAIL);
797 is ( $? >> 8, 0, "mailgate exited normally" );
798 DBIx::SearchBuilder::Record::Cachable->FlushCache;
799
800 cmp_ok( $tick->Owner, '!=', $user->id, "we didn't change owner" );
801 is( $tick->Transactions->Count, 3, "no transactions added, user can't take ticket first" );
802
803 $m->next_warning_like(qr/Permission Denied/);
804 $m->next_warning_like(qr/Could not record email: Ticket not taken/);
805 $m->no_leftover_warnings_ok;
806
807 # revoke ReplyToTicket right
808 use RT::ACE;
809 my $ace = RT::ACE->new(RT->SystemUser);
810 $ace->Load( $ace_id );
811 $ace->Delete;
812 my $acl = RT::ACL->new(RT->SystemUser);
813 $acl->Limit( FIELD => 'RightName', VALUE => 'ReplyToTicket' );
814 $acl->LimitToObject( $RT::System );
815 while( my $ace = $acl->Next ) {
816         $ace->Delete;
817 }
818
819 ok( !$user->HasRight( Right => 'ReplyToTicket', Object => $tick ), "User can't reply to ticket any more" );
820
821
822 my $group = RT::Group->new( RT->SystemUser );
823 ok( $group->LoadQueueRoleGroup( Queue => $qid, Type=> 'Owner' ), "load queue owners role group" );
824 $ace = RT::ACE->new( RT->SystemUser );
825 ($ace_id, $msg) = $group->PrincipalObj->GrantRight( Right => 'ReplyToTicket', Object => $queue );
826 ok( $ace_id, "Granted queue owners role group with ReplyToTicket right" );
827
828 ($status, $msg) = $user->PrincipalObj->GrantRight( Object => $queue, Right => 'OwnTicket' );
829 ok( $status, "successfuly granted right: $msg" );
830 ($status, $msg) = $user->PrincipalObj->GrantRight( Object => $queue, Right => 'TakeTicket' );
831 ok( $status, "successfuly granted right: $msg" );
832
833 $! = 0;
834 ok(open(MAIL, '|-', "$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action take-correspond"), "Opened the mailgate - $!");
835 print MAIL <<EOF;
836 From: ext-mailgate\@localhost
837 Subject: [$rtname \#$id] test
838
839 take-correspond with reply right granted to owner role
840 EOF
841 close (MAIL);
842 is ( $? >> 8, 0, "mailgate exited normally" );
843 DBIx::SearchBuilder::Record::Cachable->FlushCache;
844
845 $tick->Load( $id );
846 is( $tick->Owner, $user->id, "we changed owner" );
847 ok( $user->HasRight( Right => 'ReplyToTicket', Object => $tick ), "owner can reply to ticket" );
848 is( $tick->Transactions->Count, 5, "transactions added" );
849
850 $m->no_warnings_ok;
851
852 };
853