90 lines
4.0 KiB
Python
90 lines
4.0 KiB
Python
## Copyright © 2026 Olaf Kolkman
|
|
## SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
from unittest.mock import patch
|
|
|
|
from backend.app.services.email_service import send_password_reset_email, send_test_email, send_verification_email
|
|
|
|
|
|
def test_send_verification_email_uses_smtp_settings(monkeypatch):
|
|
from backend.app.core.config import settings
|
|
|
|
monkeypatch.setattr(settings, 'smtp_host', 'smtp.example.com')
|
|
monkeypatch.setattr(settings, 'smtp_port', 587)
|
|
monkeypatch.setattr(settings, 'smtp_from', 'LinkLog <no-reply@example.com>')
|
|
monkeypatch.setattr(settings, 'smtp_username', 'mailer')
|
|
monkeypatch.setattr(settings, 'smtp_password', 'secret')
|
|
monkeypatch.setattr(settings, 'smtp_use_tls', True)
|
|
monkeypatch.setattr(settings, 'public_url', 'https://linklog.example')
|
|
|
|
with patch('backend.app.services.email_service.SMTP') as smtp_class:
|
|
smtp = smtp_class.return_value.__enter__.return_value
|
|
send_verification_email('user@example.com', 'user', 'https://linklog.example/verify')
|
|
|
|
smtp_class.assert_called_once_with('smtp.example.com', 587, timeout=10)
|
|
smtp.starttls.assert_called_once_with()
|
|
smtp.login.assert_called_once_with('mailer', 'secret')
|
|
message = smtp.send_message.call_args.args[0]
|
|
assert message['To'] == 'user@example.com'
|
|
assert 'https://linklog.example/verify' in message.get_body(preferencelist=('plain',)).get_content()
|
|
html = message.get_body(preferencelist=('html',)).get_content()
|
|
assert 'cid:linklog-logo' in html
|
|
assert 'width="50" height="50"' in html
|
|
assert 'font-family:\'Asset\',Georgia,serif' in html
|
|
assert 'Hello, a message from' in html
|
|
assert 'vertical-align:top' in html
|
|
assert 'padding:20px 0 20px 12px' in html
|
|
assert 'font-size:18px' in html
|
|
assert 'href="https://linklog.example"' in html
|
|
assert '>linklog.example</a>' in html
|
|
assert any(
|
|
part.get_content_type() == 'image/svg+xml'
|
|
and part['Content-ID'] == '<linklog-logo>'
|
|
for part in message.walk()
|
|
)
|
|
|
|
|
|
def test_send_test_email_uses_configured_recipient(monkeypatch):
|
|
from backend.app.core.config import settings
|
|
|
|
monkeypatch.setattr(settings, 'smtp_host', 'smtp.example.com')
|
|
monkeypatch.setattr(settings, 'smtp_from', 'LinkLog <no-reply@example.com>')
|
|
with patch('backend.app.services.email_service.SMTP') as smtp_class:
|
|
smtp = smtp_class.return_value.__enter__.return_value
|
|
send_test_email('admin@example.com')
|
|
|
|
message = smtp.send_message.call_args.args[0]
|
|
assert message['To'] == 'admin@example.com'
|
|
assert message['Subject'] == 'LinkLog SMTP test'
|
|
assert message.get_body(preferencelist=('html',)) is not None
|
|
|
|
|
|
def test_password_reset_email_escapes_html_and_includes_logo(monkeypatch):
|
|
from backend.app.core.config import settings
|
|
|
|
monkeypatch.setattr(settings, 'smtp_host', 'smtp.example.com')
|
|
monkeypatch.setattr(settings, 'smtp_from', 'LinkLog <no-reply@example.com>')
|
|
with patch('backend.app.services.email_service.SMTP') as smtp_class:
|
|
smtp = smtp_class.return_value.__enter__.return_value
|
|
send_password_reset_email('user@example.com', '<User>', 'https://linklog.example/reset?x=1&y=2')
|
|
|
|
message = smtp.send_message.call_args.args[0]
|
|
html = message.get_body(preferencelist=('html',)).get_content()
|
|
assert '<User>' in html
|
|
assert 'x=1&y=2' in html
|
|
assert 'cid:linklog-logo' in html
|
|
|
|
|
|
def test_smtp_password_is_encrypted_at_rest():
|
|
from backend.app.services.email_service import get_smtp_settings, save_smtp_settings
|
|
from backend.app.database import get_connection
|
|
|
|
values = {
|
|
'smtp_host': 'smtp.example.com', 'smtp_port': 587, 'smtp_username': 'mailer',
|
|
'smtp_password': 'secret', 'smtp_from': 'LinkLog <no-reply@example.com>', 'smtp_use_tls': True,
|
|
}
|
|
save_smtp_settings(values)
|
|
with get_connection() as conn:
|
|
stored = conn.execute('SELECT value FROM app_settings WHERE name = ?', ('smtp',)).fetchone()['value']
|
|
assert 'secret' not in stored
|
|
assert get_smtp_settings()['smtp_password'] == 'secret' |