Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
"""Email adapter robustness against malformed IMAP responses (salvage of #2794).
|
||||
|
||||
Validates that:
|
||||
- Malformed IMAP fetch responses are skipped instead of aborting the batch
|
||||
(UIDs are marked seen before fetch, so an abort permanently loses messages)
|
||||
- Message-ID generation handles a missing '@' in EMAIL_ADDRESS
|
||||
"""
|
||||
|
||||
import os
|
||||
import unittest
|
||||
import uuid
|
||||
from email.mime.text import MIMEText
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
|
||||
def _make_adapter(address="hermes@test.com"):
|
||||
from gateway.config import PlatformConfig
|
||||
|
||||
with patch.dict(os.environ, {
|
||||
"EMAIL_ADDRESS": address,
|
||||
"EMAIL_PASSWORD": "secret",
|
||||
"EMAIL_IMAP_HOST": "imap.test.com",
|
||||
"EMAIL_SMTP_HOST": "smtp.test.com",
|
||||
}):
|
||||
from plugins.platforms.email.adapter import EmailAdapter
|
||||
|
||||
adapter = EmailAdapter(PlatformConfig(enabled=True))
|
||||
return adapter
|
||||
|
||||
|
||||
def _raw_email(sender="user@test.com", subject="Hello"):
|
||||
msg = MIMEText("Test body", "plain", "utf-8")
|
||||
msg["From"] = sender
|
||||
msg["Subject"] = subject
|
||||
msg["Message-ID"] = f"<{uuid.uuid4().hex[:8]}@test.com>"
|
||||
return msg.as_bytes()
|
||||
|
||||
|
||||
class TestImapResponseGuard(unittest.TestCase):
|
||||
"""_fetch_new_messages skips messages with unexpected IMAP structure."""
|
||||
|
||||
def _fetch_with(self, fetch_responses):
|
||||
adapter = _make_adapter()
|
||||
uids = b" ".join(
|
||||
str(i + 1).encode() for i in range(len(fetch_responses))
|
||||
)
|
||||
fetch_iter = iter(fetch_responses)
|
||||
|
||||
def uid_handler(command, *args):
|
||||
if command == "search":
|
||||
return ("OK", [uids])
|
||||
if command == "fetch":
|
||||
return next(fetch_iter)
|
||||
return ("NO", [])
|
||||
|
||||
mock_imap = MagicMock()
|
||||
mock_imap.uid.side_effect = uid_handler
|
||||
with patch("imaplib.IMAP4_SSL", return_value=mock_imap):
|
||||
return adapter._fetch_new_messages()
|
||||
|
||||
def test_normal_response_parses(self):
|
||||
results = self._fetch_with([("OK", [(b"1 (RFC822 {123}", _raw_email())])])
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]["sender_addr"], "user@test.com")
|
||||
|
||||
def test_none_element_skipped(self):
|
||||
results = self._fetch_with([("OK", [None])])
|
||||
self.assertEqual(results, [])
|
||||
|
||||
|
||||
class TestMessageIdDomain(unittest.TestCase):
|
||||
"""Message-ID generation tolerates EMAIL_ADDRESS without '@'."""
|
||||
|
||||
|
||||
def test_address_without_at(self):
|
||||
adapter = _make_adapter("not-an-email")
|
||||
self.assertEqual(adapter._message_id_domain(), "localhost")
|
||||
|
||||
|
||||
class TestTransportSecurity(unittest.TestCase):
|
||||
"""platforms.email.extra.imap_security / smtp_security select the transport (#99641)."""
|
||||
|
||||
def _adapter(self, **extra):
|
||||
from gateway.config import PlatformConfig
|
||||
|
||||
with patch.dict(os.environ, {
|
||||
"EMAIL_ADDRESS": "hermes@test.com", "EMAIL_PASSWORD": "secret",
|
||||
"EMAIL_IMAP_HOST": "127.0.0.1", "EMAIL_IMAP_PORT": "1143",
|
||||
"EMAIL_SMTP_HOST": "127.0.0.1", "EMAIL_SMTP_PORT": "1025",
|
||||
}, clear=True):
|
||||
from plugins.platforms.email.adapter import EmailAdapter
|
||||
|
||||
return EmailAdapter(PlatformConfig(enabled=True, extra=extra))
|
||||
|
||||
def test_starttls_builds_plain_imap_then_upgrades(self):
|
||||
adapter = self._adapter(imap_security="starttls", imap_tls_verify=False)
|
||||
imap = MagicMock()
|
||||
with patch("imaplib.IMAP4", return_value=imap) as imap_cls, \
|
||||
patch("imaplib.IMAP4_SSL") as imap_ssl_cls:
|
||||
self.assertIs(adapter._connect_imap(), imap)
|
||||
imap_cls.assert_called_once_with("127.0.0.1", 1143, timeout=30)
|
||||
imap_ssl_cls.assert_not_called()
|
||||
imap.starttls.assert_called_once()
|
||||
|
||||
def test_unknown_mode_falls_back_to_secure_default(self):
|
||||
adapter = self._adapter(imap_security="bogus", smtp_security="bogus")
|
||||
self.assertEqual(adapter._imap_security, "tls")
|
||||
self.assertEqual(adapter._smtp_security, "starttls") # port 1025 != 465
|
||||
# verification stays ON unless explicitly opted out
|
||||
self.assertTrue(adapter._imap_tls_verify)
|
||||
self.assertTrue(adapter._smtp_tls_verify)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user