Skip to content

feat: add MAILER_SMTP_IGNORE_TLS and optional SMTP auth#5972

Merged
jamesgeorge007 merged 10 commits intonextfrom
feat/smtp-optional-auth
Mar 25, 2026
Merged

feat: add MAILER_SMTP_IGNORE_TLS and optional SMTP auth#5972
jamesgeorge007 merged 10 commits intonextfrom
feat/smtp-optional-auth

Conversation

@mirarifhasan
Copy link
Copy Markdown
Contributor

@mirarifhasan mirarifhasan commented Mar 11, 2026

Closes BE-714 FE-1169

What's changed

This PR makes SMTP authentication optional for deployments that use unauthenticated relay servers (e.g., internal mail relays, local dev tools like Mailpit).

  • MAILER_SMTP_USER and MAILER_SMTP_PASSWORD are now optional as a pair. Both can be left empty for unauthenticated SMTP, but partial credentials (only one of the two) are rejected at the backend write path, runtime transport construction, and both admin UI flows (onboarding and settings).
  • Added MAILER_SMTP_IGNORE_TLS for SMTP servers that do not support STARTTLS.
  • SMTP label casing normalized in the admin panel (e.g., "MAILER HOST" → "SMTP Host").

The onboarding UI and the Admin SMTP configuration tab have been updated to reflect these changes.

Notes to reviewers

The both-or-neither credential constraint is enforced at four layers: backend effective-state validation before DB write, runtime transport construction, admin settings save, and onboarding submission. The onboarding check is scoped to custom SMTP mode so stale fields from toggling between URL and custom mode do not block unrelated submissions.

<!-- This is an auto-generated description by cubic. -->

Summary by cubic

Make SMTP auth optional and add MAILER_SMTP_IGNORE_TLS so unauthenticated or no‑TLS SMTP works. Updates onboarding/Admin SMTP UIs, defaults, and validation; enforces both‑or‑neither credentials. Closes BE-714, FE-1169.

  • New Features
    • Optional SMTP auth: build auth only when both MAILER_SMTP_USER and MAILER_SMTP_PASSWORD are set; fields are optional in onboarding/Admin and can be cleared to remove saved creds; both-or-neither is enforced in the backend and UIs with an error message.
    • Added MAILER_SMTP_IGNORE_TLS (default false) mapped to transport ignoreTLS; included in defaults, validation, DTOs/types, and both SMTP config UIs with i18n labels and a checkbox.

Written for commit 99c8d96. Summary will update on new commits.

<!-- End of auto-generated description by cubic. -->

Copilot AI review requested due to automatic review settings March 11, 2026 08:04
@mirarifhasan mirarifhasan self-assigned this Mar 11, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enhances the backend SMTP mailer configuration to support optional SMTP authentication credentials and introduces a new MAILER_SMTP_IGNORE_TLS infra config flag, with onboarding/admin flows updated accordingly.

Changes:

  • Added MAILER_SMTP_IGNORE_TLS to infra config enums, defaults, and boolean validation.
  • Made advanced SMTP auth optional when username/password are not provided.
  • Updated onboarding DTOs to include the new SMTP flag.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/hoppscotch-backend/src/types/InfraConfig.ts Adds the new infra config enum entry for MAILER_SMTP_IGNORE_TLS.
packages/hoppscotch-backend/src/mailer/helper.ts Makes SMTP auth optional and wires ignoreTLS into the transport options.
packages/hoppscotch-backend/src/infra-config/infra-config.service.ts Removes SMTP user/password from “configured” checks and adds boolean validation for the new key.
packages/hoppscotch-backend/src/infra-config/helper.ts Removes auth keys from required list and adds a default value for MAILER_SMTP_IGNORE_TLS.
packages/hoppscotch-backend/src/infra-config/dto/onboarding.dto.ts Adds request/response fields for MAILER_SMTP_IGNORE_TLS.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 5 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/hoppscotch-backend/src/mailer/helper.ts">

<violation number="1" location="packages/hoppscotch-backend/src/mailer/helper.ts:29">
P2: Validate SMTP auth as all-or-nothing with non-empty trimmed values; the current logic can emit `auth` with an empty username or password.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@mirarifhasan mirarifhasan marked this pull request as draft March 11, 2026 08:15
@mirarifhasan mirarifhasan marked this pull request as ready for review March 23, 2026 06:28
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Mar 23, 2026

Greptile Summary

This PR adds MAILER_SMTP_IGNORE_TLS support and makes SMTP credentials (MAILER_SMTP_USER / MAILER_SMTP_PASSWORD) optional throughout the stack — backend validation, DTOs, frontend composables, and both the onboarding and Admin settings UIs — to support unauthenticated SMTP relay servers.

Key changes:

  • MAILER_SMTP_USER and MAILER_SMTP_PASSWORD removed from required-key lists; a new validateSmtpCredentialPair method enforces the "both or neither" invariant against the effective post-update DB state in updateMany.
  • MAILER_SMTP_IGNORE_TLS added as an optional boolean config (default false), wired to nodemailer's ignoreTLS option; included in DTOs, defaults, validation, and both UIs.
  • Frontend pair validation added in both useConfigHandler (hasPartialSmtpCredentials) and useOnboardingConfigHandler before submission.
  • UI label strings moved from hard-coded English to i18n keys.

Issues found:

  • validateSmtpCredentialPair is skipped entirely when neither credential key is present in an incoming updateMany payload. A DB that already holds a mismatched credential state (e.g. from a previous failed write) will never be caught by this path. Low practical risk today since the UI always sends both, but worth hardening.
  • In useOnboardingConfigHandler.validateConfigs, the return filter sends MAILER_SMTP_USER: '' and MAILER_SMTP_PASSWORD: '' even when the user is in simple URL mode. The inline comment describes this as intentional ("explicitly clear credentials"), but the effect — silently wiping saved credentials during any onboarding re-visit in URL mode — may be surprising to operators.
  • MAILER_SMTP_IGNORE_TLS always appears in the onboarding outgoing payload (its default 'false' is truthy) even when MAILER_USE_CUSTOM_CONFIGS is false. Harmless, but inconsistent with how other custom-only keys behave.

Confidence Score: 3/5

  • Safe to merge for most deployments; no critical regressions, but the credential-clearing side-effect in URL-mode onboarding re-visits is a UX concern worth resolving before wide rollout.
  • The core logic changes are sound — the &&-based auth building and validateSmtpCredentialPair correctly address the previously flagged issues. However, two behavioural edge cases remain: the pair validator silently short-circuits when no credential key is in the payload, and the onboarding flow unconditionally clears stored credentials when re-submitted in URL mode. Neither is a critical security or data-loss bug, but together they represent subtle correctness gaps that could confuse operators of existing deployments during migration.
  • packages/hoppscotch-sh-admin/src/composables/useOnboardingConfigHandler.ts (credential-clearing behaviour) and packages/hoppscotch-backend/src/infra-config/infra-config.service.ts (validateSmtpCredentialPair short-circuit).

Important Files Changed

Filename Overview
packages/hoppscotch-backend/src/mailer/helper.ts Auth logic correctly refactored to use &&/truthy-string checks; ignoreTLS wired up. The previously flagged `
packages/hoppscotch-backend/src/infra-config/infra-config.service.ts New validateSmtpCredentialPair method correctly merges incoming and DB state. Pair validation is wired into updateMany (covers both the GQL and onboarding paths). The single-key update() method bypasses pair validation, but all its current callers use non-credential keys so practical risk is low.
packages/hoppscotch-sh-admin/src/composables/useOnboardingConfigHandler.ts Credential optionality and pair validation are added, but the return-filter sends MAILER_SMTP_IGNORE_TLS in URL mode and unconditionally clears credentials on re-visits even in non-custom mode.
packages/hoppscotch-sh-admin/src/composables/useConfigHandler.ts Clean addition of mailer_smtp_ignore_tls boolean field and hasPartialSmtpCredentials guard. Safe from null-crash because getFieldValue defaults to ''. Correctly gated behind custom-config and enabled checks.
packages/hoppscotch-backend/src/infra-config/dto/onboarding.dto.ts New field added with @IsOptional() in request DTO and @ApiProperty() / @Expose() in response DTO, consistent with all other MAILER fields.

Sequence Diagram

sequenceDiagram
    participant UI as Admin UI / Onboarding
    participant FE as useConfigHandler / useOnboardingConfigHandler
    participant GQL as GraphQL / REST API
    participant SVC as InfraConfigService
    participant DB as Database
    participant ML as Mailer (nodemailer)

    UI->>FE: User submits SMTP config
    FE->>FE: hasPartialSmtpCredentials() check
    Note over FE: !! smtpUser !== !! smtpPass → toast error
    FE->>GQL: updateInfraConfigs([...fields])
    GQL->>SVC: updateMany(infraConfigs)
    SVC->>SVC: validateEnvValues() — type/format checks
    SVC->>DB: Query missing credential from DB
    DB-->>SVC: Encrypted / plain value
    SVC->>SVC: validateSmtpCredentialPair()<br/>hasUser !== hasPass → INVALID_INPUT
    SVC->>DB: Transaction: upsert all fields
    SVC->>SVC: stopApp() — reload env
    SVC-->>GQL: E.right(configs)
    GQL-->>UI: Success

    Note over ML: On app restart
    ML->>SVC: getTransportOption(env)
    SVC->>ML: smtpUser && smtpPass → auth: {user, pass}
    Note over ML: MAILER_SMTP_IGNORE_TLS=true → ignoreTLS:true<br/>(no-op when secure:true)
    ML-->>ML: Transport ready
Loading

Comments Outside Diff (3)

  1. packages/hoppscotch-sh-admin/src/composables/useOnboardingConfigHandler.ts, line 300-306 (link)

    MAILER_SMTP_IGNORE_TLS sent in URL-mode payload

    configs['MAILER_SMTP_IGNORE_TLS'] defaults to 'false' (a non-empty string, truthy), so the return filter (val || optionalSmtpKeys.has(key)) evaluates to true and the key is always included in the outgoing payload whenever MAILER is enabled — even when MAILER_USE_CUSTOM_CONFIGS is false (simple URL mode). While harmless (the backend just persists it), it is inconsistent: MAILER_SMTP_HOST, MAILER_SMTP_PORT, and others are properly excluded from neededKeys in URL mode but still slip through the same return filter for the same reason.

    Consider adding MAILER_SMTP_IGNORE_TLS, MAILER_SMTP_SECURE, and MAILER_TLS_REJECT_UNAUTHORIZED to the set of keys that are guarded by mode (usingCustom) before inclusion in the outgoing payload, or document that sending them in URL mode is intentional.

  2. packages/hoppscotch-backend/src/infra-config/infra-config.service.ts, line 674-676 (link)

    Pair validation skipped when neither credential is in the payload

    The early-exit guard correctly skips the DB query when neither MAILER_SMTP_USER nor MAILER_SMTP_PASSWORD is being updated. However, this means a caller can set only other SMTP fields (e.g. MAILER_SMTP_HOST) while the DB already has a mismatched credential state (e.g. user set, password absent from a previous partially-failed write), and the pair validation will never run. The pairing invariant is only enforced when at least one credential key is explicitly present in the incoming payload.

    This is low-risk in practice because the UI always sends both keys together, but an API-level caller (e.g. a scripted migration) updating host/port only could silently preserve a broken credential state.

    // Current logic - silently skips if neither key is incoming
    if (!smtpKeys.some((key) => incoming.has(key))) {
      return E.right(true);
    }

    Consider always running a lightweight DB check when custom SMTP configs are active, regardless of which keys are incoming.

  3. packages/hoppscotch-sh-admin/src/composables/useOnboardingConfigHandler.ts, line 296-307 (link)

    Onboarding re-visit in URL mode silently clears stored credentials

    When a user re-visits the onboarding screen after having previously configured custom SMTP (with credentials), and then submits with MAILER_USE_CUSTOM_CONFIGS = 'false' (simple URL mode), the return filter still includes MAILER_SMTP_USER: '' and MAILER_SMTP_PASSWORD: '' because of the optionalSmtpKeys.has(key) guard. The backend will then clear both credentials.

    The comment acknowledges this as intentional ("explicitly clear previously stored credentials on re-visits"), but the behaviour may be surprising: silently wiping secrets on a subsequent onboarding visit where the user may simply be updating the SMTP URL without intending to touch credentials. At a minimum, this deserves a more prominent comment or — better — the clearing of credentials should only occur when custom-config mode was previously active and is now being turned off, not unconditionally.

Prompt To Fix All With AI
This is a comment left during a code review.
Path: packages/hoppscotch-sh-admin/src/composables/useOnboardingConfigHandler.ts
Line: 300-306

Comment:
**`MAILER_SMTP_IGNORE_TLS` sent in URL-mode payload**

`configs['MAILER_SMTP_IGNORE_TLS']` defaults to `'false'` (a non-empty string, truthy), so the return filter `(val || optionalSmtpKeys.has(key))` evaluates to `true` and the key is always included in the outgoing payload whenever MAILER is enabled — even when `MAILER_USE_CUSTOM_CONFIGS` is `false` (simple URL mode). While harmless (the backend just persists it), it is inconsistent: `MAILER_SMTP_HOST`, `MAILER_SMTP_PORT`, and others are properly excluded from `neededKeys` in URL mode but still slip through the same return filter for the same reason.

Consider adding `MAILER_SMTP_IGNORE_TLS`, `MAILER_SMTP_SECURE`, and `MAILER_TLS_REJECT_UNAUTHORIZED` to the set of keys that are guarded by mode (`usingCustom`) before inclusion in the outgoing payload, or document that sending them in URL mode is intentional.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: packages/hoppscotch-backend/src/infra-config/infra-config.service.ts
Line: 674-676

Comment:
**Pair validation skipped when neither credential is in the payload**

The early-exit guard correctly skips the DB query when neither `MAILER_SMTP_USER` nor `MAILER_SMTP_PASSWORD` is being updated. However, this means a caller can set only other SMTP fields (e.g. `MAILER_SMTP_HOST`) while the DB already has a mismatched credential state (e.g. user set, password absent from a previous partially-failed write), and the pair validation will never run. The pairing invariant is only enforced when at least one credential key is explicitly present in the incoming payload.

This is low-risk in practice because the UI always sends both keys together, but an API-level caller (e.g. a scripted migration) updating host/port only could silently preserve a broken credential state.

```ts
// Current logic - silently skips if neither key is incoming
if (!smtpKeys.some((key) => incoming.has(key))) {
  return E.right(true);
}
```

Consider always running a lightweight DB check when custom SMTP configs are active, regardless of which keys are incoming.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: packages/hoppscotch-sh-admin/src/composables/useOnboardingConfigHandler.ts
Line: 296-307

Comment:
**Onboarding re-visit in URL mode silently clears stored credentials**

When a user re-visits the onboarding screen after having previously configured custom SMTP (with credentials), and then submits with `MAILER_USE_CUSTOM_CONFIGS = 'false'` (simple URL mode), the return filter still includes `MAILER_SMTP_USER: ''` and `MAILER_SMTP_PASSWORD: ''` because of the `optionalSmtpKeys.has(key)` guard. The backend will then clear both credentials.

The comment acknowledges this as intentional ("explicitly clear previously stored credentials on re-visits"), but the behaviour may be surprising: silently wiping secrets on a subsequent onboarding visit where the user may simply be updating the SMTP URL without intending to touch credentials. At a minimum, this deserves a more prominent comment or — better — the clearing of credentials should only occur when custom-config mode was previously active and is now being turned off, not unconditionally.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (8): Last reviewed commit: "fix: enforce both-or-neither constraint ..." | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 5 files

Copilot AI review requested due to automatic review settings March 23, 2026 08:54
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 6 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/hoppscotch-sh-admin/src/composables/useOnboardingConfigHandler.ts">

<violation number="1" location="packages/hoppscotch-sh-admin/src/composables/useOnboardingConfigHandler.ts:260">
P2: SMTP auth validation now allows partial credentials (username without password, or vice versa). Require both fields together or neither to avoid invalid SMTP auth payloads passing onboarding validation.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

packages/hoppscotch-sh-admin/src/composables/useConfigHandler.ts:287

  • With SMTP auth now optional, the empty-field check excludes mailer_smtp_user and mailer_smtp_password, but there’s still no guard against saving only one of them. This can leave the instance in a partially-authenticated state that will fail when the backend constructs the SMTP transport. Add a validation rule for the email section to ensure user+password are either both non-empty (after trimming) or both empty before allowing save.
      if (section.name === 'email') {
        const { mailer_use_custom_configs, ...otherFields } = section.fields;

        // mailer_smtp_user and mailer_smtp_password are always optional (auth is optional)
        const optionalMailerKeys = ['mailer_smtp_user', 'mailer_smtp_password'];
        const excludeKeys = mailer_use_custom_configs
          ? ['mailer_smtp_url', ...optionalMailerKeys]
          : [
              'mailer_smtp_host',
              'mailer_smtp_port',
              'mailer_smtp_user',
              'mailer_smtp_password',
            ];

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings March 23, 2026 11:32
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings March 23, 2026 13:22
@nivedin nivedin requested a review from jamesgeorge007 March 23, 2026 13:24
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

packages/hoppscotch-sh-admin/src/composables/useConfigHandler.ts:287

  • optionalMailerKeys is introduced to mark SMTP user/password as optional, but the excludeKeys construction still hardcodes those keys again in the non-custom branch. This duplication makes it easy for the optional/required logic to drift over time. Consider reusing optionalMailerKeys in both branches (or using a Set) to keep the validation rules consistent and maintainable.
        // SMTP user and password are fully optional (can be blank individually or both)
        const optionalMailerKeys = ['mailer_smtp_user', 'mailer_smtp_password'];
        const excludeKeys = mailer_use_custom_configs
          ? ['mailer_smtp_url', ...optionalMailerKeys]
          : [
              'mailer_smtp_host',
              'mailer_smtp_port',
              'mailer_smtp_user',
              'mailer_smtp_password',
            ];

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

nivedin and others added 8 commits March 25, 2026 23:18
Relax SMTP auth handling by no longer throwing errors when either MAILER_SMTP_USER or MAILER_SMTP_PASSWORD is missing. The auth object is now built only with provided fields using conditional spreads, and unused error imports were removed. This simplifies and makes SMTP configuration more flexible for providers that accept partial credentials.
Validate SMTP username and password as a pair across the backend
write path, transport construction, and both admin UI flows.
Onboarding check is scoped to custom SMTP mode to avoid blocking
on stale fields after toggling.
@jamesgeorge007 jamesgeorge007 force-pushed the feat/smtp-optional-auth branch from d237dce to 99c8d96 Compare March 25, 2026 17:49
@jamesgeorge007 jamesgeorge007 merged commit 06bdd7c into next Mar 25, 2026
2 checks passed
@jamesgeorge007 jamesgeorge007 deleted the feat/smtp-optional-auth branch March 25, 2026 18:00
@jamesgeorge007 jamesgeorge007 added the feature New feature or request label Mar 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug]: Empty MAILER_SMTP_USER and MAILER_SMTP_PASSWORD considered invalid

4 participants