Project

General

Profile

Actions

Defect #44300

open

Mailer.with_deliveries(false) does not prevent emails from being sent

Added by Vincent Robert 24 days ago. Updated 4 days ago.

Status:
New
Priority:
Normal
Assignee:
-
Category:
Email notifications
Resolution:
Affected version:

Description

While investigating #44299 on a development instance where email delivery is disabled, and with the "Send email notifications during the project copy" box left unchecked, I noticed that the emails were pushed to the job queue nevertheless.

Mailer.with_deliveries only flips ActionMailer::Base.perform_deliveries, and that flag is read when the mail is delivered. Since Redmine sends everything with deliver_later, the Mailer::DeliveryJob runs after the block has already restored the flag or, with a queue backend, in a process where it was never false at all. So the mails are enqueued and sent.

The only caller may be the "Send email notifications during the project copy" checkbox of ProjectsController#copy. Unchecking it does not prevent anything: copying a project, I get one Mailer::DeliveryJob enqueued per copied issue, and the worker delivers them.

Proposed patch: skip the enqueuing itself.

class DeliveryJob < ActionMailer::MailDeliveryJob
  before_enqueue {throw :abort unless ActionMailer::Base.perform_deliveries}

This makes with_deliveries(false) effective whatever the queue adapter, and it also stops piling up delivery jobs that are discarded at delivery time on instances where email is not configured (perform_deliveries defaults to false in config/application.rb).


Files

Actions #1

Updated by Go MAEDA 21 days ago

The attached patch could not be applied with git apply or patch, so I am attaching a regenerated one with the same content.

Setting the target version to 6.1.4.

Actions #2

Updated by Holger Just 20 days ago

Note that Mailer.with_deliveries is generally not thread-safe (since it sets the global ActionMailer::Base.perform_deliveries attribute). As such, when running Redmine with a multi-threaded server, using this method may cause mails to be lost in other threads.

Accordingly, I believe Mailer.with_deliveries should rather set a thread-local variable in stead of setting the global ActionMailer::Base.perform_deliveries flag. This new variable can then be checked in the before_enqueue hook in addition to the global ActionMailer::Base.perform_deliveries flag (which should not change dynamically). This new variable could e.g. be stored in RequestStore.store[:mailer_perform_deliveries].

Actions #3

Updated by Go MAEDA 4 days ago

  • Target version changed from 6.1.4 to Candidate for next minor release
Actions

Also available in: Atom PDF