Project

General

Profile

Patch #1616 » feature_277_mailing_list_forum_integration_with_test_fixtures.diff

Diff/Patch with code and test fixtures - ignore original diff - Joshua Hoover, 2008-07-10 03:08

View differences:

test/unit/mail_handler_test.rb (working copy)
26 26
                   :trackers,
27 27
                   :projects_trackers,
28 28
                   :enumerations,
29
                   :issue_categories
29
                   :issue_categories,
30
                   :boards
30 31
  
31 32
  FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures/mail_handler'
32 33
  
......
97 98
    assert_equal Issue.find(2), journal.journalized
98 99
    assert_equal 'This is reply', journal.notes
99 100
  end
101
  
102
  def test_add_forum_message
103
    # This email subject contains: [eCookbook - Discussion] A new message on a forum
104
    message = submit_email('message_on_given_project.eml')
105
    assert message.is_a?(Message)
106
    assert !message.new_record?
107
    message.reload
108
    assert_equal 'A new message on a forum', message.subject
109
    assert_equal User.find_by_login('jsmith'), message.author
110
    assert_equal Board.find(2), message.board
111
    assert message.content.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
112
  end
113
  
114
  def test_add_forum_message_reply
115
    # This email subject contains: Re: [eCookbook - Help] First post
116
    message = submit_email('message_reply.eml')
117
    assert message.is_a?(Message)
118
    assert !message.new_record?
119
    message.reload
120
    assert_equal 'Re: First post', message.subject
121
    assert_equal User.find_by_login('jsmith'), message.author
122
    assert_equal Board.find(1), message.board
123
    assert_equal Message.find(1).id, message.parent_id
124
    assert message.content.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
125
  end
126
  
127
  def test_reject_invalid_message_project
128
    # This email subject contains: [Bad Project Name - Discussion]
129
    message = submit_email('message_invalid_project.eml')
130
    assert !message
131
  end
132
  
133
  def test_reject_invalid_message_board
134
    # This email subject contains: [eCookbook - Invalid Board Name]
135
    message = submit_email('message_invalid_board.eml')
136
    assert !message
137
  end
138
  
139
  def test_reject_invalid_user_email
140
    # This email is from: not_a_valid_user_email@somenet.foo
141
    message = submit_email('message_invalid_user_email.eml')
142
    assert !message
143
  end
100 144

  
145
  def test_reject_unsupported_email
146
    # This email is from a valid user but has no content for an issue or message
147
    message = submit_email('unsupported_email.eml')
148
    assert !message
149
  end
150
  
101 151
  private
102 152
  
103 153
  def submit_email(filename, options={})
test/fixtures/mail_handler/message_on_given_project.eml (revision 0)
1
Return-Path: <jsmith@somenet.foo>
2
Received: from osiris ([127.0.0.1])
3
	by OSIRIS
4
	with hMailServer ; Sun, 22 Jun 2008 12:28:07 +0200
5
Message-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris>
6
From: "John Smith" <jsmith@somenet.foo>
7
To: <redmine@somenet.foo>
8
Subject: [eCookbook - Discussion] A new message on a forum
9
Date: Sun, 22 Jun 2008 12:28:07 +0200
10
MIME-Version: 1.0
11
Content-Type: text/plain;
12
	format=flowed;
13
	charset="iso-8859-1";
14
	reply-type=original
15
Content-Transfer-Encoding: 7bit
16
X-Priority: 3
17
X-MSMail-Priority: Normal
18
X-Mailer: Microsoft Outlook Express 6.00.2900.2869
19
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2869
20

  
21
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas imperdiet 
22
turpis et odio. Integer eget pede vel dolor euismod varius. Phasellus 
23
blandit eleifend augue. Nulla facilisi. Duis id diam. Class aptent taciti 
24
sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In 
25
in urna sed tellus aliquet lobortis. Morbi scelerisque tortor in dolor. Cras 
26
sagittis odio eu lacus. Aliquam sem tortor, consequat sit amet, vestibulum 
27
id, iaculis at, lectus. Fusce tortor libero, congue ut, euismod nec, luctus 
28
eget, eros. Pellentesque tortor enim, feugiat in, dignissim eget, tristique 
29
sed, mauris. Pellentesque habitant morbi tristique senectus et netus et 
30
malesuada fames ac turpis egestas. Quisque sit amet libero. In hac habitasse 
31
platea dictumst.
test/fixtures/mail_handler/message_invalid_user_email.eml (revision 0)
1
Return-Path: <not_a_valid_user_email@somenet.foo>
2
Received: from osiris ([127.0.0.1])
3
	by OSIRIS
4
	with hMailServer ; Sun, 28 Jun 2008 09:28:07 +0200
5
Message-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris>
6
From: "John Doe" <not_a_valid_user_email@somenet.foo>
7
To: <redmine@somenet.foo>
8
Subject: [eCookbook - Discussion] Message from an unauthorized user
9
Date: Sun, 28 Jun 2008 09:28:07 +0200
10
MIME-Version: 1.0
11
Content-Type: text/plain;
12
	format=flowed;
13
	charset="iso-8859-1";
14
	reply-type=original
15
Content-Transfer-Encoding: 7bit
16
X-Priority: 3
17
X-MSMail-Priority: Normal
18
X-Mailer: Microsoft Outlook Express 6.00.2900.2869
19
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2869
20

  
21
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas imperdiet 
22
turpis et odio. Integer eget pede vel dolor euismod varius. Phasellus 
23
blandit eleifend augue. Nulla facilisi. Duis id diam. Class aptent taciti 
24
sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In 
25
in urna sed tellus aliquet lobortis.
test/fixtures/mail_handler/message_reply.eml (revision 0)
1
Return-Path: <jsmith@somenet.foo>
2
Received: from osiris ([127.0.0.1])
3
	by OSIRIS
4
	with hMailServer ; Sun, 22 Jun 2008 12:28:07 +0200
5
Message-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris>
6
From: "John Smith" <jsmith@somenet.foo>
7
To: <redmine@somenet.foo>
8
Subject: Re: [eCookbook - Help] First post
9
Date: Mon, 7 Jun 2008 10:28:07 +0200
10
MIME-Version: 1.0
11
Content-Type: text/plain;
12
	format=flowed;
13
	charset="iso-8859-1";
14
	reply-type=original
15
Content-Transfer-Encoding: 7bit
16
X-Priority: 3
17
X-MSMail-Priority: Normal
18
X-Mailer: Microsoft Outlook Express 6.00.2900.2869
19
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2869
20

  
21
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas imperdiet 
22
turpis et odio. Integer eget pede vel dolor euismod varius. Phasellus 
23
blandit eleifend augue. Nulla facilisi. Duis id diam. Class aptent taciti 
24
sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In 
25
in urna sed tellus aliquet lobortis. Morbi scelerisque tortor in dolor. Cras 
26
sagittis odio eu lacus. Aliquam sem tortor, consequat sit amet, vestibulum 
27
id, iaculis at, lectus. Fusce tortor libero, congue ut, euismod nec, luctus 
28
eget, eros. Pellentesque tortor enim, feugiat in, dignissim eget, tristique 
29
sed, mauris. Pellentesque habitant morbi tristique senectus et netus et 
30
malesuada fames ac turpis egestas. Quisque sit amet libero. In hac habitasse 
31
platea dictumst.
test/fixtures/mail_handler/unsupported_email.eml (revision 0)
1
Return-Path: <jsmith@somenet.foo>
2
Received: from osiris ([127.0.0.1])
3
	by OSIRIS
4
	with hMailServer ; Sun, 28 Jun 2008 09:28:07 +0200
5
Message-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris>
6
From: "John Smith" <jsmith@somenet.foo>
7
To: <redmine@somenet.foo>
8
Subject: Unsupported email from valid user
9
Date: Sun, 28 Jun 2008 09:28:07 +0200
10
MIME-Version: 1.0
11
Content-Type: text/plain;
12
	format=flowed;
13
	charset="iso-8859-1";
14
	reply-type=original
15
Content-Transfer-Encoding: 7bit
16
X-Priority: 3
17
X-MSMail-Priority: Normal
18
X-Mailer: Microsoft Outlook Express 6.00.2900.2869
19
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2869
20

  
21
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas imperdiet 
22
turpis et odio. Integer eget pede vel dolor euismod varius. Phasellus 
23
blandit eleifend augue. Nulla facilisi. Duis id diam. Class aptent taciti 
24
sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In 
25
in urna sed tellus aliquet lobortis.
test/fixtures/mail_handler/message_invalid_project.eml (revision 0)
1
Return-Path: <jsmith@somenet.foo>
2
Received: from osiris ([127.0.0.1])
3
	by OSIRIS
4
	with hMailServer ; Sun, 28 Jun 2008 09:28:07 +0200
5
Message-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris>
6
From: "John Smith" <jsmith@somenet.foo>
7
To: <redmine@somenet.foo>
8
Subject: [Bad Project Name - Discussion] Message to an invalid project
9
Date: Sun, 28 Jun 2008 09:28:07 +0200
10
MIME-Version: 1.0
11
Content-Type: text/plain;
12
	format=flowed;
13
	charset="iso-8859-1";
14
	reply-type=original
15
Content-Transfer-Encoding: 7bit
16
X-Priority: 3
17
X-MSMail-Priority: Normal
18
X-Mailer: Microsoft Outlook Express 6.00.2900.2869
19
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2869
20

  
21
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas imperdiet 
22
turpis et odio. Integer eget pede vel dolor euismod varius. Phasellus 
23
blandit eleifend augue. Nulla facilisi. Duis id diam. Class aptent taciti 
24
sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In 
25
in urna sed tellus aliquet lobortis.
test/fixtures/mail_handler/message_invalid_board.eml (revision 0)
1
Return-Path: <jsmith@somenet.foo>
2
Received: from osiris ([127.0.0.1])
3
	by OSIRIS
4
	with hMailServer ; Sun, 28 Jun 2008 09:28:07 +0200
5
Message-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris>
6
From: "John Smith" <jsmith@somenet.foo>
7
To: <redmine@somenet.foo>
8
Subject: [eCookbook - Invalid Board Name] Message to an invalid project
9
Date: Sun, 28 Jun 2008 09:28:07 +0200
10
MIME-Version: 1.0
11
Content-Type: text/plain;
12
	format=flowed;
13
	charset="iso-8859-1";
14
	reply-type=original
15
Content-Transfer-Encoding: 7bit
16
X-Priority: 3
17
X-MSMail-Priority: Normal
18
X-Mailer: Microsoft Outlook Express 6.00.2900.2869
19
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2869
20

  
21
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas imperdiet 
22
turpis et odio. Integer eget pede vel dolor euismod varius. Phasellus 
23
blandit eleifend augue. Nulla facilisi. Duis id diam. Class aptent taciti 
24
sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In 
25
in urna sed tellus aliquet lobortis.
app/models/mail_handler.rb (working copy)
51 51
  private
52 52

  
53 53
  ISSUE_REPLY_SUBJECT_RE = %r{\[[^\]]+#(\d+)\]}
54
  FORUM_MESSAGE_SUBJECT = %r{(\[.*)(#.*\])}
55
  FORUM_MESSAGE_SUBJECT_RE = %r{re: }i
56
  FORUM_MESSAGE_SUBJECT_SPLIT = %r{(\[)(.*)( - )(.*)(\])}
54 57
  
55 58
  def dispatch
56 59
    if m = email.subject.match(ISSUE_REPLY_SUBJECT_RE)
57 60
      receive_issue_update(m[1].to_i)
61
    elsif !email.subject.match(FORUM_MESSAGE_SUBJECT) && email.subject.match(/\[/)
62
      if email.subject.match(FORUM_MESSAGE_SUBJECT_RE)
63
        receive_forum_message_reply
64
      else
65
        receive_forum_message
66
      end
58 67
    else
59 68
      receive_issue
60 69
    end
......
89 98
    issue
90 99
  end
91 100
  
101
  # Creates a new forum message
102
  def receive_forum_message
103
    project = target_project
104
    board = target_board
105
    # check permission
106
    raise UnauthorizedAction unless user.allowed_to?(:edit_messages, project)
107
    message = Message.new(:author => user, :board => board)
108
    message.subject = email.subject.split(FORUM_MESSAGE_SUBJECT_SPLIT)[6].strip
109
    message.content = email.plain_text_body.chomp
110
    message.save!
111
    logger.info "MailHandler: message ##{message.id} - #{message.subject} created by #{user}" if logger && logger.info
112
    #Mailer.deliver_message_posted(message) if Setting.notified_events.include?('message_posted')
113
    message
114
  end
115
   
116
  # Creates a reply to an existing forum message
117
  def receive_forum_message_reply
118
    project = target_project
119
    board = target_board
120
    # check permission
121
    raise UnauthorizedAction unless user.allowed_to?(:edit_messages, project)
122
    message = Message.new(:author => user, :board => board)
123
    subject = email.subject.split(FORUM_MESSAGE_SUBJECT_SPLIT)[6].gsub(FORUM_MESSAGE_SUBJECT_RE, "").strip
124
    message.parent_id = Message.find(:first, 
125
                                     :conditions => [ "board_id = ? AND subject = ?",
126
                                     board, subject ],
127
                                     :order => "created_on DESC").id
128
    message.subject = "Re: " + subject
129
    message.content = email.plain_text_body.chomp
130
    message.save!
131
    logger.info "MailHandler: message ##{message.id} - #{message.subject} created by #{user} in reply to message ##{message.parent_id}" if logger && logger.info
132
    #Mailer.deliver_message_posted(message) if Setting.notified_events.include?('message_posted')
133
    message
134
  end
135
  
92 136
  def target_project
93 137
    # TODO: other ways to specify project:
94 138
    # * parse the email To field
95 139
    # * specific project (eg. Setting.mail_handler_target_project)
96
    target = Project.find_by_identifier(get_keyword(:project))
140
    unless target = Project.find_by_identifier(get_keyword(:project))
141
      target = Project.find_by_name(email.subject.split(FORUM_MESSAGE_SUBJECT_SPLIT)[2])
142
    end
97 143
    raise MissingInformation.new('Unable to determine target project') if target.nil?
98 144
    target
99 145
  end
100 146
  
147
  def target_board
148
    target = Board.find_by_name(email.subject.split(FORUM_MESSAGE_SUBJECT_SPLIT)[4].strip)
149
    raise MissingInformation.new('Unable to determine target board/forum') if target.nil?
150
    target
151
  end
152
  
101 153
  # Adds a note to an existing issue
102 154
  def receive_issue_update(issue_id)
103 155
    issue = Issue.find_by_id(issue_id)
app/models/mailer.rb (working copy)
99 99
  def message_posted(message, recipients)
100 100
    redmine_headers 'Project' => message.project.identifier,
101 101
                    'Topic-Id' => (message.parent_id || message.id)
102
    from Setting.forum_mail_from unless Setting.forum_mail_from.empty?
102 103
    recipients(recipients)
103 104
    subject "[#{message.board.project.name} - #{message.board.name}] #{message.subject}"
104 105
    body :message => message,
app/views/settings/_notifications.rhtml (working copy)
5 5
<p><label><%= l(:setting_mail_from) %></label>
6 6
<%= text_field_tag 'settings[mail_from]', Setting.mail_from, :size => 60 %></p>
7 7

  
8
<p><label><%= l(:setting_forum_mail_from) %></label>
9
<%= text_field_tag 'settings[forum_mail_from]', Setting.forum_mail_from, :size => 60 %></p>
10

  
8 11
<p><label><%= l(:setting_bcc_recipients) %></label>
9 12
<%= check_box_tag 'settings[bcc_recipients]', 1, Setting.bcc_recipients? %>
10 13
<%= hidden_field_tag 'settings[bcc_recipients]', 0 %></p>
lang/en.yml (working copy)
192 192
setting_attachment_max_size: Attachment max. size
193 193
setting_issues_export_limit: Issues export limit
194 194
setting_mail_from: Emission email address
195
setting_forum_mail_from: Forum emission email address
195 196
setting_bcc_recipients: Blind carbon copy recipients (bcc)
196 197
setting_host_name: Host name
197 198
setting_text_formatting: Text formatting
config/settings.yml (working copy)
44 44
  default: '25,50,100'
45 45
mail_from:
46 46
  default: redmine@somenet.foo
47
forum_mail_from:
48
  default: ""
47 49
bcc_recipients:
48 50
  default: 1
49 51
text_formatting:
(2-2/4)