mirror of
https://github.com/xtr-dev/payload-mailing.git
synced 2025-12-10 00:03:23 +00:00
✨ FEATURE: Add PayloadCMS task for queuing template emails
- Add sendTemplateEmailTask with comprehensive input schema - Support template rendering, email parsing, and scheduling - Include TypeScript interface SendTemplateEmailInput for type safety - Add task to exports for easy import and usage - Support custom email collection fields via extensible input - Add comprehensive documentation with usage examples Users can now: ✅ Import and add task to their Payload jobs configuration ✅ Queue emails programmatically via payload.jobs.queue() ✅ Use admin panel form interface for manual email queuing ✅ Get full TypeScript support with proper input types ✅ Extend with custom fields from their email collection Example usage: ```typescript import { sendTemplateEmailTask } from '@xtr-dev/payload-mailing' // Add to Payload config export default buildConfig({ jobs: { tasks: [sendTemplateEmailTask] } }) // Queue from code await payload.jobs.queue({ task: 'send-template-email', input: { templateSlug: 'welcome', to: ['user@example.com'], variables: { name: 'John' } } }) ``` 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,10 @@ export { MailingService } from './services/MailingService.js'
|
||||
export { default as EmailTemplates, createEmailTemplatesCollection } from './collections/EmailTemplates.js'
|
||||
export { default as Emails } from './collections/Emails.js'
|
||||
|
||||
// Tasks
|
||||
export { sendTemplateEmailTask, default as sendTemplateEmailTaskDefault } from './tasks/sendTemplateEmailTask.js'
|
||||
export type { SendTemplateEmailInput } from './tasks/sendTemplateEmailTask.js'
|
||||
|
||||
// Jobs are integrated into the plugin configuration
|
||||
|
||||
// Utility functions for developers
|
||||
|
||||
151
src/tasks/sendTemplateEmailTask.ts
Normal file
151
src/tasks/sendTemplateEmailTask.ts
Normal file
@@ -0,0 +1,151 @@
|
||||
import { renderTemplate } from '../utils/helpers.js'
|
||||
|
||||
export interface SendTemplateEmailInput {
|
||||
templateSlug: string
|
||||
to: string | string[]
|
||||
cc?: string | string[]
|
||||
bcc?: string | string[]
|
||||
variables?: Record<string, any>
|
||||
scheduledAt?: string // ISO date string
|
||||
priority?: number
|
||||
// Allow any additional fields that users might have in their email collection
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export const sendTemplateEmailTask = {
|
||||
slug: 'send-template-email',
|
||||
label: 'Send Template Email',
|
||||
inputSchema: [
|
||||
{
|
||||
name: 'templateSlug',
|
||||
type: 'text' as const,
|
||||
required: true,
|
||||
label: 'Template Slug',
|
||||
admin: {
|
||||
description: 'The slug of the email template to render'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'to',
|
||||
type: 'text' as const,
|
||||
required: true,
|
||||
label: 'To (Email Recipients)',
|
||||
admin: {
|
||||
description: 'Comma-separated list of email addresses'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'cc',
|
||||
type: 'text' as const,
|
||||
label: 'CC (Carbon Copy)',
|
||||
admin: {
|
||||
description: 'Optional comma-separated list of CC email addresses'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'bcc',
|
||||
type: 'text' as const,
|
||||
label: 'BCC (Blind Carbon Copy)',
|
||||
admin: {
|
||||
description: 'Optional comma-separated list of BCC email addresses'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'variables',
|
||||
type: 'json' as const,
|
||||
label: 'Template Variables',
|
||||
admin: {
|
||||
description: 'JSON object with variables for template rendering'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'scheduledAt',
|
||||
type: 'date' as const,
|
||||
label: 'Schedule For',
|
||||
admin: {
|
||||
description: 'Optional date/time to schedule email for future delivery'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'priority',
|
||||
type: 'number' as const,
|
||||
label: 'Priority',
|
||||
min: 1,
|
||||
max: 10,
|
||||
admin: {
|
||||
description: 'Email priority (1 = highest, 10 = lowest)'
|
||||
}
|
||||
}
|
||||
],
|
||||
handler: async ({ input, payload }: any) => {
|
||||
// Cast input to our expected type
|
||||
const taskInput = input as SendTemplateEmailInput
|
||||
|
||||
try {
|
||||
// Render the template
|
||||
const { html, text, subject } = await renderTemplate(
|
||||
payload,
|
||||
taskInput.templateSlug,
|
||||
taskInput.variables || {}
|
||||
)
|
||||
|
||||
// Parse email addresses
|
||||
const parseEmails = (emails: string | string[] | undefined): string[] | undefined => {
|
||||
if (!emails) return undefined
|
||||
if (Array.isArray(emails)) return emails
|
||||
return emails.split(',').map(email => email.trim()).filter(Boolean)
|
||||
}
|
||||
|
||||
// Prepare email data
|
||||
const emailData: any = {
|
||||
to: parseEmails(taskInput.to),
|
||||
cc: parseEmails(taskInput.cc),
|
||||
bcc: parseEmails(taskInput.bcc),
|
||||
subject,
|
||||
html,
|
||||
text,
|
||||
priority: taskInput.priority || 5,
|
||||
}
|
||||
|
||||
// Add scheduled date if provided
|
||||
if (taskInput.scheduledAt) {
|
||||
emailData.scheduledAt = new Date(taskInput.scheduledAt).toISOString()
|
||||
}
|
||||
|
||||
// Add any additional fields from input (excluding the ones we've already handled)
|
||||
const handledFields = ['templateSlug', 'to', 'cc', 'bcc', 'variables', 'scheduledAt', 'priority']
|
||||
Object.keys(taskInput).forEach(key => {
|
||||
if (!handledFields.includes(key)) {
|
||||
emailData[key] = taskInput[key]
|
||||
}
|
||||
})
|
||||
|
||||
// Create the email in the collection
|
||||
const email = await payload.create({
|
||||
collection: 'emails', // Default collection name
|
||||
data: emailData
|
||||
})
|
||||
|
||||
return {
|
||||
success: true,
|
||||
emailId: email.id,
|
||||
message: `Email queued successfully with ID: ${email.id}`,
|
||||
templateSlug: taskInput.templateSlug,
|
||||
recipients: emailData.to?.length || 0,
|
||||
scheduledAt: emailData.scheduledAt || null
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error'
|
||||
|
||||
return {
|
||||
success: false,
|
||||
error: errorMessage,
|
||||
templateSlug: taskInput.templateSlug,
|
||||
message: `Failed to queue email: ${errorMessage}`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default sendTemplateEmailTask
|
||||
Reference in New Issue
Block a user