QUESTPIE

Adapter options

Every constructor option on the four built-in mail adapters, what each one defaults to, and the Ethereal throwaway inbox for tests.

View markdown

Email covers picking an adapter and swapping one. Everything below goes in the same slot, email.adapter in questpie.config.ts, and none of it changes a template or a send call.

Console

import { ConsoleAdapter } from "questpie/adapters/console";

new ConsoleAdapter(); // both options are optional
new ConsoleAdapter({ logHtml: true });
OptionTypeDefaultNotes
logHtmlbooleanfalseWhen false the HTML body becomes a one-line hint. HTML is long.
logger(message: string) => voidconsole.logWhere every line goes.

It prints From, To, CC, BCC, Reply-To, Subject, the plain-text body, attachment filenames, and the HTML only when you ask. It never sends.

SMTP

import { SmtpAdapter } from "questpie/adapters/smtp";

new SmtpAdapter({
	transport: {
		host: "smtp.example.com",
		port: 587,
		secure: false,
		auth: { user: env.SMTP_USER, pass: env.SMTP_PASS },
	},
});

new SmtpAdapter({ transport: "smtp://user:pass@smtp.example.com:587" });
OptionTypeNotes
transportSMTPTransport | SMTPTransport.Options | stringHanded straight to nodemailer.createTransport. Required.
afterSendCallback(info: SentMessageInfo) => void | Promise<void>Runs after each send, with nodemailer's info object.

SerializableMailOptions is passed to sendMail unchanged, so CC, BCC, attachments, replyTo and custom headers all behave the way nodemailer documents them. SmtpAdapter also exposes verify(): Promise<boolean>, which proxies nodemailer's connection check.

Ethereal test inbox

createEtherealSmtpAdapter() creates a throwaway Ethereal account and returns an SmtpAdapter already wired to log a preview URL after every send.

import { createEtherealSmtpAdapter } from "questpie/adapters/smtp";

export default runtimeConfig({
	email: { adapter: createEtherealSmtpAdapter() }, // a Promise<SmtpAdapter>
});

It returns a promise, which MailerConfig.adapter accepts as-is because the mailer awaits the adapter on send. Dev and tests only. It makes a network call to create the account.

Resend

import { resendAdapter } from "questpie/adapters/resend";

resendAdapter({ apiKey: env.RESEND_API_KEY });
OptionTypeDefaultNotes
apiKeystringrequiredA Resend key, or one for a Resend-compatible provider.
baseUrlstring"https://api.resend.com"Point at a compatible API. Trailing slashes are stripped.
userAgentstring"questpie-resend-adapter"Resend wants a User-Agent on direct HTTP calls.
idempotencyKeystring | ((options) => string | undefined)noneStatic or per-message. Sets the Idempotency-Key header.
fetchtypeof fetchglobal fetchOverride for tests or a non-standard runtime.
afterSendCallback(response: ResendSendResponse, options) => void | Promise<void>noneGets the parsed JSON body, so the message id lands here.

It POSTs to <baseUrl>/emails, maps replyTo to reply_to, and base64-encodes Buffer attachments. A non-2xx response throws Resend API error (<status> <statusText>): <body>.

Plunk

import { plunkAdapter } from "questpie/adapters/plunk";

plunkAdapter({ apiKey: env.PLUNK_SECRET_KEY });
OptionTypeDefaultNotes
apiKeystringrequiredA Plunk secret key. Public keys only track events.
baseUrlstring"https://next-api.useplunk.com"Override for self-hosted Plunk.
fromNamestringnoneApplied only when from is a bare address, no Name <…>.
subscribedbooleannoneSubscribes recipients to marketing. Leave it off.
fetchtypeof fetchglobal fetchOverride for tests or a non-standard runtime.
afterSendCallback(response: PlunkSendResponse, options) => void | Promise<void>noneGets the parsed body once Plunk accepts the message.

It POSTs to <baseUrl>/v1/send with body set to html || text and reply carrying replyTo. It base64-encodes Buffer attachments, same as Resend, and sends string attachment content through unchanged.

Two failure modes, not one

Plunk throws on a non-2xx response, and also on a 2xx whose body carries success: false. Either way the message is a Plunk API error line with the status and Plunk's own error code. A cc or bcc throws before the request.

  • Email, the adapter slot, the swap, and the MailAdapter interface.
  • Emails, the templates and send calls above all of this.
  • Environment, typed env() for API keys and SMTP credentials.

On this page