Skip to content

Commit 8a3252e

Browse files
committed
feat: #30 add email sender protocol
1 parent e998232 commit 8a3252e

File tree

5 files changed

+43
-0
lines changed

5 files changed

+43
-0
lines changed

django_email_learning/ports/__init__.py

Whitespace-only changes.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from typing import Protocol
2+
from django.core.mail import EmailMultiAlternatives
3+
4+
5+
class EmailSenderProtocol(Protocol):
6+
def send_email(self, email: EmailMultiAlternatives) -> None:
7+
...

django_email_learning/services/__init__.py

Whitespace-only changes.

django_email_learning/services/deafults/__init__.py

Whitespace-only changes.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import logging
2+
from django_email_learning.ports.email_sender_protocol import EmailSenderProtocol
3+
from django.core.mail import EmailMultiAlternatives
4+
from django.core.mail.message import BadHeaderError
5+
from smtplib import SMTPException
6+
7+
logger = logging.getLogger(__name__)
8+
9+
10+
class DjangoEmailSender(EmailSenderProtocol):
11+
def _mask_email(self, email_address: str) -> str:
12+
"""Mask email address for logging privacy."""
13+
try:
14+
username, domain = email_address.split("@")
15+
masked_username = username[0] + "***"
16+
return f"{masked_username}@{domain}"
17+
except ValueError:
18+
return "***@***"
19+
20+
def _mask_recipients(self, recipients: list[str]) -> str:
21+
"""Mask all recipient email addresses for logging."""
22+
if not recipients:
23+
return "no recipients"
24+
masked = [self._mask_email(recipient) for recipient in recipients]
25+
return ", ".join(masked)
26+
27+
def send_email(self, email: EmailMultiAlternatives) -> None:
28+
try:
29+
masked_recipients = self._mask_recipients(email.to)
30+
logger.info(f"Sending email to {masked_recipients}")
31+
email.send()
32+
logger.info(f"Email sent successfully to {masked_recipients}")
33+
except (SMTPException, BadHeaderError) as e:
34+
masked_recipients = self._mask_recipients(email.to)
35+
logger.error(f"Failed to send email to {masked_recipients}: {str(e)}")
36+
raise

0 commit comments

Comments
 (0)