Skip to content

Commit

Permalink
moved build_search_query to Messages, refactored to use a class attri…
Browse files Browse the repository at this point in the history
…bute of IMAP_ATTRIBUTE_LOOKUP, so that the vendors package can overwrite and add entries to it for, for example, Gmail's IMAP extensions. added X-GM-RAW to GmailMessages' copy of the lookup to make partial subject searches work.
  • Loading branch information
zevaverbach committed Oct 18, 2018
1 parent 782d397 commit 27d19a2
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 86 deletions.
Binary file added imbox/.DS_Store
Binary file not shown.
19 changes: 12 additions & 7 deletions imbox/imbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,16 @@ def __init__(self, hostname, username=None, password=None, ssl=True,
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)
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))
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 "")))
Expand All @@ -61,16 +63,18 @@ def mark_flag(self, uid):
self.connection.uid('STORE', uid, '+FLAGS', '(\\Flagged)')

def delete(self, uid):
logger.info("Mark UID {} with \\Deleted FLAG and expunge.".format(int(uid)))
self.connection.uid('STORE', uid, '+FLAGS', '(\\Deleted)')
logger.info(
"Mark UID {} with \\Deleted FLAG and expunge.".format(int(uid)))
self.connection.expunge()

def copy(self, uid, destination_folder):
logger.info("Copy UID {} to {} folder".format(int(uid), str(destination_folder)))
logger.info("Copy UID {} to {} folder".format(
int(uid), str(destination_folder)))
return self.connection.uid('COPY', uid, destination_folder)

def move(self, uid, destination_folder):
logger.info("Move UID {} to {} folder".format(int(uid), str(destination_folder)))
logger.info("Move UID {} to {} folder".format(
int(uid), str(destination_folder)))
if self.copy(uid, destination_folder):
self.delete(uid)

Expand All @@ -83,7 +87,8 @@ def messages(self, **kwargs):
messages_class = GmailMessages

if folder:
self.connection.select(messages_class.folder_lookup.get((folder.lower())) or folder)
self.connection.select(
messages_class.FOLDER_LOOKUP.get((folder.lower())) or folder)
msg = " from folder '{}'".format(folder)
else:
msg = " from inbox"
Expand Down
35 changes: 30 additions & 5 deletions imbox/messages.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
import datetime
import logging

from imbox.parser import fetch_email_by_uid
from imbox.query import build_search_query

import logging

logger = logging.getLogger(__name__)


class Messages:

folder_lookup = {}
IMAP_ATTRIBUTE_LOOKUP = {
'unread': '(UNSEEN)',
'unflagged': '(UNFLAGGED)',
'sent_from': '(FROM "{}")',
'sent_to': '(TO "{}")',
'date__gt': '(SINCE "{}")',
'date__lt': '(BEFORE "{}")',
'date__on': '(ON "{}")',
'subject': '(SUBJECT "{}")',
}

FOLDER_LOOKUP = {}

def __init__(self,
connection,
Expand All @@ -28,12 +40,25 @@ def _fetch_email(self, uid):
parser_policy=self.parser_policy)

def _query_uids(self, **kwargs):
query_ = build_search_query(**kwargs)
message, data = self.connection.uid('search', None, query_)
query_ = self._build_search_query(**kwargs)
_, data = self.connection.uid('search', None, query_)
if data[0] is None:
return []
return data[0].split()

def _build_search_query(self, **kwargs):
query = []
for name, value in kwargs.items():
if value is not None:
if isinstance(value, datetime.date):
value = value.strftime('%d-%b-%Y')
query.append(self.IMAP_ATTRIBUTE_LOOKUP[name].format(value))

if query:
return " ".join(query)

return "(ALL)"

def _fetch_email_list(self):
for uid in self._uid_list:
yield uid, self._fetch_email(uid)
Expand Down
65 changes: 0 additions & 65 deletions imbox/query.py

This file was deleted.

7 changes: 0 additions & 7 deletions imbox/query.pyi

This file was deleted.

5 changes: 3 additions & 2 deletions imbox/vendors/gmail.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class GmailMessages(Messages):
'https://myaccount.google.com/apppasswords')
hostname = 'imap.gmail.com'
name = 'gmail'
folder_lookup = {
FOLDER_LOOKUP = {

'all_mail': '"[Gmail]/All Mail"',
'all': '"[Gmail]/All Mail"',
Expand All @@ -19,11 +19,12 @@ class GmailMessages(Messages):
'spam': '"[Gmail]/Spam"',
'starred': '"[Gmail]/Starred"',
'trash': '"[Gmail]/Trash"',

}

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

self.IMAP_ATTRIBUTE_LOOKUP['subject'] = '(X-GM-RAW "{}")'
super().__init__(connection, parser_policy, **kwargs)

0 comments on commit 27d19a2

Please sign in to comment.