Duplicate emails been sent from Heroku deployed Phoenix App - heroku

Thank you for your help. I'm new to development and Phoenix.
Recently I developed a website that sends an email when the form is submitted.
I tested the application in the iex enviroment and works just fine, it sends just one email with the information from the form. But when I deploy the application to Heroku, the email gets sent twice and I can't figure out why.
I am using SMTP with Bamboo dependencies in my mix.exs file, and I am using Bluehost SMTP configuration.
Here's what the code looks like:
mix.exs
defp deps do
[
{:phoenix, "~> 1.3.2"},
{:phoenix_pubsub, "~> 1.0"},
{:phoenix_ecto, "~> 3.2"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "~> 2.10"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:gettext, "~> 0.11"},
{:bamboo, "~> 1.0"},
{:cowboy, "~> 1.0"},
{:bamboo_smtp, "~> 1.5.0"}
]
end
config.exs
config :app, App.Mailer,
adapter: Bamboo.SMTPAdapter,
server: "mail.app.com",
hostname: "app.com",
port: 26,
username: System.get_env("USER_ID"),
password: System.get_env("USER_PASS"),
tls: :if_available,
allowed_tls_versions: [:"tlsv1", :"tlsv1.1", :"tlsv1.2"],
ssl: false,
retries: 1,
no_mx_lookups: false,
auth: :always
email.ex
defmodule App.Email do
use Bamboo.Phoenix, view: App.EmailView
def contact_email(message) do
new_email()
|> from("postmaster#app.com")
|> to("contacto#app.com")
|> put_text_layout({AppWeb.LayoutView, "email.html"})
|> subject("New lead in App")
|> assign(:message, message)
|> render("send_email.html")
|> App.Mailer.deliver_later
end
mailer.exs
defmodule App.Mailer do
use Bamboo.Mailer, otp_app: :app
end
Also, in my .gitignore file I'm ignoring my .env file that contains my environment variables, and I already set them in Heroku with:
heroku config:set VARIABLE_NAME=variable
I have no idea what could be happening and appreciate all the answers I can get. Also, if you need further information of the code, let me know.

This is just a guess, but you are probably calling App.Mailer.deliver_later (or App.Mailer.deliver_now) multiple times. Once from App.Email.contact_email and once from the controller action that receives the posted form data.
If that is the case, removing App.Mailer.deliver_later from the contact_email function is probably the solution.

Related

undefined method `check_delivery_params' for #<Mailgunner::DeliveryMethod:0x00

I deployed a rails 5 app to heroku. I used mailgun for sending emails and it works well in development. In production when I try to sign up a user, I get this error:
production.rb:
config.action_mailer.delivery_method = :mailgun
config.action_mailer.default_url_options = { :host => 'http://myappname.herokuapp.com', :protocol => 'https'}
config.action_mailer.mailgun_settings = {
domain: ENV['MAILGUN_DOMAIN'],
api_key: ENV['MAILGUN_KEY']
}
The MAILGUN_DOMAIN and MAILGUN_KEY were stored as environment variables in my PC. Is there something I did not do right? Thanks!
After installing figaro gem:
application.yml
development:
MAILGUN_DOMAIN: ******************************
MAILGUN_KEY: **************************
production:
MAILGUN_DOMAIN: ******************************
MAILGUN_KEY: **************************
I still get the same error!!
It looks like it is related to the version of the mail gem that is installed as per this issue on mailgunner.
The workaround suggested there is to explicitly add the mail gem to your Gemfile and to lock the version to 2.6.5.
gem 'mail', '2.6.5'
You'll then need to run bundle update mail --conservative to get the new version.

What is the right way to develop using Paperclip and S3, but without connecting to real S3 bucket?

My project uses Paperclip and Amazon S3, but I need a development/test environment that don't connect directly to S3. I've tried to use FakeS3, but with no luck, since I am using aws-sdk version 2 (and all other websites shows how to proceed using the v1).
There's a way to do that? How?
My Gemfile:
gem 'aws-sdk', '~> 2.5', '>= 2.5.3'
gem 'paperclip', '~> 5.1'
group :development, :test do
gem 'fakes3', '~> 0.2.4'
end
The aws-ruby-sdk v2 offers something that allow you to test your code that uses AWS sdk.
stub_data and stub_responses
If offers many options and one of them is:
# stub data in the constructor
client = Aws::S3::Client.new(stub_responses: {
list_buckets: { buckets: [{name: 'my-bucket' }] },
get_object: { body: 'data' },
})
client.list_buckets.buckets.map(&:name) #=> ['my-bucket']
client.get_object(bucket:'name', key:'key').body.read #=> 'data'
This way you control what gets returned by the SDK without needing to use the real service.
http://docs.aws.amazon.com/sdkforruby/api/Aws/ClientStubs.html

Ruby PG gem connection issue

I've searched several related posts for the issue I'm having but wasn't able to find an answer. I'm a student in a coding program where most people use Mac, but I'm on Windows ( 7, Pro, 64 ) - because of that I'm a bit locked in to the tools/software I'll post here.
I'm trying to open a connection through Ruby with the pg gem, and I'm using Sinatra and PostgreSQL. I've established the server, database, and configuration path variables for PostgreSQL, and I've successfully installed pg gem (didn't have an issue there as in some of the other posts) with the line:
gem install pg -- --with-pg-config=C:\Program Files\PostgreSQL\9.5\bin
So the problem is that when I boot up Sinatra and go to the localhost,
I get a NoMethodError, Undefined Method for nil:NilClass on a method that otherwise works for Mac users.
The method is:
configure :development do
set :db_config, { dbname: "news_aggregator_development" }
end
configure :test do
set :db_config, { dbname: "news_aggregator_test" }
end
def db_connection
begin
connection = PG.connect(Sinatra::Application.db_config)
yield(connection)
ensure
connection.close
end
end
get '/articles' do
#results = db_connection do |conn|
conn.exec("SELECT * FROM articles")
end
erb :index
end
connection returns nil, and so the close method returns with an undefined method error. I don't think there is a syntax error as I've checked with others regarding this, and I'm thinking it might be related to a connection error with pg.
First time post so please go easy on me =) Apologies if I've left out any needed information - let me know what more context could be helpful and I will try to provide it! Thank you!
Two points:
Wrap your Sinatra helpers in a helpers {} block. This will allow you to use settings.db_config instead of Sinatra::Application.db_config:
helpers do
def db_connection
connection = PG.connect(settings.db_config)
yield connection
ensure
connection.close
end
end
In your PG.connect call, you should pass the host, user, password, and any other options necessary for the pg gem to find, connect, and authenticate to your instance. The dbname alone is not enough—at least not on Windows.
configure :development do
set :db_config, {
host: "localhost",
port: 5432,
user: "foo",
password: "bar",
dbname: "news_aggregator_development"
}
end
Good luck!

How to enable redis for Dashing?

I use free heroku instance to run my Dashing project. In result, it looses the value passed previously, when my instance sleeps. I was recommended to use Redis to keep history. I tryed to follow the instruction given here. In result I got the following config.ru (as part of my dashing project):
require 'dashing'
require 'redis-objects'
require 'yaml'
configure do
set :auth_token, 'my-token'
set :default_dashboard, 'def' # https://github.com/Shopify/dashing/wiki/How-To:-Change-the-default-dashboard
helpers do
def protected!
# Put any authentication code you want in here.
# This method is run before accessing any resource.
end
end
end
def redis?
ENV.has_key? 'REDISTOGO_URL'
end
if redis?
redis_uri = URI.parse(ENV['REDISTOGO_URL'])
Redis.current = Redis.new(:host => redis_uri.host,
:port => redis_uri.port,
:password => redis_uri.password)
set :history, Redis::HashKey.new('dashing-history')
elsif File.exists?(settings.history_file)
set history: YAML.load_file(settings.history_file)
else
set history: {}
end
map Sinatra::Application.assets_prefix do
run Sinatra::Application.sprockets
end
run Sinatra::Application
and the following Gemfile:
source 'https://rubygems.org'
gem 'dashing'
gem 'redis-objects'
## Remove this if you don't need a twitter widget.
gem 'twitter', '>= 5.9.0'
But it didn't help. What I did incorrectly?
I also tried to use this tutorial. But it was giving me an error at line redis_uri = URI.parse(ENV["REDISTOGO_URL"]) (something like wrong url is given).
The problem was that the app requires the add-on Redis To Go
If Redis To Go is configured, REDISTOGO_URL is added to environment variables, it will work
For more information on how to setup Redis To Go, read the heroku article
Adding Redis to an application provides benefits, you may be using RedisToGo to power simple Resque or Sidekiq jobs, or using the raw power of Redis 2.6 Lua Scripting to do some crazy fast operations. Redis can be used a database, but it’s often used as a complementary datastore. With over 140 commands, the possibilities are endless.

Heroku does NOT compile files under assets pipelines in Rails 4

Everything goes well in local machine with assets pipeline in Rails 4 and Ruby 2.0. But when deploying to heroku, it is shown that:
-----> Preparing app for Rails asset pipeline
Running: rake assets:precompile
I, [2013-03-12T03:28:29.908234 #912] INFO -- : Writing /tmp/build_1n6yi8lwna3sj/public/assets/rails-2ee5a98f26fbf8c6c461127da73c47eb.png
I, [2013-03-12T03:28:29.914096 #912] INFO -- : Writing /tmp/build_1n6yi8lwna3sj/public/assets/trash-3c3c2861eca3747315d712bcfc182902.png
I, [2013-03-12T03:28:33.963234 #912] INFO -- : Writing /tmp/build_1n6yi8lwna3sj/public/assets/application-bf2525bd32aa2a7068dbcfaa591b3874.js
I, [2013-03-12T03:28:40.362850 #912] INFO -- : Writing /tmp/build_1n6yi8lwna3sj/public/assets/application-13374a65f29a3b4cea6f8da2816ce7ff.css
Asset precompilation completed (14.36s)
Heroku seems to compile files but put it in /tmp without any errors. My questions are:
How come Heroku compile assets files to /tmp?
My last solution was to run RAILS_ENV=production bundle exec rake assets:precompile locally, but this generated a manifest-xxxxxx.json in public/assets, rather than manifest.yml, so that heroku doesn't detect the JSON manifest file. I sorted it out by manually created a yml from the json file and heroku became happy. Has heroku's approach been outdated?
Heroku's asset plugins no longer work since Rails 4 does not support plugins. You need to use Heroku's asset gems instead. Place this in your Gemfile:
group :production do
gem 'rails_log_stdout', github: 'heroku/rails_log_stdout'
gem 'rails3_serve_static_assets', github: 'heroku/rails3_serve_static_assets'
end
Follow Heroku's guide on getting started with Rails 4.
Update (07/22/2013): Heroku now supplies a different gem to precompile assets.
group :production do
gem 'rails_12factor'
end
You need to config Rails to serve static assets in production: config/environments/production.rb
SampleApp::Application.configure do
.
.
.
config.serve_static_assets = true
.
.
.
end
UPDATE:
In Rails 4 is deprecated, and has been changed by:
config.serve_static_files = true
Since rails 4 replaced manifest.yml with manifest-(fingerprint).json, you'll want to enable static asset serving.
From Getting Started with Rails 4.x on Heroku:
gem 'rails_12factor', group: :production
then
bundle install
and, finally,
git push heroku
Fixed the issue for me. Hope this helps!
I run exactly into the same problem.
I set config.serve_static_assets = true in my environments/production.rb file until heroku wont't support the new manifest format.
So it is a temporal solution until heroku support will be added.
After hours of googling in which none of the guides on Heroku or the suggestions on StackOverFlow helped me, I finally ran into this blog post which offered this clue:
heroku labs:enable user-env-compile --app=YOUR_APP
Without this, the asset pipeline will always try to init the whole app and connect to the database (despite all the things you may have read that rails 4 now longer does this). This exposes your Heroku configuration to Rails so it can boot up successfully and run rake tasks like assets:precompile.
I needed to use this gem:
gem 'rails_12factor', group: :production #need this for rails 4 assets on heroku
And in /config/environments/production.rb I needed to set:
config.assets.compile = true
My understanding is that the rails_12_factor gem sets config.serve_static_assets = true, amongst other things.
In my case, assets compiled following the instructions above but it wasn't picking the bootstrap glyphicons 'fontawesome-webfont' so this worked for me finally after wasting so many hours researching.
Gem file
gem 'rails_12factor', group: :production
bundle install
config/application.rb
config.assets.precompile += %w(*.png *.jpg *.jpeg *.gif,
"fontawesome-webfont.ttf",
"fontawesome-webfont.eot",
"fontawesome-webfont.svg",
"fontawesome-webfont.woff")
config.assets.precompile << Proc.new do |path|
if path =~ /\.(css|js)\z/
full_path = Rails.application.assets.resolve(path).to_path
app_assets_path = Rails.root.join('app', 'assets').to_path
if full_path.starts_with? app_assets_path
puts "including asset: " + full_path
true
else
puts "excluding asset: " + full_path
false
end
else
false
end
end
environment/production.rb
config.serve_static_assets = true
Then finally, I ran
rake assets:precompile RAILS_ENV=production and pushed it to heroku and that worked.
This was an issue with the Heroku Ruby Buildpack, but an update was deployed today (2013-05-21). Please try it out and let us know.
To answer your questions:
#1) This is sprockets output; things are compiled to /tmp and then moved (See here in Sprockets). To my knowledge this has always been done this way, but it wasn't until Sprockets version was updated in Rails that we got this new debug-type output.
#2) Previously assets:precompile genereated a manifest.json file, but now in Rails 4 the manifest file has a fingerprint in it, which wasn't detected previously. This was fixed with #74.
I added this to the top of one of my css.scss files in the assets/stylesheets/ folder.
#import "font-awesome";
then ran..
rake assets:clean
and...
rake assets:precompile RAILS_ENV=production
In Rails 4.2.4 your production.rb has the line:
config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
That means, gem 'rails_12factor', group: :production doesn`t need to change it to true, as it can be set through the heroku environment variables. You also will get a warning if you remove the rails_12factor gem.
If you have problems with assets, login to the heroku console heroku run rails console and find out the asset path for a file puts helper.asset_path("application.js") .
One strange behaviour I noticed between development and production, when the file ending is not provided:
With a image /assets/images/image_01.jpg the following output from asset_pathsdiffers:
Development:
development > puts helper.asset_path('profile_01')
=> /assets/profile_01-bbd16aac5ef1d295411af44c103fcc631ab90ee94957414d4c01c3aed1055714.jpg
development > puts helper.asset_path('profile_01.jpg')
=> /assets/profile_01-bbd16aac5ef1d295411af44c103fcc631ab90ee94957414d4c01c3aed1055714.jpg
Production:
development > puts helper.asset_path('profile_01')
=> /profile_01
development > puts helper.asset_path('profile_01.jpg')
=> /assets/profile_01-bbd16aac5ef1d295411af44c103fcc631ab90ee94957414d4c01c3aed1055714.jpg
You do not have to run RAILS_ENV=production rake assets:precompile, heroku does this for you during deploy. Also you do not have to precompile the assets in development and push them to heroku.
Apart from ensuring you have the 'rails_12factor' gem installed the only thing you need to do is this.
# config/application.rb
config.assets.paths << Rails.root.join('vendor', 'assets')
It seems that although Rails knows exactly what it wants, Heroku needs reminding to include the assets folder as part of the assets paths.
Use Image Extensions
I had this same issue, but for a different reason.
Instead of
<%= asset_path 'facebook-link' %>
Use:
<%= asset_path 'facebook-link.png' %>
While the first one worked locally, when I pushed to Heroku my images were breaking and I had no clue why. Using the full file extension fixed the problem :)
Add this gem gem 'rails_serve_static_assets'
https://github.com/heroku/rails_serve_static_assets
If you are using controller specific assets as in:
<%= javascript_include_tag params[:controller] %> or <%= javascript_include_tag params[:controller] %>
Then in production you will need to explicitly precompile those (in development rails compiles files on the fly).
See official Rails guide here: http://guides.rubyonrails.org/asset_pipeline.html#controller-specific-assets
To precompile as explained in the guides (here: http://guides.rubyonrails.org/asset_pipeline.html#precompiling-assets) you will need to add the following to the config/application.rb
# config/application.rb
config.assets.precompile << Proc.new do |path|
if path =~ /\.(css|js)\z/
full_path = Rails.application.assets.resolve(path).to_path
app_assets_path = Rails.root.join('app', 'assets').to_path
if full_path.starts_with? app_assets_path
puts "including asset: " + full_path
true
else
puts "excluding asset: " + full_path
false
end
else
false
end
end
I figure I'll add this as an answer since this question is linked from the Heroku Support page if you search for "assets".
This is mostly for people who are updating their app to Rails 4, but after going through this - and many other SO posts - what finally got me was changing the following in production.rb:
config.action_dispatch.x_sendfile_header = "X-Sendfile"
To:
config.action_dispatch.x_sendfile_header = nil
I hadn't caught this when I upgraded and as usual this took me forever to figure out. Hopefully it helps someone else! Shout out to PatrickEm who asked/answered the same in his question.
This may not answer the original question's root cause, But I was having a similar symptom with a different root cause.
Pre-compilation of a JPEG files changes the file extension to JPG, meaning that asset_path("my_image.jpeg") and asset_path("my_image") didn't work. Remove the "e" from JPEG and voila, it works.
Others have described the same problem here https://blazarblogs.wordpress.com/2016/04/06/rails-force-to-precompile-jpeg-to-jpg/
Is this a bug? Or desired behaviour? And also weird that it only doesn't work in my Heroku-hosted production environment. Maybe they have some sort of configuration.

Resources