I am not able to run ar_sendmail command from my terminal. I don't think i have missed its configuration. Below is my code;
development.rb
++++++++++++++++++++++++++++++++++++++++++++++++++++
ActionMailer::Base.delivery_method = :activerecord
ActionMailer::Base.smtp_settings = {
:address => "smtp.gmail.com",
:port => 25,
:domain => "www.google.com",
:authentication => :plain,
:user_name => "ashis.lun#gmail.com",
:password => "kathmandu",
:enable_starttls_auto => true
}
require "action_mailer/ar_mailer"
Gemfile
+++++++++++++++++++++++++++
gem "ar_mailer", "1.5.1"
My Mailer
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
class Postoffice < ActionMailer::ARMailer
def recover_password_email(account, name, address)
#recipients = address
#from = "ashis.lun#gmail.com"
#subject = "Your Account at #{account.org_name} is Ready"
#body["subdomain"] = account.subdomain
#body["name"] = name
#body["org_name"] = account.org_name
#body["password"] = password
#body["email"] = address
end
end
My controller
++++++++++++++++++++++++++++++++++++++++++++++++++++
def reset_password
#user = User.find_by_email(params[:email])
begin
if #user
password = get_new_password
#user.update_attributes!(:password => password)
Postoffice.deliver_recover_password_email(#account, #user.individual.firstname, #user.email, password)
flash[:notice] = "Your password has been e-mailed to you. It should show up in a minute!"
redirect_to '/sessions/new'
end
rescue
flash[:notice] = "Sorry, there was a problem resetting your password."
redirect_to '/sessions/new'
end
end
end
Whenever I run ar_sendmail command I just get below message. If i hit RAILS_ROOT in console then I it shows /Users/me/Dev/a5his
Usage: ar_sendmail [options]
ar_sendmail scans the email table for new messages and sends them to the
website's configured SMTP host.
ar_sendmail must be run from a Rails application's root or have it specified
with --chdir.
If ar_sendmail is started with --pid-file, it will fail to start if the PID
file already exists or the contents don't match it's PID.
Sendmail options:
-b, --batch-size BATCH_SIZE Maximum number of emails to send per delay
Default: Deliver all available emails
--delay DELAY Delay between checks for new mail
in the database
Default: 60
--max-age MAX_AGE Maxmimum age for an email. After this
it will be removed from the queue.
Set to 0 to disable queue cleanup.
Default: 604800 seconds
-o, --once Only check for new mail and deliver once
Default: false
-p, --pid-file [PATH] File to store the pid in.
Defaults to /var/run/ar_sendmail.pid
when no path is given
-d, --daemonize Run as a daemon process
Default: false
--mailq Display a list of emails waiting to be sent
Setup Options:
--create-migration Prints a migration to add an Email table
to stdout
--create-model Prints a model for an Email ActiveRecord
object to stdout
Generic Options:
-c, --chdir PATH Use PATH for the application path
Default: .
-e, --environment RAILS_ENV Set the RAILS_ENV constant
Default:
-t, --table-name TABLE_NAME Name of table holding emails
Used for both sendmail and
migration creation
Default: Email
-v, --[no-]verbose Be verbose
Default:
-h, --help You're looking at it
ar_sendmail must be run from a Rails application's root to deliver email.
/Users/me/Dev/a5his does not appear to be a Rails application root.
Thanks in advance <><
How about using Delayed Job? I've used ar mailer in the past and find delayed job a much better solution.
https://github.com/collectiveidea/delayed_job
Not sure if it'll make a difference, but it says here to put
require "action_mailer/ar_mailer"
in environment.rb, not development.rb or production.rb. Other than that, I can't see anything you missed.
Try ar_sendmail --chdir /Users/me/Dev/a5his or changing into the root of your rails app before running the command
ar_sendmail must be run from a Rails application's root to deliver email.
/Users/me/Dev/a5his does not appear to be a Rails application root.
Are you running the command in the application's root?
try
cd #{Rails.root.to_s} && bundle exec ar_sendmail_rails3 -e production
If you look at the source (shown below), this message is displayed if loading config/environment fails. One instance of this I ran into was where a dependency was unmet, which was causing an exception to fire when config/environment was being loaded. To address this, you can use an irb session and try requiring config/environment to see what error may be causing the require to fail.
Dir.chdir options[:Chdir] do
begin
require 'config/environment'
rescue LoadError
usage opts, <<-EOF
#{name} must be run from a Rails application's root to deliver email.
#{Dir.pwd} does not appear to be a Rails application root.
EOF
end
end
Related
I am trying to run message queues on heroku. For this I am using RabbitMQ Bigwig plugin.
I am publishing messages using bunny gem and trying to receive messages with sneakers gem. This whole setup works smoothly on local machine.
I take following steps to setup queue
I run this rake on server to setup queue:
namespace :rabbitmq do
desc 'Setup routing'
task :setup_test_commands_queue do
require 'bunny'
conn = Bunny.new(ENV['SYNC_AMQP'], read_timeout: 10, heartbeat: 10)
conn.start
ch = conn.create_channel
# get or create exchange
x = ch.direct('testsync.pcc', :durable => true)
# get or create queue (note the durable setting)
queue = ch.queue('test.commands', :durable => true, :ack => true, :routing_key => 'test_cmd')
# bind queue to exchange
queue.bind(x, :routing_key => 'test_cmd')
conn.close
end
end
I am able to see this queue in rabbitmq management plugin with mentioned binding.
class TestPublisher
def self.publish(test)
x = channel.direct("testsync.pcc", :durable => true)
puts "publishing this = #{Test}"
x.publish(Test, :persistent => true, :routing_key => 'pcc_cmd')
end
def self.channel
#channel ||= connection.create_channel
end
def self.connection
#conn = Bunny.new(ENV['RABBITMQ_BIGWIG_TX_URL'], read_timeout: 10, heartbeat: 10) # getting configuration from rabbitmq.yml
#conn.start
end
end
I am calling TestPublisher.publish() to publish message.
I have sneaker worker like this:
require 'test_sync'
class TestsWorker
include Sneakers::Worker
from_queue "test.commands", env: nil
def work(raw_event)
puts "^"*100
puts raw_event
# o = CaseNote.create!(content: raw_event, creator_id: 1)
# puts "#########{o}"
test = Oj.load raw_event
test.execute
# event_params = JSON.parse(raw_event)
# SomeWiseService.build.call(event_params)
ack!
end
end
My Procfile
web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
worker: bundle exec rake jobs:work
sneaker: WORKERS=TestsWorker bundle exec rake sneakers:run
My Rakefile
require File.expand_path('../config/application', __FILE__)
require 'rake/dsl_definition'
require 'rake'
require 'sneakers/tasks'
Test::Application.load_tasks
My sneaker configuration
require 'sneakers'
Sneakers.configure amqp: ENV['RABBITMQ_BIGWIG_RX_URL'],
log: "log/sneakers.log",
threads: 1,
workers: 1
puts "configuring sneaker"
I am sure that message gets published. I am able to get message on rabbitmq management plugin. But sneaker does not work. There is nothing in sneakers.log that can help.
sneakers.log on heroku :
# Logfile created on 2016-04-05 14:40:59 +0530 by logger.rb/41212
Sorry for this late response. I was able to get this working on heroku. When I faced this error after hours of debugging I was not able to fix it. So I rewrote all above code and I did not check what was wrong with my previous code.
The only problem with this code and correct code is queue binding.
I had two queues on same exchange. pcc.commands with routing key pcc_cmd and test.commands with routing key test_cmd.
I was working with test_cmd but as per following line in TestPublisher
x.publish(Test, :persistent => true, :routing_key => 'pcc_cmd')
I was publishing to different queue(pcc.commands). Hence I was not able to recieve the message on test.commands queue.
In TestWorker
from_queue "test.commands", env: nil
This states that fetch messages only from test.commands queue.
Regarding sneakers.log file:
Above setup was not able to give me logs in sneakers.log file. Yes this setup works on your local development machine, but it was not working on heroku. Now days to debug such issue I ommit log attribute from configuration. like this:
require 'sneakers'
Sneakers.configure amqp: ENV['RABBITMQ_BIGWIG_RX_URL'],
# log: "log/sneakers.log",
threads: 1,
workers: 1
This way you will get sneaker logs (even heartbeat logs) in heroku logs which can be seen by running command heroku logs -a app_name --tail.
During my training, I'm working on a website and we use Ruby on Rails. We need to send mails to users so I created a mailer.
I have tried to put the smtp in both development.rb and environment.rb
config.action_mailer.default_url_options = {host: '0.0.0.0:3000'}
config.action_mailer.default charset: 'utf-8'
config.action_mailer.delivery_method = 'smtp'
config.action_mailer.perform_deliveries = true
config.action_mailer.smtp_settings = {
adress: $SMTP_SERVER,
port: $PORT,
from: $MAIL,
enable_starttls_auto: true
#authentication: 'login'
}
It tells me that the error comes from this method line 6
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
# Tell the UserMailer to send a welcome Email after save
UserMailer.welcome_email(#user).deliver_now
format.html { redirect_to(#user, :notice => 'User was successfully created.') }
format.json { render :json => #user, :status => :created, :location => #user }
else
format.html { render :action => "new" }
format.json { render :json => #user.errors, :status => :unprocessable_entity }
end
end
end
I have set the port to 587 but i keep getting the error:
Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost"
port 25
It looks as if another file was overwriting my settings. I also saw that it might be related to my ssh key not being authorized by the server.
Do know what is wrong?
Thanks in advance
First of all, when developing on localhost, it's common to not actually send out mail, rather to treat that as a deployment detail and stick with the Rails default behavior which is to spit out the mail headers and contents into the console STDOUT (where you can verify that the text looks right). Is there a specific reason why you need to test sending messages in the dev environment?
Secondly, you mentioned that you set the SMTP settings in both development.rb and environment.rb. You shouldn't need to set these settings twice; in general I'd use development.rb for settings specific to the dev environment, and environment.rb only for settings that will always apply to all environments (dev, tests, and on the live deployed server). So if you're setting the same settings in both development.rb and environment.rb, I'd start by removing one or the other; redundancy will only make your job harder down the road.
Finally, to troubleshoot this I'd start by asking Rails what its settings are rather than waiting for the mail delivery to fail. Try the following:
Start up rails console
Enter Rails.configuration.action_mailer.smtp_settings and compare the resulting hash against your expectations. This hash should contain the port and domain settings that are used when sending out all mail (in the current environment), so if ActionMailer is trying the wrong port then I'd expect the port to be wrong here too.
Where are you setting $SMTP_SERVER, $PORT and $MAIL? Is there any reason you aren't using Rails' convention for environment variables, ENV['SMTP_SERVER'] etc.?
Hope some of that helps. Good luck!
replace
config.action_mailer.delivery_method = 'smtp'
with
config.action_mailer.delivery_method = :smtp
Ensure your Rails.configuration.action_mailer.smtp_settings is symbolized keys
I ran into the same error message well developing my own application. What I discovered is that as I was not actually sending any emails in a development environment I needed to change one of the lines in the configuration file found at: /your_apps_name/config/environments/development.rb
from
config.action_mailer.raise_delivery_errors = true
to
config.action_mailer.raise_delivery_errors = false
This was causing my application to raise errors when emails were not successfully delivered, and I wasn't actually sending emails so of course they were not being delivered successfully.
The app might be using mailcatcher gem for all outbound emails on development, which you haven't installed or don't have running. At least that was my issue. Check out https://mailcatcher.me and follow the instructions given.
You need to remove config.action_mailer.perform_deliveries = true line.
I was running into this issue when running Sidekiq::Worker.drain_all in my RSpec tests, and it was driving me crazy because I had config.action_mailer.delivery_method = :test in my config/environments/test.rb.
The solution was to set config.action_mailer.delivery_method = :test in my config/environments/development.rb, which is confusing because the implication is that my config/environments/development.rb is overriding my config/environments/test.rb in my RSpec tests.
Regardless, this might fix the problem for others.
For anyone clumsy like me, I got this message when I had everything set up perfectly in my app, but I had simply forgotten to run the command that adds the mailing addon in my production environment. In my case, that line was heroku addons:create mailgun:starter.
I've got the mailman gem integrated into my rails project. It fetches emails from gmail successfully. In my app there is a model Message for my emails. The emails are properly saved as Message model.
The problem is that the emails are saved multiple times sometimes and I can't recognize a pattern. Some emails are saved once, some two times and some are saved three times.
But I can't find the failure in my code.
Here is my mailman_server script:
script/mailman_server
#!/usr/bin/env ruby
# encoding: UTF-8
require "rubygems"
require "bundler/setup"
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
require 'mailman'
Mailman.config.ignore_stdin = true
#Mailman.config.logger = Logger.new File.expand_path("../../log/mailman_#{Rails.env}.log", __FILE__)
if Rails.env == 'test'
Mailman.config.maildir = File.expand_path("../../tmp/test_maildir", __FILE__)
else
Mailman.config.logger = Logger.new File.expand_path("../../log/mailman_#{Rails.env}.log", __FILE__)
Mailman.config.poll_interval = 15
Mailman.config.imap = {
server: 'imap.gmail.com',
port: 993, # usually 995, 993 for gmail
ssl: true,
username: 'my#email.com',
password: 'my_password'
}
end
Mailman::Application.run do
default do
begin
Message.receive_message(message)
rescue Exception => e
Mailman.logger.error "Exception occurred while receiving message:\n#{message}"
Mailman.logger.error [e, *e.backtrace].join("\n")
end
end
end
The email is processed inside my Message class:
def self.receive_message(message)
if message.from.first == "my#email.com"
Message.save_bcc_mail(message)
else
Message.save_incoming_mail(message)
end
end
def self.save_incoming_mail(message)
part_to_use = message.html_part || message.text_part || message
if Kontakt.where(:email => message.from.first).empty?
encoding = part_to_use.content_type_parameters['charset']
Message.create topic: message.subject, message: part_to_use.body.decoded.force_encoding(encoding).encode('UTF-8'), communication_partner: message.from.first, inbound: true, time: message.date
else
encoding = part_to_use.content_type_parameters['charset']
Message.create topic: message.subject, message: part_to_use.body.decoded.force_encoding(encoding).encode('UTF-8'), communication_partner: message.from.first, inbound: true, time: message.date, messageable_type: 'Company', messageable_id: Kontakt.where(:email => message.from.first).first.year.id
end
end
def self.save_bcc_mail(message)
part_to_use = message.html_part || message.text_part || message
if Kontakt.where(:email => message.to.first).empty?
encoding = part_to_use.content_type_parameters['charset']
Message.create topic: message.subject, message: part_to_use.body.decoded.force_encoding(encoding).encode('UTF-8'), communication_partner: message.to.first, inbound: false, time: message.date
else
encoding = part_to_use.content_type_parameters['charset']
Message.create topic: message.subject, message: part_to_use.body.decoded.force_encoding(encoding).encode('UTF-8'), communication_partner: message.to.first, inbound: false, time: message.date, messageable_type: 'Company', messageable_id: Kontakt.where(:email => message.to.first).first.year.id
end
end
I have daemonized the mailman_server with this script:
script/mailman_daemon
#!/usr/bin/env ruby
require 'rubygems'
require "bundler/setup"
require 'daemons'
Daemons.run('script/mailman_server')
I deploy with capistrano.
This are the parts which are responsible for stopping, starting and restarting my mailman_server:
script/deploy.rb
set :rails_env, "production" #added for delayed job
after "deploy:stop", "delayed_job:stop"
after "deploy:start", "delayed_job:start"
after "deploy:restart", "delayed_job:restart"
after "deploy:stop", "mailman:stop"
after "deploy:start", "mailman:start"
after "deploy:restart", "mailman:restart"
namespace :deploy do
desc "mailman script ausfuehrbar machen"
task :mailman_executable, :roles => :app do
run "chmod +x #{current_path}/script/mailman_server"
end
desc "mailman daemon ausfuehrbar machen"
task :mailman_daemon_executable, :roles => :app do
run "chmod +x #{current_path}/script/mailman_daemon"
end
end
namespace :mailman do
desc "Mailman::Start"
task :start, :roles => [:app] do
run "cd #{current_path};RAILS_ENV=#{fetch(:rails_env)} bundle exec script/mailman_daemon start"
end
desc "Mailman::Stop"
task :stop, :roles => [:app] do
run "cd #{current_path};RAILS_ENV=#{fetch(:rails_env)} bundle exec script/mailman_daemon stop"
end
desc "Mailman::Restart"
task :restart, :roles => [:app] do
mailman.stop
mailman.start
end
end
Could it be that multiple instances of the mailman server are started during my deploy at nearly the same time and then each instance polls nearly at the same time? The second and third instance pools before the first instance marks the email as read and polls and processes the email as well?
Update 30.01.
I had set the polling intervall to 60 seconds. but that changes nothing.
I checked the folder where the mailman pid file is stored. there is only one mailman pid file. So there is definitely only one mailman server running. I checked the logfile and can see, that the messages are fetched multiple times:
Mailman v0.7.0 started
IMAP receiver enabled (my#email.com).
Polling enabled. Checking every 60 seconds.
Got new message from 'my.other#email.com' with subject 'Test nr 0'.
Got new message from 'my.other#email.com' with subject 'Test nr 1'.
Got new message from 'my.other#email.com' with subject 'test nr 2'.
Got new message from 'my.other#email.com' with subject 'test nr 2'.
Got new message from 'my.other#email.com' with subject 'test nr 3'.
Got new message from 'my.other#email.com' with subject 'test nr 4'.
Got new message from 'my.other#email.com' with subject 'test nr 4'.
Got new message from 'my.other#email.com' with subject 'test nr 4'.
So that seems to me, that the problem is definitely in my mailman server code.
Update 31.1.
Seems to me, that is has something to do with my production machine. when I'm testing this in development with the exact same configuration (changed my local database from sqlite to mysql this morning to test it) as on the production machine I don't get duplicates. Probably is everything ok with my code, but there is a problem with the production machine. Will ask my hoster if they could see a solution for this. To fix this I will go with Ariejan'S suggestion.
The solution:
I found the problem. I deploy to a machine where the tmp directory is a shared one between all releases. I forgot to define the path where the pid file of the mailman_daemon should be saved. So it was saved in the script directory instead of the /tmp/pids directory. Because of this the old mailman_daemon could not be stopped after a new deploy. That had led to an army of working mailman_daemons which were polling my mailaccount... After killing all these processes all went well! No more duplicates!
This may be some concurrency/timing issue. E.g. new mails are imported before the ones currently processing have been saved.
Edit: Just noticed you have Mailman.config.poll_interval set to 15. This means it will check for new messages every 15 seconds. Try increasing this value to the default 60 seconds. Regardless of this setting, it might be a good idea to add the deduplication code I mentioned below.
My tip would be to also store the message_id from each email, so you can easily spot duplicates.
Instead of:
Message.create(...)
do:
# This makes sure you have the latest pulled version.
message = Message.find_or_create(message_id: message.message_id)
message.update_attributes(...)
# This makes sure you only import it once, then ignore further duplicates.
if !Message.where(message_id: message.message_id).exists?
Message.create(...)
end
For more info on message_id: http://rdoc.info/github/mikel/mail/Mail/Message#message_id-instance_method
Remember that email and imap are not meant to be consistent data stores like you'd expect Postgres or Mysql to be. Hope this helps you sort out the duplicate mails.
I found the problem. I deploy to a machine where the tmp directory is a shared one between all releases. I forgot to define the path where the pid file of the mailman_daemon should be saved. So it was saved in the script directory instead of the /tmp/pids directory. Because of this the old mailman_daemon could not be stopped after a new deploy. That had led to an army of working mailman_daemons which were polling my mailaccount... After killing all these processes all went well! No more duplicates!
I'm using the whenever gem to have a rails cron job send emails. Everything seems to work just fine and i have no errors in my cron.log or my production.log file, but i never receive an email. I've checked that the email address is correct also.
Any help is appreciated.
The production.log file contains this:
Connecting to database specified by database.yml
Rendered email_mailer/send_birthday_reminders.html.erb (5.3ms)
Sent mail to tomcaflisch#gmail.com (409ms)
Here's my whenever gem schedule.rb file
set :output, "#{path}/log/cron.log"
every :hour do
runner "BirthdayRemindersController.send_birthday_email_reminders"
end
birthday_reminders_controller.rb
class BirthdayRemindersController < ApplicationController
# cron job that sends birthday reminders
def self.send_birthday_email_reminders
users = User.all
email_addresses = []
users.each_with_index do |user, i|
if user.user_details.birthday_reminders == true
email_addresses[i] = get_primary_email(user)
end
end
p "email_addresses to send to:"
p email_addresses
users.each do |user|
p "this user is"
p user.user_details.full_name
if user.user_details.birthday.try(:strftime, "%m") == Date.today.strftime("%m") && user.user_details.birthday.try(:strftime, "%d") == Date.today.strftime("%d")
p "reminder sent"
EmailMailer.send_birthday_reminders(user, email_addresses).deliver
end
end
end
end
email_mailer.rb snippet
class EmailMailer < ActionMailer::Base
include ApplicationHelper
default :from => "\"FamNFo\" <no-reply#mysite.com>"
def send_birthday_reminders(birthday_person, email_addresses)
p "we in send_birthday_reminders mailer"
p email_addresses
#birthday_person = birthday_person
mail(:subject => "Birthday Reminder For The Caflisch Family", :to => email_addresses, :reply_to => email_addresses)
end
end
capistrano's deploy.rb contains this
# needed for the 'whenever' gem
set(:whenever_command) { "RAILS_ENV=#{rails_env} bundle exec whenever"}
require "whenever/capistrano"
Check your spam folder. To make sure emails don't end up there, add an "Unsubscribe" link in each email.
This could happen if your action mailer configuration specifies perform_deliveries=false. You can check out the configuration in your environment files.
If your application is deployed to cloud services then you may be getting your emails in a spam folder. Their entire IP blocks are registered as spam at services like Spamhaus, which is a sensible precaution or else we'd be getting even more spam than usual.
You should enter your server's IP address in that field to see if you're listed as a spammer.
If you are, you can request to Spamhaus that the block be lifted.
The other big issues I have found is that the PATH and rbenv may not be initialized in the CRONTAB depending on how you have it setup.
I would recommend adding the following to the top of your .bashrc file
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
This ensures that if you are using whenever to call model methods that rbenv and ruby are fully available.
I am using Action Mailer and have my configuration settings for Action Mailer in my environment.rb file. I would like to post my project in a public repository along with an environment.rb file, but I do not want to include my mail server's login information. How does one configure Capistrano's deploy.rb so that it prompts the user for the mail server settings and then modifies or creates an environment.rb file during Capistrano's deployment.
Thanks for looking =)
There are lots of other variations on this... see this blog post for more ideas:
http://www.simonecarletti.com/blog/2009/06/capistrano-and-database-yml
Here a start...
Add this into your production.rb environment file:
ActionMailer::Base.smtp_settings = File.expand_path(File.join(RAILS_ROOT, 'config', 'actionmailer.yml'))
And in a capistrano task, you can do something like this:
desc "Generate actionmailer.yml file"
task :generate_actionmailer_yml, :roles=>:app do
secret_password = Capistrano::CLI.ui.ask "Enter your secret mail password:"
template = File.read("config/deploy/actionmailer.yml.erb")
buffer = ERB.new(template).result(binding)
put buffer, "#{shared_path}/config/actionmailer.yml"
end
desc "Link actionmailer.yml from shared"
task :link_actionmailer_yml, :roles=>:app do
run "rm -f #{current_path}/config/actionmailer.yml && ln -s #{shared_path}/config/actionmailer.yml #{current_path}/config/actionmailer.yml"
end
after "deploy:finalize_update", "deploy:link_actionmailer_yml"
Then, you create a template actionmailer.yml.erb file:
address: "my.smtp.com"
port: 587
authentication: :plain
user_name: "user#name.com"
password: <%= secret_password %>
I would add to the answer of #jkrall by suggesting the use of the Capistrano::CLI.password_prompt method instead of the Capistrano::CLI.ui.ask method, so that the password will not echo to stdin.