CSS Images in Email With Rails 3 - ruby-on-rails

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.

Related

ActionMailer email preview is not the same as one user receives in production

I am using Rails 6 and ActionMailer to send an email when the user joins. It is also probably very important to mention that I use API only application and I host it on Heroku.
I have an .html.erb view setup and it looks like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
</head>
<body>
<div style="width: 100%;display: flex;flex-direction: column;align-items: center;padding: 15px;background-color: white;font-family: 'Helvetica';color: #2c3e50">
<h1>Welcome to company!</h1>
<div style="height: 1px;background-color: dimgrey;width: 50%;margin-top: 10px; margin-bottom: 20px;"></div>
<h4 style="margin:0">Want to learn more about our platform?</h4>
<p style="margin-bottom: 30px">Check out this quick video guide.</p>
<h4 style="margin:0">Join our Discord server</h4>
<h4 style="margin:0">Follow us on social media</h4>
<p style="margin-bottom: 30px">Some icons with social media</p>
<%= link_to "Create Password", #url, style: "color: white;padding:10px;border-radius:10px;margin-bottom:20px" %>
</div>
</body>
</html>
Now, this code in preview would give this kind of view
And that is good, that is what I want.
But when user receieves it in production it looks something like this
Am I using something that I shouldn't? How do I make it look like it looks like in the preview.
Here are some more files that might interest you:
Stuff I added to production.rb regarding the mailer:
config.action_controller.asset_host = 'https://myapponheroku'
config.action_mailer.asset_host = config.action_controller.asset_host
config.action_mailer.perform_caching = false
config.action_mailer.delivery_method = :smtp
host = 'myapponheroki'
config.action_mailer.default_url_options = { host: host }
# smtp settings here
Do I have to add anything else here to make it work?
My mailer is located in app/views/user_mailer
Please ask if you need any more code snippets or information.
What email client was used for that screenshot? Could just be an email client issue and flex. Maybe to debug, you could change your view to use just a regular table and see if that fixes the formatting.
Also, I have used these in the past with success. They usually are handled by most major email clients pretty well.
https://litmus.com/community/templates

Rails not rendering public/index.html file; blank page in browser

I have a problem with my Rails + React app when I deploy it to Heroku. The React client is inside a client/ directory of the Rails app. Due to using react-router, the Rails server needs to know to render the index.html from the React build. When I deploy the client on Heroku, a script copies the content from client/build/. to the Rails app's public/ dir.
Now here is the problem: when my route detects a path like example.com/about it tries to render public/index.html. Here is the method:
def fallback_index_html
render file: "public/index.html"
end
However, the contents from this file are not sent to the browser. I get a blank page. I have added a puts "hit fallback_index_html" in the method and confirmed that this method is being hit. I have also opened the file in puts each line to confirm the file has the required html (this is what appeared in the logs from that puts and what SHOULD be sent to the browser):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<link rel="manifest" href="/manifest.json">
<link rel="shortcut icon" href="/favicon.ico">
<title>Simple Bubble</title>
<link href="/static/css/main.65027555.css" rel="stylesheet">
</head>
<body><noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="text/javascript" src="/static/js/main.21a8553c.js"></script>
</body>
</html>
The most recent fix I tried was going into config/environments/production.rb and changing config.public_file_server.enabled to true. This did not help.
I'm using Rails API, so my ApplicationController inherits from ActionController::API instead of ActionController::Base.
From Rails API docs it says:
The default API Controller stack includes all renderers, which means you can use render :json and brothers freely in your controllers. Keep in mind that templates are not going to be rendered, so you need to ensure your controller is calling either render or redirect_to in all actions, otherwise it will return 204 No Content.
Thus Rails API only cannot render HTML! The following allowed me to render the html without including everything from ActionController::Base.
class ApplicationController < ActionController::API
include ActionController::MimeResponds
def fallback_index_html
respond_to do |format|
format.html { render body: Rails.root.join('public/index.html').read }
end
end
end
The reason I am including ActionController::MimeResponds is to have access to the respond_to method.
My Rails application now renders index.html from my public directory when a subdirectory is hit and my React client / react-router takes over from there.

How to use TCPServer in Ruby on Rails?

I am using Ruby on Rails on Cloud9 IDE
$ ruby -v
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]
$ rails -v
Rails 4.2.4
I have to transmit data between server and GPS device. I put on device and did code like below.
My_Controller
class DashboardController < ApplicationController
before_action :authenticate_user!
def index
require 'socket'
server = TCPServer.new ("127.0.0.1",8000)
loop do
Thread.start(server.accept) do |client|
client.puts "Hello !"
client.puts "Time is #{Time.now}"
client.close
end
end
#bookings = Booking.where(user: current_user).joins(:customer, :driver, :car)
#customers = Customer.where(user: current_user)
end
end` ****
when i ran this i got
<html>
<head>
<meta charset='utf-8'>
<title>Error 502 - Bad Gateway</title>
<link rel="stylesheet" type="text/css" href="https://cdn.c9.io/errors/style.css" />
<style type="text/css">
.error_content {
background: rgba(255, 255, 255, 0.23);
padding: 10px;
width: 641px;
margin: 25px 0;
display: none;
}
#error-msg {
display: block;
}
</style>
</head>
<body class="errorUnknown light">
<div id="wrapper">
<h1>Error 502 - Bad Gateway</h1>
<div class="error_content" id="error-msg">
<p>Please click here to try again, if the issue persists please contact support</p>
</div>
Status Page |
Support |
Dashboard |
Home
</div>
</body>
</html>
Kindly, help me how to solve this problem..
Thanks in advance.
You go into an endless loop in the action. The request from the reverse proxy to your rails server times out. The reverse proxy sends an error message (502) to the browser.

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!

How to send mail in HTML format in Rails 2.3.11?

I've only found solutions that work in Rails 3, so far. How can I force emails sent with ActionMailer to be formatted as HTML, rather than plaintext?
/app/models/franklin.rb (the mailer)
class Franklin < ActionMailer::Base
def activation(user)
recipients user.email
from "activation#rit.oncampusapp.net"
content_type = "text/html"
subject "OnCampus # RIT Registration"
body :user => user
end
end
/app/views/franklin/activation.html.erb
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
</head>
<body>
Hi <%= #user.full_name %>,
This is your activation email for OnCampus # RIT. All you have to do is click the link below, and you'll be able to log in.
<%= link_to "Activate My Account!", "http://rit.oncampusapp.net/admin/activate?key=#{#user.activation_key}"%>
We hope to see you soon! :D
-- The OnCampus Team
</body>
</html>
Have you tried setting in the activation action content_type "text/html" instead of content_type = "text/html"
Just paste this in your notifier/mailer model method - this will solve your problem
content_type "text/html"

Resources