pony doesn't send email to gmail address? - ruby

I've got an entry form that asks for a persons name and email address. I save that email address to the session so I can access it after the form has been submitted. Then I use Pony to send a thank you/notification email to the person who submitted the form. However, while it sends without issue to a MobileMe address, it won't to a gmail address. The line I'm using to send is:
Pony.mail(:to => "#{#email}", :from => 'from#email.com', :subject => "Thanks for entering!",
:body => "Thank you!")
The #email variable is defined in the handler and gets the value from the session.
Any ideas?

Here's the helper method I use that uses Pony to send email using sendmail when in development on my Mac or via sendgrid on Heroku when in production. This works reliably and all of my test emails get sent to my various gmail addresses.
Possibly your problem is that your from address is invalid and Google is flagging that as spam. Also I note you are not setting the Content-Type header, which is typically text/html in my case.
def send_email(a_to_address, a_from_address , a_subject, a_type, a_message)
begin
case settings.environment
when :development # assumed to be on your local machine
Pony.mail :to => a_to_address, :via =>:sendmail,
:from => a_from_address, :subject => a_subject,
:headers => { 'Content-Type' => a_type }, :body => a_message
when :production # assumed to be Heroku
Pony.mail :to => a_to_address, :from => a_from_address, :subject => a_subject,
:headers => { 'Content-Type' => a_type }, :body => a_message, :via => :smtp,
:via_options => {
:address => 'smtp.sendgrid.net',
:port => 25,
:authentication => :plain,
:user_name => ENV['SENDGRID_USERNAME'],
:password => ENV['SENDGRID_PASSWORD'],
:domain => ENV['SENDGRID_DOMAIN'] }
when :test
# don't send any email but log a message instead.
logger.debug "TESTING: Email would now be sent to #{to} from #{from} with subject #{subject}."
end
rescue StandardError => error
logger.error "Error sending email: #{error.message}"
end
end

Related

Sending email from a Sinatra web app using the Heroku SendGrid add-on

I'm trying to set up SendGrid to send email via a simple web form in a Sinatra app.
I have enabled the SendGrid add-on in Heroku, and checked the environment vars via heroku config; both SENDGRID_USERNAME and SENDGRID_PASSWORD are set.
I have also created a Sender Identity on the SendGrid website, which has been verified.
When I submit the form I get:
"550 Unauthenticated senders not allowed"
When I click the "Twilio SendGrid" add-on link on the Heroku dashboard, I'm forwarded to a page on the SendGrid website, which says:
Access to sendgrid.com was denied. You don't have authorisation to view this page.
HTTP ERROR 403
Methods & settings for sending email are below:
post '/contact' do
configure_options
Pony.mail(
:from => [params[:name], "<", params[:email], ">"].join,
:to => 'hi#mydomain.com',
:subject => ["Opt-in via /contact: ", params[:name]].join,
:body => [params[:name], params[:email]].join(": ")
)
redirect '/'
end
def configure_options
Pony.options = {
:via => :smtp,
:via_options => {
:address => 'smtp.sendgrid.net',
:port => '587',
:domain => 'heroku.com',
:user_name => ENV['SENDGRID_USERNAME'],
:password => ENV['SENDGRID_PASSWORD'],
:authentication => :plain,
:enable_starttls_auto => true
}
}
end
Thanks!
SendGrid does not receive any mail so any requests you are making to SendGrid would be to send mail.
This means that you first need to set up an entity you control, and which can act as a sender even if the recipient is yourself.
You do this by creating a Sender Identity. This is the procedure when sending mail via SMTP:
https://sendgrid.com/docs/for-developers/sending-email/integrating-with-the-smtp-api/
Next, you need to crate an API key. SendGrid no longer supports basic authentication, so this code will not work:
:user_name => ENV['SENDGRID_USERNAME'],
:password => ENV['SENDGRID_PASSWORD'],
Instead, you need to use:
:user_name => 'apikey',
:password => 'your-api-key',
where 'apikey' is the literal string 'apikey', and 'your-api-key' is the 69-character API key generated by SendGrid (and shown only once).
Then, in your POST method:
post '/contact' do
configure_options
Pony.mail(
# the :from field below is the email address
# associated with your SendGrid Sender Identity:
:from => 'yourname#email.com',
:to => 'someother#email.com',
:subject => ["Opt-in via /contact: ", params[:name]].join,
:body => [params[:name], params[:email]].join(": ")
)
redirect '/'
end

Mail sent twice or more instead of once using rails 3.2

I am working with rails 3.2 and ruby 2.1.2p95. Through my application, sending 1000+ of emails. I want to send few email from smtp and few emails from sendgrid. So I have configured like below in Notifier.rb file
after_filter :set_delivery_options, :except => [:method1]
def set_delivery_options
message.delivery_method.settings.merge!(
:address => "smtp.gmail.com",
:port => 587,
:domain => "xxxxxxxx",
:user_name => "xxxxxxxxxxxxx",
:password => "xxxxxxxxxxxxx",
:authentication => "plain",
:enable_starttls_auto => true
)
end
My method is like below:
def customer_mailing(customer)
mail(
:to => customer.user.email,
:subject => "Testing",
#:bcc => EMAIL_BCC,
:content_type => "text/html"
)
set_headers
end
Whenever I call the above method, the mail is sending twice or more in some times on production server.

For Gmail with ruby's mail gem, what do I specify as my host name for :domain?

I'm trying to send a simple email using my Gmail account through ruby's mail gem but the email is never sent nor received. I followed the steps from a similar question but I wasn't sure what to put under the domain field. I believe this may be my issue but I'm not sure.
my code:
require 'mail'
options = { :address => "smtp.gmail.com",
:port => 587,
:domain => 'your.host.name',
:user_name => 'REMOVED',
:password => 'REMOVED',
:authentication => 'plain',
:enable_starttls_auto => true }
Mail.defaults do
delivery_method :smtp, options
end
mail = Mail.new do
from 'REMOVED'
to 'REMOVED'
subject 'This is a test email'
body 'test'
end
I don't see where you are calling the deliver method to send the email. Based on the documentation, there's a couple of ways to do that:
Mail.deliver do
from 'me#test.lindsaar.net'
to 'you#test.lindsaar.net'
...
end
or
mail = Mail.new do
from 'me#test.lindsaar.net'
to 'you#test.lindsaar.net'
...
end
mail.deliver!

Ruby gem 'Mail' setting up with SMTP

So I am testing out the Ruby gem 'Mail'. Below is my code. According to the sysadmin, there is no authentication necessary to send out by SMTP and the server is allowed to send by SMTP. If that makes sense.
I have used the 'net/smtp' which worked fine but I can't seem to get this 'Mail' gem to work for me. It's not giving me any errors so I'm not sure what the issue is. I am a complete ruby noob at this.
#testing out mailer
require 'mail'
Mail.defaults do
delivery_method :smtp, {
:address => '10.18.34.18',
:port => '25',
:user_name => 'anonymous',
:password => 'anonymous',
:authentication => 'plain',
:enable_starttls_auto => true}
end
mail = Mail.new do
from 'server#company.com'
to 'cvu#company.com'
subject 'This is a test email'
body File.read('test.txt')
end
mail.to_s
Try calling mail.deliver!, calling to_s just returns you a string representation of the object.
Alternatively you can call deliver with a block instead of calling new, e.g.
mail = Mail.deliver do
from 'server#company.com'
to 'cvu#company.com'
subject 'This is a test email'
body File.read('test.txt')
end
In addition to what struthersneil stated, I had to remove the authentication like so:
require 'mail'
Mail.defaults do
delivery_method :smtp, {
:address => '10.18.34.18',
:port => '25',
:enable_starttls_auto => true}
end

2 forms on same page, Sending using Pony in Sinatra, same email address

i am using Pony.mail to send mail within Sinatra, what i have now is two forms, one that only sends an email address for subscription to newsletter and the second form is a contact form, both are going through the same action.
What I am trying to achieve is if the subscription field is completed then only send those params or if the contact form is completed and sent then send those params
Heres what i come up with so far, but getting undefined method nil
post '/' do
require 'pony'
Pony.mail(
:from => params[:name] || params[:subscribe],
:to => 'myemailaddress',
:subject => params[:name] + " has contacted you via the Website" || params[:subscribe] + " has subscribed to the newsletter",
:body => params[:email] + params[:comment],
:via => :smtp,
:via_options => {
:address => 'smtp.gmail.com',
:port => '587',
:enable_starttls_auto => true,
:user_name => 'myemailaddress',
:password => 'mypassword',
:authentication => :plain,
:domain => "localhost.localdomain"
})
redirect '/success'
end
is this even possible or would each form have to be dealt with individually?
Thanks
There are several stages I'd go through to refactor this code.
1. Extract the things that are changing (and make them more Rubyish)
post '/' do
require 'pony'
from = params[:name] || params[:subscribe]
subject = "#{params[:name]} has contacted you via the Website" ||
"#{params[:subscribe]} has subscribed to the newsletter"
body = "#{params[:email]}#{params[:comment]}"
Pony.mail(
:from => from,
:to => 'myemailaddress',
:subject => subject,
:body => body,
:via => :smtp,
:via_options => {
:address => 'smtp.gmail.com',
:port => '587',
:enable_starttls_auto => true,
:user_name => 'myemailaddress',
:password => 'mypassword',
:authentication => :plain,
:domain => "localhost.localdomain"
})
redirect '/success'
end
2. Make clear your intentions
in this case, that there are two branches through the code.
post '/' do
require 'pony'
if params[:name] # contact form
from = params[:name]
subject = "#{params[:name]} has contacted you via the Website"
else # subscription form
from = params[:subscribe]
subject = "#{params[:subscribe]} has subscribed to the newsletter"
end
body = "#{params[:email]}#{params[:comment]}"
Pony.mail(
:from => from,
:to => 'myemailaddress',
:subject => subject,
:body => body,
:via => :smtp,
:via_options => {
:address => 'smtp.gmail.com',
:port => '587',
:enable_starttls_auto => true,
:user_name => 'myemailaddress',
:password => 'mypassword',
:authentication => :plain,
:domain => "localhost.localdomain"
})
redirect '/success'
end
(I'm not a big fan of setting local vars within conditional branches, but we'll ignore that for clarity. I'd probably create a hash before the conditional with the keys already done, and then populate it in the branches but YMMV.)
3. Extract what doesn't change from what does.
Sinatra has a configure block just for this kind of thing.
require 'pony'
configure :development do
set :email_options, {
:via => :smtp,
:via_options => {
:address => 'smtp.gmail.com',
:port => '587',
:enable_starttls_auto => true,
:user_name => 'myemailaddress',
:password => 'mypassword',
:authentication => :plain,
:domain => "localhost.localdomain"
}
end
Pony.options = settings.email_options
Notice I've added :development as you may want to set it up differently for production.
Now your route is a lot cleaner and easier to debug:
post '/' do
if params[:name] # contact form
from = params[:name]
subject = "#{params[:name]} has contacted you via the Website"
else # subscription form
from = params[:subscribe]
subject = "#{params[:subscribe]} has subscribed to the newsletter"
end
body = "#{params[:email]}#{params[:comment]}"
Pony.mail
:from => from,
:to => 'myemailaddress',
:subject => subject,
:body => body,
redirect '/success'
end
My last tip, would be to put as many of those Pony options into ENV vars, which will not only keep things like passwords out of source control but also allow you to change the settings a lot easier. Perhaps put them in a Rakefile and load different environments for different contexts etc.
To use environment variables, I do the following:
# Rakefile
# in this method set up some env vars
def basic_environment
# I load them in from a YAML file that is *not* in source control
# but you could just specify them here
# e.g. ENV["EMAIL_A"] = "me#example.com"
end
namespace :app do
desc "Set up the environment locally"
task :environment do
warn "Entering :app:environment"
basic_environment()
end
desc "Run the app locally"
task :run_local => "app:environment" do
exec "bin/rackup config.ru -p 4630"
end
end
# from the command line, I'd run
`bin/rake app:run_local`
# in the Sinatra app file
configure :production do
# these are actual settings I use for a Heroku app using Sendgrid
set "email_options", {
:from => ENV["EMAIL_FROM"],
:via => :smtp,
:via_options => {
:address => 'smtp.sendgrid.net',
:port => '587',
:domain => 'heroku.com',
:user_name => ENV['SENDGRID_USERNAME'],
:password => ENV['SENDGRID_PASSWORD'],
:authentication => :plain,
:enable_starttls_auto => true
},
}
end
# then a block with slightly different settings for development
configure :development do
# local settingsā€¦
set "email_options", {
:via => :smtp,
:via_options => {
:address => 'smtp.gmail.com',
:port => '587',
:enable_starttls_auto => true,
:user_name => ENV["EMAIL_A"],
:password => ENV["EMAIL_P"],
:authentication => :plain,
:domain => "localhost.localdomain"
}
}
end
I usually keep most of these setting in a YAML file locally for development, but add these to the production server directly. There are lots of ways to handle this, YMMV.

Resources