Forum: Ruby problem catching nested exception

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
9e66db063e573d94fc7a866eabae2a24?d=identicon&s=25 TJ (Guest)
on 2008-10-27 18:35
(Received via mailing list)
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 ;-)
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (candlerb)
on 2008-10-27 22:30
It's possible the exception is being raised where you do not expect it,
e.g. in smtp.finish

Try to find out exactly what line in mailing_3.rb generates the
exception. The fact that it is hidden under "... 8 levels..." is
annoying here.

I'm not sure if there's a generic way to stop Ruby suppressing the
intermediate levels of the exception report, but a simple solution is to
wrap your code with:

begin
... rest of code
rescue Exception => e
  STDERR.puts "#{e.message}\n#{e.backtrace.join("\n")}"
end
9e66db063e573d94fc7a866eabae2a24?d=identicon&s=25 TJ (Guest)
on 2008-10-28 10:10
(Received via mailing list)
On 2008-10-27, Brian Candler <b.candler@pobox.com> wrote:
> It's possible the exception is being raised where you do not expect it,
> e.g. in smtp.finish

  You are right, exception was raised by smtp.finish, and I really did
not expect it !

> Try to find out exactly what line in mailing_3.rb generates the
> exception. The fact that it is hidden under "... 8 levels..." is
> annoying here.

  Yes, and I should rewrite those nested loops in a clean way.

> I'm not sure if there's a generic way to stop Ruby suppressing the
> intermediate levels of the exception report, but a simple solution is to
> wrap your code with:
>
> begin
> .. rest of code
> rescue Exception => e
>   STDERR.puts "#{e.message}\n#{e.backtrace.join("\n")}"
> end

  Thank you for your time and all these informations.
2dac4384238ef183a10fadf10ed6968c?d=identicon&s=25 Big Bet (bigbet)
on 2009-06-18 08:54
TJ wrote:
> 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.
>

please send a copy this script,thanks
This topic is locked and can not be replied to.