Refactor email handling for improved type safety and extensibility

- Replace `BaseEmailData` with `Email` type for stricter type validation
- Update `sendEmail` API to support new typed structure and template integration
- Migrate to `@xtr-dev/payload-mailing` for enhanced email sending capabilities
- Remove unnecessary null checks and redundant code in email scheduling logic
- Regenerate PayloadCMS types for aligning with revised schema changes
- Update dev scripts and imports for seamless compatibility with the new email module
This commit is contained in:
2025-09-13 21:51:52 +02:00
parent 934b7c2de7
commit 45559804b0
6 changed files with 523 additions and 54 deletions

View File

@@ -100,7 +100,8 @@ export interface Config {
};
jobs: {
tasks: {
'process-email-queue': ProcessEmailQueueJob;
processEmails: ProcessEmailsJob;
'send-email': TaskSendEmail;
inline: {
input: unknown;
output: unknown;
@@ -232,21 +233,17 @@ export interface Email {
*/
template?: (string | null) | EmailTemplate;
/**
* Template slug used for this email
* Recipient email addresses
*/
templateSlug?: string | null;
to: string[];
/**
* Recipient email address(es), comma-separated
* CC email addresses
*/
to: string;
cc?: string[] | null;
/**
* CC email address(es), comma-separated
* BCC email addresses
*/
cc?: string | null;
/**
* BCC email address(es), comma-separated
*/
bcc?: string | null;
bcc?: string[] | null;
/**
* Sender email address (optional, uses default if not provided)
*/
@@ -362,7 +359,7 @@ export interface PayloadJob {
| {
executedAt: string;
completedAt: string;
taskSlug: 'inline' | 'process-email-queue';
taskSlug: 'inline' | 'processEmails' | 'send-email';
taskID: string;
input?:
| {
@@ -395,7 +392,7 @@ export interface PayloadJob {
id?: string | null;
}[]
| null;
taskSlug?: ('inline' | 'process-email-queue') | null;
taskSlug?: ('inline' | 'processEmails' | 'send-email') | null;
queue?: string | null;
waitUntil?: string | null;
processing?: boolean | null;
@@ -542,7 +539,6 @@ export interface EmailTemplatesSelect<T extends boolean = true> {
*/
export interface EmailsSelect<T extends boolean = true> {
template?: T;
templateSlug?: T;
to?: T;
cc?: T;
bcc?: T;
@@ -627,12 +623,69 @@ export interface PayloadMigrationsSelect<T extends boolean = true> {
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "ProcessEmailQueueJob".
* via the `definition` "ProcessEmailsJob".
*/
export interface ProcessEmailQueueJob {
export interface ProcessEmailsJob {
input?: unknown;
output?: unknown;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "TaskSend-email".
*/
export interface TaskSendEmail {
input: {
/**
* Use a template (leave empty for direct email)
*/
templateSlug?: string | null;
/**
* JSON object with variables for template rendering
*/
variables?:
| {
[k: string]: unknown;
}
| unknown[]
| string
| number
| boolean
| null;
/**
* Email subject (required if not using template)
*/
subject?: string | null;
/**
* HTML email content (required if not using template)
*/
html?: string | null;
/**
* Plain text email content (optional)
*/
text?: string | null;
/**
* Comma-separated list of email addresses
*/
to: string;
/**
* Optional comma-separated list of CC email addresses
*/
cc?: string | null;
/**
* Optional comma-separated list of BCC email addresses
*/
bcc?: string | null;
/**
* Optional date/time to schedule email for future delivery
*/
scheduledAt?: string | null;
/**
* Email priority (1 = highest, 10 = lowest)
*/
priority?: number | null;
};
output?: unknown;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "auth".

View File

@@ -1,12 +1,10 @@
import { mongooseAdapter } from '@payloadcms/db-mongodb'
import { lexicalEditor } from '@payloadcms/richtext-lexical'
import {
BlocksFeature,
FixedToolbarFeature,
HeadingFeature,
HorizontalRuleFeature,
InlineToolbarFeature,
lexicalHTML,
} from '@payloadcms/richtext-lexical'
import { MongoMemoryReplSet } from 'mongodb-memory-server'
import path from 'path'
@@ -17,7 +15,7 @@ import { fileURLToPath } from 'url'
import { testEmailAdapter } from './helpers/testEmailAdapter.js'
import { seed, seedUser } from './seed.js'
import mailingPlugin from "../src/plugin.js"
import { sendEmail } from "../src/utils/helpers.js"
import {sendEmail} from "@xtr-dev/payload-mailing"
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
@@ -85,15 +83,19 @@ const buildConfigWithMemoryDB = async () => {
// Queue the welcome email using template slug
const emailId = await sendEmail(req.payload, {
templateSlug: 'welcome-email',
to: doc.email,
variables: {
firstName: doc.firstName || doc.email?.split('@')?.[0],
siteName: 'PayloadCMS Mailing Demo',
createdAt: new Date().toISOString(),
isPremium: false,
dashboardUrl: 'http://localhost:3000/admin',
template: {
slug: 'welcome-email',
variables: {
firstName: doc.firstName || doc.email?.split('@')?.[0],
siteName: 'PayloadCMS Mailing Demo',
createdAt: new Date().toISOString(),
isPremium: false,
dashboardUrl: 'http://localhost:3000/admin',
},
},
data: {
to: doc.email,
}
})
console.log('✅ Welcome email queued successfully. Email ID:', emailId)

View File

@@ -19,13 +19,13 @@
"@payload-config": [
"./payload.config.ts"
],
"temp-project": [
"@xtr-dev/payload-mailing": [
"../src/index.ts"
],
"temp-project/client": [
"@xtr-dev/payload-mailing/client": [
"../src/exports/client.ts"
],
"temp-project/rsc": [
"@xtr-dev/payload-mailing/rsc": [
"../src/exports/rsc.ts"
]
},