Patch #4409 ยป 0001-Remove-the-body-of-incoming-emails-after-specific-de.patch
app/models/mail_handler.rb | ||
---|---|---|
81 | 81 |
MESSAGE_ID_RE = %r{^<redmine\.([a-z0-9_]+)\-(\d+)\.\d+@} |
82 | 82 |
ISSUE_REPLY_SUBJECT_RE = %r{\[[^\]]*#(\d+)\]} |
83 | 83 |
MESSAGE_REPLY_SUBJECT_RE = %r{\[[^\]]*msg(\d+)\]} |
84 |
|
|
84 | ||
85 | 85 |
def dispatch |
86 | 86 |
headers = [email.in_reply_to, email.references].flatten.compact |
87 | 87 |
if headers.detect {|h| h.to_s =~ MESSAGE_ID_RE} |
... | ... | |
131 | 131 |
if issue.subject.blank? |
132 | 132 |
issue.subject = '(no subject)' |
133 | 133 |
end |
134 |
issue.description = plain_text_body |
|
135 | 134 |
# custom fields |
136 | 135 |
issue.custom_field_values = issue.available_custom_fields.inject({}) do |h, c| |
137 | 136 |
if value = get_keyword(c.name, :override => true) |
... | ... | |
139 | 138 |
end |
140 | 139 |
h |
141 | 140 |
end |
141 |
issue.description = cleanup_body(plain_text_body) |
|
142 | 142 |
# add To and Cc as watchers before saving so the watchers can reply to Redmine |
143 | 143 |
add_watchers(issue) |
144 | 144 |
issue.save! |
... | ... | |
167 | 167 |
raise UnauthorizedAction unless status.nil? || user.allowed_to?(:edit_issues, issue.project) |
168 | 168 | |
169 | 169 |
# add the note |
170 |
journal = issue.init_journal(user, plain_text_body)
|
|
170 |
journal = issue.init_journal(user, cleanup_body(plain_text_body))
|
|
171 | 171 |
add_attachments(issue) |
172 | 172 |
# check workflow |
173 | 173 |
if status && issue.new_statuses_allowed_to(user).include?(status) |
... | ... | |
242 | 242 |
end |
243 | 243 |
end |
244 | 244 |
end |
245 |
|
|
245 | ||
246 | 246 |
# Returns the text/plain part of the email |
247 | 247 |
# If not found (eg. HTML-only email), returns the body with tags removed |
248 | 248 |
def plain_text_body |
... | ... | |
287 | 287 |
user.save ? user : nil |
288 | 288 |
end |
289 | 289 |
end |
290 | ||
291 |
private |
|
292 |
|
|
293 |
# Removes the email body of text after the truncation configurations. |
|
294 |
def cleanup_body(body) |
|
295 |
if Setting.emails_truncate.present? |
|
296 |
truncate_tokens = Setting.emails_truncate.split("\n") |
|
297 | ||
298 |
truncate_tokens.each do |token| |
|
299 |
next if token.blank? |
|
300 |
|
|
301 |
regex = Regexp.new(token + '.*', Regexp::IGNORECASE | Regexp::MULTILINE) |
|
302 |
body.gsub!(regex, '') |
|
303 |
end |
|
304 |
end |
|
305 |
|
|
306 |
return body.chomp |
|
307 |
end |
|
290 | 308 |
end |
app/views/settings/_mail_handler.rhtml | ||
---|---|---|
1 | 1 |
<% form_tag({:action => 'edit', :tab => 'mail_handler'}) do %> |
2 | 2 | |
3 | 3 |
<div class="box tabular settings"> |
4 |
<p> |
|
5 |
<label><%= l(:setting_emails_truncate) %></label> |
|
6 |
<%= text_area_tag 'settings[emails_truncate]', Setting.emails_truncate, :rows => 5, :cols => 80 %> |
|
7 |
<br /><em><%= l(:text_line_separated) %></em> |
|
8 |
</p> |
|
9 |
</div> |
|
10 | ||
11 |
<div class="box tabular settings"> |
|
4 | 12 |
<p><label><%= l(:setting_mail_handler_api_enabled) %></label> |
5 | 13 |
<%= hidden_field_tag 'settings[mail_handler_api_enabled]', 0 %> |
6 | 14 |
<%= check_box_tag 'settings[mail_handler_api_enabled]', 1, Setting.mail_handler_api_enabled?, |
... | ... | |
16 | 24 |
</div> |
17 | 25 | |
18 | 26 |
<%= submit_tag l(:button_save) %> |
27 | ||
19 | 28 |
<% end %> |
config/locales/en.yml | ||
---|---|---|
323 | 323 |
setting_issue_done_ratio_issue_field: Use the issue field |
324 | 324 |
setting_issue_done_ratio_issue_status: Use the issue status |
325 | 325 |
setting_start_of_week: Start calendars on |
326 |
setting_emails_truncate: "Truncate emails after the following strings" |
|
326 | 327 |
|
327 | 328 |
permission_add_project: Create project |
328 | 329 |
permission_edit_project: Edit project |
... | ... | |
801 | 802 |
text_tracker_no_workflow: No workflow defined for this tracker |
802 | 803 |
text_unallowed_characters: Unallowed characters |
803 | 804 |
text_comma_separated: Multiple values allowed (comma separated). |
805 |
text_line_separated: Multiple values allowed (line separated). |
|
804 | 806 |
text_issues_ref_in_commit_messages: Referencing and fixing issues in commit messages |
805 | 807 |
text_issue_added: "Issue {{id}} has been reported by {{author}}." |
806 | 808 |
text_issue_updated: "Issue {{id}} has been updated by {{author}}." |
config/settings.yml | ||
---|---|---|
174 | 174 |
default: '' |
175 | 175 |
start_of_week: |
176 | 176 |
default: '' |
177 |
emails_truncate: |
|
178 |
default: '' |
test/fixtures/mail_handler/ticket_on_given_project.eml | ||
---|---|---|
30 | 30 |
malesuada fames ac turpis egestas. Quisque sit amet libero. In hac habitasse |
31 | 31 |
platea dictumst. |
32 | 32 |
|
33 |
--- |
|
34 |
|
|
35 |
This paragraph is after the delimiter so it shouldn't appear. |
|
36 |
|
|
33 | 37 |
Nulla et nunc. Duis pede. Donec et ipsum. Nam ut dui tincidunt neque |
34 | 38 |
sollicitudin iaculis. Duis vitae dolor. Vestibulum eget massa. Sed lorem. |
35 | 39 |
Nullam volutpat cursus erat. Cras felis dolor, lacinia quis, rutrum et, |
test/fixtures/mail_handler/ticket_reply.eml | ||
---|---|---|
25 | 25 |
Content-Transfer-Encoding: quoted-printable |
26 | 26 |
|
27 | 27 |
This is reply |
28 |
|
|
29 |
--- |
|
30 |
|
|
31 |
This is my sig. |
|
32 |
|
|
28 | 33 |
------=_NextPart_000_0067_01C8D3CE.711F9CC0 |
29 | 34 |
Content-Type: text/html; |
30 | 35 |
charset="utf-8" |
test/unit/mail_handler_test.rb | ||
---|---|---|
204 | 204 |
assert issue.is_a?(Issue) |
205 | 205 |
assert_equal 1, ActionMailer::Base.deliveries.size |
206 | 206 |
end |
207 | ||
208 |
context "truncate emails based on the Setting" do |
|
209 |
context "with no setting" do |
|
210 |
setup do |
|
211 |
Setting.emails_truncate = '' |
|
212 |
end |
|
213 | ||
214 |
should "add the entire email into the issue" do |
|
215 |
issue = submit_email('ticket_on_given_project.eml') |
|
216 | ||
217 |
assert_issue_created(issue) |
|
218 |
assert issue.description.include?('---') |
|
219 |
assert issue.description.include?('This paragraph is after the delimiter') |
|
220 |
end |
|
221 |
end |
|
222 | ||
223 |
context "with a single string" do |
|
224 |
setup do |
|
225 |
Setting.emails_truncate = '---' |
|
226 |
end |
|
227 | ||
228 |
should "truncate the email at the delimiter for the issue" do |
|
229 |
issue = submit_email('ticket_on_given_project.eml') |
|
230 | ||
231 |
assert_issue_created(issue) |
|
232 |
assert !issue.description.include?('---') |
|
233 |
assert !issue.description.include?('This paragraph is after the delimiter') |
|
234 |
assert issue.description.include?('platea dictumst.') |
|
235 |
end |
|
236 | ||
237 |
end |
|
238 | ||
239 |
context "with multiple strings" do |
|
240 |
setup do |
|
241 |
Setting.emails_truncate = "---\nBREAK\nid" |
|
242 |
end |
|
243 | ||
244 |
should "truncate the email at the first delimiter found (id)" do |
|
245 |
issue = submit_email('ticket_on_given_project.eml') |
|
246 | ||
247 |
assert_issue_created(issue) |
|
248 |
assert !issue.description.include?('---') |
|
249 |
assert !issue.description.include?('This paragraph is after the delimiter') |
|
250 |
assert !issue.description.include?('platea dictumst.') |
|
251 |
assert issue.description.include?('blandit eleifend augue. Nulla facilisi. Duis ') |
|
252 |
end |
|
253 | ||
254 |
end |
|
255 | ||
256 |
|
|
257 |
end |
|
207 | 258 |
|
259 |
def test_add_issue_with_strip_delimiter_should_not_have_text_after_delimiter |
|
260 |
with_settings :emails_truncate => '---' do |
|
261 |
# This email contains: 'Project: onlinestore' |
|
262 |
issue = submit_email('ticket_on_given_project.eml') |
|
263 |
assert issue.is_a?(Issue) |
|
264 |
assert !issue.new_record? |
|
265 |
issue.reload |
|
266 |
assert_equal 'New ticket on a given project', issue.subject |
|
267 |
assert !issue.description.include?("This paragraph is after the delimiter so it shouldn't appear."), "Delimited text was not stripped" |
|
268 |
assert !issue.description.include?("---"), "Delimiter was not stripped" |
|
269 |
end |
|
270 |
end |
|
271 | ||
272 |
def test_add_issue_with_strip_delimiter_should_not_have_delimiter |
|
273 |
with_settings :emails_truncate => '---' do |
|
274 |
# This email contains: 'Project: onlinestore' |
|
275 |
issue = submit_email('ticket_on_given_project.eml') |
|
276 |
assert issue.is_a?(Issue) |
|
277 |
assert !issue.new_record? |
|
278 |
issue.reload |
|
279 |
assert_equal 'New ticket on a given project', issue.subject |
|
280 |
assert !issue.description.include?("---"), "Delimiter was not stripped" |
|
281 |
end |
|
282 |
end |
|
283 | ||
208 | 284 |
def test_add_issue_note |
209 | 285 |
journal = submit_email('ticket_reply.eml') |
210 | 286 |
assert journal.is_a?(Journal) |
... | ... | |
259 | 335 |
assert_equal 'This is a html-only email.', issue.description |
260 | 336 |
end |
261 | 337 | |
338 |
def test_add_issue_note_with_strip_delimiter_should_not_have_text_after_delimiter |
|
339 |
with_settings :emails_truncate => '---' do |
|
340 |
journal = submit_email('ticket_reply.eml') |
|
341 |
assert journal.is_a?(Journal) |
|
342 |
assert !journal.notes.include?("This is my sig"), "Delimited text was not stripped" |
|
343 |
end |
|
344 |
end |
|
345 |
|
|
346 |
def test_add_issue_note_with_strip_delimiter_should_not_have_delimiter |
|
347 |
with_settings :emails_truncate => '---' do |
|
348 |
journal = submit_email('ticket_reply.eml') |
|
349 |
assert journal.is_a?(Journal) |
|
350 |
assert !journal.notes.include?("---"), "Delimiter was not stripped" |
|
351 |
end |
|
352 |
end |
|
353 |
|
|
262 | 354 |
private |
263 | 355 |
|
264 | 356 |
def submit_email(filename, options={}) |
265 | 357 |
raw = IO.read(File.join(FIXTURES_PATH, filename)) |
266 | 358 |
MailHandler.receive(raw, options) |
267 | 359 |
end |
360 | ||
361 |
def assert_issue_created(issue) |
|
362 |
assert issue.is_a?(Issue) |
|
363 |
assert !issue.new_record? |
|
364 |
issue.reload |
|
365 |
end |
|
268 | 366 |
end |