Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ The test suite uses [Postmark](https://postmarkapp.com/) to send real test email

```bash
# .env
POSTMARK_API_KEY=your_postmark_api_key_here
POSTMARK_API_TOKEN=your_postmark_api_token_here
SENDER_EMAIL=your_email_address_here # The verified sender email in Postmark
```

Expand All @@ -138,6 +138,28 @@ pytest
ruff check .
```

### Checking Postmark Credentials

The test suite includes a utility to verify that your Postmark credentials are properly configured:

```python
from tests.email_sender import PostmarkEmailSender

# Initialize sender and check credentials
sender = PostmarkEmailSender()

# Check if credentials are set (without testing connection)
result = sender.check_credentials(test_connection=False)
print(f"Credentials set: {result['credentials_set']}")

# Check if credentials are set and test the connection
result = sender.check_credentials(test_connection=True)
if result['connection_valid']:
print("Credentials are valid and connection successful!")
else:
print(f"Connection failed: {result['error']}")
```

## Credits

- Tacomail Service: [https://tacomail.de/](https://tacomail.de/)
Expand Down
42 changes: 42 additions & 0 deletions tests/email_sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,48 @@ def __init__(self):
raise ValueError("SENDER_EMAIL not found in environment variables")
self.sender_email = sender_email

def check_credentials(self, test_connection: bool = True) -> dict:
"""Check if Postmark credentials are set and optionally test if they're usable.

Args:
test_connection: If True, attempts to connect to SMTP server to validate credentials.
If False, only checks if credentials are present.

Returns:
A dictionary with the following keys:
- credentials_set (bool): Whether both API token and sender email are present
- api_token_set (bool): Whether POSTMARK_API_TOKEN is set
- sender_email_set (bool): Whether SENDER_EMAIL is set
- connection_valid (bool or None): Whether connection to SMTP server succeeded.
None if test_connection is False.
False if credentials are missing and test_connection is True.
- error (str or None): Error message if connection test failed
"""
result = {
"api_token_set": self.api_token is not None and self.api_token != "",
"sender_email_set": self.sender_email is not None and self.sender_email != "",
"connection_valid": None,
"error": None
}
result["credentials_set"] = result["api_token_set"] and result["sender_email_set"]

if test_connection:
if not result["credentials_set"]:
result["connection_valid"] = False
result["error"] = "Missing credentials"
else:
try:
with smtplib.SMTP(self.SMTP_SERVER, self.SMTP_PORT, timeout=10) as server:
server.starttls()
# Using API token as both username and password (Postmark SMTP authentication)
server.login(self.api_token, self.api_token)
result["connection_valid"] = True
except Exception as e:
result["connection_valid"] = False
result["error"] = str(e)

return result

def send_email(self, to_email: str, subject: str, body: str):
"""Send an email using Postmark SMTP server."""
msg = MIMEMultipart()
Expand Down
45 changes: 45 additions & 0 deletions tests/test_tacomail.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,51 @@ def test_email_sender_initialization():
assert sender.SMTP_PORT == 587


def test_check_credentials_without_connection_test():
"""Test that check_credentials returns proper status without testing connection."""
sender = PostmarkEmailSender()
result = sender.check_credentials(test_connection=False)

# Should have all required keys
assert "credentials_set" in result
assert "api_token_set" in result
assert "sender_email_set" in result
assert "connection_valid" in result
assert "error" in result

# Credentials should be set (since PostmarkEmailSender.__init__ would have raised if not)
assert result["credentials_set"] is True
assert result["api_token_set"] is True
assert result["sender_email_set"] is True

# Connection should not be tested
assert result["connection_valid"] is None
assert result["error"] is None


@pytest.mark.flow
def test_check_credentials_with_connection_test():
"""Test that check_credentials validates connection to Postmark SMTP server."""
sender = PostmarkEmailSender()
result = sender.check_credentials(test_connection=True)

# Should have all required keys
assert "credentials_set" in result
assert "api_token_set" in result
assert "sender_email_set" in result
assert "connection_valid" in result
assert "error" in result

# Credentials should be set
assert result["credentials_set"] is True
assert result["api_token_set"] is True
assert result["sender_email_set"] is True

# Connection should be tested and valid
assert result["connection_valid"] is True
assert result["error"] is None


@pytest.mark.flow
def test_full_email_flow(client: TacomailClient):
# Get random email address
Expand Down