Skip to main content

Multitenancy with the Apartment gem Sending email in production

General • Asked by Francisco Quinones

Hi I did the Multitenancy app works great only problem that im having is on production the app wont send email. On local machine it send it with no problem.
Any help and what info that you need let me know thank you.


How are you setting up your mail? I imagine it will be shared throughout the system?


Dev

 config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
  # config.action_mailer.raise_delivery_errors = true
  config.action_mailer.delivery_method = :letter_opener
  # config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    address:              'smtp.gmail.com',
    port:                 '587',
    domain:               'gmail.com',
    user_name:            'USERNAME',
    password:             'PASSWORD',
    authentication:       'plain',
    enable_starttls_auto: true  }

Production

  config.action_mailer.default_url_options = { host: 'appname.herokuapp.com'}
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.perform_deliveries = true
  config.action_mailer.raise_delivery_errors = false
  config.action_mailer.default :charset => "utf-8"
  config.action_mailer.smtp_settings = {
    address:              'smtp.gmail.com',
    port:                 587,
    domain:               'gmail.com',
    user_name:            'USERNAME',
    password:             'PASSWORD',
    authentication:       'plain',
    enable_starttls_auto: true  }

Hi! any more info that you need let me know as im looking to fix this problem. Thank Chris as always.


Hey thanks for the reminder. I missed this last post.

One thing you could try is setting raise_delivery_errors to true in production so that in case you have an invalid thing setup, it would let you know rather than hiding the error.


Ok I get back to you on that thank you very much! Chris keep up the good work love everything that your doing. will recommend you!


Good luck and thanks so much Francisco! :)


I got this in the terminal
Net::SMTPAuthenticationError (535-5.7.8 Username and Password not accepted. Learn more at):


OMG! found it I was using

  user_name:            'USERNAME',
   password:             'PASSWORD',

and not this

   user_name:       ENV['USERNAME'],
   password:          ENV['PASSWORD'],

Thank you thank you


Ah ha! That would do it. :)

That's one of those times where turning on errors for this stuff in production is super helpful. Usually they don't throw errors so it doesn't break the website when an email fails to send...but this is kinda important to know!


quick question cron jobs run normal on Multitenancy app
This the code that I have if it dont run normal I was think of doing the block code so it runs in each tanent

  # Company.all.each  do |c|
  # Apartment::Tenant.switch!('c.subdomain')
   every 1.month, :at => '1st 6:00am' do
        runner "User.email_task_list"
        runner "Task.generate_new_trans" # class Task.method
   end
    # end

This might work. You'll have to test it inside the class methods to find out if the Apartment::Tenant is correctly set to verify that it's working. I imagine it would, but you can just print out the current tenant to verify it.

Possibly a better solution would be to loop through the companies inside the methods themselves instead. That would give you a bit more control over setting the tenants.


@chris another quick question. You told me to use resque better for background jobs, for some reason resque is not looking at the sub tenant, I get a error Record ID not found I think its looking on the main table and not that subdomain table.

   Couldn't find TaskTran with 'id'=26
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.4/lib/active_record/relation/finder_methods.rb:324:in `raise_record_not_found_exception!'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.4/lib/active_record/relation/finder_methods.rb:444:in `find_one'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.4/lib/active_record/relation/finder_methods.rb:423:in `find_with_ids'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.4/lib/active_record/relation/finder_methods.rb:71:in `find'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/delayed_paperclip-2.9.1/lib/delayed_paperclip.rb:34:in `process_job'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/delayed_paperclip-2.9.1/lib/delayed_paperclip/jobs/active_job.rb:12:in `perform'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activejob-4.2.4/lib/active_job/execution.rb:32:in `block in perform_now'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:117:in `call'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:117:in `call'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:555:in `block (2 levels) in compile'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:505:in `call'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:505:in `call'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:498:in `block (2 levels) in around'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:343:in `call'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:343:in `block (2 levels) in simple'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/i18n-0.7.0/lib/i18n.rb:257:in `with_locale'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activejob-4.2.4/lib/active_job/translation.rb:7:in `block (2 levels) in <module:Translation>'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:441:in `instance_exec'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:441:in `block in make_lambda'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:342:in `call'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:342:in `block in simple'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:497:in `call'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:497:in `block in around'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:505:in `call'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:505:in `call'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:498:in `block (2 levels) in around'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:343:in `call'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:343:in `block (2 levels) in simple'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activejob-4.2.4/lib/active_job/logging.rb:23:in `call'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activejob-4.2.4/lib/active_job/logging.rb:23:in `block (4 levels) in <module:Logging>'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/notifications.rb:164:in `block in instrument'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/notifications.rb:164:in `instrument'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activejob-4.2.4/lib/active_job/logging.rb:22:in `block (3 levels) in <module:Logging>'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activejob-4.2.4/lib/active_job/logging.rb:43:in `block in tag_logger'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/tagged_logging.rb:68:in `block in tagged'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/tagged_logging.rb:26:in `tagged'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/tagged_logging.rb:68:in `tagged'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activejob-4.2.4/lib/active_job/logging.rb:43:in `tag_logger'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activejob-4.2.4/lib/active_job/logging.rb:19:in `block (2 levels) in <module:Logging>'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:441:in `instance_exec'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:441:in `block in make_lambda'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:342:in `call'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:342:in `block in simple'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:497:in `call'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:497:in `block in around'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:505:in `call'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:505:in `call'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:92:in `__run_callbacks__'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:778:in `_run_perform_callbacks'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:81:in `run_callbacks'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activejob-4.2.4/lib/active_job/execution.rb:31:in `perform_now'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activejob-4.2.4/lib/active_job/execution.rb:21:in `execute'
/Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activejob-4.2.4/lib/active_job/queue_adapters/resque_adapter.rb:46:in `perform'

I think for resque, you'll need to pass in the tenant into the job as an extra parameter so that you can set the tenant in the beginning.

This is how apartment-sidekiq works https://github.com/influitive/apartment-sidekiq

Sidekiq is probably a better solution anymore than Resque. It's a lot faster and much better supported so if you haven't written too much Resque code, it might be worth switch to using the apartment-sidekiq gem with Sidekiq. It'll take care of passing in and switching to the tenant for you automatically.


@chris Thank move to sidekiq work out of the box. thank you


@chris im ready to deploy to heroku. how can I setup my cron jobs on heroku or im all set and the whenever gem will setup and tell the cron jobs to run. thank for all the help.


@chris on my sideq im getting this error any idea??

09:37:22 redis_s.1 | 33693:M 07 Dec 09:37:22.096 * 100 changes in 300 seconds. Saving...
09:37:22 redis_s.1 | 33693:M 07 Dec 09:37:22.097 * Background saving started by pid 71671
09:37:22 redis_s.1 | 71671:C 07 Dec 09:37:22.099 * DB saved on disk
09:37:22 redis_s.1 | 33693:M 07 Dec 09:37:22.197 * Background saving terminated with success
09:39:27 worker.1  | 2015-12-07T13:39:27.825Z 33694 TID-ougbxml30 DelayedPaperclip::Jobs::ActiveJob JID-9570d2fa326ad3b1bbc24651 INFO: start
09:39:28 worker.1  | 2015-12-07T13:39:28.299Z 33694 TID-ougbxml30 DelayedPaperclip::Jobs::ActiveJob JID-9570d2fa326ad3b1bbc24651 INFO: fail: 0.474 sec
09:39:28 worker.1  | 2015-12-07T13:39:28.300Z 33694 TID-ougbxml30 WARN: {"class"=>"ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper", "wrapped"=>"DelayedPaperclip::Jobs::ActiveJob", "queue"=>"paperclip", "args"=>[{"job_class"=>"DelayedPaperclip::Jobs::ActiveJob", "job_id"=>"44d6026e-5aca-4a07-9d18-054e75bd0eb7", "queue_name"=>"paperclip", "arguments"=>["TaskTran", 449, "signature_manager"], "locale"=>"es"}], "retry"=>true, "jid"=>"9570d2fa326ad3b1bbc24651", "created_at"=>1449495208.7341068, "apartment"=>"companydemo", "enqueued_at"=>1449495567.8203, "error_message"=>"One of the following schema(s) is invalid: \"companydemo\" \"public\"", "error_class"=>"Apartment::TenantNotFound", "failed_at"=>1449495209.205343, "retry_count"=>4, "retried_at"=>1449495568.298719}
09:39:28 worker.1  | 2015-12-07T13:39:28.300Z 33694 TID-ougbxml30 WARN: Apartment::TenantNotFound: One of the following schema(s) is invalid: "companydemo" "public"
09:39:28 worker.1  | 2015-12-07T13:39:28.301Z 33694 TID-ougbxml30 WARN: /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/apartment-1.0.2/lib/apartment/adapters/postgresql_adapter.rb:92:in `rescue in connect_to_new'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/apartment-1.0.2/lib/apartment/adapters/postgresql_adapter.rb:85:in `connect_to_new'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/apartment-1.0.2/lib/apartment/adapters/abstract_adapter.rb:84:in `switch!'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/apartment-1.0.2/lib/apartment/adapters/abstract_adapter.rb:97:in `switch'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/apartment-sidekiq-0.2.0/lib/apartment/sidekiq/middleware/server.rb:4:in `call'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sidekiq-3.5.3/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sidekiq-3.5.3/lib/sidekiq/middleware/server/active_record.rb:6:in `call'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sidekiq-3.5.3/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sidekiq-3.5.3/lib/sidekiq/middleware/server/retry_jobs.rb:74:in `call'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sidekiq-3.5.3/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sidekiq-3.5.3/lib/sidekiq/middleware/server/logging.rb:11:in `block in call'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sidekiq-3.5.3/lib/sidekiq/logging.rb:30:in `with_context'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sidekiq-3.5.3/lib/sidekiq/middleware/server/logging.rb:7:in `call'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sidekiq-3.5.3/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sidekiq-3.5.3/lib/sidekiq/middleware/chain.rb:132:in `call'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sidekiq-3.5.3/lib/sidekiq/middleware/chain.rb:132:in `invoke'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sidekiq-3.5.3/lib/sidekiq/processor.rb:51:in `block in process'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sidekiq-3.5.3/lib/sidekiq/processor.rb:104:in `stats'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/sidekiq-3.5.3/lib/sidekiq/processor.rb:50:in `process'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/celluloid-0.17.2/lib/celluloid/calls.rb:28:in `public_send'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/celluloid-0.17.2/lib/celluloid/calls.rb:28:in `dispatch'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/celluloid-0.17.2/lib/celluloid/call/async.rb:7:in `dispatch'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/celluloid-0.17.2/lib/celluloid/cell.rb:50:in `block in dispatch'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/celluloid-0.17.2/lib/celluloid/cell.rb:76:in `block in task'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/celluloid-0.17.2/lib/celluloid/actor.rb:339:in `block in task'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/celluloid-0.17.2/lib/celluloid/task.rb:44:in `block in initialize'
09:39:28 worker.1  | /Users/IFrank/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/celluloid-0.17.2/lib/celluloid/task/fibered.rb:14:in `block in create'

Login or Create An Account to join the conversation.

Subscribe to the newsletter

Join 22,346+ developers who get early access to new screencasts, articles, guides, updates, and more.

    By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

    More of a social being? We're also on Twitter and YouTube.