Email System
UNuxt includes a complete email system with Nodemailer integration and beautiful HTML templates for all transactional emails.
Configure SMTP
Set up your email service provider by adding SMTP credentials to your .env file:
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=your-email@example.com
SMTP_PASS=your-password
FROM_EMAIL=noreply@example.com
FROM_NAME=UNuxt
Common SMTP providers
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-app-specific-password # Not your regular password!
SMTP_HOST=smtp.sendgrid.net
SMTP_PORT=587
SMTP_USER=apikey
SMTP_PASS=your-sendgrid-api-key
SMTP_HOST=smtp.mailgun.org
SMTP_PORT=587
SMTP_USER=postmaster@your-domain.mailgun.org
SMTP_PASS=your-mailgun-smtp-password
SMTP_HOST=email-smtp.us-east-1.amazonaws.com
SMTP_PORT=587
SMTP_USER=your-ses-smtp-username
SMTP_PASS=your-ses-smtp-password
Send emails
Use the email service from anywhere in your application:
import { sendEmail } from '@unuxt/email'
import { baseTemplate } from '@unuxt/email/templates/base'
export default defineEventHandler(async (event) => {
const { email, name } = await readBody(event)
const { html, text } = baseTemplate({
title: 'Welcome to UNuxt!',
preheader: 'Thanks for joining us',
content: `
<p>Hi ${name},</p>
<p>Welcome to our platform! We're excited to have you on board.</p>
`,
actionUrl: 'https://your-app.com/get-started',
actionText: 'Get Started',
footer: 'Questions? Reply to this email.',
})
await sendEmail({
to: email,
subject: 'Welcome to UNuxt!',
html,
text,
})
return { success: true }
})
Use built-in templates
UNuxt includes pre-built templates for common transactional emails:
Password reset
import { sendEmail, resetPasswordEmail } from '@unuxt/email'
const emailOptions = resetPasswordEmail({
email: 'user@example.com',
resetUrl: 'https://app.com/reset?token=abc123',
expiresInMinutes: 60, // Optional, defaults to 60
})
await sendEmail(emailOptions)
Email verification
import { sendEmail, verifyEmailTemplate } from '@unuxt/email'
const emailOptions = verifyEmailTemplate({
email: 'user@example.com',
verifyUrl: 'https://app.com/verify?token=abc123',
})
await sendEmail(emailOptions)
Magic link
import { sendEmail, magicLinkEmail } from '@unuxt/email'
const emailOptions = magicLinkEmail({
email: 'user@example.com',
magicUrl: 'https://app.com/magic?token=abc123',
expiresInMinutes: 15, // Optional, defaults to 15
})
await sendEmail(emailOptions)
Organization invitation
import { sendEmail, organizationInvitationEmail } from '@unuxt/email'
const emailOptions = organizationInvitationEmail({
email: 'newmember@example.com',
organizationName: 'Acme Corp',
invitedBy: 'John Doe',
inviteUrl: 'https://app.com/auth/accept-invite/inv_123',
role: 'member',
})
await sendEmail(emailOptions)
Create custom templates
Build your own email templates using the base template:
import { baseTemplate } from './base'
import type { SendEmailOptions } from '../mailer'
export interface CustomEmailOptions {
email: string
userName: string
customData: string
}
export function customEmail(options: CustomEmailOptions): SendEmailOptions {
const { email, userName, customData } = options
const content = `
<p>Hi ${userName},</p>
<p>Here's your custom content: ${customData}</p>
<p>Thanks for using our service!</p>
`
const { html, text } = baseTemplate({
title: 'Custom Email',
preheader: 'Your custom email subject',
content,
actionUrl: 'https://app.com/dashboard',
actionText: 'View Dashboard',
footer: 'Need help? Contact support@example.com',
})
return {
to: email,
subject: 'Your Custom Email',
html,
text,
}
}
Handle email failures
The email system includes automatic fallbacks for development:
try {
await sendEmail(emailOptions)
console.log('Email sent successfully')
} catch (error) {
console.error('Failed to send email:', error)
// In development, URLs are logged to console
if (process.env.NODE_ENV === 'development') {
console.log('Email URL:', emailOptions.actionUrl)
}
}
Customize email styling
All email templates use the base template with consistent branding. Customize the styling in packages/email/src/templates/base.ts:
const styles = {
primaryColor: '#10b981', // Your brand color
textColor: '#1f2937',
backgroundColor: '#f9fafb',
buttonColor: '#10b981',
buttonTextColor: '#ffffff',
}
Test emails in development
Option 1: Use a test SMTP service
Services like Mailtrap or Ethereal provide test SMTP servers:
SMTP_HOST=smtp.ethereal.email
SMTP_PORT=587
SMTP_USER=your-ethereal-user
SMTP_PASS=your-ethereal-pass
Option 2: Check console output
If SMTP is not configured, URLs and email content are logged to your terminal:
[EMAIL] Email service not configured - logging to console
[AUTH] Password reset URL: http://localhost:3000/reset?token=abc123
Verify email service
Check if the email service is working:
import { verifyConnection } from '@unuxt/email'
export default defineEventHandler(async () => {
const isConnected = await verifyConnection()
return { connected: isConnected }
})
Troubleshooting
Emails not sending
- Check SMTP configuration in
.env - Verify SMTP credentials are correct
- Check server logs for errors
- Look for "Email service initialized successfully" message on startup
Gmail "Less secure app" error
Gmail no longer supports "less secure apps". Use an app-specific password:
- Enable 2FA on your Google account
- Go to App Passwords
- Generate a new app password
- Use that password in
SMTP_PASS
Connection timeout
- Check firewall settings
- Verify SMTP port (usually 587 or 465)
- Try a different port if one doesn't work
- Some ISPs block port 25