Skip to content

Commit

Permalink
mail read schedule stop mechanism, filters and their related tests
Browse files Browse the repository at this point in the history
  • Loading branch information
spandan_mondal committed Dec 12, 2024
1 parent 4c999fc commit 34821e5
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 70 deletions.
27 changes: 6 additions & 21 deletions kairon/shared/channels/mail/processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from pydantic.schema import timedelta
from pydantic.validators import datetime
from imap_tools import MailBox, AND, OR, NOT

from kairon import Utility
from kairon.exceptions import AppException
from kairon.shared.account.data_objects import Bot
from kairon.shared.channels.mail.constants import MailConstants
Expand Down Expand Up @@ -38,15 +40,6 @@ def update_event_id(self, event_id):
self.state.save()


@staticmethod
def does_mail_channel_exist(bot:str):
"""
Check if mail channel exists
"""
if Channels.objects(bot=bot, connector_type=ChannelTypes.MAIL.value).first():
return True
return False

@staticmethod
def get_mail_channel_state_data(bot:str):
"""
Expand Down Expand Up @@ -290,14 +283,6 @@ def generate_criteria(self, subjects=None, ignore_subjects=None, from_addresses=
# Combine all criteria with AND
return AND(*criteria)

@staticmethod
def comma_sep_string_to_list(comma_sep_string: str) -> List[str]:
"""
Convert comma separated string to list
"""
if not comma_sep_string:
return []
return [item.strip() for item in comma_sep_string.split(",") if item.strip()]

@staticmethod
def read_mails(bot: str) -> ([dict], str):
Expand Down Expand Up @@ -325,13 +310,13 @@ def read_mails(bot: str) -> ([dict], str):
mp.login_imap()
is_logged_in = True
subject = mp.config.get('subjects', "")
subject = MailProcessor.comma_sep_string_to_list(subject)
subject = Utility.string_to_list(subject)
ignore_subject = mp.config.get('ignore_subjects', "")
ignore_subject = MailProcessor.comma_sep_string_to_list(ignore_subject)
ignore_subject = Utility.string_to_list(ignore_subject)
from_addresses = mp.config.get('from_emails', "")
from_addresses = MailProcessor.comma_sep_string_to_list(from_addresses)
from_addresses = Utility.string_to_list(from_addresses)
ignore_from = mp.config.get('ignore_from_emails', "")
ignore_from = MailProcessor.comma_sep_string_to_list(ignore_from)
ignore_from = Utility.string_to_list(ignore_from)
read_status = mp.config.get('seen_status', 'all')
criteria = mp.generate_criteria(subject, ignore_subject, from_addresses, ignore_from, read_status)
for msg in mp.mailbox.fetch(criteria, mark_seen=False):
Expand Down
4 changes: 3 additions & 1 deletion kairon/shared/channels/mail/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from kairon import Utility
from kairon.exceptions import AppException
from kairon.shared.channels.mail.processor import MailProcessor
from kairon.shared.chat.data_objects import Channels
from kairon.shared.constants import ChannelTypes


class MailScheduler:
Expand Down Expand Up @@ -29,7 +31,7 @@ def request_epoch(bot: str):
@staticmethod
def request_stop(bot: str):
event_server_url = Utility.get_event_server_url()
if MailProcessor.does_mail_channel_exist(bot):
if Utility.is_exist(Channels, raise_error=False, bot=bot, connector_type=ChannelTypes.MAIL.value):
resp = Utility.execute_http_request(
"GET",
urljoin(
Expand Down
11 changes: 5 additions & 6 deletions kairon/shared/chat/processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,11 @@ def delete_channel_config(bot: Text, **kwargs):
:return: None
"""
kwargs.update({"bot": bot})
if kwargs.get("connector_type") != ChannelTypes.SLACK.value:
try:
from kairon.shared.channels.mail.scheduler import MailScheduler
MailScheduler.request_stop(bot)
except Exception as e:
logger.error(f"Error while stopping mail scheduler for bot {bot}. Error: {str(e)}")
try:
from kairon.shared.channels.mail.scheduler import MailScheduler
MailScheduler.request_stop(bot)
except Exception as e:
logger.error(f"Error while stopping mail scheduler for bot {bot}. Error: {str(e)}")
Utility.hard_delete_document([Channels], **kwargs)

@staticmethod
Expand Down
12 changes: 11 additions & 1 deletion kairon/shared/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2223,6 +2223,15 @@ def delete_documents(document: Document, user: str = "System"):
document["user"] = user
document.delete()

@staticmethod
def string_to_list(comma_sep_string: str, delimilter: str = ",") -> List[str]:
"""
Convert comma separated string to list
"""
if not comma_sep_string:
return []
return [item.strip() for item in comma_sep_string.split(delimilter) if item.strip()]


class StoryValidator:
@staticmethod
Expand Down Expand Up @@ -2755,4 +2764,5 @@ def __handle_member_left_bot(**kwargs):
body = body.replace("MEMBER_NAME", user_name)
body = body.replace("BOT_NAME", bot_name)
subject = f"Notification: {user_name} has left the {bot_name} bot"
return body, subject
return body, subject

35 changes: 0 additions & 35 deletions tests/unit_test/channels/mail_channel_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,39 +588,4 @@ def test_get_log_exception(self):
Channels.objects(connector_type=ChannelTypes.MAIL.value).delete()


def test_comma_sep_string_to_list(self):
# Test input with empty elements
assert MailProcessor.comma_sep_string_to_list("apple, , banana, , orange") == ["apple", "banana", "orange"]

# Test input with only commas
assert MailProcessor.comma_sep_string_to_list(",,,") == []

# Test input with no commas (single element)
assert MailProcessor.comma_sep_string_to_list("apple") == ["apple"]

# Test input with empty string
assert MailProcessor.comma_sep_string_to_list("") == []

# Test input with None
assert MailProcessor.comma_sep_string_to_list(None) == []

# Test input with special characters
assert MailProcessor.comma_sep_string_to_list("apple,@banana, #orange$") == ["apple", "@banana", "#orange$"]

# Test input with numeric values
assert MailProcessor.comma_sep_string_to_list("1, 2, 3, 4") == ["1", "2", "3", "4"]

# Test input with spaces
assert MailProcessor.comma_sep_string_to_list("apple, banana, orange") == ["apple", "banana", "orange"]


@patch('kairon.shared.channels.mail.processor.Channels')
def test_mail_channel_exist(self, mock_channels):
mock_channels.objects.return_value.first.return_value = True
assert MailProcessor.does_mail_channel_exist("test_bot") is True

@patch('kairon.shared.channels.mail.processor.Channels')
def test_mail_channel_not_exist(self, mock_channels):
mock_channels.objects.return_value.first.return_value = False
assert MailProcessor.does_mail_channel_exist("test_bot") is False

9 changes: 4 additions & 5 deletions tests/unit_test/channels/mail_scheduler_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,7 @@ def test_stop_channel_mail_reading(mock_mongo, mock_mail_processor, mock_kschedu
EventUtility.stop_channel_mail_reading(bot)
mock_delete_job.assert_called_once()


@patch('kairon.shared.channels.mail.processor.MailProcessor.does_mail_channel_exist')
@patch('kairon.shared.utils.Utility.is_exist')
@patch('kairon.shared.channels.mail.scheduler.Utility.get_event_server_url')
@patch('kairon.shared.channels.mail.scheduler.Utility.execute_http_request')
def test_request_stop_success(mock_execute_http_request, mock_get_event_server_url, mock_imp):
Expand All @@ -140,18 +139,18 @@ def test_request_stop_success(mock_execute_http_request, mock_get_event_server_u
pytest.fail("request_epoch() raised AppException unexpectedly!")


@patch('kairon.shared.channels.mail.processor.MailProcessor.does_mail_channel_exist')
@patch('kairon.shared.utils.Utility.is_exist')
@patch('kairon.shared.channels.mail.scheduler.Utility.get_event_server_url')
@patch('kairon.shared.channels.mail.scheduler.Utility.execute_http_request')
def test_request_stop__response_not_success(mock_execute_http_request, mock_get_event_server_url, mock_imp):
def test_request_stop_response_not_success(mock_execute_http_request, mock_get_event_server_url, mock_imp):
mock_get_event_server_url.return_value = "http://localhost"
mock_execute_http_request.return_value = {'success': False}
mock_imp.return_value = True
bot = "test_bot"
with pytest.raises(AppException):
MailScheduler.request_stop(bot)

@patch('kairon.shared.channels.mail.processor.MailProcessor.does_mail_channel_exist')
@patch('kairon.shared.utils.Utility.is_exist')
@patch('kairon.shared.channels.mail.scheduler.Utility.get_event_server_url')
@patch('kairon.shared.channels.mail.scheduler.Utility.execute_http_request')
def test_request_stop_no_channel_exist_exception(mock_execute_http_request, mock_get_event_server_url, mock_imp):
Expand Down
29 changes: 28 additions & 1 deletion tests/unit_test/utility_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3305,4 +3305,31 @@ async def test_handle_first_name_member_update_email_template(self, validate_and
)
validate_and_send_mail_mock.assert_called_once_with(
email, expected_subject, expected_body
)
)


def test_comma_sep_string_to_list(self):
# Test input with empty elements
assert Utility.string_to_list("apple, , banana, , orange") == ["apple", "banana", "orange"]

# Test input with only commas
assert Utility.string_to_list(",,,") == []

# Test input with no commas (single element)
assert Utility.string_to_list("apple") == ["apple"]

# Test input with empty string
assert Utility.string_to_list("") == []

# Test input with None
assert Utility.string_to_list(None) == []

# Test input with special characters
assert Utility.string_to_list("apple,@banana, #orange$") == ["apple", "@banana", "#orange$"]

# Test input with numeric values
assert Utility.string_to_list("1, 2, 3, 4") == ["1", "2", "3", "4"]

# Test input with spaces
assert Utility.string_to_list("apple, banana, orange") == ["apple", "banana", "orange"]

0 comments on commit 34821e5

Please sign in to comment.