GuidesMigration guides
Migrate from Nodemailer
Replace a Nodemailer transporter with Email SDK's dependency-free SMTP adapter.
Email SDK includes its own SMTP transport. You do not need Nodemailer for basic address fields, text/HTML bodies, headers, TLS upgrade, and SMTP auth.
Replace the transporter
import { createEmailClient } from "@opencoredev/email-sdk";
import { smtp } from "@opencoredev/email-sdk/smtp";
const email = createEmailClient({
adapters: [
smtp({
host: process.env.SMTP_HOST!,
port: Number(process.env.SMTP_PORT ?? 587),
auth: {
user: process.env.SMTP_USER!,
pass: process.env.SMTP_PASS!,
},
}),
],
});On a non-secure port, SMTP auth upgrades with STARTTLS by default. allowInsecureAuth exists only for trusted local test servers.
Replace sendMail
const result = await email.send(
{
from: "Acme <hello@acme.com>",
to: "user@example.com",
subject: "Welcome",
text: "Your account is ready.",
html: "<p>Your account is ready.</p>",
headers: [{ name: "X-App", value: "acme" }],
},
{ idempotencyKey: "welcome:user_123" },
);The transport creates multipart/alternative for text plus HTML and derives Message-ID from the idempotency key.
Account for unsupported features
The built-in SMTP adapter rejects attachments, tags, metadata, and schedules. Keep Nodemailer or build a custom adapter if your SMTP workflow depends on MIME attachments or advanced transport plugins.
Verify
SMTP_HOST=smtp.example.com npx email-sdk doctor --adapter smtp
npx email-sdk send \
--adapter smtp \
--host smtp.example.com \
--from hello@example.com \
--to user@example.com \
--subject "Migration smoke test" \
--text "Dry run only." \
--dry-runSMTP adapter
See TLS, auth, custom names, and transport limits.
