Question

I am using the external library IMAPClient. When the login fails, i see this error : imaplib.error: [AUTHENTICATIONFAILED] Authentication failed.

When i try except imaplib.error: i get : AttributeError: 'module' object has no attribute 'error'

The documentation of imaplib says that the exception should be IMAP4.error Then why is IMAPClient raising imaplib.error and how do i catch it ?

Was it helpful?

Solution

The error message you see:

imaplib.error: [AUTHENTICATIONFAILED] Authentication failed.

is describing the error as best it knows how; at the time the exception occurs, the exception class is called "imaplib.error", because whoever is raising it has described it that way (more on this later). I poked around, and I think I've found it for you:

Python 2.7.2 (default, Nov 14 2011, 19:37:59) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import imaplib
>>> imaplib.IMAP4.error
<class 'imaplib.error'>

I opened up the imaplib.py file, and found what seems like an odd exception-throwing mechanism. "IMAP4" is a class, and "error" is a class defined inside the IMAP4 class. Python doesn't appear to "nest" the classes - just the class definitions. So once an object of class "error" exists, it's an object of class "error" which was defined in the scope "imaplib". The fact that the "error" class definition was inside the "IMAP4" class lib definition is irrelevant to Python. On the other hand, in order for you to describe an object of class "error" before such an object exists, you need to reference it as imaplib.IMAP4.error in order for Python to find the definition of the class you are talking about.

Very confusing, I know, and I didn't really know all of this before I started investigating the question. Here's a brief illustration:

Python 2.7.2 (default, Nov 14 2011, 19:37:59) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> class foo(object):
...   class bar(object):
...     pass
...   def b(self):
...     return bar()
... 
>>> bar
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'bar' is not defined
>>> foo.bar
<class '__main__.bar'>
>>> foo().bar()
<__main__.bar object at 0x10048dd10>

Basically, you were trying to do a very reasonable thing, but the way the imaplib library handles exception throwing is a little odd, making your life difficult. Long story short, you should try to catch imaplib.IMAP4.error and move on with your life.

OTHER TIPS

(Disclaimer: I'm the maintainer of IMAPClient)

IMAPClient uses imaplib under the hood which is why you're seeing imaplib errors when using it. To simplify things a little, imaplib's exceptions are aliased on to the IMAPClient class. To catch errors from IMAPClient you can do something like this:

from imapclient import IMAPClient

try:
    client = IMAPClient(...)
    client.do_something(...) 
    client.logout()
except IMAPClient.Error, err:
    # handle error here

Error is the base exception class (same as imaplib.IMAP4.error). There's also AbortError and ReadOnlyError.

IMAPClient uses these exceptions when it raises errors itself so there's only one set of exceptions to worry about in your code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top