different-ai/openwork · error · EmailSendError
nodemailer_rejected
nodemailer_rejected
Error message
[${input.template}] email for ${input.recipient} failed: ${input.reason}${input.detail ? ` (${input.detail})` : ""} What it means
The Nodemailer SMTP transport wraps any exception thrown by transporter.sendMail in EmailSendError with reason "nodemailer_rejected", preserving the underlying message (SMTP error, auth failure, connection error) in detail. It means the SMTP delivery itself failed rather than an API-level rejection.
Source
Thrown at packages/email/src/send-email.ts:196
auth: smtp.user
? {
user: smtp.user,
pass: smtp.pass,
}
: undefined,
})
await transporter.sendMail({
from,
to: input.to,
subject: input.subject,
replyTo: input.replyTo,
html: input.html,
text: input.text,
})
} catch (error) {
const message = error instanceof Error ? error.message : "Unknown error"
throw new EmailSendError({ template: input.template, reason: "nodemailer_rejected", recipient: input.to, detail: message })
}
}
View on GitHub (pinned to 2b7df46e8a)
Solutions
- Read detail in the thrown EmailSendError for the exact SMTP error code/message
- Verify SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS env values and that the account is active
- Confirm the host allows outbound traffic on the configured SMTP port (many clouds block 25; use 587 with STARTTLS)
- If the error is 5xx auth/login failure, reset credentials or enable an app password
- Retry for transient 4xx SMTP responses; verify the recipient address for 550-class rejections
Example fix
// before
transporter = nodemailer.createTransport({ host: 'smtp.gmail.com', port: 25 }) // blocked + no auth
// after
transporter = nodemailer.createTransport({ host: 'smtp.gmail.com', port: 587, secure: false, auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS } }) Defensive patterns
Strategy: try-catch
Validate before calling
function assertSmtpConfig(env) {
for (const key of ['SMTP_HOST', 'SMTP_PORT', 'SMTP_USER', 'SMTP_PASS']) {
if (!env[key]) throw new Error(`Missing ${key} — nodemailer sends will fail`);
}
const port = Number(env.SMTP_PORT);
if (port !== 587 && port !== 465) console.warn(`Unusual SMTP port ${port}; many clouds block 25`);
} Try / catch
try {
await sendEmail({ template, to })
} catch (e) {
if (e instanceof EmailSendError && e.reason === 'nodemailer_rejected') {
console.error(`SMTP send failed: ${e.detail}`) // inspect SMTP code in detail
} else throw e
} Prevention
- Validate SMTP env config at startup
- Use port 587 (STARTTLS) or 465 (implicit TLS), not 25
- Use app passwords / credentials valid for SMTP auth
- Verify recipient addresses to avoid 550 rejections
- Handle transient 4xx responses with retry
When it happens
Trigger: sendEmail routed to the Nodemailer provider and transporter.sendMail throws — SMTP connection refused, bad credentials, rejected recipient, TLS failure, or timeout.
Common situations: Wrong SMTP host/port or missing credentials in env (SMTP_HOST/SMTP_USER/SMTP_PASS); provider blocking port 25/587 from cloud hosts; self-signed or expired TLS certificates; recipient address rejected by the mail server; rate limits on the SMTP account.
Related errors
- resend_network
- latest-mac.yml is missing artifact path/url.
- Failed to fetch latest-mac.yml (${response.status} ${respons
- Request timed out.
- Timed out waiting for server health
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/ff882b4f881d4a03.
Report an issue: GitHub.