From 7ec8f86a445f6fdeeb7c69bffcc073b64f783c86 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 15 Jan 2026 22:48:07 +0000 Subject: [PATCH 1/4] Initial plan From 1739eeee3c2ffd26617d8f2b433d31a7f7a6cdd1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 15 Jan 2026 22:51:35 +0000 Subject: [PATCH 2/4] Add check_credentials method to PostmarkEmailSender Co-authored-by: sokripon <79755465+sokripon@users.noreply.github.com> --- tests/email_sender.py | 36 +++++++++++++++++++++++++++++++++ tests/test_tacomail.py | 45 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/tests/email_sender.py b/tests/email_sender.py index 444c65d..d4163bd 100644 --- a/tests/email_sender.py +++ b/tests/email_sender.py @@ -20,6 +20,42 @@ 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. + - 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 and result["credentials_set"]: + try: + with smtplib.SMTP(self.SMTP_SERVER, self.SMTP_PORT, timeout=10) as server: + server.starttls() + 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() diff --git a/tests/test_tacomail.py b/tests/test_tacomail.py index 3531019..684f1d7 100644 --- a/tests/test_tacomail.py +++ b/tests/test_tacomail.py @@ -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 From b9bf5078022a12e93180d17abc2ed062fe358478 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 15 Jan 2026 22:52:37 +0000 Subject: [PATCH 3/4] Update README with credential check documentation Co-authored-by: sokripon <79755465+sokripon@users.noreply.github.com> --- README.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ed93e28..0e45fbf 100644 --- a/README.md +++ b/README.md @@ -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 ``` @@ -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/) From ed6e7bac3dc3e5d5ccf16288d84a8d568a94d6f1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 15 Jan 2026 22:54:18 +0000 Subject: [PATCH 4/4] Improve check_credentials error handling and documentation Co-authored-by: sokripon <79755465+sokripon@users.noreply.github.com> --- tests/email_sender.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/tests/email_sender.py b/tests/email_sender.py index d4163bd..d0a9808 100644 --- a/tests/email_sender.py +++ b/tests/email_sender.py @@ -34,6 +34,7 @@ def check_credentials(self, test_connection: bool = True) -> dict: - 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 = { @@ -44,15 +45,20 @@ def check_credentials(self, test_connection: bool = True) -> dict: } result["credentials_set"] = result["api_token_set"] and result["sender_email_set"] - if test_connection and result["credentials_set"]: - try: - with smtplib.SMTP(self.SMTP_SERVER, self.SMTP_PORT, timeout=10) as server: - server.starttls() - server.login(self.api_token, self.api_token) - result["connection_valid"] = True - except Exception as e: + if test_connection: + if not result["credentials_set"]: result["connection_valid"] = False - result["error"] = str(e) + 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