mail_handler_test.rb 46.8 KB
Newer Older
1
# frozen_string_literal: true
2

3
# Redmine - project management software
jplang's avatar
jplang committed
4
# Copyright (C) 2006-2017  Jean-Philippe Lang
5 6 7 8 9
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
10
#
11 12 13 14
# This program 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.
15
#
16 17 18 19
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

20
require File.expand_path('../../test_helper', __FILE__)
21

22
class MailHandlerTest < ActiveSupport::TestCase
23 24
  fixtures :users, :projects, :enabled_modules, :roles,
           :members, :member_roles, :users,
25
           :email_addresses, :user_preferences,
26 27 28
           :issues, :issue_statuses,
           :workflows, :trackers, :projects_trackers,
           :versions, :enumerations, :issue_categories,
jplang's avatar
jplang committed
29
           :custom_fields, :custom_fields_trackers, :custom_fields_projects, :custom_values,
jplang's avatar
jplang committed
30
           :boards, :messages, :watchers
31

32
  FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures/mail_handler'
33

34
  def setup
35
    ActionMailer::Base.deliveries.clear
36
    Setting.notified_events = Redmine::Notifiable.all.collect(&:name)
37
    User.current = nil
38
  end
39

40 41 42 43
  def teardown
    Setting.clear_cache
  end

44
  def test_add_issue_with_specific_overrides
45
    issue = submit_email('ticket_on_given_project.eml',
46
      :allow_override => ['status', 'start_date', 'due_date', 'assigned_to',
47
                          'fixed_version', 'estimated_hours', 'done_ratio', 'parent_issue']
48
    )
49 50 51
    assert issue.is_a?(Issue)
    assert !issue.new_record?
    issue.reload
52 53
    assert_equal Project.find(2), issue.project
    assert_equal issue.project.trackers.first, issue.tracker
54 55
    assert_equal 'New ticket on a given project', issue.subject
    assert_equal User.find_by_login('jsmith'), issue.author
56
    assert_equal IssueStatus.find_by_name('Resolved'), issue.status
57
    assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
58 59
    assert_equal '2010-01-01', issue.start_date.to_s
    assert_equal '2010-12-31', issue.due_date.to_s
60
    assert_equal User.find_by_login('jsmith'), issue.assigned_to
61
    assert_equal Version.find_by_name('Alpha'), issue.fixed_version
62 63
    assert_equal 2.5, issue.estimated_hours
    assert_equal 30, issue.done_ratio
64
    assert_equal Issue.find(4), issue.parent
65 66 67
    # keywords should be removed from the email body
    assert !issue.description.match(/^Project:/i)
    assert !issue.description.match(/^Status:/i)
68
    assert !issue.description.match(/^Start Date:/i)
69
  end
70

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
  def test_add_issue_with_all_overrides
    issue = submit_email('ticket_on_given_project.eml', :allow_override => 'all')
    assert issue.is_a?(Issue)
    assert !issue.new_record?
    issue.reload
    assert_equal Project.find(2), issue.project
    assert_equal issue.project.trackers.first, issue.tracker
    assert_equal IssueStatus.find_by_name('Resolved'), issue.status
    assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
    assert_equal '2010-01-01', issue.start_date.to_s
    assert_equal '2010-12-31', issue.due_date.to_s
    assert_equal User.find_by_login('jsmith'), issue.assigned_to
    assert_equal Version.find_by_name('Alpha'), issue.fixed_version
    assert_equal 2.5, issue.estimated_hours
    assert_equal 30, issue.done_ratio
86
    assert_equal Issue.find(4), issue.parent
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
  end

  def test_add_issue_without_overrides_should_ignore_attributes
    WorkflowRule.delete_all
    issue = submit_email('ticket_on_given_project.eml')
    assert issue.is_a?(Issue)
    assert !issue.new_record?
    issue.reload
    assert_equal Project.find(2), issue.project
    assert_equal 'New ticket on a given project', issue.subject
    assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
    assert_equal User.find_by_login('jsmith'), issue.author

    assert_equal issue.project.trackers.first, issue.tracker
    assert_equal 'New', issue.status.name
    assert_not_equal '2010-01-01', issue.start_date.to_s
    assert_nil issue.due_date
    assert_nil issue.assigned_to
    assert_nil issue.fixed_version
    assert_nil issue.estimated_hours
    assert_equal 0, issue.done_ratio
108
    assert_nil issue.parent
109 110
  end

111 112 113 114
  def test_add_issue_to_project_specified_by_subaddress
    # This email has redmine+onlinestore@somenet.foo as 'To' header
    issue = submit_email(
              'ticket_on_project_given_by_to_header.eml',
115 116
              :issue => {:tracker => 'Support request'},
              :project_from_subaddress => 'redmine@somenet.foo'
117 118 119 120 121 122 123 124
            )
    assert issue.is_a?(Issue)
    assert !issue.new_record?
    issue.reload
    assert_equal 'onlinestore', issue.project.identifier
    assert_equal 'Support request', issue.tracker.name
  end

125 126
  def test_add_issue_with_default_tracker
    # This email contains: 'Project: onlinestore'
127 128 129 130
    issue = submit_email(
              'ticket_on_given_project.eml',
              :issue => {:tracker => 'Support request'}
            )
131 132 133 134 135
    assert issue.is_a?(Issue)
    assert !issue.new_record?
    issue.reload
    assert_equal 'Support request', issue.tracker.name
  end
136

137 138 139 140 141 142 143 144 145 146 147
  def test_add_issue_with_default_version
    # This email contains: 'Project: onlinestore'
    issue = submit_email(
              'ticket_on_given_project.eml',
              :issue => {:fixed_version => 'Alpha'}
            )
    assert issue.is_a?(Issue)
    assert !issue.new_record?
    assert_equal 'Alpha', issue.reload.fixed_version.name
  end

148 149 150 151 152 153 154 155 156 157 158
  def test_add_issue_with_default_assigned_to
    # This email contains: 'Project: onlinestore'
    issue = submit_email(
              'ticket_on_given_project.eml',
              :issue => {:assigned_to => 'jsmith'}
            )
    assert issue.is_a?(Issue)
    assert !issue.new_record?
    assert_equal 'jsmith', issue.reload.assigned_to.login
  end

159
  def test_add_issue_with_status_override
160
    # This email contains: 'Project: onlinestore' and 'Status: Resolved'
161
    issue = submit_email('ticket_on_given_project.eml', :allow_override => ['status'])
162 163 164 165 166 167
    assert issue.is_a?(Issue)
    assert !issue.new_record?
    issue.reload
    assert_equal Project.find(2), issue.project
    assert_equal IssueStatus.find_by_name("Resolved"), issue.status
  end
168

169 170 171 172 173 174 175
  def test_add_issue_should_accept_is_private_attribute
    issue = submit_email('ticket_on_given_project.eml', :issue => {:is_private => '1'})
    assert issue.is_a?(Issue)
    assert !issue.new_record?
    assert_equal true, issue.reload.is_private
  end

176 177
  def test_add_issue_with_group_assignment
    with_settings :issue_group_assignment => '1' do
178
      issue = submit_email('ticket_on_given_project.eml', :allow_override => ['assigned_to']) do |email|
179 180 181 182 183 184 185 186
        email.gsub!('Assigned to: John Smith', 'Assigned to: B Team')
      end
      assert issue.is_a?(Issue)
      assert !issue.new_record?
      issue.reload
      assert_equal Group.find(11), issue.assigned_to
    end
  end
187

188
  def test_add_issue_with_partial_attributes_override
189 190 191 192 193
    issue = submit_email(
              'ticket_with_attributes.eml',
              :issue => {:priority => 'High'},
              :allow_override => ['tracker']
            )
194 195 196 197 198 199 200 201 202 203 204
    assert issue.is_a?(Issue)
    assert !issue.new_record?
    issue.reload
    assert_equal 'New ticket on a given project', issue.subject
    assert_equal User.find_by_login('jsmith'), issue.author
    assert_equal Project.find(2), issue.project
    assert_equal 'Feature request', issue.tracker.to_s
    assert_nil issue.category
    assert_equal 'High', issue.priority.to_s
    assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
  end
205

206
  def test_add_issue_with_spaces_between_attribute_and_separator
207 208 209 210
    issue = submit_email(
              'ticket_with_spaces_between_attribute_and_separator.eml',
              :allow_override => 'tracker,category,priority'
            )
211 212 213 214 215 216 217 218 219 220 221 222
    assert issue.is_a?(Issue)
    assert !issue.new_record?
    issue.reload
    assert_equal 'New ticket on a given project', issue.subject
    assert_equal User.find_by_login('jsmith'), issue.author
    assert_equal Project.find(2), issue.project
    assert_equal 'Feature request', issue.tracker.to_s
    assert_equal 'Stock management', issue.category.to_s
    assert_equal 'Urgent', issue.priority.to_s
    assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
  end

223
  def test_add_issue_with_attachment_to_specific_project
224
    issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'})
225 226 227 228 229 230 231 232 233 234 235 236 237
    assert issue.is_a?(Issue)
    assert !issue.new_record?
    issue.reload
    assert_equal 'Ticket created by email with attachment', issue.subject
    assert_equal User.find_by_login('jsmith'), issue.author
    assert_equal Project.find(2), issue.project
    assert_equal 'This is  a new ticket with attachments', issue.description
    # Attachment properties
    assert_equal 1, issue.attachments.size
    assert_equal 'Paella.jpg', issue.attachments.first.filename
    assert_equal 'image/jpeg', issue.attachments.first.content_type
    assert_equal 10790, issue.attachments.first.filesize
  end
238

239
  def test_add_issue_with_custom_fields
240 241 242
    mutiple = IssueCustomField.generate!(:field_format => 'list',
                                         :name => 'OS', :multiple => true,
                                         :possible_values => ['Linux', 'Windows', 'Mac OS X'])
243

244
    issue = submit_email('ticket_with_custom_fields.eml',
245
      :issue => {:project => 'onlinestore'}, :allow_override => ['database', 'Searchable_field', 'OS']
246
    )
247 248 249 250
    assert issue.is_a?(Issue)
    assert !issue.new_record?
    issue.reload
    assert_equal 'New ticket with custom field values', issue.subject
251 252
    assert_equal 'PostgreSQL', issue.custom_field_value(1)
    assert_equal 'Value for a custom field', issue.custom_field_value(2)
253
    assert_equal ['Mac OS X', 'Windows'], issue.custom_field_value(mutiple.id).sort
254
    assert !issue.description.match(/^searchable field:/i)
255
  end
256

257
  def test_add_issue_with_version_custom_fields
258 259 260 261
    field = IssueCustomField.create!(:name => 'Affected version',
                                     :field_format => 'version',
                                     :is_for_all => true,
                                     :tracker_ids => [1,2,3])
262

263 264 265
    issue = submit_email('ticket_with_custom_fields.eml',
      :issue => {:project => 'ecookbook'}, :allow_override => ['affected version']
    ) do |email|
266 267 268 269 270 271 272 273
      email << "Affected version: 1.0\n"
    end
    assert issue.is_a?(Issue)
    assert !issue.new_record?
    issue.reload
    assert_equal '2', issue.custom_field_value(field)
  end

274 275 276
  def test_add_issue_should_match_assignee_on_display_name
    user = User.generate!(:firstname => 'Foo Bar', :lastname => 'Foo Baz')
    User.add_to_project(user, Project.find(2))
277
    issue = submit_email('ticket_on_given_project.eml', :allow_override => ['assigned_to']) do |email|
278 279 280 281 282 283
      email.sub!(/^Assigned to.*$/, 'Assigned to: Foo Bar Foo baz')
    end
    assert issue.is_a?(Issue)
    assert_equal user, issue.assigned_to
  end

284 285 286 287 288 289 290 291
  def test_add_issue_should_set_default_start_date
    with_settings :default_issue_start_date_to_creation_date => '1' do
      issue = submit_email('ticket_with_cc.eml', :issue => {:project => 'ecookbook'})
      assert issue.is_a?(Issue)
      assert_equal Date.today, issue.start_date
    end
  end

292
  def test_add_issue_should_add_cc_as_watchers
293
    user = User.find_by_mail('dlopper@somenet.foo')
294 295 296
    issue = submit_email('ticket_with_cc.eml', :issue => {:project => 'ecookbook'})
    assert issue.is_a?(Issue)
    assert !issue.new_record?
297
    assert issue.watched_by?(user)
298
    assert_equal 1, issue.watcher_user_ids.size
299
    assert_include user, issue.watcher_users.to_a
300
  end
301

302 303 304 305 306 307 308 309 310 311 312
  def test_add_issue_from_additional_email_address
    user = User.find(2)
    user.mail = 'mainaddress@somenet.foo'
    user.save!
    EmailAddress.create!(:user => user, :address => 'jsmith@somenet.foo')

    issue = submit_email('ticket_on_given_project.eml')
    assert issue
    assert_equal user, issue.author
  end

313 314
  def test_add_issue_by_unknown_user
    assert_no_difference 'User.count' do
315 316 317 318 319
      assert_equal false,
                   submit_email(
                     'ticket_by_unknown_user.eml',
                     :issue => {:project => 'ecookbook'}
                   )
320 321
    end
  end
322

323 324
  def test_add_issue_by_anonymous_user
    Role.anonymous.add_permission!(:add_issues)
325
    Role.anonymous.add_permission!(:add_issue_watchers)
326
    assert_no_difference 'User.count' do
327 328 329 330 331
      issue = submit_email(
                'ticket_by_unknown_user.eml',
                :issue => {:project => 'ecookbook'},
                :unknown_user => 'accept'
              )
332 333
      assert issue.is_a?(Issue)
      assert issue.author.anonymous?
334 335 336
      issue.reload
      assert issue.watched_by?(User.find_by_mail('dlopper@somenet.foo'))
      assert_equal 1, issue.watchers.size
337 338
    end
  end
339 340 341 342

  def test_add_issue_by_anonymous_user_with_no_from_address
    Role.anonymous.add_permission!(:add_issues)
    assert_no_difference 'User.count' do
343 344 345 346 347
      issue = submit_email(
                'ticket_by_empty_user.eml',
                :issue => {:project => 'ecookbook'},
                :unknown_user => 'accept'
              )
348 349 350 351
      assert issue.is_a?(Issue)
      assert issue.author.anonymous?
    end
  end
352

353 354 355 356
  def test_add_issue_by_anonymous_user_on_private_project
    Role.anonymous.add_permission!(:add_issues)
    assert_no_difference 'User.count' do
      assert_no_difference 'Issue.count' do
357 358 359 360 361 362
        assert_equal false,
                     submit_email(
                       'ticket_by_unknown_user.eml',
                       :issue => {:project => 'onlinestore'},
                       :unknown_user => 'accept'
                     )
363 364 365
      end
    end
  end
366

367 368 369
  def test_add_issue_by_anonymous_user_on_private_project_without_permission_check
    assert_no_difference 'User.count' do
      assert_difference 'Issue.count' do
370 371 372 373 374 375
        issue = submit_email(
                  'ticket_by_unknown_user.eml',
                  :issue => {:project => 'onlinestore'},
                  :no_permission_check => '1',
                  :unknown_user => 'accept'
                )
376 377 378 379 380 381
        assert issue.is_a?(Issue)
        assert issue.author.anonymous?
        assert !issue.project.is_public?
      end
    end
  end
382

383 384 385
  def test_add_issue_by_created_user
    Setting.default_language = 'en'
    assert_difference 'User.count' do
386 387 388 389 390
      issue = submit_email(
                'ticket_by_unknown_user.eml',
                :issue => {:project => 'ecookbook'},
                :unknown_user => 'create'
              )
391 392 393 394 395
      assert issue.is_a?(Issue)
      assert issue.author.active?
      assert_equal 'john.doe@somenet.foo', issue.author.mail
      assert_equal 'John', issue.author.firstname
      assert_equal 'Doe', issue.author.lastname
396

397 398 399 400
      # account information
      email = ActionMailer::Base.deliveries.first
      assert_not_nil email
      assert email.subject.include?('account activation')
401 402
      login = mail_body(email).match(/\* Login: (.*)$/)[1].strip
      password = mail_body(email).match(/\* Password: (.*)$/)[1].strip
403 404 405
      assert_equal issue.author, User.try_to_login(login, password)
    end
  end
406

407 408 409 410 411 412 413 414 415 416 417
  def test_add_issue_should_send_notification
    issue = submit_email('ticket_on_given_project.eml', :allow_override => 'all')
    assert issue.is_a?(Issue)
    assert !issue.new_record?

    mail = ActionMailer::Base.deliveries.last
    assert_not_nil mail
    assert mail.subject.include?("##{issue.id}")
    assert mail.subject.include?('New ticket on a given project')
  end

418 419 420 421 422 423 424 425 426 427 428 429 430
  def test_created_user_should_be_added_to_groups
    group1 = Group.generate!
    group2 = Group.generate!

    assert_difference 'User.count' do
      submit_email(
        'ticket_by_unknown_user.eml',
        :issue => {:project => 'ecookbook'},
        :unknown_user => 'create',
        :default_group => "#{group1.name},#{group2.name}"
      )
    end
    user = User.order('id DESC').first
jplang's avatar
jplang committed
431
    assert_equal [group1, group2].sort, user.groups.sort
432 433
  end

434 435 436 437 438 439 440 441 442 443
  def test_created_user_should_not_receive_account_information_with_no_account_info_option
    assert_difference 'User.count' do
      submit_email(
        'ticket_by_unknown_user.eml',
        :issue => {:project => 'ecookbook'},
        :unknown_user => 'create',
        :no_account_notice => '1'
      )
    end

444 445 446 447 448
    # only 2 emails for the new issue notification
    assert_equal 2, ActionMailer::Base.deliveries.size
    ActionMailer::Base.deliveries.each do |email|
      assert_include 'Ticket by unknown user', email.subject
    end
449 450
  end

451 452 453 454 455 456 457 458 459 460 461 462 463
  def test_created_user_should_have_mail_notification_to_none_with_no_notification_option
    assert_difference 'User.count' do
      submit_email(
        'ticket_by_unknown_user.eml',
        :issue => {:project => 'ecookbook'},
        :unknown_user => 'create',
        :no_notification => '1'
      )
    end
    user = User.order('id DESC').first
    assert_equal 'none', user.mail_notification
  end

464 465 466 467
  def test_add_issue_without_from_header
    Role.anonymous.add_permission!(:add_issues)
    assert_equal false, submit_email('ticket_without_from_header.eml')
  end
468

469
  def test_add_issue_with_invalid_attributes
470 471 472 473 474 475 476 477 478 479 480 481
    with_settings :default_issue_start_date_to_creation_date => '0' do
      issue = submit_email(
                'ticket_with_invalid_attributes.eml',
                :allow_override => 'tracker,category,priority'
              )
      assert issue.is_a?(Issue)
      assert !issue.new_record?
      issue.reload
      assert_nil issue.assigned_to
      assert_nil issue.start_date
      assert_nil issue.due_date
      assert_equal 0, issue.done_ratio
482
      assert_nil issue.parent
483 484 485
      assert_equal 'Normal', issue.priority.to_s
      assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
    end
486 487
  end

488
  def test_add_issue_with_invalid_project_should_be_assigned_to_default_project
489 490 491
    issue = submit_email('ticket_on_given_project.eml',
                         :issue => {:project => 'ecookbook'},
                         :allow_override => 'project') do |email|
492 493 494 495 496 497 498
      email.gsub!(/^Project:.+$/, 'Project: invalid')
    end
    assert issue.is_a?(Issue)
    assert !issue.new_record?
    assert_equal 'ecookbook', issue.project.identifier
  end

499 500
  def test_add_issue_with_localized_attributes
    User.find_by_mail('jsmith@somenet.foo').update_attribute 'language', 'fr'
501 502 503 504
    issue = submit_email(
              'ticket_with_localized_attributes.eml',
              :allow_override => 'tracker,category,priority'
            )
505 506 507 508 509 510 511 512 513 514 515
    assert issue.is_a?(Issue)
    assert !issue.new_record?
    issue.reload
    assert_equal 'New ticket on a given project', issue.subject
    assert_equal User.find_by_login('jsmith'), issue.author
    assert_equal Project.find(2), issue.project
    assert_equal 'Feature request', issue.tracker.to_s
    assert_equal 'Stock management', issue.category.to_s
    assert_equal 'Urgent', issue.priority.to_s
    assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
  end
516

517
  def test_add_issue_with_japanese_keywords
518
    tracker = Tracker.generate!(:name => '開発')
519
    Project.find(1).trackers << tracker
520 521 522 523 524
    issue = submit_email(
              'japanese_keywords_iso_2022_jp.eml',
              :issue => {:project => 'ecookbook'},
              :allow_override => 'tracker'
            )
525 526 527
    assert_kind_of Issue, issue
    assert_equal tracker, issue.tracker
  end
528

529
  def test_add_issue_from_apple_mail
530 531 532 533
    issue = submit_email(
              'apple_mail_with_attachment.eml',
              :issue => {:project => 'ecookbook'}
            )
534 535
    assert_kind_of Issue, issue
    assert_equal 1, issue.attachments.size
536

537 538 539
    attachment = issue.attachments.first
    assert_equal 'paella.jpg', attachment.filename
    assert_equal 10790, attachment.filesize
540 541
    assert File.exist?(attachment.diskfile)
    assert_equal 10790, File.size(attachment.diskfile)
542
    assert_equal '4474dd534c36bdd212e2efc549507377c3e77147c9167b66dedcebfe9da8807f', attachment.digest
543
  end
544

545 546 547 548 549 550 551 552
  def test_thunderbird_with_attachment_ja
    issue = submit_email(
              'thunderbird_with_attachment_ja.eml',
              :issue => {:project => 'ecookbook'}
            )
    assert_kind_of Issue, issue
    assert_equal 1, issue.attachments.size
    attachment = issue.attachments.first
553
    assert_equal 'テスト.txt', attachment.filename
554 555 556
    assert_equal 5, attachment.filesize
    assert File.exist?(attachment.diskfile)
    assert_equal 5, File.size(attachment.diskfile)
557
    assert_equal 'f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2', attachment.digest
558 559
  end

560 561 562 563 564 565
  def test_invalid_utf8
    issue = submit_email(
              'invalid_utf8.eml',
              :issue => {:project => 'ecookbook'}
            )
    assert_kind_of Issue, issue
566
    assert_equal 'Здравствуйте?', issue.description
567 568
  end

569 570 571 572 573 574 575 576
  def test_gmail_with_attachment_ja
    issue = submit_email(
              'gmail_with_attachment_ja.eml',
              :issue => {:project => 'ecookbook'}
            )
    assert_kind_of Issue, issue
    assert_equal 1, issue.attachments.size
    attachment = issue.attachments.first
577
    assert_equal 'テスト.txt', attachment.filename
578 579 580
    assert_equal 5, attachment.filesize
    assert File.exist?(attachment.diskfile)
    assert_equal 5, File.size(attachment.diskfile)
581
    assert_equal 'f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2', attachment.digest
582 583 584 585 586 587 588 589 590
  end

  def test_thunderbird_with_attachment_latin1
    issue = submit_email(
              'thunderbird_with_attachment_iso-8859-1.eml',
              :issue => {:project => 'ecookbook'}
            )
    assert_kind_of Issue, issue
    assert_equal 1, issue.attachments.size
591 592
    u = +''
    u1 = 'ÄäÖöÜü'
593 594 595 596 597 598
    11.times { u << u1 }
    attachment = issue.attachments.first
    assert_equal "#{u}.png", attachment.filename
    assert_equal 130, attachment.filesize
    assert File.exist?(attachment.diskfile)
    assert_equal 130, File.size(attachment.diskfile)
599
    assert_equal '5635d67364de20432247e651dfe86fcb2265ad5e9750bd8bba7319a86363e738', attachment.digest
600 601 602 603 604 605 606 607 608
  end

  def test_gmail_with_attachment_latin1
    issue = submit_email(
              'gmail_with_attachment_iso-8859-1.eml',
              :issue => {:project => 'ecookbook'}
            )
    assert_kind_of Issue, issue
    assert_equal 1, issue.attachments.size
609 610
    u = +''
    u1 = 'ÄäÖöÜü'
611 612 613 614 615 616
    11.times { u << u1 }
    attachment = issue.attachments.first
    assert_equal "#{u}.txt", attachment.filename
    assert_equal 5, attachment.filesize
    assert File.exist?(attachment.diskfile)
    assert_equal 5, File.size(attachment.diskfile)
617
    assert_equal 'f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2', attachment.digest
618 619
  end

620 621 622 623 624 625 626 627 628 629 630 631
  def test_mail_with_attachment_latin2
    issue = submit_email(
              'ticket_with_text_attachment_iso-8859-2.eml',
              :issue => {:project => 'ecookbook'}
            )
    assert_kind_of Issue, issue
    assert_equal 1, issue.attachments.size
    attachment = issue.attachments.first
    assert_equal 'latin2.txt', attachment.filename
    assert_equal 19, attachment.filesize
    assert File.exist?(attachment.diskfile)
    assert_equal 19, File.size(attachment.diskfile)
632
    content = (+"p\xF8\xEDli\xB9 \xBEluou\xE8k\xFD k\xF9n").force_encoding('CP852')
633 634 635
    assert_equal content, File.read(attachment.diskfile).force_encoding('CP852')
  end

636 637 638 639 640 641 642 643
  def test_empty_attachment_should_not_be_imported
    issue = submit_email(
              'ticket_with_empty_attachment.eml',
              issue: { project: 'ecookbook' }
            )
    assert_equal 0, issue.attachments.size
  end

644
  def test_multiple_inline_text_parts_should_be_appended_to_issue_description
645 646 647 648 649 650
    issue = submit_email('multiple_text_parts.eml', :issue => {:project => 'ecookbook'})
    assert_include 'first', issue.description
    assert_include 'second', issue.description
    assert_include 'third', issue.description
  end

651 652 653 654 655
  def test_empty_text_part_should_not_stop_looking_for_content
    issue = submit_email('empty_text_part.eml', :issue => {:project => 'ecookbook'})
    assert_equal 'The html part.', issue.description
  end

656 657 658 659 660
  def test_empty_text_and_html_part_should_make_an_empty_description
    issue = submit_email('empty_text_and_html_part.eml', :issue => {:project => 'ecookbook'})
    assert_equal '', issue.description
  end

661 662 663 664 665 666 667 668 669 670 671
  def test_preferred_body_part_setting
    with_settings :mail_handler_preferred_body_part => 'plain' do
      issue = submit_email('different_contents_in_text_and_html.eml', :issue => {:project => 'ecookbook'})
      assert_equal 'The text part.', issue.description
    end
    with_settings :mail_handler_preferred_body_part => 'html' do
      issue = submit_email('different_contents_in_text_and_html.eml', :issue => {:project => 'ecookbook'})
      assert_equal 'The html part.', issue.description
    end
  end

672 673 674 675 676 677 678 679
  def test_attachment_text_part_should_be_added_as_issue_attachment
    issue = submit_email('multiple_text_parts.eml', :issue => {:project => 'ecookbook'})
    assert_not_include 'Plain text attachment', issue.description
    attachment = issue.attachments.detect {|a| a.filename == 'textfile.txt'}
    assert_not_nil attachment
    assert_include 'Plain text attachment', File.read(attachment.diskfile)
  end

680 681 682 683 684 685
  def test_add_issue_with_iso_8859_1_subject
    issue = submit_email(
              'subject_as_iso-8859-1.eml',
              :issue => {:project => 'ecookbook'}
            )
    assert_kind_of Issue, issue
686
    assert_equal 'Testmail from Webmail: ä ö ü...', issue.subject
687 688
  end

689 690 691 692 693 694
  def test_quoted_printable_utf8
    issue = submit_email(
              'quoted_printable_utf8.eml',
              :issue => {:project => 'ecookbook'}
            )
    assert_kind_of Issue, issue
695
    assert_equal 'Freundliche Grüsse', issue.description
696 697
  end

698 699 700 701 702 703
  def test_gmail_iso8859_2
    issue = submit_email(
              'gmail-iso8859-2.eml',
              :issue => {:project => 'ecookbook'}
            )
    assert_kind_of Issue, issue
704
    assert issue.description.include?('Na štriku se suši šosić.')
705 706
  end

707 708 709 710 711 712
  def test_add_issue_with_japanese_subject
    issue = submit_email(
              'subject_japanese_1.eml',
              :issue => {:project => 'ecookbook'}
            )
    assert_kind_of Issue, issue
713
    assert_equal 'テスト', issue.subject
714 715
  end

716
  def test_add_issue_with_korean_body
717 718 719 720 721
    issue = submit_email(
            'body_ks_c_5601-1987.eml',
            :issue => {:project => 'ecookbook'}
          )
    assert_kind_of Issue, issue
722
    assert_equal '고맙습니다.', issue.description
723 724
  end

725 726 727 728 729 730 731 732 733
  def test_add_issue_with_no_subject_header
    issue = submit_email(
              'no_subject_header.eml',
              :issue => {:project => 'ecookbook'}
            )
    assert_kind_of Issue, issue
    assert_equal '(no subject)', issue.subject
  end

734 735 736 737 738 739
  def test_add_issue_with_mixed_japanese_subject
    issue = submit_email(
              'subject_japanese_2.eml',
              :issue => {:project => 'ecookbook'}
            )
    assert_kind_of Issue, issue
740
    assert_equal 'Re: テスト', issue.subject
741 742
  end

743 744 745 746 747 748 749 750 751 752 753 754 755 756
  def test_add_issue_with_iso_2022_jp_ms_subject
    # The original subject is "① 丸数字テスト".
    # CIRCLED DIGIT ONE character is undefined in ISO-2022-JP but
    # defined in some vendor-extended variants such as ISO-2022-JP-MS.
    # This test makes sure that mail gem replaces an undefined characters
    # with a replacement character instead of breaking the whole subject.
    issue = submit_email(
              'subject_japanese_3.eml',
              :issue => {:project => 'ecookbook'}
            )
    assert_kind_of Issue, issue
    assert_match /丸数字テスト/, issue.subject
  end

757 758 759 760 761 762 763 764 765
  def test_should_ignore_emails_from_locked_users
    User.find(2).lock!

    MailHandler.any_instance.expects(:dispatch).never
    assert_no_difference 'Issue.count' do
      assert_equal false, submit_email('ticket_on_given_project.eml')
    end
  end

766
  def test_should_ignore_emails_from_emission_address
767 768 769 770 771
    emission_addresses = [
      'redmine@example.net',
      'Redmine <redmine@example.net>',
      'redmine@example.net (Redmine)'
    ]
772
    Role.anonymous.add_permission!(:add_issues)
773 774 775 776 777 778 779 780 781 782 783
    emission_addresses.each do |addr|
      with_settings :mail_from => addr do
        assert_no_difference 'User.count' do
          assert_equal false,
                      submit_email(
                        'ticket_from_emission_address.eml',
                        :issue => {:project => 'ecookbook'},
                        :unknown_user => 'create'
                      )
        end
      end
784 785 786
    end
  end

787
  def test_should_ignore_auto_replied_emails
788
    MailHandler.any_instance.expects(:dispatch).never
789 790
    [
      "Auto-Submitted: auto-replied",
791
      "Auto-Submitted: Auto-Replied",
792 793
      "Auto-Submitted: auto-generated",
      'X-Autoreply: yes'
794 795 796
    ].each do |header|
      raw = IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
      raw = header + "\n" + raw
797

798 799 800
      assert_no_difference 'Issue.count' do
        assert_equal false, MailHandler.receive(raw), "email with #{header} header was not ignored"
      end
801 802 803
    end
  end

804 805 806 807 808 809 810 811 812 813 814 815 816
  test "should not ignore Auto-Submitted headers not defined in RFC3834" do
    [
      "Auto-Submitted: auto-forwarded"
    ].each do |header|
      raw = IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
      raw = header + "\n" + raw

      assert_difference 'Issue.count', 1 do
        assert_not_nil MailHandler.receive(raw), "email with #{header} header was ignored"
      end
    end
  end

817
  def test_add_issue_should_send_email_notification
818
    Setting.notified_events = ['issue_added']
819 820 821 822 823
    # This email contains: 'Project: onlinestore'
    issue = submit_email('ticket_on_given_project.eml')
    assert issue.is_a?(Issue)
    assert_equal 1, ActionMailer::Base.deliveries.size
  end
824

825
  def test_update_issue
826 827 828 829
    journal = submit_email('ticket_reply.eml')
    assert journal.is_a?(Journal)
    assert_equal User.find_by_login('jsmith'), journal.user
    assert_equal Issue.find(2), journal.journalized
830
    assert_match /This is reply/, journal.notes
jplang's avatar
jplang committed
831
    assert_equal false, journal.private_notes
832
    assert_equal 'Feature request', journal.issue.tracker.name
833 834
  end

835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858
  def test_update_issue_should_accept_issue_id_after_space_inside_brackets
    journal = submit_email('ticket_reply_with_status.eml') do |email|
      assert email.sub!(/^Subject:.*$/, "Subject: Re: [Feature request #2] Add ingredients categories")
    end
    assert journal.is_a?(Journal)
    assert_equal Issue.find(2), journal.journalized
  end

  def test_update_issue_should_accept_issue_id_inside_brackets
    journal = submit_email('ticket_reply_with_status.eml') do |email|
      assert email.sub!(/^Subject:.*$/, "Subject: Re: [#2] Add ingredients categories")
    end
    assert journal.is_a?(Journal)
    assert_equal Issue.find(2), journal.journalized
  end

  def test_update_issue_should_ignore_bogus_issue_ids_in_subject
    journal = submit_email('ticket_reply_with_status.eml') do |email|
      assert email.sub!(/^Subject:.*$/, "Subject: Re: [12345#1][bogus#1][Feature request #2] Add ingredients categories")
    end
    assert journal.is_a?(Journal)
    assert_equal Issue.find(2), journal.journalized
  end

859
  def test_update_issue_with_attribute_changes
860 861 862 863
    journal = submit_email('ticket_reply_with_status.eml',
                           :allow_override => ['status', 'assigned_to',
                                               'start_date', 'due_date',
                                               'float field'])
864 865 866 867 868
    assert journal.is_a?(Journal)
    issue = Issue.find(journal.issue.id)
    assert_equal User.find_by_login('jsmith'), journal.user
    assert_equal Issue.find(2), journal.journalized
    assert_match /This is reply/, journal.notes
869
    assert_equal 'Feature request', journal.issue.tracker.name
870
    assert_equal IssueStatus.find_by_name("Resolved"), issue.status
871 872
    assert_equal '2010-01-01', issue.start_date.to_s
    assert_equal '2010-12-31', issue.due_date.to_s
873
    assert_equal User.find_by_login('jsmith'), issue.assigned_to
874
    assert_equal "52.6", issue.custom_value_for(CustomField.find_by_name('Float field')).value
875 876 877
    # keywords should be removed from the email body
    assert !journal.notes.match(/^Status:/i)
    assert !journal.notes.match(/^Start Date:/i)
878
  end
879

880 881 882 883 884 885 886 887 888 889 890 891
  def test_update_issue_with_attachment
    assert_difference 'Journal.count' do
      assert_difference 'JournalDetail.count' do
        assert_difference 'Attachment.count' do
          assert_no_difference 'Issue.count' do
            journal = submit_email('ticket_with_attachment.eml') do |raw|
              raw.gsub! /^Subject: .*$/, 'Subject: Re: [Cookbook - Feature #2] (New) Add ingredients categories'
            end
          end
        end
      end
    end
892
    journal = Journal.order('id DESC').first
893 894
    assert_equal Issue.find(2), journal.journalized
    assert_equal 1, journal.details.size
895

896 897 898 899
    detail = journal.details.first
    assert_equal 'attachment', detail.property
    assert_equal 'Paella.jpg', detail.value
  end
900

901 902 903 904 905 906 907 908 909 910 911 912 913 914 915
  def test_update_issue_should_discard_all_changes_on_validation_failure
    Issue.any_instance.stubs(:valid?).returns(false)
    assert_no_difference 'Journal.count' do
      assert_no_difference 'JournalDetail.count' do
        assert_no_difference 'Attachment.count' do
          assert_no_difference 'Issue.count' do
            journal = submit_email('ticket_with_attachment.eml') do |raw|
              raw.gsub! /^Subject: .*$/, 'Subject: Re: [Cookbook - Feature #2] (New) Add ingredients categories'
            end
          end
        end
      end
    end
  end

916
  def test_update_issue_should_send_email_notification
917 918
    journal = submit_email('ticket_reply.eml')
    assert journal.is_a?(Journal)
919
    assert_equal 3, ActionMailer::Base.deliveries.size
920
  end
921

922
  def test_update_issue_should_not_set_defaults
923 924 925 926
    journal = submit_email(
                'ticket_reply.eml',
                :issue => {:tracker => 'Support request', :priority => 'High'}
              )
927 928 929 930 931
    assert journal.is_a?(Journal)
    assert_match /This is reply/, journal.notes
    assert_equal 'Feature request', journal.issue.tracker.name
    assert_equal 'Normal', journal.issue.priority.name
  end
932

933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954
  def test_update_issue_should_add_cc_as_watchers
    Watcher.delete_all
    issue = Issue.find(2)

    assert_difference 'Watcher.count' do
      assert submit_email('issue_update_with_cc.eml')
    end
    issue.reload
    assert_equal 1, issue.watcher_user_ids.size
    assert issue.watched_by?(User.find_by_mail('dlopper@somenet.foo'))
  end

  def test_update_issue_should_not_add_cc_as_watchers_if_already_watching
    Watcher.delete_all
    issue = Issue.find(2)
    Watcher.create!(:watchable => issue, :user => User.find_by_mail('dlopper@somenet.foo'))

    assert_no_difference 'Watcher.count' do
      assert submit_email('issue_update_with_cc.eml')
    end
  end

jplang's avatar
jplang committed
955
  def test_replying_to_a_private_note_should_add_reply_as_private
956 957 958
    private_journal = Journal.create!(:notes => 'Private notes',
                                      :journalized => Issue.find(1),
                                      :private_notes => true, :user_id => 2)
jplang's avatar
jplang committed
959 960 961 962 963 964 965 966 967 968 969 970

    assert_difference 'Journal.count' do
      journal = submit_email('ticket_reply.eml') do |email|
        email.sub! %r{^In-Reply-To:.*$}, "In-Reply-To: <redmine.journal-#{private_journal.id}.20060719210421@osiris>"
      end

      assert_kind_of Journal, journal
      assert_match /This is reply/, journal.notes
      assert_equal true, journal.private_notes
    end
  end

971 972 973 974 975 976 977 978 979
  def test_reply_to_a_message
    m = submit_email('message_reply.eml')
    assert m.is_a?(Message)
    assert !m.new_record?
    m.reload
    assert_equal 'Reply via email', m.subject
    # The email replies to message #2 which is part of the thread of message #1
    assert_equal Message.find(1), m.parent
  end
980

981 982 983 984 985 986 987 988
  def test_reply_to_a_message_by_subject
    m = submit_email('message_reply_by_subject.eml')
    assert m.is_a?(Message)
    assert !m.new_record?
    m.reload
    assert_equal 'Reply to the first post', m.subject
    assert_equal Message.find(1), m.parent
  end
989

990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
  def test_should_convert_tags_of_html_only_emails
    with_settings :text_formatting => 'textile' do
      issue = submit_email('ticket_html_only.eml', :issue => {:project => 'ecookbook'})
      assert issue.is_a?(Issue)
      assert !issue.new_record?
      issue.reload
      assert_equal 'HTML email', issue.subject
      assert_equal "This is a *html-only* email.\r\n\r\nh1. With a title\r\n\r\nand a paragraph.", issue.description
    end
  end

  def test_should_handle_outlook_web_access_2010_html_only
    issue = submit_email('outlook_web_access_2010_html_only.eml', :issue => {:project => 'ecookbook'})
    assert issue.is_a?(Issue)
    issue.reload
    assert_equal 'Upgrade Redmine to 3.0.x', issue.subject
    assert_equal "A mess.\r\n\r\n--Geoff Maciolek\r\nMYCOMPANYNAME, LLC", issue.description
  end

  def test_should_handle_outlook_2010_html_only
    issue = submit_email('outlook_2010_html_only.eml', :issue => {:project => 'ecookbook'})
1011 1012
    assert issue.is_a?(Issue)
    issue.reload
1013 1014 1015 1016
    assert_equal 'Test email', issue.subject
    assert_equal "Simple, unadorned test email generated by Outlook 2010. It is in HTML format, but" +
      " no special formatting has been chosen. I’m going to save this as a draft and then manually" +
      " drop it into the Inbox for scraping by Redmine 3.0.2.", issue.description
1017
  end
1018

jplang's avatar
jplang committed
1019 1020 1021 1022 1023 1024
  test "truncate emails with no setting should add the entire email into the issue" do
    with_settings :mail_handler_body_delimiters => '' do
      issue = submit_email('ticket_on_given_project.eml')
      assert_issue_created(issue)
      assert issue.description.include?('---')
      assert issue.description.include?('This paragraph is after the delimiter')
1025
    end
jplang's avatar
jplang committed
1026
  end
1027

jplang's avatar
jplang committed
1028 1029 1030 1031 1032 1033
  test "truncate emails with a single string should truncate the email at the delimiter for the issue" do
    with_settings :mail_handler_body_delimiters => '---' do
      issue = submit_email('ticket_on_given_project.eml')
      assert_issue_created(issue)
      assert issue.description.include?('This paragraph is before delimiters')
      assert issue.description.include?('--- This line starts with a delimiter')
1034
      assert !issue.description.match(/^---#{"\u00A0"}$/)
jplang's avatar
jplang committed
1035
      assert !issue.description.include?('This paragraph is after the delimiter')
1036
    end
jplang's avatar
jplang committed
1037
  end
1038

jplang's avatar
jplang committed
1039 1040 1041 1042 1043 1044 1045
  test "truncate emails with a single quoted reply should truncate the email at the delimiter with the quoted reply symbols (>)" do
    with_settings :mail_handler_body_delimiters => '--- Reply above. Do not remove this line. ---' do
      journal = submit_email('issue_update_with_quoted_reply_above.eml')
      assert journal.is_a?(Journal)
      assert journal.notes.include?('An update to the issue by the sender.')
      assert !journal.notes.match(Regexp.escape("--- Reply above. Do not remove this line. ---"))
      assert !journal.notes.include?('Looks like the JSON api for projects was missed.')
1046
    end
jplang's avatar
jplang committed
1047
  end
1048

jplang's avatar
jplang committed
1049 1050 1051 1052 1053 1054 1055
  test "truncate emails with multiple quoted replies should truncate the email at the delimiter with the quoted reply symbols (>)" do
    with_settings :mail_handler_body_delimiters => '--- Reply above. Do not remove this line. ---' do
      journal = submit_email('issue_update_with_multiple_quoted_reply_above.eml')
      assert journal.is_a?(Journal)
      assert journal.notes.include?('An update to the issue by the sender.')
      assert !journal.notes.match(Regexp.escape("--- Reply above. Do not remove this line. ---"))
      assert !journal.notes.include?('Looks like the JSON api for projects was missed.')
1056
    end
jplang's avatar
jplang committed
1057
  end
1058

jplang's avatar
jplang committed
1059 1060 1061 1062 1063 1064 1065 1066 1067
  test "truncate emails with multiple strings should truncate the email at the first delimiter found (BREAK)" do
    with_settings :mail_handler_body_delimiters => "---\nBREAK" do
      issue = submit_email('ticket_on_given_project.eml')
      assert_issue_created(issue)
      assert issue.description.include?('This paragraph is before delimiters')
      assert !issue.description.include?('BREAK')
      assert !issue.description.include?('This paragraph is between delimiters')
      assert !issue.description.match(/^---$/)
      assert !issue.description.include?('This paragraph is after the delimiter')
1068 1069
    end
  end
1070

1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089
  test "truncate emails using a regex delimiter" do
    delimiter = "On .*, .* at .*, .* <.*<mailto:.*>> wrote:"
    with_settings :mail_handler_enable_regex_delimiters => '1', :mail_handler_body_delimiters => delimiter do
      issue = submit_email('ticket_reply_from_mail.eml')
      assert_issue_created(issue)
      assert issue.description.include?('This paragraph is before delimiter')
      assert !issue.description.include?('On Wed, 11 Oct at 1:05 PM, Jon Smith <jsmith@somenet.foo<mailto:jsmith@somenet.foo>> wrote:')
      assert !issue.description.include?('This paragraph is after the delimiter')
    end

    with_settings :mail_handler_enable_regex_delimiters => '0', :mail_handler_body_delimiters => delimiter do
      issue = submit_email('ticket_reply_from_mail.eml')
      assert_issue_created(issue)
      assert issue.description.include?('This paragraph is before delimiter')
      assert issue.description.include?('On Wed, 11 Oct at 1:05 PM, Jon Smith <jsmith@somenet.foo<mailto:jsmith@somenet.foo>> wrote:')
      assert issue.description.include?('This paragraph is after the delimiter')
    end
  end

1090 1091 1092 1093 1094 1095 1096 1097 1098
  def test_attachments_that_match_mail_handler_excluded_filenames_should_be_ignored
    with_settings :mail_handler_excluded_filenames => '*.vcf, *.jpg' do
      issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'})
      assert issue.is_a?(Issue)
      assert !issue.new_record?
      assert_equal 0, issue.reload.attachments.size
    end
  end

1099 1100 1101 1102 1103 1104 1105 1106 1107 1108
  def test_attachments_that_match_mail_handler_excluded_filenames_by_regex_should_be_ignored
    with_settings :mail_handler_excluded_filenames => '.+\.vcf,(pa|nut)ella\.jpg',
                  :mail_handler_enable_regex_excluded_filenames => 1 do
      issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'})
      assert issue.is_a?(Issue)
      assert !issue.new_record?
      assert_equal 0, issue.reload.attachments.size
    end
  end

1109 1110 1111 1112 1113 1114 1115 1116 1117
  def test_attachments_that_do_not_match_mail_handler_excluded_filenames_should_be_attached
    with_settings :mail_handler_excluded_filenames => '*.vcf, *.gif' do
      issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'})
      assert issue.is_a?(Issue)
      assert !issue.new_record?
      assert_equal 1, issue.reload.attachments.size
    end
  end

1118 1119 1120 1121 1122
  def test_email_with_long_subject_line
    issue = submit_email('ticket_with_long_subject.eml')
    assert issue.is_a?(Issue)
    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]
  end
1123

1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
  def test_first_keyword_should_be_matched
    issue = submit_email('ticket_with_duplicate_keyword.eml', :allow_override => 'priority')
    assert issue.is_a?(Issue)
    assert_equal 'High', issue.priority.name
  end

  def test_keyword_after_delimiter_should_be_ignored
    with_settings :mail_handler_body_delimiters => "== DELIMITER ==" do
      issue = submit_email('ticket_with_keyword_after_delimiter.eml', :allow_override => 'priority')
      assert issue.is_a?(Issue)
      assert_equal 'Normal', issue.priority.name
    end
  end

1138 1139 1140 1141 1142 1143 1144
  def test_new_user_from_attributes_should_return_valid_user
    to_test = {
      # [address, name] => [login, firstname, lastname]
      ['jsmith@example.net', nil] => ['jsmith@example.net', 'jsmith', '-'],
      ['jsmith@example.net', 'John'] => ['jsmith@example.net', 'John', '-'],
      ['jsmith@example.net', 'John Smith'] => ['jsmith@example.net', 'John', 'Smith'],
      ['jsmith@example.net', 'John Paul Smith'] => ['jsmith@example.net', 'John', 'Paul Smith'],
1145 1146 1147 1148
      ['jsmith@example.net', 'AVeryLongFirstnameThatExceedsTheMaximumLength Smith'] =>
         ['jsmith@example.net', 'AVeryLongFirstnameThatExceedsT', 'Smith'],
      ['jsmith@example.net', 'John AVeryLongLastnameThatExceedsTheMaximumLength'] =>
         ['jsmith@example.net', 'John', 'AVeryLongLastnameThatExceedsTh']
1149 1150 1151
    }
    to_test.each do |attrs, expected|
      user = MailHandler.new_user_from_attributes(attrs.first, attrs.last)
jplang's avatar
jplang committed
1152
      assert user.valid?, user.errors.full_messages.to_s
1153 1154 1155 1156
      assert_equal attrs.first, user.mail
      assert_equal expected[0], user.login
      assert_equal expected[1], user.firstname
      assert_equal expected[2], user.lastname
1157
      assert_equal 'only_my_events', user.mail_notification
1158 1159 1160 1161
    end
  end

  def test_new_user_from_attributes_should_use_default_login_if_invalid
1162
    user = MailHandler.new_user_from_attributes('foo+bar@example.net')
1163 1164
    assert user.valid?
    assert user.login =~ /^user[a-f0-9]+$/
1165
    assert_equal 'foo+bar@example.net', user.mail
1166 1167
  end

1168 1169 1170 1171 1172 1173 1174 1175
  def test_new_user_with_utf8_encoded_fullname_should_be_decoded
    assert_difference 'User.count' do
      issue = submit_email(
                'fullname_of_sender_as_utf8_encoded.eml',
                :issue => {:project => 'ecookbook'},
                :unknown_user => 'create'
              )
    end
1176
    user = User.order('id DESC').first
1177
    assert_equal "foo@example.org", user.mail
1178 1179
    assert_equal 'Ää', user.firstname
    assert_equal 'Öö', user.lastname
1180 1181
  end

maeda's avatar
maeda committed
1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195
  def test_new_user_with_fullname_in_parentheses
    assert_difference 'User.count' do
      issue = submit_email(
                'fullname_of_sender_in_parentheses.eml',
                :issue => {:project => 'ecookbook'},
                :unknown_user => 'create'
              )
    end
    user = User.order('id DESC').first
    assert_equal "jdoe@example.net", user.mail
    assert_equal 'John', user.firstname
    assert_equal 'Doe', user.lastname
  end

1196 1197 1198 1199
  def test_extract_options_from_env_should_return_options
    options = MailHandler.extract_options_from_env({
      'tracker' => 'defect',
      'project' => 'foo',
1200 1201
      'unknown_user' => 'create',
      'no_notification' => '1'
1202 1203 1204 1205
    })

    assert_equal({
      :issue => {:tracker => 'defect', :project => 'foo'},
1206
      :unknown_user => 'create', :no_notification => '1'
1207 1208 1209
    }, options)
  end

jplang's avatar
jplang committed
1210 1211 1212 1213 1214 1215
  def test_safe_receive_should_rescue_exceptions_and_return_false
    MailHandler.stubs(:receive).raises(Exception.new "Something went wrong")

    assert_equal false, MailHandler.safe_receive
  end

1216
  private
1217

1218 1219
  def submit_email(filename, options={})
    raw = IO.read(File.join(FIXTURES_PATH, filename))
1220
    yield raw if block_given?
1221 1222
    MailHandler.receive(raw, options)
  end
1223 1224 1225 1226 1227 1228

  def assert_issue_created(issue)
    assert issue.is_a?(Issue)
    assert !issue.new_record?
    issue.reload
  end
1229
end