Merge pull request #139 from zevaverbach/vendors
created vendors package
This commit is contained in:
@@ -6,3 +6,4 @@ __version__ = '.'.join([str(x) for x in __version_info__])
|
|||||||
|
|
||||||
__all__ = ['Imbox']
|
__all__ = ['Imbox']
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,42 @@
|
|||||||
|
import imaplib
|
||||||
|
|
||||||
from imbox.imap import ImapTransport
|
from imbox.imap import ImapTransport
|
||||||
from imbox.messages import Messages
|
from imbox.messages import Messages
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from imbox.vendors import GmailMessages, hostname_vendorname_dict, name_authentication_string_dict
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Imbox:
|
class Imbox:
|
||||||
|
|
||||||
|
authentication_error_message = None
|
||||||
|
|
||||||
def __init__(self, hostname, username=None, password=None, ssl=True,
|
def __init__(self, hostname, username=None, password=None, ssl=True,
|
||||||
port=None, ssl_context=None, policy=None, starttls=False):
|
port=None, ssl_context=None, policy=None, starttls=False,
|
||||||
|
vendor=None):
|
||||||
|
|
||||||
self.server = ImapTransport(hostname, ssl=ssl, port=port,
|
self.server = ImapTransport(hostname, ssl=ssl, port=port,
|
||||||
ssl_context=ssl_context, starttls=starttls)
|
ssl_context=ssl_context, starttls=starttls)
|
||||||
|
|
||||||
self.hostname = hostname
|
self.hostname = hostname
|
||||||
self.username = username
|
self.username = username
|
||||||
self.password = password
|
self.password = password
|
||||||
self.parser_policy = policy
|
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(
|
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 "")))
|
hostname=hostname, username=username, ssl=(" over SSL" if ssl or starttls else "")))
|
||||||
|
|
||||||
@@ -57,16 +76,22 @@ class Imbox:
|
|||||||
def messages(self, **kwargs):
|
def messages(self, **kwargs):
|
||||||
folder = kwargs.get('folder', False)
|
folder = kwargs.get('folder', False)
|
||||||
|
|
||||||
|
messages_class = Messages
|
||||||
|
|
||||||
|
if self.vendor == 'gmail':
|
||||||
|
messages_class = GmailMessages
|
||||||
|
|
||||||
if folder:
|
if folder:
|
||||||
self.connection.select(folder)
|
self.connection.select(messages_class.folder_lookup.get((folder.lower())) or folder)
|
||||||
msg = " from folder '{}'".format(folder)
|
msg = " from folder '{}'".format(folder)
|
||||||
else:
|
else:
|
||||||
msg = " from inbox"
|
msg = " from inbox"
|
||||||
|
|
||||||
logger.info("Fetch list of messages{}".format(msg))
|
logger.info("Fetch list of messages{}".format(msg))
|
||||||
return Messages(connection=self.connection,
|
|
||||||
parser_policy=self.parser_policy,
|
return messages_class(connection=self.connection,
|
||||||
**kwargs)
|
parser_policy=self.parser_policy,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
def folders(self):
|
def folders(self):
|
||||||
return self.connection.list()
|
return self.connection.list()
|
||||||
@@ -8,6 +8,8 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class Messages:
|
class Messages:
|
||||||
|
|
||||||
|
folder_lookup = {}
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
connection,
|
connection,
|
||||||
parser_policy,
|
parser_policy,
|
||||||
|
|||||||
@@ -138,6 +138,8 @@ def fetch_email_by_uid(uid, connection, parser_policy):
|
|||||||
|
|
||||||
email_object = parse_email(raw_email, policy=parser_policy)
|
email_object = parse_email(raw_email, policy=parser_policy)
|
||||||
flags = parse_flags(raw_headers.decode())
|
flags = parse_flags(raw_headers.decode())
|
||||||
|
if len(flags) > 0:
|
||||||
|
print(type(flags[0]))
|
||||||
email_object.__dict__['flags'] = flags
|
email_object.__dict__['flags'] = flags
|
||||||
|
|
||||||
return email_object
|
return email_object
|
||||||
|
|||||||
@@ -26,5 +26,9 @@ def parse_attachment(message_part: Message) -> Optional[Dict[str, Union[int, str
|
|||||||
def decode_content(message: Message) -> str: ...
|
def decode_content(message: Message) -> str: ...
|
||||||
|
|
||||||
def fetch_email_by_uid(uid: bytes, connection: IMAP4_SSL, parser_policy: Optional[Policy]) -> Struct: ...
|
def fetch_email_by_uid(uid: bytes, connection: IMAP4_SSL, parser_policy: Optional[Policy]) -> Struct: ...
|
||||||
|
raw_headers: bytes
|
||||||
|
raw_email: bytes
|
||||||
|
|
||||||
|
def parse_flags(headers: str) -> Union[list, List[bytes]]: ...
|
||||||
|
|
||||||
def parse_email(raw_email: bytes, policy: Optional[Policy]) -> Struct: ...
|
def parse_email(raw_email: bytes, policy: Optional[Policy]) -> Struct: ...
|
||||||
|
|||||||
11
imbox/vendors/__init__.py
vendored
Normal file
11
imbox/vendors/__init__.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
from imbox.vendors.gmail import GmailMessages
|
||||||
|
|
||||||
|
vendors = [GmailMessages]
|
||||||
|
|
||||||
|
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__ = [v.__name__ for v in vendors]
|
||||||
|
|
||||||
|
__all__ += ['hostname_vendorname_dict',
|
||||||
|
'name_authentication_string_dict']
|
||||||
9
imbox/vendors/__init__.pyi
vendored
Normal file
9
imbox/vendors/__init__.pyi
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from typing import List, Dict, Optional
|
||||||
|
|
||||||
|
from imbox.messages import Messages
|
||||||
|
|
||||||
|
vendors: List[Messages]
|
||||||
|
|
||||||
|
hostname_vendorname_dict: Dict[str, str]
|
||||||
|
name_authentication_string_dict: Dict[str, Optional[str]]
|
||||||
|
|
||||||
29
imbox/vendors/gmail.py
vendored
Normal file
29
imbox/vendors/gmail.py
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
from imbox.messages import Messages
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
14
imbox/vendors/gmail.pyi
vendored
Normal file
14
imbox/vendors/gmail.pyi
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import datetime
|
||||||
|
from email._policybase import Policy
|
||||||
|
from imaplib import IMAP4, IMAP4_SSL
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
from imbox.messages import Messages
|
||||||
|
|
||||||
|
|
||||||
|
class GmailMessages(Messages):
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
connection: Union[IMAP4, IMAP4_SSL],
|
||||||
|
parser_policy: Policy,
|
||||||
|
**kwargs: Union[bool, str, datetime.date]) -> None: ...
|
||||||
Reference in New Issue
Block a user