'Problem with Recursive Exception to Send Continuous Email Notification in Python

I'm trying to make an exception that will call itself if it catch an exception. The goal is to send notification email without interruption due to errors from the server. But I got stuck with stack overflow first due to too many recursion happening when the email sent reached the daily send quota, so I went around it by not sending after the quota was exceeded. Then another problem arise when other types of exception are caught. somehow the program exited after it successfully send an email after a few recursion due to temporary server error. here's the exception I made :

try:
        mailObj.login(sender, pw)
        mailObj.sendmail(sender, receiver, emailText.as_string())
    except Exception as e:
        print ("fail to send email. error : ", e)
        if str(e).find("Daily user sending quota exceeded") == -1 :
            print("not send quota exceeded, retrying in 5")
            time.sleep(5)
            send_mail(body)
    else :
        print("mail sent")

And here's the CMD screenshot of what happened when it suddenly exit : Recursive exception stop the program and dump all exception calledyou can see that it just suddenly exited the program when the email is sent after several recursion

What I want to achieve is a continuous notification-email-sending function in python. Using this Recursive exception is the way I know how to do it. it sure is better if your solution can solve this problem, but feel free to share your way of sending continuous email without interruption if you know a better way.



Solution 1:[1]

In the first place, you should always avoid catching all the Exceptions in your program, it sure may seem the easy way, but it can cause you many problems when executing or debugging your code

see this post for more details

In your case, you should treat your exceptions in 2 separate except blocs, since clearly you have 2 different type of exceptions

  • The first one if the send quota is exceeded
  • For the second exception, you should be more specific with the type of exception you want to catch, not only it's a better practice, but you can track what went wrong in your program more easily

and the second your code will look something like this:

try:
    mailObj.login(sender, pw)
    mailObj.sendmail(sender, receiver, emailText.as_string())
except DailyUserQuota as e:
    print("fail to send email. error : ", e)
except TheOtherExceptionYouExpecting as e:
    print("fail to send email. error : ", e)
    print("not send quota exceeded, retrying in 5")
    time.sleep(5)
    # sending the email again
else :
    print("mail sent")

Now with this out of the way, catching the exceptions outside send_mail() function should fix your error (at least it will make it easier to debug), so instead of using a recursion try to use a loop, like this for exemple:

sending_email = True
while sending_email:
    try:
        send_mail(body)
    except DailyUserQuota as e:
        print("fail to send email. error : ", e)
        sending_email = False
    except TheOtherExceptionYouExpecting as e:
        print("fail to send email. error : ", e)
        print("not send quota exceeded, retrying in 5")
        time.sleep(5) # trying to send the email again after 5 seconds
    else :
        sending_email = False
        print("mail sent")

This code will basically do the same thing your code does but without the recursion and without raising Exceptions inside your except block, which is never a good thing.

In a final note, you should avoid posting images in your posts for codes, error messages, logs etc. refer to this post to understand why

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1