ruby-on-railsemailactionmaileraction-mailbox

Is it possible to forward the mail object in Action Mailer


We're currently letting users email each other without seeing each other's actual email addresses (double blind) by letting them send emails to username@parse.example.com which works great.

class ForwardsMailbox < ApplicationMailbox
  before_processing :ensure_users
 
  def process
    content = mail.multipart? ? mail.parts.first.body.decoded : mail.decoded
    UserMailer.with(sender: sender, recipient: recipient, subject: mail.subject, content: content).forward_email.deliver_later
  end
 
  private 
  def sender
    @sender ||= User.find_by(email: mail.from.first)
  end
  def recipient
    @recipient ||= User.find_by(username: mail.to.first.split('@').first)
  end
  def ensure_users
    bounce_with UserMailer.invalid_user(inbound_email) if sender.nil? or recipient.nil?
  end
end

Is it possible to forward the whole mail object instead of extracting its contents, checking if it is multipart etc?


Solution

  • Try to give this a shot. Reuse the mail object in your process method and directly deliver the message yourself. You'll need to reach into ActionMailer to get your delivery methods configured correctly, but I believe it'll work.

    def process
      mail.to = sender.email
      mail.from = recipient...
      ActionMailer::Base.wrap_delivery_behavior(mail) # this sets delivery to use what we specified in our rails config.
      mail.deliver # This delivers our email to the smtp server / API
    end
    

    How this works:

    Behind the scenes Mailers are just calling deliver on a Mail object to send emails. You can go peruse through ActionMailer::MessageDelivery if you'd like to see that in action. We're just using that functionality directly here.

    I'd recommend staying away from using Mailers in this instance because copying over all the fields from your original mail object to the mailer's mail object is going to require a lot of trial and error.

    One thing to note: the headers remain unchanged when the message is re-delivered, so things like Message-ID will still be the same (which may or may not be a problem, just something to consider).

    Last, if you're concerned at all about deliver being a blocking call to an API/SMTP server like I was, worry not! It looks like ActionMailbox already ensures that the process method runs via ActiveJob, so you shouldn't have to worry about an SMTP/API request taking a while and blocking a web request (see ActionMailbox guides).