Rails 4, Mailer preview, preview attached images - ruby-on-rails

I have problem with rails 4.1.6 mailer preview.
I want to see attached images in preview mode, but it doesn't work. I think it's incorrect
There is my code:
Mailer file
class AppMailer < ActionMailer::Base
default from: "robot#mysite.com"
# AppMailer.test_mail.deliver
def test_mail
attachments.inline['rails.png'] = File.read(Rails.root.join('app', 'assets', 'images', 'rails.png'))
mail(
to: 'my-email#gmail.com',
subject: "test letter",
template_path: "mailers",
template_name: "test"
)
end
end
Preview file
class MailerPreview < ActionMailer::Preview
def app_mailer
AppMailer.test_mail
end
end
Template file
%p Hello, World!
%p= image_tag attachments['rails.png'].url
When I go to
/rails/mailers/mailer/app_mailer
I see preview page, but images doesn't work. There is resulted html code
<p>Hello, World!</p>
<p><img src="cid:544d1354a8aa0_fda8082dbf8258ca#admins-air.mail"></p>
So. I think, I should to find a way to get path/to/file instead CID in preview mode
(When I sent letter to my mailbox - letter looks fine)
What I am doing wrong in preview mode?

For Rails >= 4.2 to preview images you should create initializer:
# config/initializer/preview_interceptors.rb
ActionMailer::Base.register_preview_interceptor(ActionMailer::InlinePreviewInterceptor)

Until the Rails mail previewer is enhanced to support attachment viewing, I'm using this (hack-ish) enhancement to Mail::Part#url to embed the attachment data into the URL itself. This lets see my inline images in the previewer (assuming I have INLINE_MAIL_PART_URLS turned on) while preserving the original behaviour in the appropriate settings.
module InlineMailPartUrls
def url
if ENV["INLINE_MAIL_PART_URLS"] == "true"
"data:#{mime_type};base64,#{Base64.encode64(body.decoded)}"
else
super
end
end
end
class Mail::Part
prepend InlineMailPartUrls
end
I save this code to config/initializers/inline_mail_part_urls.
https://gist.github.com/softcraft-development/2ed70a2a4d6e2c829fac

You're not doing anything wrong; it's a shortcoming in the way the Rails Mail Previewer is designed.
The Rails Mailer code, reasonably, generates URLs for attachments that reference mail "parts" in a multipart email. The "cid" in the URL for your <img> tag refers to the "content ID" of the particular part/attachment. This is how URLs within an email work.
However, the previewer controller isn't rendering in the context of an email client: it's a standard web browser. There is no "cid" URL protocol scheme, and no multi-part email to reference (it's all just standard HTML documents). Rails::MailersController currently isn't smart enough to realize this, and just renders the email as-is.
To make this work, it'd have to detect all references to cid: URLs and replace them with regular http: URLs back to itself, then return the content for the various attachments.
There's an open issue on GitHub/rails to do this, but as of yet it's not complete.

Related

Can't access root_url method when building a PDF file offline using WickedPdf

We use WickedPdf, a wkhtmltopdf wrapper, for generating most of our PDF files on-screen as we can use the same .haml file for both HTML and PDF versions.
I'd like to generate some of the PDF files to be stored for future use. We already do something like this in a mailer to generate and attach a PDF. This works fine...
# mailer
pdf = WickedPdf.new.pdf_from_string(render_to_string('account/customer_invoices/show_pdf.html', :layout => 'pdf'))
attachments["invoice.pdf"] = pdf
But when I try the same trick from within a model instead of a mailer, I get the following error...
ActionView::Template::Error:
undefined method `root_url' for #<#<Class:0x007fad308a8538>:0x007fad308a83d0>
The standard answer I've seen for accessing the root_url from within a model is to add the following, but it doesn't work as I'm actually accessing it from the view, not the model.
include Rails.application.routes.url_helpers
If I understand correctly you call root_url in the view.
Try changing that to
Rails.application.routes.url_helpers.root_url

Is it possible to generate PDF from rails and automatically attach to a mailer?

Same as question, I would like to generate a PDF document with some content from database. And automatically attach it to an email to users. Do you think gem like WickedPDF or Prawn can achieve that?
Edit
I have a Heroku Setup, does it affect my ability to use WickedPDF and WKpdf2html?
You can generate pdf from html also and attach that to your mail using PDFKit
here are codes inside your controller
html=render_to_string(:partial=> "confirmation")
pdfkit_instance = PDFKit.new(html)
UserMailer.registration_confirmation(#user,pdfkit_instance.to_pdf).deliver
in your mailer class use the following
def registration_confirmation(user,pdf_file)
attachments["#{user.company_name}_#{Time.now.strftime("%m%d_%Y")}.pdf"] =pdf_file
mail(:to => "#{user.name} <#{user.email}>", :subject => "yoursubject "
end
For installing PDFKit you can go through the blog http://blog.andolasoft.com/2012/10/usage-of-pdfkit-with-rails-328-and-ruby.html
Yes, they can generate pdf files in your tmp dir (or wherever you like) and then you can use these files as attachments.

sending emails using templates in Mandrill

I've read through the docs and still am unclear on how to actually use these templates in mandrill.
Currently I have a rails app with the standard Rails mailers (located in: App > views > welcome_mailer > welcome_email.html.erb) being sent through the Mandrill SMTP setup. This is working fine.
Now, I have a template in Mandrill ready to go, now what?
How do I actually use this template, do I need to adjust the code on my app to make a different call, or do I need to do something on the mandrill dashboard to tell it to use the new template instead of the rails version being sent now.
How do I actually use this template?
Thank you in advance.
You can use mandrill_mailer gem, inherit your mailer from MandrillMailer::TemplateMailer and then send it as usual InvitationMailer.invite(invitation).deliver.
Without any gems :
To use mandrill template you first need to create one in your mandrill account and then in your mailer add a correct header which tells the name of the template. Then mandrill will by magic automatically call that template.
Example:
# app/mailers
class CardMailer < ActionMailer::Base
default from: "admin#domain.ch"
def welcome(card)
mail to: card.responsable.email,
from: "\"Andrey\" <admin#domain.ch>",
subject: 'Welcome in my website'
headers['X-MC-MergeVars'] = "{\"TYPE\":\"#{card.card_type.name}\"}" # variables
headers['X-MC-Template'] = "welcome" # template
headers['X-MC-AutoText'] = 1 # generate text version
headers['X-MC-InlineCSS'] = "true" # inline css
end
end
In my case, it uses my "welcome" template. Just use the name of your mandrill template.
As you can see, there are many other headers available. See the full-list here.
Note : even if you don't use rails template any more, you still need one in your view.

Rails 3 ActionMailer corrupts attachments

I'm using Rails 3.2.13 and have been following along with the ActionMailer guide (http://guides.rubyonrails.org/action_mailer_basics.html#sending-emails-with-attachments), but I'm having difficulty with sending email attachments.
After execution the email sends properly but the attachment is always corrupted. In particular, I see the rendered email and the correct filename for the attachment but as a 1KB file that can't be opened. I've seen similar issues around stack overflow and elsewhere (e.g. Rails 3: Sending Mail with Attachment - corrupted file after first send and Rails 3.0.7 ActionMailer attachment issue), but none of the solutions offered have been able to help. I've tried two different transports (Gmail SMTP and Sendgrid), several file types (png, pdf, etc.), and both inline and normal attachments, but always with the same effect.
Here's the code for the mailer:
class UserMailer < ActionMailer::Base
# A hash of default values for email messages
default from: "me#mysite.com"
def welcome_email(user)
#user = user
#url = "http://localhost:3000"
attachments['logo_email.png'] = File.read("public/img/logo_email.png")
mail(:to => user.email, :subject => "Welcome")
end
end
Where I'm calling it in my controller it looks like this (I'm using delayed_job here, but the attachment is corrupted even without it):
UserMailer.delay.welcome_email(#user)
Apparently, this is a Windows-only behavior in how the file is (not) read in. You need to specify both the "r" (read only) and "b" (binary) for Ruby in Windows to read it correctly.
http://ruby-doc.org/core-1.9.3/IO.html
See the following related issue
Read contents of a local file into a variable in Rails
Try the following:
attachments['logo_email.png'] = File.read("public/img/logo_email.png", mode: "rb")

How do I preview emails in Rails?

This might be a dumb question but when I'm putting together an HTML email in Rails, is there a particularly easy built-in way to preview the template it in the browser or do I need to write some sort of custom controller that pulls it in as its view?
Action Mailer now has a built in way of previewing emails in Rails 4.1. For example, check this out:
# located in test/mailers/previews/notifier_mailer_preview.rb
class NotifierPreview < ActionMailer::Preview
# Accessible from http://localhost:3000/rails/mailers/notifier/welcome
def welcome
Notifier.welcome(User.first)
end
end
Daniel's answer is a good start, but if your email templates contain any dynamic data, it won't work. E.g. suppose your email is an order receipt and within it you print out #order.total_price - using the previous method the #order variable will be nil.
Here's a little recipe I use:
First, since this email preview functionality is definitely for internal use only, I set up some generic routes in the admin namespace:
#routes.rb
MySite::Application.routes.draw do
namespace :admin do
match 'mailer(/:action(/:id(.:format)))' => 'mailer#:action'
end
end
Next, I create the controller. In this controller, I create one method per email template. Since most emails contain dynamic data, we need to populate whatever member variables the template expects.
This could be done with fixtures, but I typically prefer to just grab some pseudo-random real data. Remember - this is NOT a unit test - this is purely a development aid. It doesn't need to produce the same result every single time - in fact - it's probably better if it doesn't!
#app/controllers/admin/mailer_controller.rb
class Admin::MailerController < Admin::ApplicationController
def preview_welcome()
#user = User.last
render :file => 'mailer/welcome.html.erb', :layout => 'mailer'
end
end
Note that when we render the template, we use layout=>:mailer. This embeds the body of your email inside the HTML email layout that you've created instead of inside your typical web application layout (e.g. application.html.erb).
And that's pretty much it. Now I can visit http://example.com/admin/mailer/preview_welcome to preview change to my welcome email template.
37Signals also has their own mail testing gem called mail_view. It's pretty fantastic.
The easiest setup I've seen is MailCatcher. Setup took 2 minutes, and it works for new mailers out of the box.
I use email_preview. Give it a try.
Easiest solution in rails 6: just remember one url:
http://localhost:3000/rails/mailers
I'm surprised no one's mentioned letter_opener. It's a gem that will render and open emails as a browser page whenever an email is delivered in dev.
I recently wrote a gem named Maily to preview, edit (template file) and deliver the application emails via a browser. It also provides a friendly way to hook data, a flexible authorization system and a minimalist UI.
I have planned to add new features in the near future, like:
Multiple hooks per email
Parametrize emails via UI (arguments of mailer method)
Play with translations keys (list, highlight, ...)
I hope it can help you.
rails generates a mail preview if you use rails g mailer CustomMailer.
You will get a file CustomMailerPreview inside spec/mailers/previews folder.
Here you can write your method that will call the mailer and it'll generate a preview.
For ex -
class CustomMailerPreview < ActionMailer::Preview
def contact_us_mail_preview
CustomMailer.my_mail(user: User.first)
end
end
Preview all emails at http://localhost:3000/rails/mailers/custom_mailer
You can use Rails Email Preview
REP is a rails engine to preview and test send emails, with I18n support, easy premailer integration, and optional CMS editing with comfortable_mexican_sofa.
There is no way to preview it directly out of the Mailer.
But as you wrote, you can write a controller, which looks something like this.
class EmailPreviewsControllers < ActionController::Base
def show
render "#{params[:mailer]}_mailer/#{params[:method]}"
end
end
But I think, that's not the best way to test emails, if they look correctly.
Rails Email Preview helps us to quickly view the email in web browser in development mode.
1) Add “gem ‘rails_email_preview’, ‘~> 0.2.29’ “ to gem file and bundle install.
2) Run “rails g rails_email_preview:install” this creates initializer in config folder and add routes.
3) Run “rails g rails_email_preview:update_previews” this crates mailer_previews folder in app directory.
Generator will add a stub to each of your emails, then u populate the stub with mock data.
Ex:
class UserMailerPreview
def invitation
UserMailer.invitation mock_user(‘Alice’), mock_user(‘Bob’)
end
def welcome
UserMailer.welcome mock_user
end
private
def mock_user(name = ‘Bill Gates’)
fake_id User.new(name: name, email: “user#{rand 100}#test.com”)
end
def fake_id(obj)
obj.define_singleton_method(:id) { 123 + rand(100) }
obj
end
end
4) Parameters in search query will be available as an instance variable to preview class. Ex: if we have a URL like
“/emails/user_mailer_preview-welcome?user_id=1” #user_id is defined in welcome method of UserMailerPreview it helps us to send mail to specific user.
class UserMailerPreview
def welcome
user = #user_id ? User.find(#user_id) : mock_user
UserMailer.welcome(user)
end
end
5) To access REP url’s like this
rails_email_preview.rep_root_url
rails_email_preview.rep_emails_url
rails_email_preview.rep_email_url(‘user_mailer-welcome’)
6) We can send emails via REP, this will use environment mailer settings. Uncomment this line in the initializer to disable sending mail in test environment.
config.enable_send_email = false
Source : RailsCarma Blog : Previewing Emails in Rails Applications With the Mail_View Gem
I prefer mails_viewer gem. This gem is quite useful as it save the HTML template into tmp folder.

Resources