From 2e6feccf549f7168be0470c156d4291054e9630a Mon Sep 17 00:00:00 2001 From: Bas van den Aakster Date: Sat, 13 Sep 2025 22:31:05 +0200 Subject: [PATCH] Remove `emailWrapper` hook and all associated references. - Simplified email sending logic by dropping custom layout wrapping. - Updated service, config, types, and readme to remove `emailWrapper` usage. - Retained focus on core email functionality while ensuring consistent formatting. --- README.md | 282 +-------------------------------- dev/payload.config.ts | 50 ------ dev/seed.ts | 2 +- src/services/MailingService.ts | 25 +-- src/types/index.ts | 18 +-- 5 files changed, 9 insertions(+), 368 deletions(-) diff --git a/README.md b/README.md index 2381749..3f01fe3 100644 --- a/README.md +++ b/README.md @@ -139,10 +139,6 @@ mailingPlugin({ retryDelay: 300000, // 5 minutes (default) // Advanced options - emailWrapper: (email) => ({ // optional layout wrapper - ...email, - html: `${email.html}` - }), richTextEditor: lexicalEditor(), // optional custom editor onReady: async (payload) => { // optional initialization hook console.log('Mailing plugin ready!') @@ -227,7 +223,7 @@ Thanks for joining {{siteName}}. We're excited to have you! **What you can do:** • Create beautiful emails with rich text formatting -• Use the emailWrapper hook to add custom layouts + • Queue and schedule emails effortlessly Your account was created on {{formatDate createdAt "long"}}. @@ -238,282 +234,6 @@ The {{siteName}} Team ## Advanced Features -### Custom HTML Layouts with Email Wrapper Hook - -The `emailWrapper` hook allows you to apply consistent HTML layouts and styling to all emails sent through the plugin. This is perfect for adding company branding, headers, footers, and responsive styling. - -#### Basic Email Wrapper - -```typescript -mailingPlugin({ - // ... other config - emailWrapper: (email) => { - const wrappedHtml = ` - - - - - - ${email.subject} - - - -
-
-

My Company

-
-
- ${email.html} -
- -
- - - ` - - return { - ...email, - html: wrappedHtml, - text: `MY COMPANY\n\n${email.text}\n\n© 2024 My Company\nUnsubscribe: [link] | Contact Support: [link]` - } - } -}) -``` - -#### Advanced Email Wrapper with Dynamic Content - -```typescript -mailingPlugin({ - // ... other config - emailWrapper: (email) => { - // You can access email properties and customize based on content - const isTransactional = email.subject?.includes('Receipt') || email.subject?.includes('Confirmation'); - const headerColor = isTransactional ? '#28a745' : '#007bff'; - const headerText = isTransactional ? 'Order Confirmation' : 'My Company'; - - const wrappedHtml = ` - - - - - - - ${email.subject} - - - - -
- - - -
- - - ` - - // Also enhance the plain text version - const wrappedText = ` -${headerText.toUpperCase()} -${'='.repeat(headerText.length)} - -${email.text || email.html?.replace(/<[^>]*>/g, '')} - ---- -© ${new Date().getFullYear()} My Company. All rights reserved. -Contact Support: support@mycompany.com -Privacy Policy: [link] -Unsubscribe: [link] - `.trim(); - - return { - ...email, - html: wrappedHtml, - text: wrappedText - } - } -}) -``` - -#### External CSS and Assets - -You can also reference external stylesheets and assets: - -```typescript -mailingPlugin({ - emailWrapper: (email) => { - const wrappedHtml = ` - - - - - - ${email.subject} - - - - - -
- My Company -
- ${email.html} -
- Footer -
- - - `; - - return { ...email, html: wrappedHtml }; - } -}) -``` - -#### Template-Specific Layouts - -You can customize layouts based on email templates: - -```typescript -mailingPlugin({ - emailWrapper: (email, context) => { - // Access template information if available - const templateSlug = context?.templateSlug; - - let layoutClass = 'default-layout'; - let headerColor = '#007bff'; - - if (templateSlug === 'welcome-email') { - layoutClass = 'welcome-layout'; - headerColor = '#28a745'; - } else if (templateSlug === 'invoice-email') { - layoutClass = 'invoice-layout'; - headerColor = '#dc3545'; - } - - const wrappedHtml = ` - - - - - ${email.subject} - - - -
- ${email.html} -
- - - `; - - return { ...email, html: wrappedHtml }; - } -}) -``` - -The `emailWrapper` hook receives the email object with `html`, `text`, and `subject` properties, and should return the modified email object with your custom layout applied. - ### Custom Rich Text Editor Override the rich text editor used for templates: diff --git a/dev/payload.config.ts b/dev/payload.config.ts index a01890d..aa61182 100644 --- a/dev/payload.config.ts +++ b/dev/payload.config.ts @@ -282,56 +282,6 @@ const buildConfigWithMemoryDB = async () => { ], }), - emailWrapper: (email) => { - // Example: wrap email content in a custom layout - const wrappedHtml = ` - - - - - - ${email.subject} - - - -
-
-

My Company

-
-
- ${email.html} -
- -
- - - ` - - const wrappedText = ` -MY COMPANY -========== - -${email.text || email.html?.replace(/<[^>]*>/g, '')} - ---- -This email was sent from My Company. -If you have questions, contact support@mycompany.com - ` - - return { - ...email, - html: wrappedHtml, - text: wrappedText.trim(), - } - }, // Called after mailing plugin is fully initialized onReady: async (payload) => { diff --git a/dev/seed.ts b/dev/seed.ts index d297517..dbe5f01 100644 --- a/dev/seed.ts +++ b/dev/seed.ts @@ -102,7 +102,7 @@ export const seed = async (payload: Payload) => { format: 0, mode: 'normal', style: '', - text: 'Use the emailWrapper hook to add custom layouts', + text: 'Create beautiful emails with rich text formatting', type: 'text', version: 1, }, diff --git a/src/services/MailingService.ts b/src/services/MailingService.ts index 1e517a4..a849f5f 100644 --- a/src/services/MailingService.ts +++ b/src/services/MailingService.ts @@ -8,7 +8,7 @@ import { EmailTemplate, QueuedEmail, MailingTransportConfig, - EmailObject + BaseEmail } from '../types/index.js' import { serializeRichTextToHTML, serializeRichTextToText } from '../utils/richTextSerializer.js' @@ -238,10 +238,10 @@ export class MailingService implements IMailingService { const email = await this.payload.findByID({ collection: this.emailsCollection as any, id: emailId, - }) as QueuedEmail + }) as BaseEmail - let emailObject: EmailObject = { - from: email.from || this.getDefaultFrom(), + const mailOptions = { + from: email.from, to: email.to, cc: email.cc || undefined, bcc: email.bcc || undefined, @@ -249,23 +249,6 @@ export class MailingService implements IMailingService { subject: email.subject, html: email.html, text: email.text || undefined, - variables: email.variables, - } - - // Apply emailWrapper hook if configured - if (this.config.emailWrapper) { - emailObject = await this.config.emailWrapper(emailObject) - } - - const mailOptions = { - from: emailObject.from, - to: emailObject.to, - cc: emailObject.cc || undefined, - bcc: emailObject.bcc || undefined, - replyTo: emailObject.replyTo || undefined, - subject: emailObject.subject, - html: emailObject.html, - text: emailObject.text || undefined, } await this.transporter.sendMail(mailOptions) diff --git a/src/types/index.ts b/src/types/index.ts index b29b150..c8a997c 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,20 +1,9 @@ import { Payload } from 'payload' -import type { CollectionConfig, RichTextField, TypedCollection } from 'payload' +import type { CollectionConfig, RichTextField } from 'payload' import { Transporter } from 'nodemailer' +import {Email} from "../payload-types.js" -export interface EmailObject { - to: string | string[] - cc?: string | string[] - bcc?: string | string[] - from?: string - replyTo?: string - subject: string - html: string - text?: string - variables?: Record -} - -export type EmailWrapperHook = (email: EmailObject) => EmailObject | Promise +export type BaseEmail = Omit & {template: Omit} export type TemplateRendererHook = (template: string, variables: Record) => string | Promise @@ -31,7 +20,6 @@ export interface MailingPluginConfig { queue?: string retryAttempts?: number retryDelay?: number - emailWrapper?: EmailWrapperHook templateRenderer?: TemplateRendererHook templateEngine?: TemplateEngine richTextEditor?: RichTextField['editor']