Skip to content

Commit

Permalink
added authentication_error_message as a class attribute to Imbox.…
Browse files Browse the repository at this point in the history
… If `Imbox.vendor` is not None, look for a custom authentication error string, and raise it if there's a problem logging in. The default error value is raised if there is no custom string.

created `name_authentication_string_dict` from all subclasses of `Messages` in `vendors/__init__.py`, for the lookup mentioned above.

Implement architecture discussed in #131, deciding whether to use `Messages` or a subclass of it in `Imbox.messages` based on the `Imbox.vendor` value.  Use the `folder_lookup` dict, present on `Messages` but only filled in on its subclasses, to select the right folder based on a lowercased "standard" name given as the value of `folder`.

created a blank `folder_lookup` on `Messages`.

filled in the first vendor that subclasses `Messages`, `GmailMessages`.  It contains class attributes `authentication_error_message`, `hostname`, `name`, used for purposes described above, as well as `folder_lookup` which is a dict containing aliases, sometimes several, for Gmail's unique folder naming scheme.  These aliases are meant to be "human-friendly" for intuitive `folder` selection in calls to `Imbox.messages`.

fixes #131.
  • Loading branch information
zevaverbach committed Jul 27, 2018
1 parent 7d11b59 commit 1fbb851
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 11 deletions.
32 changes: 23 additions & 9 deletions imbox/imbox.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import imaplib

from imbox.imap import ImapTransport
from imbox.messages import Messages

import logging

from imbox.vendors import GmailMessages, hostname_vendorname_dict
from imbox.vendors import GmailMessages, hostname_vendorname_dict, name_authentication_string_dict

logger = logging.getLogger(__name__)


class Imbox:

authentication_error_message = None

def __init__(self, hostname, username=None, password=None, ssl=True,
port=None, ssl_context=None, policy=None, starttls=False,
vendor=None):
Expand All @@ -21,10 +25,20 @@ def __init__(self, hostname, username=None, password=None, ssl=True,
self.username = username
self.password = password
self.parser_policy = policy
self.connection = self.server.connect(username, password)
self.vendor = vendor or hostname_vendorname_dict.get(self.hostname)

if self.vendor is not None:
self.authentication_error_message = name_authentication_string_dict.get(self.vendor)

try:
self.connection = self.server.connect(username, password)
except imaplib.IMAP4.error as e:
if self.authentication_error_message is None:
raise
raise imaplib.IMAP4.error(self.authentication_error_message + '\n' + str(e))

logger.info("Connected to IMAP Server with user {username} on {hostname}{ssl}".format(
hostname=hostname, username=username, ssl=(" over SSL" if ssl or starttls else "")))
self.vendor = vendor or hostname_vendorname_dict.get(self.hostname)

def __enter__(self):
return self
Expand Down Expand Up @@ -62,19 +76,19 @@ def move(self, uid, destination_folder):
def messages(self, **kwargs):
folder = kwargs.get('folder', False)

messages_class = Messages

if self.vendor == 'gmail':
messages_class = GmailMessages

if folder:
self.connection.select(folder)
self.connection.select(messages_class.folder_lookup.get((folder.lower())) or folder)
msg = " from folder '{}'".format(folder)
else:
msg = " from inbox"

logger.info("Fetch list of messages{}".format(msg))

messages_class = Messages

if self.vendor == 'gmail':
messages_class = GmailMessages

return messages_class(connection=self.connection,
parser_policy=self.parser_policy,
**kwargs)
Expand Down
2 changes: 2 additions & 0 deletions imbox/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

class Messages:

folder_lookup = {}

def __init__(self,
connection,
parser_policy,
Expand Down
7 changes: 5 additions & 2 deletions imbox/vendors/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from imbox.vendors.gmail import GmailMessages

vendors = [GmailMessages]

hostname_vendorname_dict = {GmailMessages.hostname: GmailMessages.name}
hostname_vendorname_dict = {vendor.hostname: vendor.name for vendor in vendors}
name_authentication_string_dict = {vendor.name: vendor.authentication_error_message for vendor in vendors}

__all__ = ['GmailMessages',
'hostname_vendorname_dict']
'hostname_vendorname_dict',
'name_authentication_string_dict']
23 changes: 23 additions & 0 deletions imbox/vendors/gmail.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,28 @@


class GmailMessages(Messages):
authentication_error_message = ('If you\'re not using an app-specific password, grab one here: '
'https://myaccount.google.com/apppasswords')
hostname = 'imap.gmail.com'
name = 'gmail'
folder_lookup = {

'all_mail': '"[Gmail]/All Mail"',
'all': '"[Gmail]/All Mail"',
'all mail': '"[Gmail]/All Mail"',
'sent': '"[Gmail]/Sent Mail"',
'sent mail': '"[Gmail]/Sent Mail"',
'sent_mail': '"[Gmail]/Sent Mail"',
'drafts': '"[Gmail]/Drafts"',
'important': '"[Gmail]/Important"',
'spam': '"[Gmail]/Spam"',
'starred': '"[Gmail]/Starred"',
'trash': '"[Gmail]/Trash"',

}

def __init__(self,
connection,
parser_policy,
**kwargs):
super().__init__(connection, parser_policy, **kwargs)

0 comments on commit 1fbb851

Please sign in to comment.