SMTP-backed mail provider for Beignet, implemented with Nodemailer.
The provider installs the app-facing ctx.ports.mailer port and exposes
ctx.ports.smtp.transporter only as an escape hatch for Nodemailer-specific
features.
bun add @beignet/provider-mail-smtp nodemailer
import { mailSmtpProvider } from "@beignet/provider-mail-smtp";
import { createServer } from "@beignet/core/server";
const server = await createServer({
ports: basePorts,
providers: [mailSmtpProvider],
createContext: ({ ports }) => ({ ports }),
routes,
});
Required environment variables:
| Variable | Description |
|---|---|
MAIL_HOST |
SMTP server hostname |
MAIL_PORT |
SMTP server port. Port 465 uses SSL. |
MAIL_USER |
SMTP username |
MAIL_PASS |
SMTP password |
MAIL_FROM |
Default sender address |
await ctx.ports.mailer.send({
to: "user@example.com",
subject: "Welcome",
text: "Thanks for joining.",
});
The same MailerPort works with Resend, memory fakes, and other adapters:
await ctx.ports.mailer.send({
from: { email: "support@example.com", name: "Support" },
to: ["user@example.com", "admin@example.com"],
cc: "audit@example.com",
replyTo: "support@example.com",
subject: "Account updated",
text: "Your account was updated.",
html: "<p>Your account was updated.</p>",
});
Use the Nodemailer transporter only when you need an SMTP-specific feature not
covered by MailerPort:
await ctx.ports.smtp.transporter.sendMail({
from: "sender@example.com",
to: "user@example.com",
subject: "Invoice",
text: "Attached.",
attachments: [
{
filename: "invoice.pdf",
path: "/path/to/invoice.pdf",
},
],
});
When ctx.ports.devtools is installed, this provider records mail.send,
mail.sent, and mail.failed events under the mail watcher.
Delivery failures throw MailDeliveryError from @beignet/core/mail.
Startup configuration and connection problems throw during provider setup.
MIT