From: TJ Date: 2008-10-28T02:34:41+09:00 Subject: problem catching nested exception Hello, I'm new to ruby and just wrote a script that try to send many email, reading them from a database. For each domain, the script opens a TCP socket to the first available MX, and try to send as many email as it can. My problem is that my script does not always catch exception as I want, and I think my exception handling in nested loops is not correct. Here is a code extract, starting with a SMTP connection : begin Timeout.timeout 1 do smtp = Net::SMTP.start mx, 25, $hostname end rescue Exception => e case e when Timeout::Error error = 'timeout connect' when Errno::ECONNREFUSED error = 'connection refused' when Errno::ECONNRESET error = 'connection reset' when Errno::EHOSTUNREACH error = 'host not reachable' else error = "unknown #{e.to_s}" end puts " KO #{error}, next MX" if $verbose next end domain.addr.each do |addr| puts " #{addr.email} (#{addr.id})" if $verbose begin Timeout.timeout 1 do smtp.send_message data, mailing.return_path, addr.email end rescue Exception => ee case ee when Net::SMTPServerBusy, Net::SMTPSyntaxError, Net::SMTPFatalError, Net::SMTPUnknownError error = ee.to_s.strip when Timeout::Error error = '001 timeout send' when EOFError error = '002 eof' when Errno::ECONNRESET error = '004 connection reset' when TypeError error = '090 strange TypeError' else error = "unknown #{ee.to_s}" end puts " KO #{error}" if $verbose next end puts " OK" if $verbose end smtp.finish break "Most of the time" it works, but sometimes my script failed that way : email@address (693792) KO 451 This server employs greylisting as a means of reducing spam. Please resend e-mail shortly. /usr/lib/ruby/1.8/net/protocol.rb:133:in `sysread': Connection reset by peer (Errno::ECONNRESET) from /usr/lib/ruby/1.8/net/protocol.rb:133:in `rbuf_fill' from /usr/lib/ruby/1.8/timeout.rb:56:in `timeout' from /usr/lib/ruby/1.8/timeout.rb:76:in `timeout' from /usr/lib/ruby/1.8/net/protocol.rb:132:in `rbuf_fill' from /usr/lib/ruby/1.8/net/protocol.rb:116:in `readuntil' from /usr/lib/ruby/1.8/net/protocol.rb:126:in `readline' from /usr/lib/ruby/1.8/net/smtp.rb:664:in `recv_response' from /usr/lib/ruby/1.8/net/smtp.rb:651:in `getok' ... 8 levels... from /root/bin/mailing_3.rb:195:in `each' from /root/bin/mailing_3.rb:195 from /root/bin/mailing_3.rb:193:in `each' from /root/bin/mailing_3.rb:193 I do not understand why Errno::ECONNRESET is not catch, because I use it in each rescue block, and I do not see why it would be thrown in another part of the script. I also do not understand why "sometimes" it work as I want and "sometimes" not. I removed some part of the script in this post because of its length, full script is available at : http://pastie.org/301549 Any comment will be greatly welcomed, not only for my exception problem, but I really need to understand that last one ;-)