Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uniform interface for getting email body? #1600

Open
sdhull opened this issue Jan 13, 2024 · 1 comment
Open

Uniform interface for getting email body? #1600

sdhull opened this issue Jan 13, 2024 · 1 comment

Comments

@sdhull
Copy link

sdhull commented Jan 13, 2024

Apologies if a better venue for this question would be Stackoverflow or similar—feel free to send me away.

We're on mail 2.8.0.1 & Rails 6.0.6

We have a situation at work where a mailer (actionmailer) has multiple actions which all render the same template, eg:

  def mail_email_template(template, mail_options)
    process_email_template(template)   # sets ivars @liquid_subject and @liquid_body

    mail(mail_options.merge(subject: @liquid_subject)) do |format|
      # Only format html because we use Premailer to take care of text format
      format.html { render "email_template" }   # renders @liquid_body
    end
  end

We also have an after_action that parses the email and adjusts styling based on customer preferences, eg:

  def apply_branding_button_colors
    settings = @user.email_template_branding_settings
    return unless settings
    styler = Email::HtmlStyler.new(mail.decode_body, settings)
    mail.body = styler.html
  end

However, when writing specs to troubleshoot a bug, I found that when the email had an ics attachment, mail.decode_body returned nil, but mail.html_part.to_s returned the email body. So I thought I'd switch to that to be safer, but in a different mailer action being tested (no attachment), mail.html_part.to_s returned an empty string, while mail.body.to_s returned the html body!

(mail in this context is the ActionMailer::Base#mail method which returns an instance of Mail::Message.)

So finally I ended up with email_body = mail.body.to_s.presence || mail.html_part.to_s as a best effort but I wanted to ask:

Am I missing something? Is there a uniform interface to reliably get a string representation of the email body?

@timoschilling
Copy link

The reason for that is that a Mail::Message with one part is different to a Mail::Message with multiple part. Having a html part and an attachment means it's multipart. You solution email_body = mail.body.to_s.presence || mail.html_part.to_s is right, maybe just use decoded and not to_s, it's the same but more explicit.

What you can do is that you always add a text part to your mail, so it will always be multipart, no matter an attachment exists or not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants