Skip to content

Commit

Permalink
Merge pull request rickypc#11 from Pakkanen1/master
Browse files Browse the repository at this point in the history
Fixing "walk multipart email", adding "cc" criteria, adding "get email count" keyword, updating tests
  • Loading branch information
lasselindqvist authored Aug 24, 2020
2 parents 2b72b57 + 8c69dc1 commit 99d9519
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 73 deletions.
10 changes: 7 additions & 3 deletions src/ImapLibrary2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ def walk_multipart_email(self, email_index):
| Walk Multipart Email | INDEX |
"""
if not self._is_walking_multipart(email_index):
data = self._imap.uid('fetch', email_index, '(RFC822)')[1][0][1]
data = self._imap.uid('fetch', email_index, '(RFC822)')[1][0][1].decode('UTF-8')
msg = message_from_string(data)
self._start_multipart_walk(email_index, msg)
try:
Expand All @@ -356,6 +356,9 @@ def walk_multipart_email(self, email_index):
# return number of parts
return len(self._mp_msg.get_payload())

def get_email_count(self, **kwargs):
return len(self._check_emails(**kwargs))

def _check_emails(self, **kwargs):
"""Returns filtered email."""
folder = '"%s"' % str(kwargs.pop('folder', self.FOLDER))
Expand All @@ -375,13 +378,16 @@ def _criteria(**kwargs):
criteria = []
recipient = kwargs.pop('recipient', kwargs.pop('to_email', kwargs.pop('toEmail', None)))
sender = kwargs.pop('sender', kwargs.pop('from_email', kwargs.pop('fromEmail', None)))
cc = kwargs.pop('cc', kwargs.pop('cc_email', kwargs.pop('ccEmail', None)))
status = kwargs.pop('status', None)
subject = kwargs.pop('subject', None)
text = kwargs.pop('text', None)
if recipient:
criteria += ['TO', '"%s"' % recipient]
if sender:
criteria += ['FROM', '"%s"' % sender]
if cc:
criteria += ['CC', '"%s"' % cc]
if subject:
criteria += ['SUBJECT', '"%s"' % subject]
if text:
Expand Down Expand Up @@ -412,5 +418,3 @@ def _get_all_emails(self):
"""Saves all existing emails to internal variable."""
typ, mails = self._imap.uid('search', None, 'ALL')
self._mails = mails[0].split()


95 changes: 25 additions & 70 deletions test/utest/test_imaplibrary.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@

from sys import path
path.append('src')
from ImapLibrary import ImapLibrary
from ImapLibrary2 import ImapLibrary2
import mock
import unittest


class ImapLibraryTests(unittest.TestCase):
class ImapLibrary2Tests(unittest.TestCase):
"""Imap library test class."""

def setUp(self):
"""Instantiate the Imap library class."""
self.library = ImapLibrary()
self.library = ImapLibrary2()
self.password = 'password'
self.port = 143
self.port_secure = 993
Expand All @@ -48,7 +48,7 @@ def setUp(self):

def test_should_have_default_values(self):
"""Imap library instance should have default values set."""
self.assertIsInstance(self.library, ImapLibrary)
self.assertIsInstance(self.library, ImapLibrary2)
self.assertIsNone(self.library._email_index)
self.assertIsNone(self.library._imap)
self.assertIsInstance(self.library._mails, list)
Expand All @@ -59,7 +59,7 @@ def test_should_have_default_values(self):
self.assertEqual(self.library.PORT_SECURE, self.port_secure)
self.assertEqual(self.library.FOLDER, self.folder)

@mock.patch('ImapLibrary.IMAP4_SSL')
@mock.patch('ImapLibrary2.IMAP4_SSL')
def test_should_open_secure_mailbox(self, mock_imap):
"""Open mailbox should open secure connection to IMAP server
with requested credentials.
Expand All @@ -70,7 +70,7 @@ def test_should_open_secure_mailbox(self, mock_imap):
self.library._imap.login.assert_called_with(self.username, self.password)
self.library._imap.select.assert_called_with(self.folder_check)

@mock.patch('ImapLibrary.IMAP4_SSL')
@mock.patch('ImapLibrary2.IMAP4_SSL')
def test_should_open_secure_mailbox_with_custom_port(self, mock_imap):
"""Open mailbox should open secure connection to IMAP server
with requested credentials and custom port.
Expand All @@ -81,7 +81,7 @@ def test_should_open_secure_mailbox_with_custom_port(self, mock_imap):
self.library._imap.login.assert_called_with(self.username, self.password)
self.library._imap.select.assert_called_with(self.folder_check)

@mock.patch('ImapLibrary.IMAP4_SSL')
@mock.patch('ImapLibrary2.IMAP4_SSL')
def test_should_open_secure_mailbox_with_custom_folder(self, mock_imap):
"""Open mailbox should open secure connection to IMAP server with
requested credentials to a custom folder
Expand All @@ -92,7 +92,7 @@ def test_should_open_secure_mailbox_with_custom_folder(self, mock_imap):
self.library._imap.login.assert_called_with(self.username, self.password)
self.library._imap.select.assert_called_with('"Outbox"')

@mock.patch('ImapLibrary.IMAP4_SSL')
@mock.patch('ImapLibrary2.IMAP4_SSL')
def test_should_open_secure_mailbox_with_server_key(self, mock_imap):
"""Open mailbox should open secure connection to IMAP server
using 'server' key with requested credentials.
Expand All @@ -103,7 +103,7 @@ def test_should_open_secure_mailbox_with_server_key(self, mock_imap):
self.library._imap.login.assert_called_with(self.username, self.password)
self.library._imap.select.assert_called_with(self.folder_check)

@mock.patch('ImapLibrary.IMAP4')
@mock.patch('ImapLibrary2.IMAP4')
def test_should_open_non_secure_mailbox(self, mock_imap):
"""Open mailbox should open non-secure connection to IMAP server
with requested credentials.
Expand All @@ -114,7 +114,7 @@ def test_should_open_non_secure_mailbox(self, mock_imap):
self.library._imap.login.assert_called_with(self.username, self.password)
self.library._imap.select.assert_called_with(self.folder_check)

@mock.patch('ImapLibrary.IMAP4_SSL')
@mock.patch('ImapLibrary2.IMAP4_SSL')
def test_should_return_email_index(self, mock_imap):
"""Returns email index from connected IMAP session."""
self.library.open_mailbox(host=self.server, user=self.username,
Expand All @@ -127,7 +127,7 @@ def test_should_return_email_index(self, mock_imap):
'"%s"' % self.sender)
self.assertEqual(index, '0')

@mock.patch('ImapLibrary.IMAP4_SSL')
@mock.patch('ImapLibrary2.IMAP4_SSL')
def test_should_return_email_index_with_sender_filter(self, mock_imap):
"""Returns email index from connected IMAP session
with sender filter.
Expand All @@ -152,7 +152,7 @@ def test_should_return_email_index_with_sender_filter(self, mock_imap):
'"%s"' % self.sender)
self.assertEqual(index, '0')

@mock.patch('ImapLibrary.IMAP4_SSL')
@mock.patch('ImapLibrary2.IMAP4_SSL')
def test_should_return_email_index_with_recipient_filter(self, mock_imap):
"""Returns email index from connected IMAP session
with recipient filter.
Expand All @@ -175,9 +175,9 @@ def test_should_return_email_index_with_recipient_filter(self, mock_imap):
self.library._imap.select.assert_called_with(self.folder_check)
self.library._imap.uid.assert_called_with('search', None, 'TO',
'"%s"' % self.recipient)
self.assertEqual(index, '0')
self.assertEqual(index, '0')

@mock.patch('ImapLibrary.IMAP4_SSL')
@mock.patch('ImapLibrary2.IMAP4_SSL')
def test_should_return_email_index_with_subject_filter(self, mock_imap):
"""Returns email index from connected IMAP session
with subject filter.
Expand All @@ -192,7 +192,7 @@ def test_should_return_email_index_with_subject_filter(self, mock_imap):
'"%s"' % self.subject)
self.assertEqual(index, '0')

@mock.patch('ImapLibrary.IMAP4_SSL')
@mock.patch('ImapLibrary2.IMAP4_SSL')
def test_should_return_email_index_with_text_filter(self, mock_imap):
"""Returns email index from connected IMAP session with text filter."""
self.library.open_mailbox(host=self.server, user=self.username,
Expand All @@ -205,7 +205,7 @@ def test_should_return_email_index_with_text_filter(self, mock_imap):
'"%s"' % self.text)
self.assertEqual(index, '0')

@mock.patch('ImapLibrary.IMAP4_SSL')
@mock.patch('ImapLibrary2.IMAP4_SSL')
def test_should_return_email_index_with_status_filter(self, mock_imap):
"""Returns email index from connected IMAP session with status filter."""
self.library.open_mailbox(host=self.server, user=self.username,
Expand All @@ -217,7 +217,7 @@ def test_should_return_email_index_with_status_filter(self, mock_imap):
self.library._imap.uid.assert_called_with('search', None, self.status)
self.assertEqual(index, '0')

@mock.patch('ImapLibrary.IMAP4_SSL')
@mock.patch('ImapLibrary2.IMAP4_SSL')
def test_should_return_email_index_with_folder_filter(self, mock_imap):
"""Returns email index from connected IMAP session with
folder filter.
Expand All @@ -232,7 +232,7 @@ def test_should_return_email_index_with_folder_filter(self, mock_imap):
self.library._imap.select.assert_called_with(self.folder_filter)
self.assertEqual(index, '0')

@mock.patch('ImapLibrary.IMAP4_SSL')
@mock.patch('ImapLibrary2.IMAP4_SSL')
def test_should_return_email_index_without_filter(self, mock_imap):
"""Returns email index from connected IMAP session without filter."""
self.library.open_mailbox(host=self.server, user=self.username,
Expand All @@ -244,23 +244,7 @@ def test_should_return_email_index_without_filter(self, mock_imap):
self.library._imap.uid.assert_called_with('search', None, self.status)
self.assertEqual(index, '0')

# DEPRECATED
@mock.patch('ImapLibrary.IMAP4_SSL')
def test_should_return_email_index_from_deprecated_keyword(self, mock_imap):
"""Returns email index from connected IMAP session
using deprecated keyword.
"""
self.library.open_mailbox(host=self.server, user=self.username,
password=self.password)
self.library._imap.select.return_value = ['OK', ['1']]
self.library._imap.uid.return_value = ['OK', ['0']]
index = self.library.wait_for_mail(sender=self.sender)
self.library._imap.select.assert_called_with(self.folder_check)
self.library._imap.uid.assert_called_with('search', None, 'FROM',
'"%s"' % self.sender)
self.assertEqual(index, '0')

@mock.patch('ImapLibrary.IMAP4_SSL')
@mock.patch('ImapLibrary2.IMAP4_SSL')
def test_should_return_email_index_after_delay(self, mock_imap):
"""Returns email index from connected IMAP session after some delay."""
self.library.open_mailbox(host=self.server, user=self.username,
Expand All @@ -273,7 +257,7 @@ def test_should_return_email_index_after_delay(self, mock_imap):
'"%s"' % self.sender)
self.assertEqual(index, '0')

@mock.patch('ImapLibrary.IMAP4_SSL')
@mock.patch('ImapLibrary2.IMAP4_SSL')
def test_should_raise_exception_on_timeout(self, mock_imap):
"""Raise exception on timeout."""
self.library.open_mailbox(host=self.server, user=self.username,
Expand All @@ -286,7 +270,7 @@ def test_should_raise_exception_on_timeout(self, mock_imap):
self.assertTrue("No email received within 0s" in context.exception)
self.library._imap.select.assert_called_with(self.folder_check)

@mock.patch('ImapLibrary.IMAP4_SSL')
@mock.patch('ImapLibrary2.IMAP4_SSL')
def test_should_raise_exception_on_select_error(self, mock_imap):
"""Raise exception on imap select error."""
self.library.open_mailbox(host=self.server, user=self.username,
Expand All @@ -297,7 +281,7 @@ def test_should_raise_exception_on_select_error(self, mock_imap):
self.assertTrue("imap.select error: NOK, ['1']" in context.exception)
self.library._imap.select.assert_called_with(self.folder_check)

@mock.patch('ImapLibrary.IMAP4_SSL')
@mock.patch('ImapLibrary2.IMAP4_SSL')
def test_should_raise_exception_on_search_error(self, mock_imap):
"""Raise exception on imap search error."""
self.library.open_mailbox(host=self.server, user=self.username,
Expand All @@ -312,17 +296,7 @@ def test_should_raise_exception_on_search_error(self, mock_imap):
self.library._imap.uid.assert_called_with('search', None, 'FROM', '"%s"' %
self.sender)

@mock.patch('ImapLibrary.IMAP4_SSL')
def test_should_delete_all_emails(self, mock_imap):
"""Delete all emails."""
self.library.open_mailbox(host=self.server, user=self.username,
password=self.password)
self.library._mails = ['0']
self.library.delete_all_emails()
self.library._imap.uid.assert_called_with('store', '0', '+FLAGS', r'(\DELETED)')
self.library._imap.expunge.assert_called_with()

@mock.patch('ImapLibrary.IMAP4_SSL')
@mock.patch('ImapLibrary2.IMAP4_SSL')
def test_should_delete_email(self, mock_imap):
"""Delete specific email."""
self.library.open_mailbox(host=self.server, user=self.username,
Expand All @@ -331,34 +305,15 @@ def test_should_delete_email(self, mock_imap):
self.library._imap.uid.assert_called_with('store', '0', '+FLAGS', r'(\DELETED)')
self.library._imap.expunge.assert_called_with()

@mock.patch('ImapLibrary.IMAP4_SSL')
def test_should_mark_all_emails_as_read(self, mock_imap):
"""Mark all emails as read."""
self.library.open_mailbox(host=self.server, user=self.username,
password=self.password)
self.library._mails = ['0']
self.library.mark_all_emails_as_read()
self.library._imap.uid.assert_called_with('store', '0', '+FLAGS', r'\SEEN')

# DEPRECATED
@mock.patch('ImapLibrary.IMAP4_SSL')
def test_should_mark_all_emails_as_read_from_deprecated_keyword(self, mock_imap):
"""Mark all emails as read using deprecated keyword."""
self.library.open_mailbox(host=self.server, user=self.username,
password=self.password)
self.library._mails = ['0']
self.library.mark_as_read()
self.library._imap.uid.assert_called_with('store', '0', '+FLAGS', r'\SEEN')

@mock.patch('ImapLibrary.IMAP4_SSL')
@mock.patch('ImapLibrary2.IMAP4_SSL')
def test_should_mark_email_as_read(self, mock_imap):
"""Mark specific email as read."""
self.library.open_mailbox(host=self.server, user=self.username,
password=self.password)
self.library.mark_email_as_read('0')
self.library._imap.uid.assert_called_with('store', '0', '+FLAGS', r'\SEEN')

@mock.patch('ImapLibrary.IMAP4_SSL')
@mock.patch('ImapLibrary2.IMAP4_SSL')
def test_should_close_mailbox(self, mock_imap):
"""Close opened connection."""
self.library.open_mailbox(host=self.server, user=self.username,
Expand Down

0 comments on commit 99d9519

Please sign in to comment.