Repository: rails/rails
File: actionmailer/lib/action_mailer/message_delivery.rb (Ruby)

Code before:
# frozen_string_literal: true

require "delegate"

module ActionMailer
  class << self
    # Enqueue many emails at once to be delivered through Active Job.
    # When the individual job runs, it will send the email using +deliver_now+.
    def deliver_all_later(*deliveries, **options)
      _deliver_all_later("deliver_now", *deliveries, **options)
    end

    # Enqueue many emails at once to be delivered through Active Job.
    # When the individual job runs, it will send the email using +deliver_now!+.
    # That means that the message will be sent bypassing checking +perform_deliveries+
    # and +raise_delivery_errors+, so use with caution.
    def deliver_all_later!(*deliveries, **options)
      _deliver_all_later("deliver_now!", *deliveries, **options)
    end

    private
      def _deliver_all_later(delivery_method, *deliveries, **options)
        deliveries.flatten!

        jobs = deliveries.map do |delivery|
          mailer_class = delivery.mailer_class
          delivery_job = mailer_class.delivery_job

          delivery_job
            .new(mailer_class.name, delivery.action.to_s, delivery_method, params: delivery.params, args: delivery.args)
            .set(options)
        end

        ActiveJob.perform_all_later(jobs)
      end
  end

  # = Action Mailer \MessageDelivery
  #
  # The +ActionMailer::MessageDelivery+ class is used by
  # ActionMailer::Base when creating a new mailer.
  # <tt>MessageDelivery</tt> is a wrapper (+Delegator+ subclass) around a lazy
  # created +Mail::Message+. You can get direct access to the
  # +Mail::Message+, deliver the email or schedule the email to be sent
  # through Active Job.
  #
  #   Notifier.welcome(User.first)               # an ActionMailer::MessageDelivery object
  #   Notifier.welcome(User.first).deliver_now   # sends the email

Review comment (suggestion):
after some research, i think what happens is the following:
- `flatten!` tries to call `respond_to?` on each element
- `respond_to?` gets delegated to `__getobj__`
- which calls `@mail_message ||= processed_mailer.message`
- and `processed_mailer` triggers the inline processing of the mailer

Code after:
# frozen_string_literal: true

require "delegate"

module ActionMailer
  class << self
    # Enqueue many emails at once to be delivered through Active Job.
    # When the individual job runs, it will send the email using +deliver_now+.
    def deliver_all_later(*deliveries, **options)
      _deliver_all_later("deliver_now", *deliveries, **options)
    end

    # Enqueue many emails at once to be delivered through Active Job.
    # When the individual job runs, it will send the email using +deliver_now!+.
    # That means that the message will be sent bypassing checking +perform_deliveries+
    # and +raise_delivery_errors+, so use with caution.
    def deliver_all_later!(*deliveries, **options)
      _deliver_all_later("deliver_now!", *deliveries, **options)
    end

    private
      def _deliver_all_later(delivery_method, *deliveries, **options)
        deliveries = deliveries.first if deliveries.first.is_a?(Array)

        jobs = deliveries.map do |delivery|
          mailer_class = delivery.mailer_class
          delivery_job = mailer_class.delivery_job

          delivery_job
            .new(mailer_class.name, delivery.action.to_s, delivery_method, params: delivery.params, args: delivery.args)
            .set(options)
        end

        ActiveJob.perform_all_later(jobs)
      end
  end

  # = Action Mailer \MessageDelivery
  #
  # The +ActionMailer::MessageDelivery+ class is used by
  # ActionMailer::Base when creating a new mailer.
  # <tt>MessageDelivery</tt> is a wrapper (+Delegator+ subclass) around a lazy
  # created +Mail::Message+. You can get direct access to the
  # +Mail::Message+, deliver the email or schedule the email to be sent
  # through Active Job.
  #
  #   Notifier.welcome(User.first)               # an ActionMailer::MessageDelivery object
  #   Notifier.welcome(User.first).deliver_now   # sends the email