Skip to content

[Bug]: SMTP authentication is forced for unauthenticated relays #1419

Description

@thriz0

Bug Description

Kaneo cannot send workspace invitation emails through an SMTP relay that does not require authentication.

The same SMTP relay works correctly with Nodemailer when no auth object is configured. However, Kaneo always initializes the Nodemailer transport with:

auth: {
  user: process.env.SMTP_USER,
  pass: process.env.SMTP_PASSWORD,
}

When these variables are not configured, Nodemailer still attempts SMTP authentication.

Steps To Reproduce

  1. Configure Kaneo with an SMTP relay that does not require authentication.
  2. Set SMTP_HOST, SMTP_PORT, SMTP_SECURE, and SMTP_FROM.
  3. Do not set SMTP_USER or SMTP_PASSWORD.
  4. Start Kaneo.
  5. Create a workspace or open an existing workspace.
  6. Invite another user by email.

Expected Behavior

Kaneo should send the workspace invitation email without attempting SMTP authentication when SMTP_USER and SMTP_PASSWORD are not configured.

The Nodemailer transport should omit the auth property entirely in this case.

Actual result

The invitation email is not sent.

Kaneo logs:

Error sending workspace invitation email
Error: Missing credentials for "PLAIN"

When SMTP credentials are added, Kaneo instead attempts authentication and the relay rejects it:

Error: Invalid login: 535 authentication failed
...
code: 'EAUTH'
command: 'AUTH PLAIN'

Screenshots

No response

Environment

  • Kaneo Version: 2.9.8

Additional Context

The current implementation appears to always pass an auth object to Nodemailer:

const transporter = nodemailer.createTransport({
  host: process.env.SMTP_HOST,
  secure: process.env.SMTP_SECURE !== "false",
  port: Number(process.env.SMTP_PORT),
  auth: {
    user: process.env.SMTP_USER,
    pass: process.env.SMTP_PASSWORD,
  },
  requireTLS: process.env.SMTP_REQUIRE_TLS === "true",
  ignoreTLS: process.env.SMTP_IGNORE_TLS === "true",
});

The auth property should only be included when both SMTP_USER and SMTP_PASSWORD are defined.

For example:

const smtpUser = process.env.SMTP_USER;
const smtpPassword = process.env.SMTP_PASSWORD;

const transporter = nodemailer.createTransport({
  host: process.env.SMTP_HOST,
  secure: process.env.SMTP_SECURE !== "false",
  port: Number(process.env.SMTP_PORT),
  ...(smtpUser && smtpPassword
    ? {
        auth: {
          user: smtpUser,
          pass: smtpPassword,
        },
      }
    : {}),
  requireTLS: process.env.SMTP_REQUIRE_TLS === "true",
  ignoreTLS: process.env.SMTP_IGNORE_TLS === "true",
});

This would support both authenticated SMTP servers and unauthenticated internal relays.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions