gateway.t 27 KB
Newer Older
1
#!/usr/bin/perl -w
2
# BEGIN BPS TAGGED BLOCK {{{
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 
# COPYRIGHT:
#  
# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC 
#                                          <jesse.com>
# 
# (Except where explicitly superseded by other copyright notices)
# 
# 
# LICENSE:
# 
# This work is made available to you under the terms of Version 2 of
# the GNU General Public License. A copy of that license should have
# been provided with this software, but in any event can be snarfed
# from www.gnu.org.
# 
# This work is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
Ruslan Zakirov's avatar
Ruslan Zakirov committed
26
27
28
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 or visit their web page on the internet at
# http://www.gnu.org/copyleft/gpl.html.
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 
# 
# CONTRIBUTION SUBMISSION POLICY:
# 
# (The following paragraph is not intended to limit the rights granted
# to you to modify and distribute this software under the terms of
# the GNU General Public License and is only of importance to you if
# you choose to contribute your changes and enhancements to the
# community by submitting them to Best Practical Solutions, LLC.)
# 
# By intentionally submitting any modifications, corrections or
# derivatives to this work, or any other work intended for use with
# Request Tracker, to Best Practical Solutions, LLC, you confirm that
# you are the copyright holder for those contributions and you grant
# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
# royalty-free, perpetual, license to use, copy, create derivative
# works based on those contributions, and sublicense and distribute
# those contributions and any derivatives thereof.
# 
48
# END BPS TAGGED BLOCK }}}
49
50
51
52
53
54
55

=head1 NAME

rt-mailgate - Mail interface to RT3.

=cut

Jesse Vincent's avatar
Jesse Vincent committed
56
use strict;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
57
58
use warnings;

59

60
use RT::Test config => 'Set( $UnsafeEmailCommands, 1);', tests => 159;
61
my ($baseurl, $m) = RT::Test->started_ok;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
62
63

use RT::Tickets;
64

Ruslan Zakirov's avatar
Ruslan Zakirov committed
65
use MIME::Entity;
66
use Digest::MD5 qw(md5_base64);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
67
use LWP::UserAgent;
68

Ruslan Zakirov's avatar
Ruslan Zakirov committed
69
# TODO: --extension queue
Ruslan Zakirov's avatar
Ruslan Zakirov committed
70

Ruslan Zakirov's avatar
Ruslan Zakirov committed
71
my $url = $m->rt_base_url;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
72

73
diag "Make sure that when we call the mailgate without URL, it fails";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
74
75
76
77
78
79
80
81
{
    my $text = <<EOF;
From: root\@localhost
To: rt\@@{[RT->Config->Get('rtname')]}
Subject: This is a test of new ticket creation

Foob!
EOF
82
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text, url => undef);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
83
84
85
86
    is ($status >> 8, 1, "The mail gateway exited with a failure");
    ok (!$id, "No ticket id") or diag "by mistake ticket #$id";
}

87
diag "Make sure that when we call the mailgate with wrong URL, it tempfails";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
88
89
{
    my $text = <<EOF;
90
From: root\@localhost
Jesse Vincent's avatar
Jesse Vincent committed
91
To: rt\@@{[RT->Config->Get('rtname')]}
92
93
94
95
Subject: This is a test of new ticket creation

Foob!
EOF
96
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text, url => 'http://this.test.for.non-connection.is.expected.to.generate.an.error');
Ruslan Zakirov's avatar
Ruslan Zakirov committed
97
98
99
100
101
    is ($status >> 8, 75, "The mail gateway exited with a failure");
    ok (!$id, "No ticket id");
}

my $everyone_group;
102
diag "revoke rights tests depend on";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
103
104
105
106
107
108
109
110
111
112
{
    $everyone_group = RT::Group->new( $RT::SystemUser );
    $everyone_group->LoadSystemInternalGroup( 'Everyone' );
    ok ($everyone_group->Id, "Found group 'everyone'");

    foreach( qw(CreateTicket ReplyToTicket CommentOnTicket) ) {
        $everyone_group->PrincipalObj->RevokeRight(Right => $_);
    }
}

113
diag "Test new ticket creation by root who is privileged and superuser";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
114
115
{
    my $text = <<EOF;
116
From: root\@localhost
Jesse Vincent's avatar
Jesse Vincent committed
117
To: rt\@@{[RT->Config->Get('rtname')]}
118
119
120
121
122
123
Subject: This is a test of new ticket creation

Blah!
Foob!
EOF

124
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
125
126
    is ($status >> 8, 0, "The mail gateway exited normally");
    ok ($id, "Created ticket");
127

Ruslan Zakirov's avatar
Ruslan Zakirov committed
128
    my $tick = RT::Test->last_ticket;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
129
130
    isa_ok ($tick, 'RT::Ticket');
    is ($tick->Id, $id, "correct ticket id");
CL Sung's avatar
CL Sung committed
131
    is ($tick->Subject , 'This is a test of new ticket creation', "Created the ticket");
Ruslan Zakirov's avatar
Ruslan Zakirov committed
132
}
133

134
diag "Test the 'X-RT-Mail-Extension' field in the header of a ticket";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
135
136
137
138
139
140
141
142
143
{
    my $text = <<EOF;
From: root\@localhost
To: rt\@@{[RT->Config->Get('rtname')]}
Subject: This is a test of the X-RT-Mail-Extension field
Blah!
Foob!
EOF
    local $ENV{'EXTENSION'} = "bad value with\nnewlines\n";
144
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
145
146
147
    is ($status >> 8, 0, "The mail gateway exited normally");
    ok ($id, "Created ticket #$id");

Ruslan Zakirov's avatar
Ruslan Zakirov committed
148
    my $tick = RT::Test->last_ticket;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
149
150
    isa_ok ($tick, 'RT::Ticket');
    is ($tick->Id, $id, "correct ticket id");
151
    is ($tick->Subject, 'This is a test of the X-RT-Mail-Extension field', "Created the ticket");
Ruslan Zakirov's avatar
Ruslan Zakirov committed
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

    my $transactions = $tick->Transactions;
    $transactions->OrderByCols({ FIELD => 'id', ORDER => 'DESC' });
    $transactions->Limit( FIELD => 'Type', OPERATOR => '!=', VALUE => 'EmailRecord');
    my $txn = $transactions->First;
    isa_ok ($txn, 'RT::Transaction');
    is ($txn->Type, 'Create', "correct type");

    my $attachment = $txn->Attachments->First;
    isa_ok ($attachment, 'RT::Attachment');
    # XXX: We eat all newlines in header, that's not what RFC's suggesting
    is (
        $attachment->GetHeader('X-RT-Mail-Extension'),
        "bad value with newlines",
        'header is in place, without trailing newline char'
    );
}

170
diag "Make sure that not standard --extension is passed";
171
172
173
174
175
176
177
178
{
    my $text = <<EOF;
From: root\@localhost
To: rt\@@{[RT->Config->Get('rtname')]}
Subject: This is a test of new ticket creation

Foob!
EOF
179
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text, extension => 'some-extension-arg' );
180
181
182
    is ($status >> 8, 0, "The mail gateway exited normally");
    ok ($id, "Created ticket #$id");

Ruslan Zakirov's avatar
Ruslan Zakirov committed
183
    my $tick = RT::Test->last_ticket;
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
    isa_ok ($tick, 'RT::Ticket');
    is ($tick->Id, $id, "correct ticket id");

    my $transactions = $tick->Transactions;
    $transactions->OrderByCols({ FIELD => 'id', ORDER => 'DESC' });
    $transactions->Limit( FIELD => 'Type', OPERATOR => '!=', VALUE => 'EmailRecord');
    my $txn = $transactions->First;
    isa_ok ($txn, 'RT::Transaction');
    is ($txn->Type, 'Create', "correct type");

    my $attachment = $txn->Attachments->First;
    isa_ok ($attachment, 'RT::Attachment');
    is (
        $attachment->GetHeader('X-RT-Mail-Extension'),
        'some-extension-arg',
        'header is in place'
    );
}

203
diag "Test new ticket creation without --action argument";
204
205
{
    my $text = <<EOF;
206
207
208
209
210
211
212
From: root\@localhost
To: rt\@$RT::rtname
Subject: using mailgate without --action arg

Blah!
Foob!
EOF
213
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text, extension => 'some-extension-arg' );
214
215
216
    is ($status >> 8, 0, "The mail gateway exited normally");
    ok ($id, "Created ticket #$id");

Ruslan Zakirov's avatar
Ruslan Zakirov committed
217
    my $tick = RT::Test->last_ticket;
218
219
220
221
222
    isa_ok ($tick, 'RT::Ticket');
    is ($tick->Id, $id, "correct ticket id");
    is ($tick->Subject, 'using mailgate without --action arg', "using mailgate without --action arg");
}

223
diag "This is a test of new ticket creation as an unknown user";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
224
225
{
    my $text = <<EOF;
Jesse Vincent's avatar
Jesse Vincent committed
226
227
From: doesnotexist\@@{[RT->Config->Get('rtname')]}
To: rt\@@{[RT->Config->Get('rtname')]}
228
229
230
231
232
Subject: This is a test of new ticket creation as an unknown user

Blah!
Foob!
EOF
233
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
234
235
236
    is ($status >> 8, 0, "The mail gateway exited normally");
    ok (!$id, "no ticket created");

Ruslan Zakirov's avatar
Ruslan Zakirov committed
237
    my $tick = RT::Test->last_ticket;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
238
239
    isa_ok ($tick, 'RT::Ticket');
    ok ($tick->Id, "found ticket ".$tick->Id);
CL Sung's avatar
CL Sung committed
240
    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");
Ruslan Zakirov's avatar
Ruslan Zakirov committed
241
242
243
244
245
246

    my $u = RT::User->new($RT::SystemUser);
    $u->Load("doesnotexist\@@{[RT->Config->Get('rtname')]}");
    ok( !$u->Id, "user does not exist and was not created by failed ticket submission");
}

247
diag "grant everybody with CreateTicket right";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
248
{
249
250
251
252
253
    ok( RT::Test->set_rights(
        { Principal => $everyone_group->PrincipalObj,
          Right => [qw(CreateTicket)],
        },
    ), "Granted everybody the right to create tickets");
Ruslan Zakirov's avatar
Ruslan Zakirov committed
254
255
256
}

my $ticket_id;
257
diag "now everybody can create tickets. can a random unkown user create tickets?";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
258
259
{
    my $text = <<EOF;
Jesse Vincent's avatar
Jesse Vincent committed
260
261
From: doesnotexist\@@{[RT->Config->Get('rtname')]}
To: rt\@@{[RT->Config->Get('rtname')]}
262
263
264
265
266
Subject: This is a test of new ticket creation as an unknown user

Blah!
Foob!
EOF
267
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
268
269
270
    is ($status >> 8, 0, "The mail gateway exited normally");
    ok ($id, "ticket created");

Ruslan Zakirov's avatar
Ruslan Zakirov committed
271
    my $tick = RT::Test->last_ticket;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
272
273
274
    isa_ok ($tick, 'RT::Ticket');
    ok ($tick->Id, "found ticket ".$tick->Id);
    is ($tick->Id, $id, "correct ticket id");
CL Sung's avatar
CL Sung committed
275
    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");
Ruslan Zakirov's avatar
Ruslan Zakirov committed
276
277
278
279
280
281
282

    my $u = RT::User->new( $RT::SystemUser );
    $u->Load( "doesnotexist\@@{[RT->Config->Get('rtname')]}" );
    ok ($u->Id, "user does not exist and was created by ticket submission");
    $ticket_id = $id;
}

283
diag "can another random reply to a ticket without being granted privs? answer should be no.";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
284
285
{
    my $text = <<EOF;
Jesse Vincent's avatar
Jesse Vincent committed
286
287
From: doesnotexist-2\@@{[RT->Config->Get('rtname')]}
To: rt\@@{[RT->Config->Get('rtname')]}
Ruslan Zakirov's avatar
Ruslan Zakirov committed
288
Subject: [@{[RT->Config->Get('rtname')]} #$ticket_id] This is a test of a reply as an unknown user
289

290
Blah!  (Should not work.)
291
292
Foob!
EOF
293
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
294
295
296
297
298
299
300
301
    is ($status >> 8, 0, "The mail gateway exited normally");
    ok (!$id, "no way to reply to the ticket");

    my $u = RT::User->new($RT::SystemUser);
    $u->Load('doesnotexist-2@'.RT->Config->Get('rtname'));
    ok( !$u->Id, " user does not exist and was not created by ticket correspondence submission");
}

302
diag "grant everyone 'ReplyToTicket' right";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
303
{
304
305
306
307
308
    ok( RT::Test->set_rights(
        { Principal => $everyone_group->PrincipalObj,
          Right => [qw(CreateTicket ReplyToTicket)],
        },
    ), "Granted everybody the right to reply to tickets" );
Ruslan Zakirov's avatar
Ruslan Zakirov committed
309
310
}

311
diag "can another random reply to a ticket after being granted privs? answer should be yes";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
312
313
{
    my $text = <<EOF;
Jesse Vincent's avatar
Jesse Vincent committed
314
315
From: doesnotexist-2\@@{[RT->Config->Get('rtname')]}
To: rt\@@{[RT->Config->Get('rtname')]}
Ruslan Zakirov's avatar
Ruslan Zakirov committed
316
Subject: [@{[RT->Config->Get('rtname')]} #$ticket_id] This is a test of a reply as an unknown user
317
318
319
320

Blah!
Foob!
EOF
321
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
322
323
    is ($status >> 8, 0, "The mail gateway exited normally");
    is ($id, $ticket_id, "replied to the ticket");
324

Ruslan Zakirov's avatar
Ruslan Zakirov committed
325
326
327
328
    my $u = RT::User->new($RT::SystemUser);
    $u->Load('doesnotexist-2@'.RT->Config->Get('rtname'));
    ok ($u->Id, "user exists and was created by ticket correspondence submission");
}
329

330
diag "add a reply to the ticket using '--extension ticket' feature";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
331
332
333
334
335
336
337
338
339
340
{
    my $text = <<EOF;
From: doesnotexist-2\@@{[RT->Config->Get('rtname')]}
To: rt\@@{[RT->Config->Get('rtname')]}
Subject: This is a test of a reply as an unknown user

Blah!
Foob!
EOF
    local $ENV{'EXTENSION'} = $ticket_id;
341
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text, extension => 'ticket');
Ruslan Zakirov's avatar
Ruslan Zakirov committed
342
343
344
    is ($status >> 8, 0, "The mail gateway exited normally");
    is ($id, $ticket_id, "replied to the ticket");

Ruslan Zakirov's avatar
Ruslan Zakirov committed
345
    my $tick = RT::Test->last_ticket;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
    isa_ok ($tick, 'RT::Ticket');
    ok ($tick->Id, "found ticket ".$tick->Id);
    is ($tick->Id, $id, "correct ticket id");

    my $transactions = $tick->Transactions;
    $transactions->OrderByCols({ FIELD => 'id', ORDER => 'DESC' });
    $transactions->Limit( FIELD => 'Type', OPERATOR => '!=', VALUE => 'EmailRecord');
    my $txn = $transactions->First;
    isa_ok ($txn, 'RT::Transaction');
    is ($txn->Type, 'Correspond', "correct type");

    my $attachment = $txn->Attachments->First;
    isa_ok ($attachment, 'RT::Attachment');
    is ($attachment->GetHeader('X-RT-Mail-Extension'), $id, 'header is in place');
}
361

362
diag "can another random comment on a ticket without being granted privs? answer should be no";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
363
364
{
    my $text = <<EOF;
Jesse Vincent's avatar
Jesse Vincent committed
365
366
From: doesnotexist-3\@@{[RT->Config->Get('rtname')]}
To: rt\@@{[RT->Config->Get('rtname')]}
Ruslan Zakirov's avatar
Ruslan Zakirov committed
367
Subject: [@{[RT->Config->Get('rtname')]} #$ticket_id] This is a test of a comment as an unknown user
368

369
Blah!  (Should not work.)
370
371
Foob!
EOF
372
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text, action => 'comment');
Ruslan Zakirov's avatar
Ruslan Zakirov committed
373
374
    is ($status >> 8, 0, "The mail gateway exited normally");
    ok (!$id, "no way to comment on the ticket");
375

Ruslan Zakirov's avatar
Ruslan Zakirov committed
376
377
378
379
    my $u = RT::User->new($RT::SystemUser);
    $u->Load('doesnotexist-3@'.RT->Config->Get('rtname'));
    ok( !$u->Id, " user does not exist and was not created by ticket comment submission");
}
380
381


382
diag "grant everyone 'CommentOnTicket' right";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
383
{
384
385
386
387
388
    ok( RT::Test->set_rights(
        { Principal => $everyone_group->PrincipalObj,
          Right => [qw(CreateTicket ReplyToTicket CommentOnTicket)],
        },
    ), "Granted everybody the right to comment on tickets");
Ruslan Zakirov's avatar
Ruslan Zakirov committed
389
}
390

391
diag "can another random reply to a ticket after being granted privs? answer should be yes";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
392
393
{
    my $text = <<EOF;
Jesse Vincent's avatar
Jesse Vincent committed
394
395
From: doesnotexist-3\@@{[RT->Config->Get('rtname')]}
To: rt\@@{[RT->Config->Get('rtname')]}
Ruslan Zakirov's avatar
Ruslan Zakirov committed
396
Subject: [@{[RT->Config->Get('rtname')]} #$ticket_id] This is a test of a comment as an unknown user
397
398
399
400

Blah!
Foob!
EOF
401
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text, action => 'comment');
Ruslan Zakirov's avatar
Ruslan Zakirov committed
402
403
404
405
406
407
408
409
    is ($status >> 8, 0, "The mail gateway exited normally");
    is ($id, $ticket_id, "replied to the ticket");

    my $u = RT::User->new($RT::SystemUser);
    $u->Load('doesnotexist-3@'.RT->Config->Get('rtname'));
    ok ($u->Id, " user exists and was created by ticket comment submission");
}

410
diag "add comment to the ticket using '--extension action' feature";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
411
412
413
414
415
416
417
418
419
420
{
    my $text = <<EOF;
From: doesnotexist-3\@@{[RT->Config->Get('rtname')]}
To: rt\@@{[RT->Config->Get('rtname')]}
Subject: [@{[RT->Config->Get('rtname')]} #$ticket_id] This is a test of a comment via '--extension action'

Blah!
Foob!
EOF
    local $ENV{'EXTENSION'} = 'comment';
421
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text, extension => 'action');
Ruslan Zakirov's avatar
Ruslan Zakirov committed
422
423
424
    is ($status >> 8, 0, "The mail gateway exited normally");
    is ($id, $ticket_id, "added comment to the ticket");

Ruslan Zakirov's avatar
Ruslan Zakirov committed
425
    my $tick = RT::Test->last_ticket;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
426
427
428
429
430
431
    isa_ok ($tick, 'RT::Ticket');
    ok ($tick->Id, "found ticket ".$tick->Id);
    is ($tick->Id, $id, "correct ticket id");

    my $transactions = $tick->Transactions;
    $transactions->OrderByCols({ FIELD => 'id', ORDER => 'DESC' });
Ruslan Zakirov's avatar
Ruslan Zakirov committed
432
433
434
435
436
437
    $transactions->Limit(
        FIELD => 'Type',
        OPERATOR => 'NOT ENDSWITH',
        VALUE => 'EmailRecord',
        ENTRYAGGREGATOR => 'AND',
    );
Ruslan Zakirov's avatar
Ruslan Zakirov committed
438
439
440
441
442
443
444
445
446
    my $txn = $transactions->First;
    isa_ok ($txn, 'RT::Transaction');
    is ($txn->Type, 'Comment', "correct type");

    my $attachment = $txn->Attachments->First;
    isa_ok ($attachment, 'RT::Attachment');
    is ($attachment->GetHeader('X-RT-Mail-Extension'), 'comment', 'header is in place');
}

447
diag "Testing preservation of binary attachments";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
448
449
{
    # Get a binary blob (Best Practical logo) 
450
    my $LOGO_FILE = $RT::MasonComponentRoot .'/NoAuth/images/bpslogo.png';
Ruslan Zakirov's avatar
Ruslan Zakirov committed
451
452
453
454
455
456
457
458
459
460
461

    # Create a mime entity with an attachment
    my $entity = MIME::Entity->build(
        From    => 'root@localhost',
        To      => 'rt@localhost',
        Subject => 'binary attachment test',
        Data    => ['This is a test of a binary attachment'],
    );

    $entity->attach(
        Path     => $LOGO_FILE,
462
        Type     => 'image/png',
Ruslan Zakirov's avatar
Ruslan Zakirov committed
463
464
465
        Encoding => 'base64',
    );
    # Create a ticket with a binary attachment
466
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($entity);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
467
468
469
    is ($status >> 8, 0, "The mail gateway exited normally");
    ok ($id, "created ticket");

Ruslan Zakirov's avatar
Ruslan Zakirov committed
470
    my $tick = RT::Test->last_ticket;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
471
472
473
    isa_ok ($tick, 'RT::Ticket');
    ok ($tick->Id, "found ticket ".$tick->Id);
    is ($tick->Id, $id, "correct ticket id");
CL Sung's avatar
CL Sung committed
474
    is ($tick->Subject , 'binary attachment test', "Created the ticket - ".$tick->Id);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
475
476
477

    my $file = `cat $LOGO_FILE`;
    ok ($file, "Read in the logo image");
478
    diag "for the raw file the md5 hex is ". Digest::MD5::md5_hex($file);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
479
480
481

    # Verify that the binary attachment is valid in the database
    my $attachments = RT::Attachments->new($RT::SystemUser);
482
    $attachments->Limit(FIELD => 'ContentType', VALUE => 'image/png');
Ruslan Zakirov's avatar
Ruslan Zakirov committed
483
484
485
486
487
488
489
490
    my $txn_alias = $attachments->Join(
        ALIAS1 => 'main',
        FIELD1 => 'TransactionId',
        TABLE2 => 'Transactions',
        FIELD2 => 'id',
    );
    $attachments->Limit( ALIAS => $txn_alias, FIELD => 'ObjectType', VALUE => 'RT::Ticket' );
    $attachments->Limit( ALIAS => $txn_alias, FIELD => 'ObjectId', VALUE => $id );
491
    is ($attachments->Count, 1, 'Found only one png attached to the ticket');
Ruslan Zakirov's avatar
Ruslan Zakirov committed
492
493
494
495
    my $attachment = $attachments->First;
    ok ($attachment->Id, 'loaded attachment object');
    my $acontent = $attachment->Content;

496
    diag "coming from the database, md5 hex is ".Digest::MD5::md5_hex($acontent);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
497
498
499
500
501
    is ($acontent, $file, 'The attachment isn\'t screwed up in the database.');

    # Grab the binary attachment via the web ui
    my $ua = new LWP::UserAgent;
    my $full_url = "$url/Ticket/Attachment/". $attachment->TransactionId
502
        ."/". $attachment->id. "/bpslogo.png?&user=root&pass=password";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
503
504
505
506
507
508
    my $r = $ua->get( $full_url );

    # Verify that the downloaded attachment is the same as what we uploaded.
    is ($file, $r->content, 'The attachment isn\'t screwed up in download');
}

509
diag "Simple I18N testing";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
510
511
{
    my $text = <<EOF;
512
From: root\@localhost
Jesse Vincent's avatar
Jesse Vincent committed
513
To: rtemail\@@{[RT->Config->Get('rtname')]}
514
515
516
517
518
519
520
521
Subject: This is a test of I18N ticket creation
Content-Type: text/plain; charset="utf-8"

2 accented lines
\303\242\303\252\303\256\303\264\303\273
\303\241\303\251\303\255\303\263\303\272
bye
EOF
522
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
523
524
525
    is ($status >> 8, 0, "The mail gateway exited normally");
    ok ($id, "created ticket");

Ruslan Zakirov's avatar
Ruslan Zakirov committed
526
    my $tick = RT::Test->last_ticket;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
527
528
529
    isa_ok ($tick, 'RT::Ticket');
    ok ($tick->Id, "found ticket ". $tick->Id);
    is ($tick->Id, $id, "correct ticket");
CL Sung's avatar
CL Sung committed
530
    is ($tick->Subject , 'This is a test of I18N ticket creation', "Created the ticket - ". $tick->Subject);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
531
532
533
534
535
536
537
538
539
540
541
542
543
544

    my $unistring = "\303\241\303\251\303\255\303\263\303\272";
    Encode::_utf8_on($unistring);
    is (
        $tick->Transactions->First->Content,
        $tick->Transactions->First->Attachments->First->Content,
        "Content is ". $tick->Transactions->First->Attachments->First->Content
    );
    ok (
        $tick->Transactions->First->Content =~ /$unistring/i,
        $tick->Id." appears to be unicode ". $tick->Transactions->First->Attachments->First->Id
    );
}

545
diag "supposedly I18N fails on the second message sent in.";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
546
547
{
    my $text = <<EOF;
548
From: root\@localhost
Jesse Vincent's avatar
Jesse Vincent committed
549
To: rtemail\@@{[RT->Config->Get('rtname')]}
550
551
552
553
554
555
556
557
Subject: This is a test of I18N ticket creation
Content-Type: text/plain; charset="utf-8"

2 accented lines
\303\242\303\252\303\256\303\264\303\273
\303\241\303\251\303\255\303\263\303\272
bye
EOF
558
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
559
560
    is ($status >> 8, 0, "The mail gateway exited normally");
    ok ($id, "created ticket");
561

Ruslan Zakirov's avatar
Ruslan Zakirov committed
562
    my $tick = RT::Test->last_ticket;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
563
564
565
    isa_ok ($tick, 'RT::Ticket');
    ok ($tick->Id, "found ticket ". $tick->Id);
    is ($tick->Id, $id, "correct ticket");
CL Sung's avatar
CL Sung committed
566
    is ($tick->Subject , 'This is a test of I18N ticket creation', "Created the ticket");
567

Ruslan Zakirov's avatar
Ruslan Zakirov committed
568
569
    my $unistring = "\303\241\303\251\303\255\303\263\303\272";
    Encode::_utf8_on($unistring);
570

Ruslan Zakirov's avatar
Ruslan Zakirov committed
571
572
573
574
575
    ok (
        $tick->Transactions->First->Content =~ $unistring,
        "It appears to be unicode - ". $tick->Transactions->First->Content
    );
}
576

577
diag "check that mailgate doesn't suffer from empty Reply-To:";
578
579
580
581
582
583
584
585
586
587
{
    my $text = <<EOF;
From: root\@localhost
Reply-To: 
To: rtemail\@@{[RT->Config->Get('rtname')]}
Subject: test
Content-Type: text/plain; charset="utf-8"

test
EOF
588
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
589
590
591
    is ($status >> 8, 0, "The mail gateway exited normally");
    ok ($id, "created ticket");

Ruslan Zakirov's avatar
Ruslan Zakirov committed
592
    my $tick = RT::Test->last_ticket;
593
594
595
596
597
598
599
    isa_ok ($tick, 'RT::Ticket');
    ok ($tick->Id, "found ticket ". $tick->Id);
    is ($tick->Id, $id, "correct ticket");

    like $tick->RequestorAddresses, qr/root\@localhost/, 'correct requestor';
}

600

Ruslan Zakirov's avatar
Ruslan Zakirov committed
601
my ($val,$msg) = $everyone_group->PrincipalObj->RevokeRight(Right => 'CreateTicket');
602
603
ok ($val, $msg);

604
SKIP: {
605
606
skip "Advanced mailgate actions require an unsafe configuration", 47
    unless RT->Config->Get('UnsafeEmailCommands');
Ruslan Zakirov's avatar
Ruslan Zakirov committed
607

608
# create new queue to be shure we don't mess with rights
609
610
611
612
use RT::Queue;
my $queue = RT::Queue->new($RT::SystemUser);
my ($qid) = $queue->Create( Name => 'ext-mailgate');
ok( $qid, 'queue created for ext-mailgate tests' );
613

614
# {{{ Check take and resolve actions
615

616
617
# create ticket that is owned by nobody
use RT::Ticket;
618
my $tick = RT::Ticket->new($RT::SystemUser);
619
my ($id) = $tick->Create( Queue => 'ext-mailgate', Subject => 'test');
620
621
ok( $id, 'new ticket created' );
is( $tick->Owner, $RT::Nobody->Id, 'owner of the new ticket is nobody' );
622

623
$! = 0;
624
ok(open(MAIL, "|$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action take"), "Opened the mailgate - $!");
625
626
print MAIL <<EOF;
From: root\@localhost
Jesse Vincent's avatar
Jesse Vincent committed
627
Subject: [@{[RT->Config->Get('rtname')]} \#$id] test
628
629
630
631
632
633
634
635
636
637
638
639
640

EOF
close (MAIL);
is ($? >> 8, 0, "The mail gateway exited normally");

$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');

641
my $status;
642
643
644
645
646
($status, $msg) = $tick->SetOwner( $RT::Nobody->Id, 'Force' );
ok( $status, 'successfuly changed owner: '. ($msg||'') );
is( $tick->Owner, $RT::Nobody->Id, 'set owner back to nobody');


647
$! = 0;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
648
ok(open(MAIL, "|$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action take-correspond"), "Opened the mailgate - $@");
649
650
print MAIL <<EOF;
From: root\@localhost
Jesse Vincent's avatar
Jesse Vincent committed
651
Subject: [@{[RT->Config->Get('rtname')]} \#$id] correspondence
652

653
654
655
656
657
test
EOF
close (MAIL);
is ($? >> 8, 0, "The mail gateway exited normally");

658
659
DBIx::SearchBuilder::Record::Cachable->FlushCache;

660
661
$tick = RT::Ticket->new($RT::SystemUser);
$tick->Load( $id );
662
is( $tick->Id, $id, "load correct ticket #$id");
663
664
665
is( $tick->OwnerObj->EmailAddress, 'root@localhost', 'successfuly take ticket via email');
my $txns = $tick->Transactions;
$txns->Limit( FIELD => 'Type', VALUE => 'Correspond');
666
$txns->OrderBy( FIELD => 'id', ORDER => 'DESC' );
667
668
# +1 because of auto open
is( $tick->Transactions->Count, 6, 'no superfluous transactions');
669
is( $txns->First->Subject, "[$RT::rtname \#$id] correspondence", 'successfuly add correspond within take via email' );
670

671
$! = 0;
Alex Vandiver's avatar
Alex Vandiver committed
672
ok(open(MAIL, "|$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action resolve"), "Opened the mailgate - $!");
673
674
print MAIL <<EOF;
From: root\@localhost
Jesse Vincent's avatar
Jesse Vincent committed
675
Subject: [@{[RT->Config->Get('rtname')]} \#$id] test
676
677
678
679
680
681
682
683
684
685
686
687
688

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->Status, 'resolved', 'successfuly resolved ticket via email');
is( $tick->Transactions->Count, 7, 'no superfluous transactions');

689
690
691
692
693
694
695
696
697
698
699
700
701
702
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',
			 );
ok( $uid, 'user created for ext-mailgate tests' );
ok( !$user->HasRight( Right => 'OwnTicket', Object => $queue ), "User can't own ticket" );

$tick = RT::Ticket->new($RT::SystemUser);
($id) = $tick->Create( Queue => $qid, Subject => 'test' );
ok( $id, 'create new ticket' );

703
704
my $rtname = RT->Config->Get('rtname');

705
$! = 0;
706
707
708
ok(open(MAIL, "|$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action take"), "Opened the mailgate - $!");
print MAIL <<EOF;
From: ext-mailgate\@localhost
709
Subject: [$rtname \#$id] test
710
711
712
713
714
715
716
717
718
719
720
721
722

EOF
close (MAIL);
is ( $? >> 8, 0, "mailgate exited normally" );
DBIx::SearchBuilder::Record::Cachable->FlushCache;

cmp_ok( $tick->Owner, '!=', $user->id, "we didn't change owner" );

($status, $msg) = $user->PrincipalObj->GrantRight( Object => $queue, Right => 'ReplyToTicket' );
ok( $status, "successfuly granted right: $msg" );
my $ace_id = $status;
ok( $user->HasRight( Right => 'ReplyToTicket', Object => $tick ), "User can reply to ticket" );

723
$! = 0;
724
725
726
ok(open(MAIL, "|$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action correspond-take"), "Opened the mailgate - $!");
print MAIL <<EOF;
From: ext-mailgate\@localhost
727
Subject: [$rtname \#$id] test
728
729
730
731
732
733
734
735
736
737

correspond-take
EOF
close (MAIL);
is ( $? >> 8, 0, "mailgate exited normally" );
DBIx::SearchBuilder::Record::Cachable->FlushCache;

cmp_ok( $tick->Owner, '!=', $user->id, "we didn't change owner" );
is( $tick->Transactions->Count, 3, "one transactions added" );

738
$! = 0;
739
740
741
ok(open(MAIL, "|$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action take-correspond"), "Opened the mailgate - $!");
print MAIL <<EOF;
From: ext-mailgate\@localhost
742
Subject: [$rtname \#$id] test
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778

correspond-take
EOF
close (MAIL);
is ( $? >> 8, 0, "mailgate exited normally" );
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" );

# revoke ReplyToTicket right
use RT::ACE;
my $ace = RT::ACE->new($RT::SystemUser);
$ace->Load( $ace_id );
$ace->Delete;
my $acl = RT::ACL->new($RT::SystemUser);
$acl->Limit( FIELD => 'RightName', VALUE => 'ReplyToTicket' );
$acl->LimitToObject( $RT::System );
while( my $ace = $acl->Next ) {
	$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" );
$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" );

($status, $msg) = $user->PrincipalObj->GrantRight( Object => $queue, Right => 'OwnTicket' );
ok( $status, "successfuly granted right: $msg" );
($status, $msg) = $user->PrincipalObj->GrantRight( Object => $queue, Right => 'TakeTicket' );
ok( $status, "successfuly granted right: $msg" );

779
$! = 0;
780
781
782
ok(open(MAIL, "|$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action take-correspond"), "Opened the mailgate - $!");
print MAIL <<EOF;
From: ext-mailgate\@localhost
783
Subject: [$rtname \#$id] test
784
785
786
787
788
789
790
791
792
793
794

take-correspond with reply right granted to owner role
EOF
close (MAIL);
is ( $? >> 8, 0, "mailgate exited normally" );
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" );
795
796


797
# }}}
798
799
};