Skip to main content
The Nuxt Lettermint module provides access to the Lettermint SDK’s fluent API for advanced use cases and more control over email composition.

Fluent API overview

The fluent API allows you to chain methods to build your email step by step. This is useful when you need more control over the email construction or want to conditionally add properties.

Server-side fluent API

Access the Lettermint SDK directly on the server using useLettermint():
server/api/advanced-send.ts
import { useLettermint } from '#imports'

export default defineEventHandler(async () => {
  const lettermint = useLettermint()

  const result = await lettermint.email
    .from('[email protected]')
    .to('[email protected]')
    .subject('Test SDK Email')
    .html('<h1>Hello from Lettermint SDK</h1>')
    .tag('sdk-test')
    .send()

  return {
    success: true,
    result,
  }
})
The server-side useLettermint() returns the Lettermint SDK instance, not the client composable. These are two different functions with the same name but different contexts.

Available fluent methods

The Lettermint SDK provides the following chainable methods:
MethodDescriptionExample
.from(email)Set sender email.from('[email protected]')
.to(email)Add recipient.to('[email protected]')
.cc(email)Add CC recipient.cc('[email protected]')
.bcc(email)Add BCC recipient.bcc('[email protected]')
.replyTo(email)Set reply-to address.replyTo('[email protected]')
.subject(text)Set email subject.subject('Welcome!')
.text(content)Set plain text content.text('Hello world')
.html(content)Set HTML content.html('<h1>Hello</h1>')
.tag(name)Add a tag.tag('welcome')
.headers(obj)Set custom headers.headers({ 'X-Custom': 'value' })
.metadata(obj)Set metadata.metadata({ userId: '123' })
.attach(filename, content)Add attachment.attach('file.pdf', base64Data)
.send()Send the email.send()
All methods except .send() return the email builder, allowing you to chain multiple calls.

Conditional email building

The fluent API is perfect for building emails conditionally:
server/api/conditional-email.ts
import { useLettermint } from '#imports'

export default defineEventHandler(async (event) => {
  const lettermint = useLettermint()
  const { user, includeCopy, urgentFlag } = await readBody(event)

  // Start building the email
  let email = lettermint.email
    .from('[email protected]')
    .to(user.email)
    .subject('Your Report')
    .html('<h1>Report Ready</h1>')

  // Conditionally add CC
  if (includeCopy && user.managerEmail) {
    email = email.cc(user.managerEmail)
  }

  // Conditionally add tags
  if (urgentFlag) {
    email = email.tag('urgent')
  }
  email = email.tag('report')

  // Conditionally add metadata
  if (user.id) {
    email = email.metadata({
      userId: user.id,
      reportType: 'monthly'
    })
  }

  return await email.send()
})

Multiple recipients with fluent API

You can call recipient methods multiple times to add multiple recipients:
server/api/multi-recipient.ts
import { useLettermint } from '#imports'

export default defineEventHandler(async () => {
  const lettermint = useLettermint()
  const recipients = ['[email protected]', '[email protected]', '[email protected]']

  // Start with base email
  let email = lettermint.email
    .from('[email protected]')
    .subject('Team Update')
    .html('<h1>Important Update</h1>')

  // Add all recipients
  recipients.forEach(recipient => {
    email = email.to(recipient)
  })

  return await email.send()
})

Multiple tags

Add multiple tags by chaining .tag() calls:
server/api/multi-tag.ts
import { useLettermint } from '#imports'

export default defineEventHandler(async () => {
  const lettermint = useLettermint()

  return await lettermint.email
    .from('[email protected]')
    .to('[email protected]')
    .subject('Spring Sale')
    .html('<h1>50% Off Everything</h1>')
    .tag('campaign')
    .tag('promotional')
    .tag('spring-2024')
    .tag('sale')
    .send()
})

Working with attachments

The .attach() method accepts a filename and base64-encoded content:
server/api/send-attachment.ts
import { useLettermint } from '#imports'
import { readFile } from 'fs/promises'

export default defineEventHandler(async () => {
  const lettermint = useLettermint()

  // Read and encode file
  const fileBuffer = await readFile('./report.pdf')
  const base64Content = fileBuffer.toString('base64')

  return await lettermint.email
    .from('[email protected]')
    .to('[email protected]')
    .subject('Monthly Report')
    .html('<h1>Monthly Report Attached</h1>')
    .attach('report.pdf', base64Content)
    .send()
})

Custom headers

Add custom headers for tracking, routing, or other purposes:
server/api/custom-headers.ts
import { useLettermint } from '#imports'

export default defineEventHandler(async () => {
  const lettermint = useLettermint()

  return await lettermint.email
    .from('[email protected]')
    .to('[email protected]')
    .subject('Welcome')
    .html('<h1>Welcome to our app</h1>')
    .headers({
      'X-Campaign-ID': 'welcome-2024',
      'X-Priority': 'high',
      'X-Email-Type': 'transactional'
    })
    .send()
})

Metadata for tracking

Metadata is not sent in the email but stored by Lettermint for tracking and analytics:
server/api/tracked-email.ts
import { useLettermint } from '#imports'

export default defineEventHandler(async () => {
  const lettermint = useLettermint()

  return await lettermint.email
    .from('[email protected]')
    .to('[email protected]')
    .subject('Password Reset')
    .html('<h1>Reset your password</h1>')
    .metadata({
      userId: '12345',
      action: 'password-reset',
      ipAddress: '192.168.1.1',
      userAgent: 'Mozilla/5.0...',
      timestamp: new Date().toISOString()
    })
    .tag('security')
    .send()
})
Metadata values must be strings. The module automatically converts objects to strings when using sendEmail(), but with the fluent API you should ensure values are strings.

How sendEmail() uses the fluent API

The sendEmail() function is implemented using the fluent API. Here’s how it works internally:
src/runtime/server/utils/lettermint.ts
export async function sendEmail(options: SendEmailOptions) {
  const lettermint = useLettermint()

  let email = lettermint.email
    .from(options.from)
    .subject(options.subject)

  // Add recipients (handling arrays)
  if (Array.isArray(options.to)) {
    options.to.forEach((recipient) => {
      email = email.to(recipient)
    })
  }
  else {
    email = email.to(options.to)
  }

  // Add optional fields
  if (options.text) email = email.text(options.text)
  if (options.html) email = email.html(options.html)

  // Handle CC (with array support)
  if (options.cc) {
    if (Array.isArray(options.cc)) {
      options.cc.forEach((recipient) => {
        email = email.cc(recipient)
      })
    }
    else {
      email = email.cc(options.cc)
    }
  }

  // Handle BCC (with array support)
  if (options.bcc) {
    if (Array.isArray(options.bcc)) {
      options.bcc.forEach((recipient) => {
        email = email.bcc(recipient)
      })
    }
    else {
      email = email.bcc(options.bcc)
    }
  }

  // Add tags
  if (options.tags) {
    options.tags.forEach((tag) => {
      email = email.tag(tag)
    })
  }

  // Add headers
  if (options.headers) {
    email = email.headers(options.headers)
  }

  // Add metadata
  if (options.metadata) {
    email = email.metadata(options.metadata as Record<string, string>)
  }

  // Add attachments
  if (options.attachments) {
    options.attachments.forEach((attachment) => {
      email = email.attach(
        attachment.filename,
        typeof attachment.content === 'string' 
          ? attachment.content 
          : attachment.content.toString('base64'),
      )
    })
  }

  return await email.send()
}

When to use fluent API vs sendEmail()

Use sendEmail() when:
  • You have all email data upfront as an object
  • You’re working with form submissions or API requests
  • You want simple, straightforward email sending
  • You’re migrating from another email service
Use fluent API when:
  • You need to build emails conditionally
  • You want more explicit control over email composition
  • You’re working with complex email logic
  • You prefer a more expressive, chainable syntax

sendEmail() approach

const result = await sendEmail({
  from: '[email protected]',
  to: recipients,
  subject: 'Update',
  html: content,
  tags: ['newsletter']
})
Best for: Simple, data-driven emails

Fluent API approach

let email = lettermint.email
  .from('[email protected]')
  .subject('Update')

recipients.forEach(r => {
  email = email.to(r)
})

if (isUrgent) {
  email = email.tag('urgent')
}

await email.send()
Best for: Complex, conditional logic

Next steps

Custom endpoints

Create custom API endpoints with additional logic

Configuration

Learn about all configuration options

Build docs developers (and LLMs) love