feat/CUS-11074-Added send test plan results to email latest#352
Conversation
📝 WalkthroughWalkthroughA new Maven module introducing a hook class that automatically sends test plan execution results via HTML email after test completion. The module includes project configuration, dependencies for API interaction and email delivery, and a comprehensive implementation for fetching results, formatting reports, and SMTP transmission. Changes
Sequence DiagramsequenceDiagram
actor User
participant Hook as SendTestPlanResultsToEmailLatest
participant API as Testsigma API
participant SMTP as SMTP Service
User->>Hook: Test plan execution completes
Hook->>Hook: Extract API key & email recipients from test data
Hook->>API: Build run ID chain, fetch all run details
API-->>Hook: Return execution results for all runs
Hook->>API: Paginate through test_case_results
API-->>Hook: Return failed test cases & result metrics
Hook->>Hook: Extract counts from testPlanResultMetric or run details
Hook->>Hook: Construct HTML email with summary & failed cases by suite
Hook->>SMTP: Send formatted HTML email to recipients
SMTP-->>Hook: Email transmission confirmation/error
Hook->>Hook: Log email outcome
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Warning Review ran into problems🔥 ProblemsGit: Failed to clone repository. Please run the Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
send_testplan_results_to_email_latest/pom.xml (1)
17-17: Update JUnit Jupiter to a stable GA version.Line 17 uses
5.8.0-M1, a milestone pre-release. Replace with the latest stable GA version5.14.3, which maintains Java 11 compatibility.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@send_testplan_results_to_email_latest/pom.xml` at line 17, Update the Maven property <junit.jupiter.version> value from the pre-release "5.8.0-M1" to the stable GA "5.14.3" so the project uses the latest stable JUnit Jupiter release while retaining Java 11 compatibility; locate the <junit.jupiter.version> property in the pom.xml and replace its value accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@send_testplan_results_to_email_latest/src/main/java/com/testsigma/addons/hook/SendTestPlanResultsToEmailLatest.java`:
- Around line 128-134: The current System.out.println and setSuccessMessage in
SendTestPlanResultsToEmailLatest expose full recipient email addresses via the
variables to and toList; change both places (the block using
System.out.println/setSuccessMessage and the other occurrence around line 836)
to avoid PII by logging only the recipient count and an optional non-identifying
summary (e.g., "1 recipient" or "N recipients") or a masked representation
(e.g., show only the domain or replace local-part with ****), and ensure
variables toList and to are not concatenated directly into log or message
strings.
- Around line 44-49: Remove the hardcoded SMTP credentials in
SendTestPlanResultsToEmailLatest (DEFAULT_FROM_EMAIL, SMTP_HOST, SMTP_PORT,
SMTP_USER, SMTP_PASSWORD) and instead load them from a secure runtime source
(e.g., environment variables, a injected configuration/property source, or a
secrets manager client) with proper validation and clear error handling when
missing; ensure SMTP_PASSWORD is never committed, provide a safe fallback or
fail-fast behavior, and document that the secret must be rotated and provided
via the chosen secret store at deployment time.
- Around line 62-68: Replace the hard-coded Long runId (302912L) with the actual
RunResult ID: use the runresult object’s ID (runresult.getId()) when assigning
runId so the hook operates on the current execution; locate the runId assignment
near buildRunIdsChain() and ensure the runId variable is a Long and set from
runresult.getId() before any subsequent API calls or processing.
- Around line 813-817: The SMTP send can block indefinitely because JavaMail
defaults to infinite socket timeouts; update the Properties object used to
create the mail Session (the props variable in SendTestPlanResultsToEmailLatest)
to include explicit timeout settings such as mail.smtp.connectiontimeout,
mail.smtp.timeout and mail.smtp.writetimeout (values in milliseconds, e.g.
"10000" for 10s) so Transport.send(msg) cannot hang indefinitely; add
props.put("mail.smtp.connectiontimeout", "10000"),
props.put("mail.smtp.timeout", "10000") and props.put("mail.smtp.writetimeout",
"10000") (or configurable values) alongside the existing mail.smtp.* properties
before creating the Session/calling Transport.send.
In
`@send_testplan_results_to_email_latest/src/main/resources/testsigma-sdk.properties`:
- Line 1: The committed API credential value for the property
testsigma-sdk.api.key must be removed and rotated immediately; replace the
literal value in testsigma-sdk.properties with a placeholder (e.g. empty or
${TESTSIGMA_API_KEY}) and change the application to read the real key from a
secure runtime source (environment variable, secret manager, or CI/CD secret
injection) rather than from source control; after replacing the file,
revoke/rotate the exposed JWT/API key in the provider console and update
deployments to use the new secret via your chosen secret-injection mechanism.
---
Nitpick comments:
In `@send_testplan_results_to_email_latest/pom.xml`:
- Line 17: Update the Maven property <junit.jupiter.version> value from the
pre-release "5.8.0-M1" to the stable GA "5.14.3" so the project uses the latest
stable JUnit Jupiter release while retaining Java 11 compatibility; locate the
<junit.jupiter.version> property in the pom.xml and replace its value
accordingly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 838f68fe-3330-492f-a717-ddef534d2aa5
📒 Files selected for processing (3)
send_testplan_results_to_email_latest/pom.xmlsend_testplan_results_to_email_latest/src/main/java/com/testsigma/addons/hook/SendTestPlanResultsToEmailLatest.javasend_testplan_results_to_email_latest/src/main/resources/testsigma-sdk.properties
| private static final String DEFAULT_FROM_EMAIL = "ent_support@testsigma.com"; | ||
| private static final String SMTP_HOST = "smtp.gmail.com"; | ||
| private static final String SMTP_PORT = "587"; | ||
| private static final String SMTP_USER = "ent_support@testsigma.com"; | ||
| private static final String SMTP_PASSWORD = "asla sdqa frwa uynz"; | ||
|
|
There was a problem hiding this comment.
Do not hardcode SMTP credentials in source.
Lines 47-49 contain static SMTP credentials (including password). This is a critical secret-management issue; rotate immediately and source credentials from secure runtime test data.
🔐 Suggested direction
- private static final String SMTP_USER = "ent_support@testsigma.com";
- private static final String SMTP_PASSWORD = "asla sdqa frwa uynz";
+ `@TestData`(reference = "{SMTP USER}")
+ private com.testsigma.sdk.TestData smtpUser;
+
+ `@TestData`(reference = "{SMTP PASSWORD}")
+ private com.testsigma.sdk.TestData smtpPassword;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@send_testplan_results_to_email_latest/src/main/java/com/testsigma/addons/hook/SendTestPlanResultsToEmailLatest.java`
around lines 44 - 49, Remove the hardcoded SMTP credentials in
SendTestPlanResultsToEmailLatest (DEFAULT_FROM_EMAIL, SMTP_HOST, SMTP_PORT,
SMTP_USER, SMTP_PASSWORD) and instead load them from a secure runtime source
(e.g., environment variables, a injected configuration/property source, or a
secrets manager client) with proper validation and clear error handling when
missing; ensure SMTP_PASSWORD is never committed, provide a safe fallback or
fail-fast behavior, and document that the secret must be rotated and provided
via the chosen secret store at deployment time.
| List<Long> runIdsInOrder = buildRunIdsChain(); | ||
| // Long runId = runresult.getId(); | ||
|
|
||
| Long runId = 302912L; | ||
|
|
||
| String tsApiToken = apiKey.getValue().toString().trim(); | ||
| String toRaw = toEmail != null && toEmail.getValue() != null ? toEmail.getValue().toString().trim() : ""; |
There was a problem hiding this comment.
Remove debug run ID; use the actual @RunResult ID.
Line 65 hardcodes 302912L, so this hook can fetch/send results for the wrong execution. This is a correctness blocker.
✅ Suggested fix
List<Long> runIdsInOrder = buildRunIdsChain();
-// Long runId = runresult.getId();
-
- Long runId = 302912L;
+ if (runresult == null || runresult.getId() == null) {
+ setErrorMessage("RunResult is unavailable for this hook execution.");
+ return Result.FAILED;
+ }
+ Long runId = runresult.getId();
- String tsApiToken = apiKey.getValue().toString().trim();
+ if (apiKey == null || apiKey.getValue() == null || apiKey.getValue().toString().trim().isEmpty()) {
+ setErrorMessage("API KEY is required. Please set the API KEY test data.");
+ return Result.FAILED;
+ }
+ String tsApiToken = apiKey.getValue().toString().trim();📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| List<Long> runIdsInOrder = buildRunIdsChain(); | |
| // Long runId = runresult.getId(); | |
| Long runId = 302912L; | |
| String tsApiToken = apiKey.getValue().toString().trim(); | |
| String toRaw = toEmail != null && toEmail.getValue() != null ? toEmail.getValue().toString().trim() : ""; | |
| List<Long> runIdsInOrder = buildRunIdsChain(); | |
| if (runresult == null || runresult.getId() == null) { | |
| setErrorMessage("RunResult is unavailable for this hook execution."); | |
| return Result.FAILED; | |
| } | |
| Long runId = runresult.getId(); | |
| if (apiKey == null || apiKey.getValue() == null || apiKey.getValue().toString().trim().isEmpty()) { | |
| setErrorMessage("API KEY is required. Please set the API KEY test data."); | |
| return Result.FAILED; | |
| } | |
| String tsApiToken = apiKey.getValue().toString().trim(); | |
| String toRaw = toEmail != null && toEmail.getValue() != null ? toEmail.getValue().toString().trim() : ""; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@send_testplan_results_to_email_latest/src/main/java/com/testsigma/addons/hook/SendTestPlanResultsToEmailLatest.java`
around lines 62 - 68, Replace the hard-coded Long runId (302912L) with the
actual RunResult ID: use the runresult object’s ID (runresult.getId()) when
assigning runId so the hook operates on the current execution; locate the runId
assignment near buildRunIdsChain() and ensure the runId variable is a Long and
set from runresult.getId() before any subsequent API calls or processing.
| System.out.println(toList.size() == 1 | ||
| ? "Test plan results email sent successfully to " + to | ||
| : "Test plan results email sent successfully to " + toList.size() + " recipients: " + to); | ||
|
|
||
| setSuccessMessage(toList.size() == 1 | ||
| ? "Test plan results email sent successfully to " + to | ||
| : "Test plan results email sent successfully to " + toList.size() + " recipients: " + to); |
There was a problem hiding this comment.
Avoid logging full recipient email addresses.
Lines 128-134 and Line 836 log raw recipient lists. That’s avoidable PII exposure in logs/messages.
🧹 Suggested safer messaging
- System.out.println(toList.size() == 1
- ? "Test plan results email sent successfully to " + to
- : "Test plan results email sent successfully to " + toList.size() + " recipients: " + to);
+ System.out.println("Test plan results email sent successfully to " + toList.size() + " recipient(s).");
- setSuccessMessage(toList.size() == 1
- ? "Test plan results email sent successfully to " + to
- : "Test plan results email sent successfully to " + toList.size() + " recipients: " + to);
+ setSuccessMessage("Test plan results email sent successfully to " + toList.size() + " recipient(s).");Also applies to: 836-836
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@send_testplan_results_to_email_latest/src/main/java/com/testsigma/addons/hook/SendTestPlanResultsToEmailLatest.java`
around lines 128 - 134, The current System.out.println and setSuccessMessage in
SendTestPlanResultsToEmailLatest expose full recipient email addresses via the
variables to and toList; change both places (the block using
System.out.println/setSuccessMessage and the other occurrence around line 836)
to avoid PII by logging only the recipient count and an optional non-identifying
summary (e.g., "1 recipient" or "N recipients") or a masked representation
(e.g., show only the domain or replace local-part with ****), and ensure
variables toList and to are not concatenated directly into log or message
strings.
| Properties props = new Properties(); | ||
| props.put("mail.smtp.host", host); | ||
| props.put("mail.smtp.port", port); | ||
| props.put("mail.smtp.auth", String.valueOf(user != null && !user.isEmpty())); | ||
| props.put("mail.smtp.starttls.enable", "true"); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -name "SendTestPlanResultsToEmailLatest.java" -type fRepository: testsigmahq/testsigma-addons
Length of output: 1895
🌐 Web query:
Java Mail SMTP timeout properties mail.smtp.connectiontimeout mail.smtp.timeout
💡 Result:
In JavaMail/Jakarta Mail’s SMTP provider, these properties control socket-level timeouts (values are milliseconds, set as strings in the Properties used to create the Session):
mail.smtp.connectiontimeout: connect timeout (time allowed to establish the TCP connection). Default: infinite. [1]mail.smtp.timeout: read timeout (time blocked waiting for a server response / socket read). Default: infinite. [1]
Related (often used alongside them):
mail.smtp.writetimeout: write timeout (time allowed for socket writes; implemented by closing the socket via a scheduled task; overhead: one thread per connection). Default: infinite. [1]
Notes:
- If you use SMTP-over-SSL via the
smtpsprotocol, the equivalent properties aremail.smtps.connectiontimeout,mail.smtps.timeout, etc. [1] - These timeouts are not a “total send deadline”; they apply to individual connect/read/write operations. [2]
Example:
Properties props = new Properties();
props.put("mail.smtp.connectiontimeout", "5000");
props.put("mail.smtp.timeout", "5000");
props.put("mail.smtp.writetimeout", "5000");Sources: JavaMail SMTP provider docs [1]; explanation of timeout behavior [2].
Configure SMTP timeout properties to prevent indefinite blocking.
Transport.send(msg) at line 835 will block indefinitely if the SMTP server doesn't respond, since JavaMail defaults to infinite socket timeouts. This can freeze the hook thread. Add the following timeout properties (values in milliseconds):
props.put("mail.smtp.host", host);
props.put("mail.smtp.port", port);
props.put("mail.smtp.auth", String.valueOf(user != null && !user.isEmpty()));
props.put("mail.smtp.starttls.enable", "true");
+ props.put("mail.smtp.connectiontimeout", "30000");
+ props.put("mail.smtp.timeout", "30000");
+ props.put("mail.smtp.writetimeout", "30000");🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@send_testplan_results_to_email_latest/src/main/java/com/testsigma/addons/hook/SendTestPlanResultsToEmailLatest.java`
around lines 813 - 817, The SMTP send can block indefinitely because JavaMail
defaults to infinite socket timeouts; update the Properties object used to
create the mail Session (the props variable in SendTestPlanResultsToEmailLatest)
to include explicit timeout settings such as mail.smtp.connectiontimeout,
mail.smtp.timeout and mail.smtp.writetimeout (values in milliseconds, e.g.
"10000" for 10s) so Transport.send(msg) cannot hang indefinitely; add
props.put("mail.smtp.connectiontimeout", "10000"),
props.put("mail.smtp.timeout", "10000") and props.put("mail.smtp.writetimeout",
"10000") (or configurable values) alongside the existing mail.smtp.* properties
before creating the Session/calling Transport.send.
| @@ -0,0 +1 @@ | |||
| testsigma-sdk.api.key=eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIzMmYwYTg1MC02NjMyLWIyN2ItOTBhYS1jZDkwMDcwNzRlMWUiLCJ1bmlxdWVJZCI6IjE3MyIsImlkZW50aXR5QWNjb3VudFVVSWQiOiJmZTJhMzhjYi04Yjg5LTc3YTQtODk0Yi04MGYzYjlhMzcxM2UifQ.9hbvEw3JT8CeT_gneBWPoymTn__kZ4XaR6v_tVcNok94-YOn4yQjeRWWaOCubOMR2AuFBg8snf3t5kBt9dDhlw No newline at end of file | |||
There was a problem hiding this comment.
Remove committed API credential and rotate it immediately.
Line 1 includes a JWT-like API key in plaintext. For a public addon, this is a release blocker: revoke/rotate this key and inject it at runtime from secure secret input instead of source control.
🔐 Suggested immediate change
-testsigma-sdk.api.key=eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIzMmYwYTg1MC02NjMyLWIyN2ItOTBhYS1jZDkwMDcwNzRlMWUiLCJ1bmlxdWVJZCI6IjE3MyIsImlkZW50aXR5QWNjb3VudFVVSWQiOiJmZTJhMzhjYi04Yjg5LTc3YTQtODk0Yi04MGYzYjlhMzcxM2UifQ.9hbvEw3JT8CeT_gneBWPoymTn__kZ4XaR6v_tVcNok94-YOn4yQjeRWWaOCubOMR2AuFBg8snf3t5kBt9dDhlw
+testsigma-sdk.api.key=📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| testsigma-sdk.api.key=eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIzMmYwYTg1MC02NjMyLWIyN2ItOTBhYS1jZDkwMDcwNzRlMWUiLCJ1bmlxdWVJZCI6IjE3MyIsImlkZW50aXR5QWNjb3VudFVVSWQiOiJmZTJhMzhjYi04Yjg5LTc3YTQtODk0Yi04MGYzYjlhMzcxM2UifQ.9hbvEw3JT8CeT_gneBWPoymTn__kZ4XaR6v_tVcNok94-YOn4yQjeRWWaOCubOMR2AuFBg8snf3t5kBt9dDhlw | |
| testsigma-sdk.api.key= |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@send_testplan_results_to_email_latest/src/main/resources/testsigma-sdk.properties`
at line 1, The committed API credential value for the property
testsigma-sdk.api.key must be removed and rotated immediately; replace the
literal value in testsigma-sdk.properties with a placeholder (e.g. empty or
${TESTSIGMA_API_KEY}) and change the application to read the real key from a
secure runtime source (environment variable, secret manager, or CI/CD secret
injection) rather than from source control; after replacing the file,
revoke/rotate the exposed JWT/API key in the provider console and update
deployments to use the new secret via your chosen secret-injection mechanism.
Publish this addon as public (IN Region)
Addon Name: Send TestPlan Results To Email Latest
Jarvis Link: https://jarvis-in.testsigma.com/ui/tenants/3/addons
Jira : https://testsigma.atlassian.net/browse/CUS-11074
Added send test plan results to email latest
Summary by CodeRabbit