##// END OF EJS Templates
add test of quoted printable UTF-8 mail reviving (#14675)...
Toshi MARUYAMA -
r12626:14c02f50cc44
parent child
Show More
@@ -0,0 +1,19
1 Date: Tue, 13 Aug 2013 10:56:04 +0700
2 From: John Smith <JSmith@somenet.foo>
3 Content-Type: multipart/alternative; boundary=001a11c260fa53f8dc04e3cc380b
4 Subject: issue 14675
5 To: redmine@somenet.foo
6
7 --001a11c260fa53f8dc04e3cc380b
8 Content-Type: text/plain; charset=UTF-8
9 Content-Transfer-Encoding: quoted-printable
10
11 Freundliche Gr=C3=BCsse
12
13 --001a11c260fa53f8dc04e3cc380b
14 Content-Type: text/html; charset=UTF-8
15 Content-Transfer-Encoding: quoted-printable
16
17 <div dir=3D"ltr">Freundliche Gr=C3=BCsse<br></div>
18
19 --001a11c260fa53f8dc04e3cc380b--
@@ -1,887 +1,898
1 1 # encoding: utf-8
2 2 #
3 3 # Redmine - project management software
4 4 # Copyright (C) 2006-2014 Jean-Philippe Lang
5 5 #
6 6 # This program is free software; you can redistribute it and/or
7 7 # modify it under the terms of the GNU General Public License
8 8 # as published by the Free Software Foundation; either version 2
9 9 # of the License, or (at your option) any later version.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software
18 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 19
20 20 require File.expand_path('../../test_helper', __FILE__)
21 21
22 22 class MailHandlerTest < ActiveSupport::TestCase
23 23 fixtures :users, :projects, :enabled_modules, :roles,
24 24 :members, :member_roles, :users,
25 25 :issues, :issue_statuses,
26 26 :workflows, :trackers, :projects_trackers,
27 27 :versions, :enumerations, :issue_categories,
28 28 :custom_fields, :custom_fields_trackers, :custom_fields_projects,
29 29 :boards, :messages
30 30
31 31 FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures/mail_handler'
32 32
33 33 def setup
34 34 ActionMailer::Base.deliveries.clear
35 35 Setting.notified_events = Redmine::Notifiable.all.collect(&:name)
36 36 end
37 37
38 38 def teardown
39 39 Setting.clear_cache
40 40 end
41 41
42 42 def test_add_issue
43 43 ActionMailer::Base.deliveries.clear
44 44 lft1 = new_issue_lft
45 45 # This email contains: 'Project: onlinestore'
46 46 issue = submit_email('ticket_on_given_project.eml')
47 47 assert issue.is_a?(Issue)
48 48 assert !issue.new_record?
49 49 issue.reload
50 50 assert_equal Project.find(2), issue.project
51 51 assert_equal issue.project.trackers.first, issue.tracker
52 52 assert_equal 'New ticket on a given project', issue.subject
53 53 assert_equal User.find_by_login('jsmith'), issue.author
54 54 assert_equal IssueStatus.find_by_name('Resolved'), issue.status
55 55 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
56 56 assert_equal '2010-01-01', issue.start_date.to_s
57 57 assert_equal '2010-12-31', issue.due_date.to_s
58 58 assert_equal User.find_by_login('jsmith'), issue.assigned_to
59 59 assert_equal Version.find_by_name('Alpha'), issue.fixed_version
60 60 assert_equal 2.5, issue.estimated_hours
61 61 assert_equal 30, issue.done_ratio
62 62 assert_equal [issue.id, lft1, lft1 + 1], [issue.root_id, issue.lft, issue.rgt]
63 63 # keywords should be removed from the email body
64 64 assert !issue.description.match(/^Project:/i)
65 65 assert !issue.description.match(/^Status:/i)
66 66 assert !issue.description.match(/^Start Date:/i)
67 67 # Email notification should be sent
68 68 mail = ActionMailer::Base.deliveries.last
69 69 assert_not_nil mail
70 70 assert mail.subject.include?('New ticket on a given project')
71 71 end
72 72
73 73 def test_add_issue_with_default_tracker
74 74 # This email contains: 'Project: onlinestore'
75 75 issue = submit_email(
76 76 'ticket_on_given_project.eml',
77 77 :issue => {:tracker => 'Support request'}
78 78 )
79 79 assert issue.is_a?(Issue)
80 80 assert !issue.new_record?
81 81 issue.reload
82 82 assert_equal 'Support request', issue.tracker.name
83 83 end
84 84
85 85 def test_add_issue_with_status
86 86 # This email contains: 'Project: onlinestore' and 'Status: Resolved'
87 87 issue = submit_email('ticket_on_given_project.eml')
88 88 assert issue.is_a?(Issue)
89 89 assert !issue.new_record?
90 90 issue.reload
91 91 assert_equal Project.find(2), issue.project
92 92 assert_equal IssueStatus.find_by_name("Resolved"), issue.status
93 93 end
94 94
95 95 def test_add_issue_with_attributes_override
96 96 issue = submit_email(
97 97 'ticket_with_attributes.eml',
98 98 :allow_override => 'tracker,category,priority'
99 99 )
100 100 assert issue.is_a?(Issue)
101 101 assert !issue.new_record?
102 102 issue.reload
103 103 assert_equal 'New ticket on a given project', issue.subject
104 104 assert_equal User.find_by_login('jsmith'), issue.author
105 105 assert_equal Project.find(2), issue.project
106 106 assert_equal 'Feature request', issue.tracker.to_s
107 107 assert_equal 'Stock management', issue.category.to_s
108 108 assert_equal 'Urgent', issue.priority.to_s
109 109 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
110 110 end
111 111
112 112 def test_add_issue_with_group_assignment
113 113 with_settings :issue_group_assignment => '1' do
114 114 issue = submit_email('ticket_on_given_project.eml') do |email|
115 115 email.gsub!('Assigned to: John Smith', 'Assigned to: B Team')
116 116 end
117 117 assert issue.is_a?(Issue)
118 118 assert !issue.new_record?
119 119 issue.reload
120 120 assert_equal Group.find(11), issue.assigned_to
121 121 end
122 122 end
123 123
124 124 def test_add_issue_with_partial_attributes_override
125 125 issue = submit_email(
126 126 'ticket_with_attributes.eml',
127 127 :issue => {:priority => 'High'},
128 128 :allow_override => ['tracker']
129 129 )
130 130 assert issue.is_a?(Issue)
131 131 assert !issue.new_record?
132 132 issue.reload
133 133 assert_equal 'New ticket on a given project', issue.subject
134 134 assert_equal User.find_by_login('jsmith'), issue.author
135 135 assert_equal Project.find(2), issue.project
136 136 assert_equal 'Feature request', issue.tracker.to_s
137 137 assert_nil issue.category
138 138 assert_equal 'High', issue.priority.to_s
139 139 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
140 140 end
141 141
142 142 def test_add_issue_with_spaces_between_attribute_and_separator
143 143 issue = submit_email(
144 144 'ticket_with_spaces_between_attribute_and_separator.eml',
145 145 :allow_override => 'tracker,category,priority'
146 146 )
147 147 assert issue.is_a?(Issue)
148 148 assert !issue.new_record?
149 149 issue.reload
150 150 assert_equal 'New ticket on a given project', issue.subject
151 151 assert_equal User.find_by_login('jsmith'), issue.author
152 152 assert_equal Project.find(2), issue.project
153 153 assert_equal 'Feature request', issue.tracker.to_s
154 154 assert_equal 'Stock management', issue.category.to_s
155 155 assert_equal 'Urgent', issue.priority.to_s
156 156 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
157 157 end
158 158
159 159 def test_add_issue_with_attachment_to_specific_project
160 160 issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'})
161 161 assert issue.is_a?(Issue)
162 162 assert !issue.new_record?
163 163 issue.reload
164 164 assert_equal 'Ticket created by email with attachment', issue.subject
165 165 assert_equal User.find_by_login('jsmith'), issue.author
166 166 assert_equal Project.find(2), issue.project
167 167 assert_equal 'This is a new ticket with attachments', issue.description
168 168 # Attachment properties
169 169 assert_equal 1, issue.attachments.size
170 170 assert_equal 'Paella.jpg', issue.attachments.first.filename
171 171 assert_equal 'image/jpeg', issue.attachments.first.content_type
172 172 assert_equal 10790, issue.attachments.first.filesize
173 173 end
174 174
175 175 def test_add_issue_with_custom_fields
176 176 issue = submit_email('ticket_with_custom_fields.eml', :issue => {:project => 'onlinestore'})
177 177 assert issue.is_a?(Issue)
178 178 assert !issue.new_record?
179 179 issue.reload
180 180 assert_equal 'New ticket with custom field values', issue.subject
181 181 assert_equal 'PostgreSQL', issue.custom_field_value(1)
182 182 assert_equal 'Value for a custom field', issue.custom_field_value(2)
183 183 assert !issue.description.match(/^searchable field:/i)
184 184 end
185 185
186 186 def test_add_issue_with_version_custom_fields
187 187 field = IssueCustomField.create!(:name => 'Affected version', :field_format => 'version', :is_for_all => true, :tracker_ids => [1,2,3])
188 188
189 189 issue = submit_email('ticket_with_custom_fields.eml', :issue => {:project => 'ecookbook'}) do |email|
190 190 email << "Affected version: 1.0\n"
191 191 end
192 192 assert issue.is_a?(Issue)
193 193 assert !issue.new_record?
194 194 issue.reload
195 195 assert_equal '2', issue.custom_field_value(field)
196 196 end
197 197
198 198 def test_add_issue_should_match_assignee_on_display_name
199 199 user = User.generate!(:firstname => 'Foo Bar', :lastname => 'Foo Baz')
200 200 User.add_to_project(user, Project.find(2))
201 201 issue = submit_email('ticket_on_given_project.eml') do |email|
202 202 email.sub!(/^Assigned to.*$/, 'Assigned to: Foo Bar Foo baz')
203 203 end
204 204 assert issue.is_a?(Issue)
205 205 assert_equal user, issue.assigned_to
206 206 end
207 207
208 208 def test_add_issue_with_cc
209 209 issue = submit_email('ticket_with_cc.eml', :issue => {:project => 'ecookbook'})
210 210 assert issue.is_a?(Issue)
211 211 assert !issue.new_record?
212 212 issue.reload
213 213 assert issue.watched_by?(User.find_by_mail('dlopper@somenet.foo'))
214 214 assert_equal 1, issue.watcher_user_ids.size
215 215 end
216 216
217 217 def test_add_issue_by_unknown_user
218 218 assert_no_difference 'User.count' do
219 219 assert_equal false,
220 220 submit_email(
221 221 'ticket_by_unknown_user.eml',
222 222 :issue => {:project => 'ecookbook'}
223 223 )
224 224 end
225 225 end
226 226
227 227 def test_add_issue_by_anonymous_user
228 228 Role.anonymous.add_permission!(:add_issues)
229 229 assert_no_difference 'User.count' do
230 230 issue = submit_email(
231 231 'ticket_by_unknown_user.eml',
232 232 :issue => {:project => 'ecookbook'},
233 233 :unknown_user => 'accept'
234 234 )
235 235 assert issue.is_a?(Issue)
236 236 assert issue.author.anonymous?
237 237 end
238 238 end
239 239
240 240 def test_add_issue_by_anonymous_user_with_no_from_address
241 241 Role.anonymous.add_permission!(:add_issues)
242 242 assert_no_difference 'User.count' do
243 243 issue = submit_email(
244 244 'ticket_by_empty_user.eml',
245 245 :issue => {:project => 'ecookbook'},
246 246 :unknown_user => 'accept'
247 247 )
248 248 assert issue.is_a?(Issue)
249 249 assert issue.author.anonymous?
250 250 end
251 251 end
252 252
253 253 def test_add_issue_by_anonymous_user_on_private_project
254 254 Role.anonymous.add_permission!(:add_issues)
255 255 assert_no_difference 'User.count' do
256 256 assert_no_difference 'Issue.count' do
257 257 assert_equal false,
258 258 submit_email(
259 259 'ticket_by_unknown_user.eml',
260 260 :issue => {:project => 'onlinestore'},
261 261 :unknown_user => 'accept'
262 262 )
263 263 end
264 264 end
265 265 end
266 266
267 267 def test_add_issue_by_anonymous_user_on_private_project_without_permission_check
268 268 lft1 = new_issue_lft
269 269 assert_no_difference 'User.count' do
270 270 assert_difference 'Issue.count' do
271 271 issue = submit_email(
272 272 'ticket_by_unknown_user.eml',
273 273 :issue => {:project => 'onlinestore'},
274 274 :no_permission_check => '1',
275 275 :unknown_user => 'accept'
276 276 )
277 277 assert issue.is_a?(Issue)
278 278 assert issue.author.anonymous?
279 279 assert !issue.project.is_public?
280 280 assert_equal [issue.id, lft1, lft1 + 1], [issue.root_id, issue.lft, issue.rgt]
281 281 end
282 282 end
283 283 end
284 284
285 285 def test_add_issue_by_created_user
286 286 Setting.default_language = 'en'
287 287 assert_difference 'User.count' do
288 288 issue = submit_email(
289 289 'ticket_by_unknown_user.eml',
290 290 :issue => {:project => 'ecookbook'},
291 291 :unknown_user => 'create'
292 292 )
293 293 assert issue.is_a?(Issue)
294 294 assert issue.author.active?
295 295 assert_equal 'john.doe@somenet.foo', issue.author.mail
296 296 assert_equal 'John', issue.author.firstname
297 297 assert_equal 'Doe', issue.author.lastname
298 298
299 299 # account information
300 300 email = ActionMailer::Base.deliveries.first
301 301 assert_not_nil email
302 302 assert email.subject.include?('account activation')
303 303 login = mail_body(email).match(/\* Login: (.*)$/)[1].strip
304 304 password = mail_body(email).match(/\* Password: (.*)$/)[1].strip
305 305 assert_equal issue.author, User.try_to_login(login, password)
306 306 end
307 307 end
308 308
309 309 def test_created_user_should_be_added_to_groups
310 310 group1 = Group.generate!
311 311 group2 = Group.generate!
312 312
313 313 assert_difference 'User.count' do
314 314 submit_email(
315 315 'ticket_by_unknown_user.eml',
316 316 :issue => {:project => 'ecookbook'},
317 317 :unknown_user => 'create',
318 318 :default_group => "#{group1.name},#{group2.name}"
319 319 )
320 320 end
321 321 user = User.order('id DESC').first
322 322 assert_same_elements [group1, group2], user.groups
323 323 end
324 324
325 325 def test_created_user_should_not_receive_account_information_with_no_account_info_option
326 326 assert_difference 'User.count' do
327 327 submit_email(
328 328 'ticket_by_unknown_user.eml',
329 329 :issue => {:project => 'ecookbook'},
330 330 :unknown_user => 'create',
331 331 :no_account_notice => '1'
332 332 )
333 333 end
334 334
335 335 # only 1 email for the new issue notification
336 336 assert_equal 1, ActionMailer::Base.deliveries.size
337 337 email = ActionMailer::Base.deliveries.first
338 338 assert_include 'Ticket by unknown user', email.subject
339 339 end
340 340
341 341 def test_created_user_should_have_mail_notification_to_none_with_no_notification_option
342 342 assert_difference 'User.count' do
343 343 submit_email(
344 344 'ticket_by_unknown_user.eml',
345 345 :issue => {:project => 'ecookbook'},
346 346 :unknown_user => 'create',
347 347 :no_notification => '1'
348 348 )
349 349 end
350 350 user = User.order('id DESC').first
351 351 assert_equal 'none', user.mail_notification
352 352 end
353 353
354 354 def test_add_issue_without_from_header
355 355 Role.anonymous.add_permission!(:add_issues)
356 356 assert_equal false, submit_email('ticket_without_from_header.eml')
357 357 end
358 358
359 359 def test_add_issue_with_invalid_attributes
360 360 issue = submit_email(
361 361 'ticket_with_invalid_attributes.eml',
362 362 :allow_override => 'tracker,category,priority'
363 363 )
364 364 assert issue.is_a?(Issue)
365 365 assert !issue.new_record?
366 366 issue.reload
367 367 assert_nil issue.assigned_to
368 368 assert_nil issue.start_date
369 369 assert_nil issue.due_date
370 370 assert_equal 0, issue.done_ratio
371 371 assert_equal 'Normal', issue.priority.to_s
372 372 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
373 373 end
374 374
375 375 def test_add_issue_with_invalid_project_should_be_assigned_to_default_project
376 376 issue = submit_email('ticket_on_given_project.eml', :issue => {:project => 'ecookbook'}, :allow_override => 'project') do |email|
377 377 email.gsub!(/^Project:.+$/, 'Project: invalid')
378 378 end
379 379 assert issue.is_a?(Issue)
380 380 assert !issue.new_record?
381 381 assert_equal 'ecookbook', issue.project.identifier
382 382 end
383 383
384 384 def test_add_issue_with_localized_attributes
385 385 User.find_by_mail('jsmith@somenet.foo').update_attribute 'language', 'fr'
386 386 issue = submit_email(
387 387 'ticket_with_localized_attributes.eml',
388 388 :allow_override => 'tracker,category,priority'
389 389 )
390 390 assert issue.is_a?(Issue)
391 391 assert !issue.new_record?
392 392 issue.reload
393 393 assert_equal 'New ticket on a given project', issue.subject
394 394 assert_equal User.find_by_login('jsmith'), issue.author
395 395 assert_equal Project.find(2), issue.project
396 396 assert_equal 'Feature request', issue.tracker.to_s
397 397 assert_equal 'Stock management', issue.category.to_s
398 398 assert_equal 'Urgent', issue.priority.to_s
399 399 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
400 400 end
401 401
402 402 def test_add_issue_with_japanese_keywords
403 403 ja_dev = "\xe9\x96\x8b\xe7\x99\xba"
404 404 ja_dev.force_encoding('UTF-8') if ja_dev.respond_to?(:force_encoding)
405 405 tracker = Tracker.create!(:name => ja_dev)
406 406 Project.find(1).trackers << tracker
407 407 issue = submit_email(
408 408 'japanese_keywords_iso_2022_jp.eml',
409 409 :issue => {:project => 'ecookbook'},
410 410 :allow_override => 'tracker'
411 411 )
412 412 assert_kind_of Issue, issue
413 413 assert_equal tracker, issue.tracker
414 414 end
415 415
416 416 def test_add_issue_from_apple_mail
417 417 issue = submit_email(
418 418 'apple_mail_with_attachment.eml',
419 419 :issue => {:project => 'ecookbook'}
420 420 )
421 421 assert_kind_of Issue, issue
422 422 assert_equal 1, issue.attachments.size
423 423
424 424 attachment = issue.attachments.first
425 425 assert_equal 'paella.jpg', attachment.filename
426 426 assert_equal 10790, attachment.filesize
427 427 assert File.exist?(attachment.diskfile)
428 428 assert_equal 10790, File.size(attachment.diskfile)
429 429 assert_equal 'caaf384198bcbc9563ab5c058acd73cd', attachment.digest
430 430 end
431 431
432 432 def test_thunderbird_with_attachment_ja
433 433 issue = submit_email(
434 434 'thunderbird_with_attachment_ja.eml',
435 435 :issue => {:project => 'ecookbook'}
436 436 )
437 437 assert_kind_of Issue, issue
438 438 assert_equal 1, issue.attachments.size
439 439 ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt"
440 440 ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
441 441 attachment = issue.attachments.first
442 442 assert_equal ja, attachment.filename
443 443 assert_equal 5, attachment.filesize
444 444 assert File.exist?(attachment.diskfile)
445 445 assert_equal 5, File.size(attachment.diskfile)
446 446 assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest
447 447 end
448 448
449 449 def test_gmail_with_attachment_ja
450 450 issue = submit_email(
451 451 'gmail_with_attachment_ja.eml',
452 452 :issue => {:project => 'ecookbook'}
453 453 )
454 454 assert_kind_of Issue, issue
455 455 assert_equal 1, issue.attachments.size
456 456 ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt"
457 457 ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
458 458 attachment = issue.attachments.first
459 459 assert_equal ja, attachment.filename
460 460 assert_equal 5, attachment.filesize
461 461 assert File.exist?(attachment.diskfile)
462 462 assert_equal 5, File.size(attachment.diskfile)
463 463 assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest
464 464 end
465 465
466 466 def test_thunderbird_with_attachment_latin1
467 467 issue = submit_email(
468 468 'thunderbird_with_attachment_iso-8859-1.eml',
469 469 :issue => {:project => 'ecookbook'}
470 470 )
471 471 assert_kind_of Issue, issue
472 472 assert_equal 1, issue.attachments.size
473 473 u = ""
474 474 u.force_encoding('UTF-8') if u.respond_to?(:force_encoding)
475 475 u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc"
476 476 u1.force_encoding('UTF-8') if u1.respond_to?(:force_encoding)
477 477 11.times { u << u1 }
478 478 attachment = issue.attachments.first
479 479 assert_equal "#{u}.png", attachment.filename
480 480 assert_equal 130, attachment.filesize
481 481 assert File.exist?(attachment.diskfile)
482 482 assert_equal 130, File.size(attachment.diskfile)
483 483 assert_equal '4d80e667ac37dddfe05502530f152abb', attachment.digest
484 484 end
485 485
486 486 def test_gmail_with_attachment_latin1
487 487 issue = submit_email(
488 488 'gmail_with_attachment_iso-8859-1.eml',
489 489 :issue => {:project => 'ecookbook'}
490 490 )
491 491 assert_kind_of Issue, issue
492 492 assert_equal 1, issue.attachments.size
493 493 u = ""
494 494 u.force_encoding('UTF-8') if u.respond_to?(:force_encoding)
495 495 u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc"
496 496 u1.force_encoding('UTF-8') if u1.respond_to?(:force_encoding)
497 497 11.times { u << u1 }
498 498 attachment = issue.attachments.first
499 499 assert_equal "#{u}.txt", attachment.filename
500 500 assert_equal 5, attachment.filesize
501 501 assert File.exist?(attachment.diskfile)
502 502 assert_equal 5, File.size(attachment.diskfile)
503 503 assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest
504 504 end
505 505
506 506 def test_multiple_inline_text_parts_should_be_appended_to_issue_description
507 507 issue = submit_email('multiple_text_parts.eml', :issue => {:project => 'ecookbook'})
508 508 assert_include 'first', issue.description
509 509 assert_include 'second', issue.description
510 510 assert_include 'third', issue.description
511 511 end
512 512
513 513 def test_attachment_text_part_should_be_added_as_issue_attachment
514 514 issue = submit_email('multiple_text_parts.eml', :issue => {:project => 'ecookbook'})
515 515 assert_not_include 'Plain text attachment', issue.description
516 516 attachment = issue.attachments.detect {|a| a.filename == 'textfile.txt'}
517 517 assert_not_nil attachment
518 518 assert_include 'Plain text attachment', File.read(attachment.diskfile)
519 519 end
520 520
521 521 def test_add_issue_with_iso_8859_1_subject
522 522 issue = submit_email(
523 523 'subject_as_iso-8859-1.eml',
524 524 :issue => {:project => 'ecookbook'}
525 525 )
526 526 str = "Testmail from Webmail: \xc3\xa4 \xc3\xb6 \xc3\xbc..."
527 527 str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
528 528 assert_kind_of Issue, issue
529 529 assert_equal str, issue.subject
530 530 end
531 531
532 def test_quoted_printable_utf8
533 issue = submit_email(
534 'quoted_printable_utf8.eml',
535 :issue => {:project => 'ecookbook'}
536 )
537 assert_kind_of Issue, issue
538 str = "Freundliche Gr\xc3\xbcsse"
539 str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
540 assert_equal str, issue.description
541 end
542
532 543 def test_add_issue_with_japanese_subject
533 544 issue = submit_email(
534 545 'subject_japanese_1.eml',
535 546 :issue => {:project => 'ecookbook'}
536 547 )
537 548 assert_kind_of Issue, issue
538 549 ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88"
539 550 ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
540 551 assert_equal ja, issue.subject
541 552 end
542 553
543 554 def test_add_issue_with_korean_body
544 555 # Make sure mail bodies with a charset unknown to Ruby
545 556 # but known to the Mail gem 2.5.4 are handled correctly
546 557 kr = "\xEA\xB3\xA0\xEB\xA7\x99\xEC\x8A\xB5\xEB\x8B\x88\xEB\x8B\xA4."
547 558 if !kr.respond_to?(:force_encoding)
548 559 puts "\nOn Ruby 1.8, skip Korean encoding mail body test"
549 560 else
550 561 kr.force_encoding('UTF-8')
551 562 issue = submit_email(
552 563 'body_ks_c_5601-1987.eml',
553 564 :issue => {:project => 'ecookbook'}
554 565 )
555 566 assert_kind_of Issue, issue
556 567 assert_equal kr, issue.description
557 568 end
558 569 end
559 570
560 571 def test_add_issue_with_no_subject_header
561 572 issue = submit_email(
562 573 'no_subject_header.eml',
563 574 :issue => {:project => 'ecookbook'}
564 575 )
565 576 assert_kind_of Issue, issue
566 577 assert_equal '(no subject)', issue.subject
567 578 end
568 579
569 580 def test_add_issue_with_mixed_japanese_subject
570 581 issue = submit_email(
571 582 'subject_japanese_2.eml',
572 583 :issue => {:project => 'ecookbook'}
573 584 )
574 585 assert_kind_of Issue, issue
575 586 ja = "Re: \xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88"
576 587 ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
577 588 assert_equal ja, issue.subject
578 589 end
579 590
580 591 def test_should_ignore_emails_from_locked_users
581 592 User.find(2).lock!
582 593
583 594 MailHandler.any_instance.expects(:dispatch).never
584 595 assert_no_difference 'Issue.count' do
585 596 assert_equal false, submit_email('ticket_on_given_project.eml')
586 597 end
587 598 end
588 599
589 600 def test_should_ignore_emails_from_emission_address
590 601 Role.anonymous.add_permission!(:add_issues)
591 602 assert_no_difference 'User.count' do
592 603 assert_equal false,
593 604 submit_email(
594 605 'ticket_from_emission_address.eml',
595 606 :issue => {:project => 'ecookbook'},
596 607 :unknown_user => 'create'
597 608 )
598 609 end
599 610 end
600 611
601 612 def test_should_ignore_auto_replied_emails
602 613 MailHandler.any_instance.expects(:dispatch).never
603 614 [
604 615 "X-Auto-Response-Suppress: OOF",
605 616 "Auto-Submitted: auto-replied",
606 617 "Auto-Submitted: Auto-Replied",
607 618 "Auto-Submitted: auto-generated"
608 619 ].each do |header|
609 620 raw = IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
610 621 raw = header + "\n" + raw
611 622
612 623 assert_no_difference 'Issue.count' do
613 624 assert_equal false, MailHandler.receive(raw), "email with #{header} header was not ignored"
614 625 end
615 626 end
616 627 end
617 628
618 629 def test_add_issue_should_send_email_notification
619 630 Setting.notified_events = ['issue_added']
620 631 ActionMailer::Base.deliveries.clear
621 632 # This email contains: 'Project: onlinestore'
622 633 issue = submit_email('ticket_on_given_project.eml')
623 634 assert issue.is_a?(Issue)
624 635 assert_equal 1, ActionMailer::Base.deliveries.size
625 636 end
626 637
627 638 def test_update_issue
628 639 journal = submit_email('ticket_reply.eml')
629 640 assert journal.is_a?(Journal)
630 641 assert_equal User.find_by_login('jsmith'), journal.user
631 642 assert_equal Issue.find(2), journal.journalized
632 643 assert_match /This is reply/, journal.notes
633 644 assert_equal false, journal.private_notes
634 645 assert_equal 'Feature request', journal.issue.tracker.name
635 646 end
636 647
637 648 def test_update_issue_with_attribute_changes
638 649 # This email contains: 'Status: Resolved'
639 650 journal = submit_email('ticket_reply_with_status.eml')
640 651 assert journal.is_a?(Journal)
641 652 issue = Issue.find(journal.issue.id)
642 653 assert_equal User.find_by_login('jsmith'), journal.user
643 654 assert_equal Issue.find(2), journal.journalized
644 655 assert_match /This is reply/, journal.notes
645 656 assert_equal 'Feature request', journal.issue.tracker.name
646 657 assert_equal IssueStatus.find_by_name("Resolved"), issue.status
647 658 assert_equal '2010-01-01', issue.start_date.to_s
648 659 assert_equal '2010-12-31', issue.due_date.to_s
649 660 assert_equal User.find_by_login('jsmith'), issue.assigned_to
650 661 assert_equal "52.6", issue.custom_value_for(CustomField.find_by_name('Float field')).value
651 662 # keywords should be removed from the email body
652 663 assert !journal.notes.match(/^Status:/i)
653 664 assert !journal.notes.match(/^Start Date:/i)
654 665 end
655 666
656 667 def test_update_issue_with_attachment
657 668 assert_difference 'Journal.count' do
658 669 assert_difference 'JournalDetail.count' do
659 670 assert_difference 'Attachment.count' do
660 671 assert_no_difference 'Issue.count' do
661 672 journal = submit_email('ticket_with_attachment.eml') do |raw|
662 673 raw.gsub! /^Subject: .*$/, 'Subject: Re: [Cookbook - Feature #2] (New) Add ingredients categories'
663 674 end
664 675 end
665 676 end
666 677 end
667 678 end
668 679 journal = Journal.order('id DESC').first
669 680 assert_equal Issue.find(2), journal.journalized
670 681 assert_equal 1, journal.details.size
671 682
672 683 detail = journal.details.first
673 684 assert_equal 'attachment', detail.property
674 685 assert_equal 'Paella.jpg', detail.value
675 686 end
676 687
677 688 def test_update_issue_should_send_email_notification
678 689 ActionMailer::Base.deliveries.clear
679 690 journal = submit_email('ticket_reply.eml')
680 691 assert journal.is_a?(Journal)
681 692 assert_equal 1, ActionMailer::Base.deliveries.size
682 693 end
683 694
684 695 def test_update_issue_should_not_set_defaults
685 696 journal = submit_email(
686 697 'ticket_reply.eml',
687 698 :issue => {:tracker => 'Support request', :priority => 'High'}
688 699 )
689 700 assert journal.is_a?(Journal)
690 701 assert_match /This is reply/, journal.notes
691 702 assert_equal 'Feature request', journal.issue.tracker.name
692 703 assert_equal 'Normal', journal.issue.priority.name
693 704 end
694 705
695 706 def test_replying_to_a_private_note_should_add_reply_as_private
696 707 private_journal = Journal.create!(:notes => 'Private notes', :journalized => Issue.find(1), :private_notes => true, :user_id => 2)
697 708
698 709 assert_difference 'Journal.count' do
699 710 journal = submit_email('ticket_reply.eml') do |email|
700 711 email.sub! %r{^In-Reply-To:.*$}, "In-Reply-To: <redmine.journal-#{private_journal.id}.20060719210421@osiris>"
701 712 end
702 713
703 714 assert_kind_of Journal, journal
704 715 assert_match /This is reply/, journal.notes
705 716 assert_equal true, journal.private_notes
706 717 end
707 718 end
708 719
709 720 def test_reply_to_a_message
710 721 m = submit_email('message_reply.eml')
711 722 assert m.is_a?(Message)
712 723 assert !m.new_record?
713 724 m.reload
714 725 assert_equal 'Reply via email', m.subject
715 726 # The email replies to message #2 which is part of the thread of message #1
716 727 assert_equal Message.find(1), m.parent
717 728 end
718 729
719 730 def test_reply_to_a_message_by_subject
720 731 m = submit_email('message_reply_by_subject.eml')
721 732 assert m.is_a?(Message)
722 733 assert !m.new_record?
723 734 m.reload
724 735 assert_equal 'Reply to the first post', m.subject
725 736 assert_equal Message.find(1), m.parent
726 737 end
727 738
728 739 def test_should_strip_tags_of_html_only_emails
729 740 issue = submit_email('ticket_html_only.eml', :issue => {:project => 'ecookbook'})
730 741 assert issue.is_a?(Issue)
731 742 assert !issue.new_record?
732 743 issue.reload
733 744 assert_equal 'HTML email', issue.subject
734 745 assert_equal 'This is a html-only email.', issue.description
735 746 end
736 747
737 748 test "truncate emails with no setting should add the entire email into the issue" do
738 749 with_settings :mail_handler_body_delimiters => '' do
739 750 issue = submit_email('ticket_on_given_project.eml')
740 751 assert_issue_created(issue)
741 752 assert issue.description.include?('---')
742 753 assert issue.description.include?('This paragraph is after the delimiter')
743 754 end
744 755 end
745 756
746 757 test "truncate emails with a single string should truncate the email at the delimiter for the issue" do
747 758 with_settings :mail_handler_body_delimiters => '---' do
748 759 issue = submit_email('ticket_on_given_project.eml')
749 760 assert_issue_created(issue)
750 761 assert issue.description.include?('This paragraph is before delimiters')
751 762 assert issue.description.include?('--- This line starts with a delimiter')
752 763 assert !issue.description.match(/^---$/)
753 764 assert !issue.description.include?('This paragraph is after the delimiter')
754 765 end
755 766 end
756 767
757 768 test "truncate emails with a single quoted reply should truncate the email at the delimiter with the quoted reply symbols (>)" do
758 769 with_settings :mail_handler_body_delimiters => '--- Reply above. Do not remove this line. ---' do
759 770 journal = submit_email('issue_update_with_quoted_reply_above.eml')
760 771 assert journal.is_a?(Journal)
761 772 assert journal.notes.include?('An update to the issue by the sender.')
762 773 assert !journal.notes.match(Regexp.escape("--- Reply above. Do not remove this line. ---"))
763 774 assert !journal.notes.include?('Looks like the JSON api for projects was missed.')
764 775 end
765 776 end
766 777
767 778 test "truncate emails with multiple quoted replies should truncate the email at the delimiter with the quoted reply symbols (>)" do
768 779 with_settings :mail_handler_body_delimiters => '--- Reply above. Do not remove this line. ---' do
769 780 journal = submit_email('issue_update_with_multiple_quoted_reply_above.eml')
770 781 assert journal.is_a?(Journal)
771 782 assert journal.notes.include?('An update to the issue by the sender.')
772 783 assert !journal.notes.match(Regexp.escape("--- Reply above. Do not remove this line. ---"))
773 784 assert !journal.notes.include?('Looks like the JSON api for projects was missed.')
774 785 end
775 786 end
776 787
777 788 test "truncate emails with multiple strings should truncate the email at the first delimiter found (BREAK)" do
778 789 with_settings :mail_handler_body_delimiters => "---\nBREAK" do
779 790 issue = submit_email('ticket_on_given_project.eml')
780 791 assert_issue_created(issue)
781 792 assert issue.description.include?('This paragraph is before delimiters')
782 793 assert !issue.description.include?('BREAK')
783 794 assert !issue.description.include?('This paragraph is between delimiters')
784 795 assert !issue.description.match(/^---$/)
785 796 assert !issue.description.include?('This paragraph is after the delimiter')
786 797 end
787 798 end
788 799
789 800 def test_attachments_that_match_mail_handler_excluded_filenames_should_be_ignored
790 801 with_settings :mail_handler_excluded_filenames => '*.vcf, *.jpg' do
791 802 issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'})
792 803 assert issue.is_a?(Issue)
793 804 assert !issue.new_record?
794 805 assert_equal 0, issue.reload.attachments.size
795 806 end
796 807 end
797 808
798 809 def test_attachments_that_do_not_match_mail_handler_excluded_filenames_should_be_attached
799 810 with_settings :mail_handler_excluded_filenames => '*.vcf, *.gif' do
800 811 issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'})
801 812 assert issue.is_a?(Issue)
802 813 assert !issue.new_record?
803 814 assert_equal 1, issue.reload.attachments.size
804 815 end
805 816 end
806 817
807 818 def test_email_with_long_subject_line
808 819 issue = submit_email('ticket_with_long_subject.eml')
809 820 assert issue.is_a?(Issue)
810 821 assert_equal issue.subject, 'New ticket on a given project with a very long subject line which exceeds 255 chars and should not be ignored but chopped off. And if the subject line is still not long enough, we just add more text. And more text. Wow, this is really annoying. Especially, if you have nothing to say...'[0,255]
811 822 end
812 823
813 824 def test_new_user_from_attributes_should_return_valid_user
814 825 to_test = {
815 826 # [address, name] => [login, firstname, lastname]
816 827 ['jsmith@example.net', nil] => ['jsmith@example.net', 'jsmith', '-'],
817 828 ['jsmith@example.net', 'John'] => ['jsmith@example.net', 'John', '-'],
818 829 ['jsmith@example.net', 'John Smith'] => ['jsmith@example.net', 'John', 'Smith'],
819 830 ['jsmith@example.net', 'John Paul Smith'] => ['jsmith@example.net', 'John', 'Paul Smith'],
820 831 ['jsmith@example.net', 'AVeryLongFirstnameThatExceedsTheMaximumLength Smith'] => ['jsmith@example.net', 'AVeryLongFirstnameThatExceedsT', 'Smith'],
821 832 ['jsmith@example.net', 'John AVeryLongLastnameThatExceedsTheMaximumLength'] => ['jsmith@example.net', 'John', 'AVeryLongLastnameThatExceedsTh']
822 833 }
823 834
824 835 to_test.each do |attrs, expected|
825 836 user = MailHandler.new_user_from_attributes(attrs.first, attrs.last)
826 837
827 838 assert user.valid?, user.errors.full_messages.to_s
828 839 assert_equal attrs.first, user.mail
829 840 assert_equal expected[0], user.login
830 841 assert_equal expected[1], user.firstname
831 842 assert_equal expected[2], user.lastname
832 843 assert_equal 'only_my_events', user.mail_notification
833 844 end
834 845 end
835 846
836 847 def test_new_user_from_attributes_should_use_default_login_if_invalid
837 848 user = MailHandler.new_user_from_attributes('foo+bar@example.net')
838 849 assert user.valid?
839 850 assert user.login =~ /^user[a-f0-9]+$/
840 851 assert_equal 'foo+bar@example.net', user.mail
841 852 end
842 853
843 854 def test_new_user_with_utf8_encoded_fullname_should_be_decoded
844 855 assert_difference 'User.count' do
845 856 issue = submit_email(
846 857 'fullname_of_sender_as_utf8_encoded.eml',
847 858 :issue => {:project => 'ecookbook'},
848 859 :unknown_user => 'create'
849 860 )
850 861 end
851 862 user = User.order('id DESC').first
852 863 assert_equal "foo@example.org", user.mail
853 864 str1 = "\xc3\x84\xc3\xa4"
854 865 str2 = "\xc3\x96\xc3\xb6"
855 866 str1.force_encoding('UTF-8') if str1.respond_to?(:force_encoding)
856 867 str2.force_encoding('UTF-8') if str2.respond_to?(:force_encoding)
857 868 assert_equal str1, user.firstname
858 869 assert_equal str2, user.lastname
859 870 end
860 871
861 872 def test_extract_options_from_env_should_return_options
862 873 options = MailHandler.extract_options_from_env({
863 874 'tracker' => 'defect',
864 875 'project' => 'foo',
865 876 'unknown_user' => 'create'
866 877 })
867 878
868 879 assert_equal({
869 880 :issue => {:tracker => 'defect', :project => 'foo'},
870 881 :unknown_user => 'create'
871 882 }, options)
872 883 end
873 884
874 885 private
875 886
876 887 def submit_email(filename, options={})
877 888 raw = IO.read(File.join(FIXTURES_PATH, filename))
878 889 yield raw if block_given?
879 890 MailHandler.receive(raw, options)
880 891 end
881 892
882 893 def assert_issue_created(issue)
883 894 assert issue.is_a?(Issue)
884 895 assert !issue.new_record?
885 896 issue.reload
886 897 end
887 898 end
General Comments 0
You need to be logged in to leave comments. Login now