heartcombo / devise

Flexible authentication solution for Rails with Warden.
http://blog.plataformatec.com.br/tag/devise/
MIT License
23.94k stars 5.54k forks source link

Errno::EPIPE in Devise::RegistrationsController#create #1536

Closed mvilrokx closed 12 years ago

mvilrokx commented 12 years ago

I have a rails application that I upgraded from 2.3 to 3.1 (through 3.0). I am using the latest devise gem with my rails 3.1 application and really didn't change anything except to get the app back up and running after the upgrade. However, devise emails are not going out (e.g. on registration) anymore. This was all working fine on Rails 2.3. After I set config.action_mailer.raise_delivery_errors = true on my development server (on Engine Yard), I am getting the above error. Here's the rest of the stack trace:

mail (2.3.0) lib/mail/network/delivery_methods/sendmail.rb:57:in write' mail (2.3.0) lib/mail/network/delivery_methods/sendmail.rb:57:inputs' mail (2.3.0) lib/mail/network/delivery_methods/sendmail.rb:57:in block in call' mail (2.3.0) lib/mail/network/delivery_methods/sendmail.rb:56:inpopen' mail (2.3.0) lib/mail/network/delivery_methods/sendmail.rb:56:in call' mail (2.3.0) lib/mail/network/delivery_methods/sendmail.rb:52:indeliver!' mail (2.3.0) lib/mail/message.rb:1989:in do_delivery' mail (2.3.0) lib/mail/message.rb:230:inblock in deliver' actionmailer (3.1.3) lib/action_mailer/base.rb:432:in block in deliver_mail' activesupport (3.1.3) lib/active_support/notifications.rb:53:inblock in instrument' activesupport (3.1.3) lib/active_support/notifications/instrumenter.rb:21:in instrument' activesupport (3.1.3) lib/active_support/notifications.rb:53:ininstrument' actionmailer (3.1.3) lib/action_mailer/base.rb:430:in deliver_mail' mail (2.3.0) lib/mail/message.rb:230:indeliver' devise (1.5.3) lib/devise/models/confirmable.rb:50:in send_confirmation_instructions' activesupport (3.1.3) lib/active_support/callbacks.rb:424:in_run_create_callbacks' activesupport (3.1.3) lib/active_support/callbacks.rb:81:in run_callbacks' activerecord (3.1.3) lib/active_record/callbacks.rb:268:increate' activerecord (3.1.3) lib/active_record/persistence.rb:294:in create_or_update' activerecord (3.1.3) lib/active_record/callbacks.rb:264:inblock in create_or_update' activesupport (3.1.3) lib/active_support/callbacks.rb:399:in _run_save_callbacks' activesupport (3.1.3) lib/active_support/callbacks.rb:81:inrun_callbacks' activerecord (3.1.3) lib/active_record/callbacks.rb:264:in create_or_update' activerecord (3.1.3) lib/active_record/persistence.rb:37:insave' activerecord (3.1.3) lib/active_record/validations.rb:50:in save' activerecord (3.1.3) lib/active_record/attribute_methods/dirty.rb:22:insave' activerecord (3.1.3) lib/active_record/transactions.rb:241:in block (2 levels) in save' activerecord (3.1.3) lib/active_record/transactions.rb:295:inblock in with_transaction_returning_status' activerecord (3.1.3) lib/active_record/connection_adapters/abstract/database_statements.rb:192:in transaction' activerecord (3.1.3) lib/active_record/transactions.rb:208:intransaction' activerecord (3.1.3) lib/active_record/transactions.rb:293:in with_transaction_returning_status' activerecord (3.1.3) lib/active_record/transactions.rb:241:inblock in save' activerecord (3.1.3) lib/active_record/transactions.rb:252:in rollback_active_record_state!' activerecord (3.1.3) lib/active_record/transactions.rb:240:insave' devise (1.5.3) app/controllers/devise/registrations_controller.rb:16:in create' actionpack (3.1.3) lib/action_controller/metal/implicit_render.rb:4:insend_action' actionpack (3.1.3) lib/abstract_controller/base.rb:167:in process_action' actionpack (3.1.3) lib/action_controller/metal/rendering.rb:10:inprocess_action' actionpack (3.1.3) lib/abstract_controller/callbacks.rb:18:in block in process_action' activesupport (3.1.3) lib/active_support/callbacks.rb:452:in_run576969675process_action88874271callbacks' activesupport (3.1.3) lib/active_support/callbacks.rb:386:in _run_process_action_callbacks' activesupport (3.1.3) lib/active_support/callbacks.rb:81:inrun_callbacks' actionpack (3.1.3) lib/abstract_controller/callbacks.rb:17:in process_action' actionpack (3.1.3) lib/action_controller/metal/rescue.rb:17:inprocess_action' actionpack (3.1.3) lib/action_controller/metal/instrumentation.rb:30:in block in process_action' activesupport (3.1.3) lib/active_support/notifications.rb:53:inblock in instrument' activesupport (3.1.3) lib/active_support/notifications/instrumenter.rb:21:in instrument' activesupport (3.1.3) lib/active_support/notifications.rb:53:ininstrument' actionpack (3.1.3) lib/action_controller/metal/instrumentation.rb:29:in process_action' actionpack (3.1.3) lib/action_controller/metal/params_wrapper.rb:201:inprocess_action' activerecord (3.1.3) lib/active_record/railties/controller_runtime.rb:18:in process_action' actionpack (3.1.3) lib/abstract_controller/base.rb:121:inprocess' actionpack (3.1.3) lib/abstract_controller/rendering.rb:45:in process' actionpack (3.1.3) lib/action_controller/metal.rb:193:indispatch' actionpack (3.1.3) lib/action_controller/metal/rack_delegation.rb:14:in dispatch' actionpack (3.1.3) lib/action_controller/metal.rb:236:inblock in action' actionpack (3.1.3) lib/action_dispatch/routing/route_set.rb:65:in call' actionpack (3.1.3) lib/action_dispatch/routing/route_set.rb:65:indispatch' actionpack (3.1.3) lib/action_dispatch/routing/route_set.rb:29:in call' actionpack (3.1.3) lib/action_dispatch/routing/mapper.rb:41:incall' rack-mount (0.8.3) lib/rack/mount/route_set.rb:152:in block in call' rack-mount (0.8.3) lib/rack/mount/code_generation.rb:96:inblock in recognize' rack-mount (0.8.3) lib/rack/mount/code_generation.rb:68:in optimized_each' rack-mount (0.8.3) lib/rack/mount/code_generation.rb:95:inrecognize' rack-mount (0.8.3) lib/rack/mount/route_set.rb:141:in call' actionpack (3.1.3) lib/action_dispatch/routing/route_set.rb:532:incall' oa-core (0.3.2) lib/omniauth/strategy.rb:44:in call!' oa-core (0.3.2) lib/omniauth/strategy.rb:30:incall' oa-core (0.3.2) lib/omniauth/builder.rb:30:in call' warden (1.1.0) lib/warden/manager.rb:35:inblock in call' warden (1.1.0) lib/warden/manager.rb:34:in catch' warden (1.1.0) lib/warden/manager.rb:34:incall' actionpack (3.1.3) lib/action_dispatch/middleware/best_standards_support.rb:17:in call' rack (1.3.5) lib/rack/etag.rb:23:incall' rack (1.3.5) lib/rack/conditionalget.rb:35:in call' actionpack (3.1.3) lib/action_dispatch/middleware/head.rb:14:incall' actionpack (3.1.3) lib/action_dispatch/middleware/params_parser.rb:21:in call' actionpack (3.1.3) lib/action_dispatch/middleware/flash.rb:247:incall' rack (1.3.5) lib/rack/session/abstract/id.rb:195:in context' rack (1.3.5) lib/rack/session/abstract/id.rb:190:incall' actionpack (3.1.3) lib/action_dispatch/middleware/cookies.rb:331:in call' activerecord (3.1.3) lib/active_record/query_cache.rb:64:incall' activerecord (3.1.3) lib/active_record/connection_adapters/abstract/connection_pool.rb:477:in call' actionpack (3.1.3) lib/action_dispatch/middleware/callbacks.rb:29:inblock in call' activesupport (3.1.3) lib/active_support/callbacks.rb:392:in _run_call_callbacks' activesupport (3.1.3) lib/active_support/callbacks.rb:81:inrun_callbacks' actionpack (3.1.3) lib/action_dispatch/middleware/callbacks.rb:28:in call' actionpack (3.1.3) lib/action_dispatch/middleware/reloader.rb:68:incall' rack (1.3.5) lib/rack/sendfile.rb:101:in call' actionpack (3.1.3) lib/action_dispatch/middleware/remote_ip.rb:48:incall' actionpack (3.1.3) lib/action_dispatch/middleware/show_exceptions.rb:47:in call' railties (3.1.3) lib/rails/rack/logger.rb:13:incall' rack (1.3.5) lib/rack/methodoverride.rb:24:in call' rack (1.3.5) lib/rack/runtime.rb:17:incall' activesupport (3.1.3) lib/active_support/cache/strategy/local_cache.rb:72:in call' rack (1.3.5) lib/rack/lock.rb:15:incall' actionpack (3.1.3) lib/action_dispatch/middleware/static.rb:53:in call' railties (3.1.3) lib/rails/engine.rb:456:incall' railties (3.1.3) lib/rails/railtie/configurable.rb:30:in method_missing' /usr/lib/passenger/lib/phusion_passenger/rack/request_handler.rb:92:inprocess_request' /usr/lib/passenger/lib/phusion_passenger/abstract_request_handler.rb:207:in main_loop' /usr/lib/passenger/lib/phusion_passenger/rack/application_spawner.rb:120:inrun' /usr/lib/passenger/lib/phusion_passenger/rack/application_spawner.rb:65:in block in spawn_application' /usr/lib/passenger/lib/phusion_passenger/utils.rb:252:insafe_fork' /usr/lib/passenger/lib/phusion_passenger/rack/application_spawner.rb:58:in spawn_application' /usr/lib/passenger/lib/phusion_passenger/rack/application_spawner.rb:41:inspawn_application' /usr/lib/passenger/lib/phusion_passenger/spawn_manager.rb:159:in spawn_application' /usr/lib/passenger/lib/phusion_passenger/spawn_manager.rb:287:inhandle_spawn_application' /usr/lib/passenger/lib/phusion_passenger/abstract_server.rb:352:in main_loop' /usr/lib/passenger/lib/phusion_passenger/abstract_server.rb:196:instart_synchronously' /usr/lib/passenger/bin/passenger-spawn-server:63:in `

'

Any help would be appreciated.

josevalim commented 12 years ago

Devise is simply using your Rails setup which is trying to use sendmail for e-mail delivery. So if this is not working, it is probably because sendmail does not work on Engine Yard or your mail configurations were not set properly.

mvilrokx commented 12 years ago

Hi Jose,

Sorry but I tried everything and I cannot get this working (tried re-opening the issue but I do not seem to have permission to do this), is there any way you can give me some more information? The error I am getting is just not getting me anywhere, I don't even know where to look.

sendmail is working fine on EngineYard, I can send emails form the command line without a problem and they get routed correctly (through sendgrid) and arrive withing milliseconds.

This also works perfectly fine on my local development server, it just does not work when I push this application to EngineYard.

Also, this used to work fine before it was a RAils 3.1 application. Has anything changed for Devise in Rails 3 that I need to look at?

Any help much appreciated.

Cheers, Mark.

josevalim commented 12 years ago

Can you provide a way to reproduce the issue? Devise did not change related to mail delivery, so I don't know why this error is coming up. Also, your app fails to deliver only devise e-mail or any e-mail?

josevalim commented 12 years ago

Also, try updating the mail gem version and pinging the EY guys. :)

mvilrokx commented 12 years ago

Thanks for re-opening Jose.

As per your last comment, I have been hassling EY, but guess what they say :-). I am following up more with them tomorrow.

As for your other questions, as of now, I only have devise sending emails. I will create a new test app and try out sending emails that way. Even I can only reproduce it on EY so not sure how I could provide something you can try.

I do not have the mail gem in my Gemfile, should I? I am on the latest version of Rails 3.1.3 so I assume that comes with the latest mail gem? It looks like it is using (from the dump) version 2.3 which I think is the latest version.

I was actually looking more for a way to debug this. I am just getting this message but I have no idea where to start.

josevalim commented 12 years ago

The mail gem is a Rails 3.1.3 dependency. To debug, do this then:

1) Check if doing bundle update mail will update the mail gem and maybe solve the problem;

2) If not, create a new mailer in your current application and try to deliver the e-mail. If it works, it is probably a Devise issue, if not, probably EY one;

3) You may need to create a test app anyway after trying 1) and 2) to provide EY or us a way to reproduce the problem. But this should be the last step.

mvilrokx commented 12 years ago

Hurray, I figured out what the problem was (and it was not devise).

What really helped was sending an email from the Rails console (User.find(1).send_confirmation_instructions). That actually gave me the reason why it was failing (sendmail: recipients with -t option not supported), from there it was easy. Here's a full explanation in case somebody else hits this issue (probably typical on EngineYard, see explanation as to why):

As per the above extra error I saw, the issue has to do with the -t option being passed to "sendmail". This is done by default by the mail gem (which comes with, and is used by Rails 3.x). E.g. if you look into https://github.com/mikel/mail/blob/master/lib/mail/network/delivery_methods/sendmail.rb you can see:

def initialize(values) self.settings = { :location => '/usr/sbin/sendmail', :arguments => '-i -t' }.merge(values) end

-t is used to indicate that the recipients will be specified in the message itself (prefixed by either 'To:', 'cc:' or 'bcc:') and therefore there is no point in specifying the recipients on the actual command line. E.g. if you do

$ sendmail -t foo.bar@example.com To: test@example.com Subject: Test

body

Ctrl-D (to send email)

foo.bar@example.com will be completely ignored and the email instead will go to test@example.com. This actually works perfectly fine.

Now, where it gets interesting is on EY, sendmail is actually ssmtp (sendmail just symlinks to ssmtp) and ssmpt will error when you issue the exact same command with the error I was getting:

/usr/sbin/ssmtp -t foo.bar@example.com ssmtp: recipients with -t option not supported

and on the EY servers:

sendmail -t foo.bar@example.com sendmail: recipients with -t option not supported

because on EY:

$ ls -lrt /usr/bin/sendmail lrwxrwxrwx 1 root root 15 Dec 21 08:38 /usr/bin/sendmail -> /usr/sbin/ssmtp

This explains why this works fine on my local dev server (I don't use ssmtp, I actually use sendmail).

It seems that Rails IS providing the email address as part of the command line and therefore ssmtp raises an error and Rails barfs. The solution is as simple as overwriting the default arguments provided by the mail gem. You do this in your environment files, e.g. in config/environments/development.rb:

config.action_mailer.sendmail_settings = { :arguments => '-i' }

Sending emails started working after I added this.

Thanks for all the help!

Cheers, Mark.