gateway.t 29.4 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

Kevin Falcone's avatar
Kevin Falcone committed
60
use RT::Test config => 'Set( $UnsafeEmailCommands, 1);', tests => 228, actual_server => 1;
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
    is ($status >> 8, 1, "The mail gateway exited with a failure");
    ok (!$id, "No ticket id") or diag "by mistake ticket #$id";
Shawn M Moore's avatar
Shawn M Moore committed
85
    $m->no_warnings_ok;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
86
87
}

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

Foob!
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');
Ruslan Zakirov's avatar
Ruslan Zakirov committed
98
99
    is ($status >> 8, 75, "The mail gateway exited with a failure");
    ok (!$id, "No ticket id");
Shawn M Moore's avatar
Shawn M Moore committed
100
    $m->no_warnings_ok;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
101
102
103
}

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

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

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

Blah!
Foob!
EOF

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

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

137
diag "Test the 'X-RT-Mail-Extension' field in the header of a ticket";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
138
139
140
141
142
143
144
145
146
{
    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";
147
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
148
149
150
    is ($status >> 8, 0, "The mail gateway exited normally");
    ok ($id, "Created ticket #$id");

Ruslan Zakirov's avatar
Ruslan Zakirov committed
151
    my $tick = RT::Test->last_ticket;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
152
153
    isa_ok ($tick, 'RT::Ticket');
    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");
Ruslan Zakirov's avatar
Ruslan Zakirov committed
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

    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'
    );
Shawn M Moore's avatar
Shawn M Moore committed
171
    $m->no_warnings_ok;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
172
173
}

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

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

Ruslan Zakirov's avatar
Ruslan Zakirov committed
187
    my $tick = RT::Test->last_ticket;
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
    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'
    );
Shawn M Moore's avatar
Shawn M Moore committed
205
    $m->no_warnings_ok;
206
207
}

208
diag "Test new ticket creation without --action argument";
209
210
{
    my $text = <<EOF;
211
212
213
214
215
216
217
From: root\@localhost
To: rt\@$RT::rtname
Subject: using mailgate without --action arg

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

Ruslan Zakirov's avatar
Ruslan Zakirov committed
222
    my $tick = RT::Test->last_ticket;
223
224
225
    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");
Shawn M Moore's avatar
Shawn M Moore committed
226
    $m->no_warnings_ok;
227
228
}

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

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

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

248
    my $u = RT::User->new(RT->SystemUser);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
249
250
    $u->Load("doesnotexist\@@{[RT->Config->Get('rtname')]}");
    ok( !$u->Id, "user does not exist and was not created by failed ticket submission");
Shawn M Moore's avatar
Shawn M Moore committed
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/);
Shawn M Moore's avatar
Shawn M Moore committed
254
255
256
257
    TODO: {
        local $TODO = "we're a bit noisy for this warning case";
        $m->no_leftover_warnings_ok;
    }
Ruslan Zakirov's avatar
Ruslan Zakirov committed
258
259
}

260
diag "grant everybody with CreateTicket right";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
261
{
262
263
264
265
266
    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
267
268
269
}

my $ticket_id;
270
diag "now everybody can create tickets. can a random unkown user create tickets?";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
271
272
{
    my $text = <<EOF;
Jesse Vincent's avatar
Jesse Vincent committed
273
274
From: doesnotexist\@@{[RT->Config->Get('rtname')]}
To: rt\@@{[RT->Config->Get('rtname')]}
275
276
277
278
279
Subject: This is a test of new ticket creation as an unknown user

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

Ruslan Zakirov's avatar
Ruslan Zakirov committed
284
    my $tick = RT::Test->last_ticket;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
285
286
287
    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
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");
Ruslan Zakirov's avatar
Ruslan Zakirov committed
289

290
    my $u = RT::User->new( RT->SystemUser );
Ruslan Zakirov's avatar
Ruslan Zakirov committed
291
292
293
    $u->Load( "doesnotexist\@@{[RT->Config->Get('rtname')]}" );
    ok ($u->Id, "user does not exist and was created by ticket submission");
    $ticket_id = $id;
Shawn M Moore's avatar
Shawn M Moore committed
294
    $m->no_warnings_ok;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
295
296
}

297
diag "can another random reply to a ticket without being granted privs? answer should be no.";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
298
299
{
    my $text = <<EOF;
Jesse Vincent's avatar
Jesse Vincent committed
300
301
From: doesnotexist-2\@@{[RT->Config->Get('rtname')]}
To: rt\@@{[RT->Config->Get('rtname')]}
Ruslan Zakirov's avatar
Ruslan Zakirov committed
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
306
Foob!
EOF
307
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
308
309
310
    is ($status >> 8, 0, "The mail gateway exited normally");
    ok (!$id, "no way to reply to the ticket");

311
    my $u = RT::User->new(RT->SystemUser);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
312
313
    $u->Load('doesnotexist-2@'.RT->Config->Get('rtname'));
    ok( !$u->Id, " user does not exist and was not created by ticket correspondence submission");
Shawn M Moore's avatar
Shawn M Moore committed
314
315
316
317
318
    $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\)/);
    TODO: {
        local $TODO = "we're a bit noisy for this warning case";
        $m->no_leftover_warnings_ok;
    }
Ruslan Zakirov's avatar
Ruslan Zakirov committed
319
320
}

321
diag "grant everyone 'ReplyToTicket' right";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
322
{
323
324
325
326
327
    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
328
329
}

330
diag "can another random reply to a ticket after being granted privs? answer should be yes";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
331
332
{
    my $text = <<EOF;
Jesse Vincent's avatar
Jesse Vincent committed
333
334
From: doesnotexist-2\@@{[RT->Config->Get('rtname')]}
To: rt\@@{[RT->Config->Get('rtname')]}
Ruslan Zakirov's avatar
Ruslan Zakirov committed
335
Subject: [@{[RT->Config->Get('rtname')]} #$ticket_id] This is a test of a reply as an unknown user
336
337
338
339

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

344
    my $u = RT::User->new(RT->SystemUser);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
345
346
    $u->Load('doesnotexist-2@'.RT->Config->Get('rtname'));
    ok ($u->Id, "user exists and was created by ticket correspondence submission");
Shawn M Moore's avatar
Shawn M Moore committed
347
    $m->no_warnings_ok;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
348
}
349

350
diag "add a reply to the ticket using '--extension ticket' feature";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
351
352
353
354
355
356
357
358
359
360
{
    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;
361
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text, extension => 'ticket');
Ruslan Zakirov's avatar
Ruslan Zakirov committed
362
363
364
    is ($status >> 8, 0, "The mail gateway exited normally");
    is ($id, $ticket_id, "replied to the ticket");

Ruslan Zakirov's avatar
Ruslan Zakirov committed
365
    my $tick = RT::Test->last_ticket;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
366
367
368
369
370
371
372
373
374
375
376
377
378
379
    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');
Shawn M Moore's avatar
Shawn M Moore committed
380
    $m->no_warnings_ok;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
381
}
382

383
diag "can another random comment on a ticket without being granted privs? answer should be no";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
384
385
{
    my $text = <<EOF;
Jesse Vincent's avatar
Jesse Vincent committed
386
387
From: doesnotexist-3\@@{[RT->Config->Get('rtname')]}
To: rt\@@{[RT->Config->Get('rtname')]}
Ruslan Zakirov's avatar
Ruslan Zakirov committed
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
392
Foob!
EOF
393
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text, action => 'comment');
Ruslan Zakirov's avatar
Ruslan Zakirov committed
394
395
    is ($status >> 8, 0, "The mail gateway exited normally");
    ok (!$id, "no way to comment on the ticket");
396

397
    my $u = RT::User->new(RT->SystemUser);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
398
399
    $u->Load('doesnotexist-3@'.RT->Config->Get('rtname'));
    ok( !$u->Id, " user does not exist and was not created by ticket comment submission");
Shawn M Moore's avatar
Shawn M Moore committed
400
401
402
403
404
    $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\)/);
    TODO: {
        local $TODO = "we're a bit noisy for this warning case";
        $m->no_leftover_warnings_ok;
    }
Ruslan Zakirov's avatar
Ruslan Zakirov committed
405
}
406
407


408
diag "grant everyone 'CommentOnTicket' right";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
409
{
410
411
412
413
414
    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
415
}
416

417
diag "can another random reply to a ticket after being granted privs? answer should be yes";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
418
419
{
    my $text = <<EOF;
Jesse Vincent's avatar
Jesse Vincent committed
420
421
From: doesnotexist-3\@@{[RT->Config->Get('rtname')]}
To: rt\@@{[RT->Config->Get('rtname')]}
Ruslan Zakirov's avatar
Ruslan Zakirov committed
422
Subject: [@{[RT->Config->Get('rtname')]} #$ticket_id] This is a test of a comment as an unknown user
423
424
425
426

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

431
    my $u = RT::User->new(RT->SystemUser);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
432
433
    $u->Load('doesnotexist-3@'.RT->Config->Get('rtname'));
    ok ($u->Id, " user exists and was created by ticket comment submission");
Shawn M Moore's avatar
Shawn M Moore committed
434
    $m->no_warnings_ok;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
435
436
}

437
diag "add comment to the ticket using '--extension action' feature";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
438
439
440
441
442
443
444
445
446
447
{
    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';
448
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text, extension => 'action');
Ruslan Zakirov's avatar
Ruslan Zakirov committed
449
450
451
    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
452
    my $tick = RT::Test->last_ticket;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
453
454
455
456
457
458
    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
459
460
461
462
463
464
    $transactions->Limit(
        FIELD => 'Type',
        OPERATOR => 'NOT ENDSWITH',
        VALUE => 'EmailRecord',
        ENTRYAGGREGATOR => 'AND',
    );
Ruslan Zakirov's avatar
Ruslan Zakirov committed
465
466
467
468
469
470
471
    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');
Shawn M Moore's avatar
Shawn M Moore committed
472
    $m->no_warnings_ok;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
473
474
}

475
diag "Testing preservation of binary attachments";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
476
477
{
    # Get a binary blob (Best Practical logo) 
478
    my $LOGO_FILE = $RT::MasonComponentRoot .'/NoAuth/images/bpslogo.png';
Ruslan Zakirov's avatar
Ruslan Zakirov committed
479
480
481
482
483
484
485
486
487
488
489

    # 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,
490
        Type     => 'image/png',
Ruslan Zakirov's avatar
Ruslan Zakirov committed
491
492
493
        Encoding => 'base64',
    );
    # Create a ticket with a binary attachment
494
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($entity);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
495
496
497
    is ($status >> 8, 0, "The mail gateway exited normally");
    ok ($id, "created ticket");

Ruslan Zakirov's avatar
Ruslan Zakirov committed
498
    my $tick = RT::Test->last_ticket;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
499
500
501
    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
502
    is ($tick->Subject , 'binary attachment test', "Created the ticket - ".$tick->Id);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
503
504
505

    my $file = `cat $LOGO_FILE`;
    ok ($file, "Read in the logo image");
506
    diag "for the raw file the md5 hex is ". Digest::MD5::md5_hex($file);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
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');
Ruslan Zakirov's avatar
Ruslan Zakirov committed
511
512
513
514
515
516
517
518
    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 );
519
    is ($attachments->Count, 1, 'Found only one png attached to the ticket');
Ruslan Zakirov's avatar
Ruslan Zakirov committed
520
521
522
523
    my $attachment = $attachments->First;
    ok ($attachment->Id, 'loaded attachment object');
    my $acontent = $attachment->Content;

524
    diag "coming from the database, md5 hex is ".Digest::MD5::md5_hex($acontent);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
525
526
527
528
529
    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
530
        ."/". $attachment->id. "/bpslogo.png?&user=root&pass=password";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
531
532
533
534
    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');
Shawn M Moore's avatar
Shawn M Moore committed
535
536

    $m->no_warnings_ok;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
537
538
}

539
diag "Simple I18N testing";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
540
541
{
    my $text = <<EOF;
542
From: root\@localhost
Jesse Vincent's avatar
Jesse Vincent committed
543
To: rtemail\@@{[RT->Config->Get('rtname')]}
544
545
546
547
548
549
550
551
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
552
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
553
554
555
    is ($status >> 8, 0, "The mail gateway exited normally");
    ok ($id, "created ticket");

Ruslan Zakirov's avatar
Ruslan Zakirov committed
556
    my $tick = RT::Test->last_ticket;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
557
558
559
    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
560
    is ($tick->Subject , 'This is a test of I18N ticket creation', "Created the ticket - ". $tick->Subject);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
561
562
563
564
565
566
567
568
569
570
571
572

    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
    );
Shawn M Moore's avatar
Shawn M Moore committed
573
574

    $m->no_warnings_ok;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
575
576
}

577
diag "supposedly I18N fails on the second message sent in.";
Ruslan Zakirov's avatar
Ruslan Zakirov committed
578
579
{
    my $text = <<EOF;
580
From: root\@localhost
Jesse Vincent's avatar
Jesse Vincent committed
581
To: rtemail\@@{[RT->Config->Get('rtname')]}
582
583
584
585
586
587
588
589
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
590
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
591
592
    is ($status >> 8, 0, "The mail gateway exited normally");
    ok ($id, "created ticket");
593

Ruslan Zakirov's avatar
Ruslan Zakirov committed
594
    my $tick = RT::Test->last_ticket;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
595
596
597
    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
598
    is ($tick->Subject , 'This is a test of I18N ticket creation', "Created the ticket");
599

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

Ruslan Zakirov's avatar
Ruslan Zakirov committed
603
604
605
606
    ok (
        $tick->Transactions->First->Content =~ $unistring,
        "It appears to be unicode - ". $tick->Transactions->First->Content
    );
Shawn M Moore's avatar
Shawn M Moore committed
607
608

    $m->no_warnings_ok;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
609
}
610

611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
diag "make sure we check that UTF-8 is really UTF-8";
{
    my $text = <<EOF;
From: root\@localhost
To: rtemail\@@{[RT->Config->Get('rtname')]}
Subject: This is test wrong utf-8 chars
Content-Type: text/plain; charset="utf-8"

utf-8: informaci\303\263n confidencial
latin1: informaci\363n confidencial

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

    my $tick = RT::Test->last_ticket;
    is ($tick->Id, $id, "correct ticket");

    my $content = $tick->Transactions->First->Content;
    Encode::_utf8_off($content);

    like $content, qr{informaci\303\263n confidencial};
    like $content, qr{informaci\357\277\275n confidencial};

    $m->no_warnings_ok;
}

640
diag "check that mailgate doesn't suffer from empty Reply-To:";
641
642
643
644
645
646
647
648
649
650
{
    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
651
    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
652
653
654
    is ($status >> 8, 0, "The mail gateway exited normally");
    ok ($id, "created ticket");

Ruslan Zakirov's avatar
Ruslan Zakirov committed
655
    my $tick = RT::Test->last_ticket;
656
657
658
659
660
    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';
Shawn M Moore's avatar
Shawn M Moore committed
661
662

    $m->no_warnings_ok;
663
664
}

665

Ruslan Zakirov's avatar
Ruslan Zakirov committed
666
my ($val,$msg) = $everyone_group->PrincipalObj->RevokeRight(Right => 'CreateTicket');
667
668
ok ($val, $msg);

669
SKIP: {
670
671
skip "Advanced mailgate actions require an unsafe configuration", 47
    unless RT->Config->Get('UnsafeEmailCommands');
Ruslan Zakirov's avatar
Ruslan Zakirov committed
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
677
my ($qid) = $queue->Create( Name => 'ext-mailgate');
ok( $qid, 'queue created for ext-mailgate tests' );
678

679

680
681
# create ticket that is owned by nobody
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
690
print MAIL <<EOF;
From: root\@localhost
Jesse Vincent's avatar
Jesse Vincent committed
691
Subject: [@{[RT->Config->Get('rtname')]} \#$id] test
692
693
694
695
696

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

697
$tick = RT::Ticket->new(RT->SystemUser);
698
699
700
701
702
703
704
$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');

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

Shawn M Moore's avatar
Shawn M Moore committed
710
711
$m->no_warnings_ok;

712

713
$! = 0;
714
ok(open(MAIL, '|-', "$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action take-correspond"), "Opened the mailgate - $@");
715
716
print MAIL <<EOF;
From: root\@localhost
Jesse Vincent's avatar
Jesse Vincent committed
717
Subject: [@{[RT->Config->Get('rtname')]} \#$id] correspondence
718

719
720
721
722
723
test
EOF
close (MAIL);
is ($? >> 8, 0, "The mail gateway exited normally");

724
725
DBIx::SearchBuilder::Record::Cachable->FlushCache;

726
$tick = RT::Ticket->new(RT->SystemUser);
727
$tick->Load( $id );
728
is( $tick->Id, $id, "load correct ticket #$id");
729
730
731
is( $tick->OwnerObj->EmailAddress, 'root@localhost', 'successfuly take ticket via email');
my $txns = $tick->Transactions;
$txns->Limit( FIELD => 'Type', VALUE => 'Correspond');
732
$txns->OrderBy( FIELD => 'id', ORDER => 'DESC' );
733
734
# +1 because of auto open
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

Shawn M Moore's avatar
Shawn M Moore committed
737
738
739
$m->no_warnings_ok;


740
$! = 0;
741
ok(open(MAIL, '|-', "$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action resolve"), "Opened the mailgate - $!");
742
743
print MAIL <<EOF;
From: root\@localhost
Jesse Vincent's avatar
Jesse Vincent committed
744
Subject: [@{[RT->Config->Get('rtname')]} \#$id] test
745
746
747
748
749
750
751

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

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

752
$tick = RT::Ticket->new(RT->SystemUser);
753
754
755
756
757
$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');

758
use RT::User;
759
my $user = RT::User->new( RT->SystemUser );
760
761
762
763
764
765
766
767
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" );

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

772
773
my $rtname = RT->Config->Get('rtname');

Shawn M Moore's avatar
Shawn M Moore committed
774
775
$m->no_warnings_ok;

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

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" );

Shawn M Moore's avatar
Shawn M Moore committed
794
795
796
797
$m->next_warning_like(qr/Permission Denied/);
$m->next_warning_like(qr/Could not record email: Ticket not taken/);
$m->no_leftover_warnings_ok;

798
$! = 0;
799
ok(open(MAIL, '|-', "$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action correspond-take"), "Opened the mailgate - $!");
800
801
print MAIL <<EOF;
From: ext-mailgate\@localhost
802
Subject: [$rtname \#$id] test
803
804
805
806
807
808
809
810
811
812

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" );

Shawn M Moore's avatar
Shawn M Moore committed
813
814
815
816
$m->next_warning_like(qr/Permission Denied/);
$m->next_warning_like(qr/Could not record email: Ticket not taken/);
$m->no_leftover_warnings_ok;

817
$! = 0;
818
ok(open(MAIL, '|-', "$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action take-correspond"), "Opened the mailgate - $!");
819
820
print MAIL <<EOF;
From: ext-mailgate\@localhost
821
Subject: [$rtname \#$id] test
822
823
824
825
826
827
828
829
830
831

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" );

Shawn M Moore's avatar
Shawn M Moore committed
832
833
834
835
$m->next_warning_like(qr/Permission Denied/);
$m->next_warning_like(qr/Could not record email: Ticket not taken/);
$m->no_leftover_warnings_ok;

836
837
# revoke ReplyToTicket right
use RT::ACE;
838
my $ace = RT::ACE->new(RT->SystemUser);
839
840
$ace->Load( $ace_id );
$ace->Delete;
841
my $acl = RT::ACL->new(RT->SystemUser);
842
843
844
845
846
847
848
849
850
$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" );


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
855
856
857
858
859
860
861
($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" );

862
$! = 0;
863
ok(open(MAIL, '|-', "$RT::BinPath/rt-mailgate --url $url --queue ext-mailgate --action take-correspond"), "Opened the mailgate - $!");
864
865
print MAIL <<EOF;
From: ext-mailgate\@localhost
866
Subject: [$rtname \#$id] test
867
868
869
870
871
872
873
874
875
876
877

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" );
878

Shawn M Moore's avatar
Shawn M Moore committed
879
$m->no_warnings_ok;
880

881
882
};