Patch #1616 » feature_277_mailing_list_forum_integration.diff
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={}) |
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: |