How to display images in a Rails mailer email? - ruby-on-rails

I have an app that sends an email when a user signs up. I've got the emails to send successfully but the images are not getting sent. I'm hosting on Heroku and using Sendgrid to send emails.
Here's my signup_email.html.erb view:
<tr>
<td style="padding: 20px 0; text-align: center">
<img
src="<%= Rails.application.config.action_mailer.default_url_options[:host] %>assets/email/logo.png"
width="200"
height="50"
alt="logo"
border="0"
style="height: auto; background: #dddddd; font-family: sans-serif; font-size: 15px; line-height: 15px; color: #555555;"
/>
</td>
</tr>
This is not an issue where the browser hides images by default because I've tested on various browsers and tried to show images. The image path in the email shows: heroku-root/assets/email/logo.png
Here's the signup user_mailer.rb:
class UserMailer < ActionMailer::Base
default from: "App <welcome#app.com>"
def signup_email(user)
#user = user
mail(:to => user.email, :subject => "Thank you for joining!")
end
end
I've precompiled assets with rake assets:precompile so the logo is stored in public/assets/email directory.
The production.rb setting:
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = false
# Generate digests for assets URLs
config.assets.digest = true
config.action_mailer.default_url_options = { :host => ENV['DEFAULT_MAILER_HOST'] }
config.action_mailer.delivery_method = :smtp
config.serve_static_assets = true
I've tried using the inline attachment method from the Rails documentation but emails weren't getting sent at all.
class UserMailer < ActionMailer::Base
default from: "App <welcome#app.com>"
def signup_email(user)
#user = user
attachments.inline["logo.png"] = File.read("#{Rails.root}app/assets/email/logo.png")
mail(:to => user.email, :subject => "Thank you for joining!")
end
end
In the view, I call the logo like this:
<%= image_tag(attachments['logo.png'].url) %>
With the method above the emails don't get sent at all and I get the error that it couldn't find the file logo.

You should just be able to use the regular old <%= image_tag("logo.png") %> helpers just like you would use in your views. You may need to set your asset_host so that it includes a full URL for the images in the emails since they aren't displayed in the browser under your domain.
# I believe these should do the trick:
config.action_controller.asset_host = 'http://localhost:3000'
config.action_mailer.asset_host = config.action_controller.asset_host

Related

Rails link_to full url

I'm trying to get a link_to to generate the full url link of a survey in my sample survey app. The way I'm doing it is this in my mailer view:
<p>The survey is located <%= link_to("here", survey_url(#survey)) %>.</p>
The link that's generated is http://localhost:3000/surveys/2.
However, when the same code is run in production, the link that's generated is http://example.herokuapp.com/surveys/2 when it should be http://example.com/surveys/2.
The config files:
development.rb:
config.action_mailer.default_url_options = { :host => 'localhost:3000'}
production.rb:
config.action_mailer.default_url_options = { :host => 'http://example.com'}
Any idea why heroku is adding .herokuapp to the end of the host url/what I can do to generate the url as http://example.com/surveys/2?

Passing params to iframe in rails not working

I'm a rails noob so I know I'm probably totally missing something here. I'm trying to pass a url to an iframe through my products controller.
This is my setup.
Products Controller
def open_url
#url = params[:url]
end
index.html.erb
<%= link_to "More Info", open_path(url: "http://www.ceratoboutique.com" + product.destination_url) %>
open_url.html.erb
<iframe src= "<%= #url %>" style="border: 0; position:fixed; top:0; left:0; right:0; bottom:0; width:100%; height:100%" />
routes.rb
get '/open' => 'products#open_url', via: 'get'
I,ve checked out these two questions
Rails 4 - Passing Params via link_to?
Opening a Link in a New Window within an iFrame
but i'm still lost, the url is passed to the browser but it does not seem to pass to the #url variable in my controller.
Debug Dump
!ruby/hash:ActionController::Parameters
url: http://www.ceratoboutique.com/collections/tops/products/combo-blouse
controller: products
action: open_url
I decided to stick to rails conventions and make it a restful link. I still do not know why the original implementations did not work, but it worked using the show method in the controller.
Controller
def show
#url = Product.find(params[:id])
end
index.html.erb
<%= link_to "More Info", product_path(product) %>
show.html.erb
<iframe src= "<%= "http://www.ceratoboutique.com" + #product.destination_url %>" style="border: 0; position:fixed; top:0; left:0; right:0; bottom:0; width:100%; height:100%" />
****Edit Added More Info for including I-Frame ****
I ran into a lot of problems trying to get my iframe to work in chrome and on Heroku so I combined the process if anyone needs it ever. I first deployed to Heroku with full SSL running on my site, then realized that iframe did not work in chrome for sites that were not running SSL. I redeployed configuring force SSL to false, but heroku still forced my app to SSL. I realized that config.force_ssl = true enables Strict Transport Security header(HSTS) with max-age of one year, so I had to expire HSTS using the following.
Expire SSL in application controller
class ApplicationController < ActionController::Base
before_filter :expire_hsts
def expire_hsts
response.headers["Strict-Transport-Security"] = 'max-age=0'
end
In Production.rb
config.force_ssl = false
Then to make sure the x-frame showed in chrome browsers I added the following.
enable x-frame in chrome
config.action_dispatch.default_headers = { 'X-Frame-Options' => 'ALLOWALL' }
You may want to run SSL on some of your pages, which can be done rather easily via the SSL enforcer gem linked below.
ssl-enforcer gem
https://github.com/tobmatth/rack-ssl-enforcer
Best of luck on navigating the ugliness that is the iFrame!

Is it possible to suppress fingerprinting for image assets used in emails (Rails 3.1)?

In my mailer views, I include images as follows:
<%= image_tag "header.png" , :alt => "" %>
Which results in the following HTML in the generated email
<img alt="" src="http://example.com/assets/header-247cf573710c22ec2c14eafefeb4c7c1.png">
However, in the case of images used in emails, I would prefer NOT to include the fingerprinting. If I change the header image slightly, I would prefer that when a user drags up an old email, they see the new image, rather then getting an error because the old, fingerprinted URL is no longer valid.
In Rails 3.1.1 both versions of assets are available, and you can use the :digest => false option to make Rails give you the plain path to the asset
<image alt="" src="<%= asset_path 'header.png', :digest => false %>" />
You can set this digest for the entire project in your development or production environment config file by adding the below:
# Generate digests for assets URLs
config.assets.digest = false

CSS Images in Email With Rails 3

I'm trying to send out an email with Rails 3 and Action Mailer. The email goes out fine, but I want it to be HTML formatted with some basic styling which includes background images. I understand that the images might get blocked until the user allows them to be shown, but I still think it would be best to link to the images on my web server.
The email template called registration_confirmation.html.erb starts out like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Untitled Document</title>
<style type="text/css">
body {
background: url(/images/mainbg_repeat.jpg) top repeat-x #cfcfcf;
margin: 0px 0px 0px 0px;
font-family: Arial, Helvetica, sans-serif;
font-size: 12px;
color: #565656;
}
What is the best way to get the url link for the background image to have the full host included so that the background will show up in the email?
In response to my other answer, #Kevin wrote:
Thanks for the answer, I did think of doing something like that but I
don't think it's possible with the way I have it setup. The mailer
call is happening in a after_create call in a model rather than in a
controller so I don't think I have access to the request object as you
mentioned (or am I mistaken). I do have this in my mailer initializer:
ActionMailer::Base.default_url_options[:host] = "localhost:3000" Can I
somehow use that hos parameter in my mailer to make it work?
The answer is yes. All rails url-construction helpers should use these defualt_url_options. In addition to setting the :host, you should also force it to use absolute urls by settings this option:
ActionMailer::Base.default_url_options[:only_path] = false
Also, set the asset host like this:
config.action_mailer.asset_host = 'http://localhost:3000'
Then just use the image_path helper instead of hand-writing the url, like this:
<style type="text/css">
body {
background: url(<%= image_path('mainbg_repeat.jpg') %>) top repeat-x #cfcfcf;
}
</style>
NOTE: Setting default_url_options directly like that is deprecated. Here's the new way to do it:
config.action_mailer.default_url_options = {
:host => 'localhost:3000',
:only_path => false
}
Pass your request host as a parameter to the mailer method, and then pass it from the method to the view. So, for example, your mailer method might look like this (example lifted from rails docs and modified here):
class UserMailer < ActionMailer::Base
default :from => "notifications#example.com"
def registration_confirmation(user, host)
#user = user
#host = host
mail(:to => user.email, :subject => "Welcome to My Awesome Site")
end
end
You would call it like this:
def some_action
UserMailer.registration_confirmation(#user, request.host).deliver
end
Then in your view, you would just use the #host:
<style type="text/css">
body {
background: url(http://<%= #host %>/images/mainbg_repeat.jpg) top repeat-x #cfcfcf;
}
</style>
This is all assuming the image server is the same as the server running the request. If the image server is hosted elsewhere, you have to output a constant here. You could put something like this in lib/settings.rb:
module Settings
IMAGE_HOST = 'superawesome.images.com'
end
Then in your view, you'd just output the constant there, like this:
<style type="text/css">
body {
background: url(http://<%= Settings::IMAGE_HOST %>/images/mainbg_repeat.jpg) top repeat-x #cfcfcf;
}
</style>
If you do not care about performance, the roadie gem can handle urls in the stylesheets for you.

Rails 3.1 Assets in ActionMailer with image_tag

Assets are working fine for my web views, but for some reason my Mailer doesn't use the asset pipeline. I am trying to use an image_tag in my mailer view:
=link_to image_tag("logo.png")
However, that renders as
<img alt="logo" src="http://mydomain.com/assets/logo.png">
instead of
<img alt="logo" src="http://mydomain.com/assets/logo-xxxxxxxxx...png">
Am I missing something here?
My settings are:
config.action_mailer.default_url_options = { :host => config.domain }
config.action_mailer.asset_host = "http://" + config.domain
Thank you!
Try to put in your mail template the following instead of the link_to ( the link_to makes no sense because you link here your image to nothing, and I don't see the a href as output in your html) :
= asset_path("logo.png")
also put in your specific environment file :
config.action_mailer.default :content_type => "text/html"
Like this you are sure that you always use HTML as default content type. If u are using images in the mails it is better to put it as html.

Resources