I'm having an issue with my Rails application--I'm having trouble sending both a HTML and plaintext version of my email. NOTE: the email does send; however, it's not styled correctly... there is a link to the results below.
It's recommended everywhere that if you want to send HTML you should also send a plain text alternative too. Unfortunately, it appears that I'm doing something wrong, as my application does not allow me to send both HTML and plaintext, without the HTML looking very weird.
here is my mailer model:
class ProjectMembersMailer < ActionMailer::Base
def membership_invitation(membership)
#project = membership.project
#user = membership.user
mail( :subject => %(Invitation to join project #{#project.business_name}),
:from => %("App" <no-reply#appname.com>),
:to => #user.account.email,
:content_type => "text/html" ) do |format|
format.html
format.text
end
end
end
My project_member_mailer views have two files: membership_invitation.html.haml and membership_invitation.text.erb (please note that the second file is using .erb, but even if I convert it to a .haml extension for consistency I get the same error)
Here is picture of that the output looks like when I attempt to send it using the code above. Please note that I removed some of the text.
Basically it looks like it's sending the text version above the html version of the file. Is there an alternate way to sending both plaintext and HTML emails without this happening? Or am I missing something--like, should these emails not be sent simultaneously? Any help would be greatly appreciated. Thank you so much for your time and help!
According to the Action Mailer Rails Guide you do not need to use the "format" method, and should remove the "content-type" parameter too.
mail will automatically detect that there are both html and text templates and will automatically create the email as multipart/alternative
Just try:
mail( :subject => %(Invitation to join project #{#project.business_name}),
:from => %("App" <no-reply#appname.com>),
:to => #user.account.email)
I had the exact same problem, and it can be fixed with just one simple thing. Place format.text over format.html
def membership_invitation(membership)
#project = membership.project
#user = membership.user
mail( :subject => %(Invitation to join project #{#project.business_name}),
:from => %("App" <no-reply#appname.com>),
:to => #user.account.email,
:content_type => "text/html" ) do |format|
format.text
format.html
end
end
Related
I am trying to embed an <a> link within the text of an email I'm sending through mailgun. What is the correct syntax?
RestClient.post "https://api:#{ENV['MAILGUN_SECRET']}"\
"#api.mailgun.net/v3/#{ENV['MAILGUN_DOMAIN']}/messages",
:from => "Mailgun <mailgun##{ENV['MAILGUN_DOMAIN']}>",
:to => "#{#lead.email}",
:subject => "Test",
:text => "Here is the message, here(http://www.foo.com) is the link"
I dont think that you can send a "text" email with HTML you have to pick one
I like to send all my emails a HTML
This is how my mailer looks like:
class SomeMailer < ActionMailer::Base
def email_method(post_id, lead_id)
#post = Post.find(post_id)
#lead = Lead.find(lead_id)
mail(
:from => "Email Sender<info#example.com>",
:to => #lead.email,
:reply_to => 'Email Sender<info#example.com>',
:subject => "Test"
)
end
end
now this is the fun part. Create a folder called SomeMailer in app/views so you end up with app/views/some_mailer
now create a file in that directory called email_method.html.erb that contains your html like:
Here is the message, here( foo.com ) is the link
I hope that this helps
I'm using devise to authenticate users. I want them to be able to look at the page without being logged in, but if they wish to download the csv data, they must be logged in. Here's how i've set up the csv download part
respond_to do |format|
format.html{
render :layout => 'indices_show'
}
format.csv{
export_to_csv(idxp)
}
end
and here is the export_to_csv function
def export_to_csv(idxf)
cash = params[:cash]
#title = get_title(#index)
if (cash =='1')
navs = #index.navsc.from(idxf)
r = #index.returnsc.from(idxf)
else
navs = #index.navs.from(idxf)
r = #index.returns.from(idxf)
end
dates = #index.dates.from(idxf)
csv_string = CSV.generate do |csv|
csv << [#title]
csv << ["Date", "Return", "NAV"]
dates.each_with_index do |d, i|
csv << [d,r[i],navs[i]]
end
end
send_data csv_string,
:type => 'text/csv; charset=iso-8859-1; header=present',
:disposition => "attachment; filename ="+ #title +".csv"
end
At the top of this controller, I have,
before_action :authenticate_user!, only:[:export_to_csv]
but it doesn't do anything as the user is still able to download the data without being logged in. I've found a semi work around by doing this,
respond_to do |format|
format.html{
render :layout => 'indices_show'
}
format.csv{
if (user_signed_in?)
export_to_csv(idxp)
else
redirect_to new_user_session_path
end
}
end
The problem here is that once the user logs in, it redirects to the homepage. Is there a way such that when a user clicks the download button, they are forced to sign in, and upon signing in they are redirected back to that page and the data is downloaded? Thanks
The before_action isn't working because export_to_csv is not the method being called as the action - that would normally be the method your routing maps to - i.e. probably the method with your respond_to code in it. Of course, you can split the method into two separate ones and have one for html and one for csv and then have the before_action set up for the csv one. That's perhaps not so nice, especially if it's just two different viewing formats for the same data. If they're not very similar views, perhaps it would be appropriate to separate them. It depends on your app.
Another option is to use your second approach but modify it. Before the redirect_to new_user_session_path, try inserting a call to store_location_for(:user, request.request_uri), or perhaps pass request.original_url. See here for the doc/code:
https://github.com/plataformatec/devise/blob/master/lib/devise/controllers/store_location.rb#L26
You can see that if the stored location is present, it's used in preference to the root path:
https://github.com/plataformatec/devise/blob/master/lib/devise/controllers/helpers.rb#L143
Note that store_location_for seems to be a recent addition to devise. I'm actually using 3.1.x and it doesn't seem to be defined - you'd have to set the user_return_to session variable directly because that's what is checked during signin in 3.1.x.
As Tim said, export_to_csv is not the method being filtered by before_action. It is firing actions based on the controller action methods at the top, and since you are trying to limit access lower down, it has already let the user through.
I'm not sure what the action name is that you are using, so I am going to assume it's show.
You can supply a conditional to your before_action line that may limit what you were hoping for.
before_action :authenticate_user!, only: [:show], if: proc { request.csv? }
I am sending email using the Mail gem. Here's my code:
require 'mail'
require 'net/smtp'
Mail.defaults do
delivery_method :smtp, { :address => "smtp.arrakis.es",
:port => 587,
:domain => 'webmail.arrakis.com',
:user_name => 'myname#domain.com',
:password => 'pass',
:authentication => 'plain',
:enable_starttls_auto => true }
end
Mail::ContentTypeField.new("text/html") #this doesnt work
msgstr= File.read('text2.txt')
list.each do |entity|
begin
Mail.deliver do
from 'myname#domain.com'
to "#{entity}"
subject 'a good subject'
body msgstr
end
rescue => e
end
end
end
I don't know how to set up the content type, so that I can format my email as html for example. Though I actually just wish to be able to define bold text like my email client does: bold text. Does anybody know which content-type I need to specify in order to achieve this, and how to implement it with mail?
Just a note, the code above works fine for sending plain text email.
From the documentation
Writing and sending a multipart/alternative (html and text) email
Mail makes some basic assumptions and makes doing the common thing as
simple as possible.... (asking a lot from a mail library)
mail = Mail.deliver do
to 'nicolas#test.lindsaar.net.au'
from 'Mikel Lindsaar <mikel#test.lindsaar.net.au>'
subject 'First multipart email sent with Mail'
text_part do
body 'This is plain text'
end
html_part do
content_type 'text/html; charset=UTF-8'
body '<h1>This is HTML</h1>'
end
end
#Simone Carletti's answer is essentially correct, but I was struggling with this and didn't want a plain text portion to my email and a separate HTML portion. If you just want the entire email to be HTML, something like this will work:
mail = Mail.deliver do
to 'nicolas#test.lindsaar.net.au'
from 'Mikel Lindsaar <mikel#test.lindsaar.net.au>'
subject 'First email sent with Mail'
content_type 'text/html; charset=UTF-8'
body '<h1>This is HTML</h1>'
end
I may have missed it, I didn't see anything in the Mail gem documentation describing how to do that, which I would think would be more common than making a multipart message. The documentation only seems to cover plain text messages and multipart messages.
Following the instructions here: http://www.padrinorb.com/guides/padrino-mailer
I have the delivery method added on the app.rb file:
class OscarAffiliate < Padrino::Application
register Padrino::Rendering
register Padrino::Mailer
register Padrino::Helpers
enable :sessions
set :delivery_method, :smtp => {
:address => "email-smtp.us-east-1.amazonaws.com",
:port => 587,
:user_name => 'AKIAIQ5YXCWFKFXFFRZA',
:password => 'AqMNMFecKSYR/TRu8kJgocysAL5SmIUsu2i8u/KAfeF/',
:authentication => :plain,
:enable_starttls_auto => true
}
But via the generation through Padrino and the Mailer generation, I do not have the recommended "sessions" controller in which this should belong:
post :create do
email(:from => "tony#reyes.com", :to => "john#smith.com", :subject => "Welcome!", :body=>"Body")
end
Am I missing something?
I have the form for a basic data collection at an office and just need an email to be sent to 5 recipients with all the form fields in the message body.
Thanks
It appears to me that you're trying to email a person (or multiple people) after a form is submitted. Possibly you're saving information from that form to a database. I think that you are a little confused on how to use Padrino mailers. Allow me to clarify: In order to send an email, using Padrino's mailer functionality, with a full body of content, you must create a Padrino Mailer (I've outlined this below). Then you must configure that mailer so that you may pass variables to it when you call it. Those variables can then be used in the view, which your mailer renders into the email body before sending the email. This is one way of accomplishing what it appears you are trying to do and it is probably the most straight-forward. You can find more information about this procedd under "Mailer Usage" on the help page you provided in your question. I've outlined an example usage, tailored to what I believe your needs are, below.
Instructions
I threw together this code sample and tested it against my AWS account; it should work in production.
In your app/app.rb file, include the following (you have already done so):
set :delivery_method, :smtp => {
:address => 'email-smtp.us-east-1.amazonaws.com',
:port => 587,
:user_name => 'SMTP_KEY_HERE',
:password => 'SMTP_SECRET_HERE',
:authentication => :plain,
:enable_starttls_auto => true
}
Then create a Mailer in app/mailers/affiliate.rb:
# Defines the mailer
DemoPadrinoMailer.mailer :affiliate do
# Action in the mailer that sends the email. The "do" part passes the data you included in the call from your controller to your mailer.
email :send_email do |name, email|
# The from address coinciding with the registered/authorized from address used on SES
from 'your-aws-sender-email#yoursite.com'
# Send the email to this person
to 'recipient-email#yoursite.com'
# Subject of the email
subject 'Affiliate email'
# This passes the data you passed to the mailer into the view
locals :name => name, :email => email
# This is the view to use to redner the email, found at app/views/mailers/affiliate/send_email.erb
render 'affiliate/send_email'
end
end
The Affiliate Mailer's send_email view should be located in app/view/mailers/affiliate/send_email.erb and look like this:
Name: <%= name %>
Email: <%= email %>
Finally, you can call your mailer from inside whatever method (and controller) you're accepting form submissions from. Be sure to replace the strings with actual form data. In this example, I used a POSTed create action, which did not save any data (thus the strings with fake data):
post :create do
# Deliver the email, pass the data in after everything else; here I pass in strings instead of something that was being saved to the database
deliver(:affiliate , :send_email, "John Doe", "john.doe#example.com")
end
I sincerely hope that this helps you in your journey with Padrino, and welcome to the Stack Overflow community!
Sincerely,
Robert Klubenspies
Environment: Rails 2.3.11 w/ MySQL 5.0
Here is my slideshow model:
class Slideshow < ActiveRecord::Base
validates_presence_of :title, :description
end
Using the console, if I run:
Slideshow.new(:title => "", :description => "").save!
it returns:
Validation failed: Title can't be blank, Description can't be blank
which is correct.
However, when I submit a blank HTML form to the create action:
def create
#slideshow = Slideshow.new(params[:slideshow])
if #slideshow.save
redirect_to(...)
else
render(:action => 'new')
end
end
only the :title field fails validation. I've verified that what is being passed in the params is:
Parameters: {"commit"=>"Submit", "slideshow"=>{"title"=>"", "description"=>""}, "action"=>"create", "controller"=>"manage/slideshows"}
Why is the description field NOT failing validation here?
Thanks.
Try this :
validates_length_of :description
for more details ... http://apidock.com/rails/ActiveRecord/Validations/ClassMethods/validates_length_of
when You submit a blank HTML form to the create action, it should go in else of create action and your form should have this line:
<%= f.error_messages %>
to show you the errors.
This turned out to be a syntax issue. It was occurring on a testing server where there were two models with very similar names (one an updated version of the other). During testing I used the wrong one. My apologies for any unnecessary head-scratching :)