feat: Implement email sending utilities and templates for job notifications
Some checks failed
CI/CD Pipeline / test (push) Failing after 4m9s
Some checks failed
CI/CD Pipeline / test (push) Failing after 4m9s
- Added email_service.py for sending emails with SMTP configuration. - Introduced email_templates.py to render job alert email subjects and bodies. - Enhanced scraper.py to extract contact information from job listings. - Updated settings.js to handle negative keyword input validation. - Created email.html and email_templates.html for managing email subscriptions and templates in the admin interface. - Modified base.html to include links for email alerts and templates. - Expanded user settings.html to allow management of negative keywords. - Updated utils.py to include functions for retrieving negative keywords and email settings. - Enhanced job filtering logic to exclude jobs containing negative keywords.
This commit is contained in:
106
tests/test_email_service.py
Normal file
106
tests/test_email_service.py
Normal file
@@ -0,0 +1,106 @@
|
||||
import pytest
|
||||
|
||||
from web.email_service import (
|
||||
EmailConfigurationError,
|
||||
send_email,
|
||||
)
|
||||
|
||||
|
||||
def test_send_email_disabled(monkeypatch):
|
||||
called = {}
|
||||
|
||||
def _fake_smtp(*args, **kwargs): # pragma: no cover - should not be called
|
||||
called["used"] = True
|
||||
raise AssertionError(
|
||||
"SMTP should not be invoked when email is disabled")
|
||||
|
||||
monkeypatch.setattr("web.email_service.smtplib.SMTP", _fake_smtp)
|
||||
monkeypatch.setattr("web.email_service.smtplib.SMTP_SSL", _fake_smtp)
|
||||
|
||||
result = send_email(
|
||||
subject="Hi",
|
||||
body="Test",
|
||||
to="user@example.com",
|
||||
settings={"enabled": False},
|
||||
)
|
||||
assert result is False
|
||||
assert called == {}
|
||||
|
||||
|
||||
def test_send_email_sends_message(monkeypatch):
|
||||
events = {"starttls": False, "login": None, "sent": None}
|
||||
|
||||
class FakeSMTP:
|
||||
def __init__(self, *, host, port, timeout):
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.timeout = timeout
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc, tb):
|
||||
return False
|
||||
|
||||
def ehlo(self):
|
||||
events.setdefault("ehlo", 0)
|
||||
events["ehlo"] += 1
|
||||
|
||||
def starttls(self):
|
||||
events["starttls"] = True
|
||||
|
||||
def login(self, username, password):
|
||||
events["login"] = (username, password)
|
||||
|
||||
def send_message(self, message, *, from_addr, to_addrs):
|
||||
events["sent"] = {
|
||||
"from": from_addr,
|
||||
"to": tuple(to_addrs),
|
||||
"subject": message["Subject"],
|
||||
}
|
||||
|
||||
monkeypatch.setattr("web.email_service.smtplib.SMTP", FakeSMTP)
|
||||
monkeypatch.setattr("web.email_service.smtplib.SMTP_SSL", FakeSMTP)
|
||||
|
||||
settings = {
|
||||
"enabled": True,
|
||||
"from_address": "jobs@example.com",
|
||||
"smtp": {
|
||||
"host": "smtp.example.com",
|
||||
"port": 2525,
|
||||
"timeout": 15,
|
||||
"username": "jobs",
|
||||
"password": "secret",
|
||||
"use_tls": True,
|
||||
"use_ssl": False,
|
||||
},
|
||||
}
|
||||
|
||||
result = send_email(
|
||||
subject="New Jobs",
|
||||
body="You have new jobs waiting.",
|
||||
to=["a@example.com", "b@example.com"],
|
||||
cc="c@example.com",
|
||||
bcc=["d@example.com"],
|
||||
settings=settings,
|
||||
)
|
||||
|
||||
assert result is True
|
||||
assert events["starttls"] is True
|
||||
assert events["login"] == ("jobs", "secret")
|
||||
assert events["sent"] == {
|
||||
"from": "jobs@example.com",
|
||||
"to": ("a@example.com", "b@example.com", "c@example.com", "d@example.com"),
|
||||
"subject": "New Jobs",
|
||||
}
|
||||
|
||||
|
||||
def test_send_email_requires_host():
|
||||
settings = {
|
||||
"enabled": True,
|
||||
"from_address": "jobs@example.com",
|
||||
"smtp": {"host": "", "port": 587},
|
||||
}
|
||||
with pytest.raises(EmailConfigurationError):
|
||||
send_email(subject="Hi", body="Test",
|
||||
to="user@example.com", settings=settings)
|
||||
Reference in New Issue
Block a user