What is the right way to embed an image into email using Rails?
-
http://stackoverflow.com/questions/7520936/css-images-in-email-with-rails-3 and http://stackoverflow.com/questions/472450/how-do-i-create-email-with-css-and-images-from-rails will give more information. – Mika Aug 17 '12 at 22:43
7 Answers
I combined the answer from Oksana with a custom helper approach and got the following to work quite nicely.
app/helpers/email_helper.rb
module EmailHelper
def email_image_tag(image, **options)
attachments[image] = File.read(Rails.root.join("app/assets/images/#{image}"))
image_tag attachments[image].url, **options
end
end
app/mailers/base_mailer.rb
class BaseMailer < ActionMailer::Base
helper(EmailHelper)
end
app/mailers/my_mailer.rb
class MyMailer < BaseMailer
def send_my_mail(email)
mail to: email, subject: "My Subject"
end
end
Then for example where I want to attach the company logo in my email layout file I would use
app/views/layouts/email.html.erb
<%= email_image_tag("company_logo.png") %>
Note the **options makes the tag more extensible but it will only work in ruby >=2. To make this work in ruby < 2 you will have to use the older way of handling key word options.
Update 03/25/2022: Rails 6 no longer supports add_template_helper
, and now replaces it with helper
, as explained by this answer that links to the commit that did so.

- 3,928
- 4
- 33
- 58

- 4,328
- 2
- 31
- 35
-
2what's interesting is that images with dashes in the file name will turn into underscores when using this method – Pavan Katepalli May 12 '15 at 16:42
-
1Don't think it is anything I have written there. Could be a result of URL.encode in the rails image_tag helper but I haven't experienced this before. – Tyrone Wilson May 12 '15 at 18:20
-
Hey tdubs it seems like this works, but on mobile in gmail it'll attach all the images and not show them inline. I think you have to specify the mime_type and encoding – Pavan Katepalli May 13 '15 at 02:16
-
11Make sure you use `attachments.inline[]=` in your helper or mailer for an inline image. – Matt Jan 13 '17 at 06:51
-
4In rails 4.2, If you are embedding image inline and want to see them in your `ActionMailer::Preview` you need to add a initializer with the following: `ActionMailer::Base.register_preview_interceptor(ActionMailer::InlinePreviewInterceptor)`. Source: http://stackoverflow.com/a/35537303/4553162 – mahi-man Mar 06 '17 at 22:33
-
6@Matt should be more up-voted and the answer should be edited. The line `attachment[image]` needs to be `attachment.inline[image]` in `app/helpers/email_helper.rb` for the image to be rendered as inline. (Rails 5) – unmultimedio Jun 23 '17 at 21:07
-
@unmultimedio why not suggest an edit with your changes and I'm sure the community will approve if it makes for a better answer to the question. Otherwise PM your thoughts and I'll consider adding it in :) – Tyrone Wilson Jun 24 '17 at 06:52
-
-
@buncis, there's an answer further down about that, which you can check out. https://stackoverflow.com/a/35147532/1212371 – Tyrone Wilson May 02 '23 at 08:38
-
@buncis you not need to setup asset_host because this snippet gonna encode ur picture into a base64 image therefore you not need to host it [Mail will automatically Base64 encode an attachment.](https://guides.rubyonrails.org/action_mailer_basics.html#adding-attachments) – buncis May 02 '23 at 15:23
RAILS 5
In your mail method add your inline attachment pointing to your image:
class ConfirmationMailer < ActionMailer::Base
def confirmation_email
attachments.inline["logo.png"] = File.read("#{Rails.root}/app/assets/images/logo.png")
mail(to: email, subject: 'test subject')
end
end
Then in your mail html view an image_tag
with the attachment url:
<%= image_tag(attachments['logo.png'].url) %>

- 4,503
- 1
- 27
- 41
Adding onto Oksana and tdubs' answers
The module tdubs wrote works on desktop, but for the mobile gmail client, the images appeared as attachments. To fix this, do this for the
app/helpers/email_helper.rb
module EmailHelper
def email_image_tag(image, **options)
attachments[image] = {
:data => File.read(Rails.root.join("app/assets/images/emails/#{image}")),
:mime_type => "image/png",
:encoding => "base64"
}
image_tag attachments[image].url, **options
end
end
For the rest, follow tdubs's answer.

- 2,372
- 4
- 29
- 52
-
5Careful with your code. You're specifying a specific mime type and encoding and chances are not all of your images will match both of those – Tom Prats May 01 '16 at 02:36
-
5
-
2@NateFlink, it could be that you aren't using the correct mime type? I think the answer is an example so you would probably need to get the mime type from the image variable so instead of `mime_type: "image/png"` I would use `mime_type: "image/#{image.split('.').last}"` – Tyrone Wilson Jan 13 '17 at 06:54
-
3@NateFlink I also get that error but if I remove the `:encoding` then it works fine. – Matt Feb 01 '17 at 17:44
-
1I get the following error when implementing your fix: invalid byte sequence in UTF-8 Extracted source (around line #4): def email_image_tag(image, **options) byebug attachments[image] = { :data => File.read(Rails.root.join("app/assets/images/emails/# {image}")), :mime_type => "image/png", :encoding => "base64" – Constantine May 04 '17 at 18:03
-
`mime_type = system("file", "--mime-type", "--brief", full_path).strip` and `mime_encoding = system("file", "--mime-encoding", "--brief", "full_path").strip` – Meredith Mar 26 '22 at 03:09
After a lot of research i have found very cleaner way to embed image in email.
Just add following line in production.rb
and development.rb
config.action_mailer.asset_host = 'YOUR HOST URL'
In your view embed image by using following code.
<%= image_tag('My Web Site Logo.png') %>
Note: Make sure to update YOUR HOST URL and My Web Site Logo.png in above code.
For basic details of usage of Action Mailer, please refer to ActionMailer::Base.

- 16,329
- 10
- 59
- 65
-
5Be careful doing this. You will need to host that image at that url forever or people will no longer be able to view the email correctly. Much better to embed with base64 encoded images – Joe Woodward Sep 12 '16 at 04:50
-
-
2This is the opposite of embedding an image in an email. This is loading a remote image in an email. – Barry Oct 07 '19 at 09:18
Copy pasted from here
Inline Attachments
You can also specify that a file should be displayed inline with other HTML. This is useful if you want to display a corporate logo or a photo.
class Notifier < ApplicationMailer
def welcome(recipient)
attachments.inline['photo.png'] = File.read('path/to/photo.png')
mail(to: recipient, subject: "Here is what we look like")
end
end
And then to reference the image in the view, you create a welcome.html.erb file and make a call to image_tag passing in the attachment you want to display and then call url on the attachment to get the relative content id path for the image source:
<h1>Please Don't Cringe</h1>
<%= image_tag attachments['photo.png'].url -%>
As we are using Action View's image_tag method, you can pass in any other options you want:
<h1>Please Don't Cringe</h1>
<%= image_tag attachments['photo.png'].url, alt: 'Our Photo', class: 'photo' -%>

- 281
- 3
- 10
In rails 6, if you use the solution of @Tyron, you'll need to replace add_template_helper
with helper
in the BaseMailer. So, it becomes:
class BaseMailer < ActionMailer::Base
helper(EmailHelper)
end

- 53
- 6
I don't know much about rails, but I've worked on projects in C# that create emails and then insert them in a users inbox via the Google APIs. To create the email, I had to generate the email string from scratch. If you enable multipart for the email, then the image bytes will be included in a multipart section using base64 encoding.
You may want to check out the TMail and RubyMail packages to see if they support these actions for you.

- 3,585
- 5
- 31
- 41