Docs
Email

Email

Transactional email via Resend for auth flows, workflow approvals, and analysis delivery.

What Sends Email

TriggerSourceDescription
Email verificationlib/mails/auth-emails.tsSent on signup (OTP code)
Magic link loginlib/mails/auth-emails.tsPasswordless sign-in link
Team invitationlib/mails/auth-emails.tsInvite a user to your team
Workflow plan approvallib/ai/workflows/emails.tsSent after a workflow is created (draft state)
Workflow step approvallib/ai/workflows/emails.tsSent when a step requires human review
Workflow completedlib/ai/workflows/emails.tsRun finished successfully
Workflow failedlib/ai/workflows/emails.tsRun hit an unrecoverable error
Legal analysis deliverysend-analysis-email.ts toolSent by the legal-analyzer agent

Workflow Email Functions

// lib/ai/workflows/emails.ts
 
// Plan approval — sent immediately after workflow creation
sendPlanApprovalEmail({
  to: string,
  workflowId: string,
  workflowTitle: string,
  goal: string,
  steps: WorkflowStep[],
  token: string,         // 24h JWT
})
 
// Step approval — sent when a step has needsApproval: true
sendStepApprovalEmail({
  to: string,
  workflowId: string,
  runNumber: number,
  stepDescription: string,
  approvalPrompt: string,
  toolOutput: string,    // preview of what the tool produced
  token: string,         // 2h JWT
})
 
// Run finished
sendRunCompletedEmail({ to, workflowTitle, workflowId, runNumber })
 
// Run failed
sendRunFailedEmail({ to, workflowTitle, workflowId, runNumber, stepDescription, error })

Approval emails include one-time JWT links:

Link typeRouteExpiry
Plan approvalGET /api/workflows/[id]/approve?token=...24 hours
Step approveGET /api/workflows/resume?token=...&action=approve2 hours
Step rejectGET /api/workflows/resume?token=...&action=reject&note=...2 hours

Tokens are HS256 JWTs signed with WORKFLOW_TOKEN_SECRET using the jose library.

Bot-Prefetch Guard

Email clients (Outlook, Gmail) send a prefetch GET to any link in an email to generate a preview. Without protection, this would trigger workflow approvals before the user even opens the email.

GET /api/workflows/resume checks the User-Agent header and returns a neutral 200 OK (no side effects) for known bot/crawler user agents. Only requests with a human browser UA actually execute the approval.

Required Environment Variables

RESEND_API_KEY=re_...
EMAIL_FROM=Ship AI SaaS <noreply@yourdomain.com>

You must verify your sending domain in the Resend dashboard before emails will deliver in production. The noreply@yourdomain.com address must be on a verified domain. See the Resend docs for the verification steps.