{"_id":"@bkosm/medusa-notification-ses","_rev":"10-bde583c0bd7aa847d874c0c586f9c3d0","name":"@bkosm/medusa-notification-ses","dist-tags":{"latest":"1.2.0"},"versions":{"1.0.0":{"name":"@bkosm/medusa-notification-ses","version":"1.0.0","keywords":["medusa-provider","medusa-provider-ses"],"author":{"name":"bkosm"},"license":"MIT","_id":"@bkosm/medusa-notification-ses@1.0.0","maintainers":[{"name":"bkosm","email":"bartoshmen@gmail.com"}],"homepage":"https://github.com/bkosm/medusa-notification-ses#readme","bugs":{"url":"https://github.com/bkosm/medusa-notification-ses/issues"},"dist":{"shasum":"a97888657a9f38316df6be8c7c4d139d3a2d90e5","tarball":"https://registry.npmjs.org/@bkosm/medusa-notification-ses/-/medusa-notification-ses-1.0.0.tgz","fileCount":23,"integrity":"sha512-ujPRy7IjKZlAOOSWzyta+HfXcldEU9GQzElsmw4K0pKZmC+vr8qbg3BCrg5hkStLjAXj03fEd+0S0o5BIxrzXw==","signatures":[{"sig":"MEYCIQC9ihLaFW1S3zY3lKHNnrpo3flcPAGcj/chckMQyb0cyAIhAKUrtnXC+rxtYwYBrYT2htyMpvP3fDKrabR6df5HBcYM","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":45432},"main":"dist/index.js","types":"./dist/index.d.ts","engines":{"node":">=22"},"gitHead":"4272d520c4bb960d2e075fe926e8156f7b8b8ad9","scripts":{"test":"jest --passWithNoTests src","build":"rimraf dist && tsc --build ./tsconfig.json","watch":"tsc --watch","semantic-release":"semantic-release","test:integration":"jest --detectOpenHandles --forceExit -- integration-tests/**/*.spec.ts"},"_npmUser":{"name":"bkosm","actor":{"name":"bkosm","type":"user","email":"bartoshmen@gmail.com"},"email":"bartoshmen@gmail.com"},"repository":{"url":"git+https://github.com/bkosm/medusa-notification-ses.git","type":"git","directory":"."},"_npmVersion":"10.9.2","description":"AWS SES notification provider for Medusa","directories":{},"_nodeVersion":"22.16.0","dependencies":{"ajv":"^8.17.1","handlebars":"^4.7.8","nodemailer":"^6.9.12","ajv-formats":"^3.0.1","@aws-sdk/client-ses":"^3.821.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.0.3","rimraf":"^6.0.1","@swc/core":"^1.11.29","@swc/jest":"^0.2.38","typescript":"^5.8.3","semantic-release":"^24.2.5","@types/nodemailer":"^6.4.17","aws-sdk-client-mock":"^4.1.0","@semantic-release/git":"^10.0.1","@semantic-release/npm":"^12.0.1","@semantic-release/changelog":"^6.0.3"},"peerDependencies":{"@medusajs/framework":"^2.8.3"},"_npmOperationalInternal":{"tmp":"tmp/medusa-notification-ses_1.0.0_1750861540248_0.49206748927584276","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@bkosm/medusa-notification-ses","version":"1.0.1","keywords":["medusa-provider","medusa-provider-ses"],"author":{"name":"bkosm"},"license":"MIT","_id":"@bkosm/medusa-notification-ses@1.0.1","maintainers":[{"name":"bkosm","email":"bartoshmen@gmail.com"}],"homepage":"https://github.com/bkosm/medusa-notification-ses#readme","bugs":{"url":"https://github.com/bkosm/medusa-notification-ses/issues"},"dist":{"shasum":"c1f52ab90da8b76b478126033af8fa441bfa5837","tarball":"https://registry.npmjs.org/@bkosm/medusa-notification-ses/-/medusa-notification-ses-1.0.1.tgz","fileCount":23,"integrity":"sha512-i9Fc40RJRwwDXah2q3zkAqFQFMDaxVrP3oYWm+9erDA33DGRKT1TaMZnqu5VJnMUBwsD+BnTHbWy7SWJivYDpg==","signatures":[{"sig":"MEYCIQDJYq/1Acg2JY4XjK0RC6LUVCWVM+LG1cEPwXg5VpTdwgIhAMWZTZCRtuTwuZ17QjKtJ0ipxd/6o9GorCNXIV8ATo1v","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":45470},"main":"dist/index.js","types":"./dist/index.d.ts","engines":{"node":">=22"},"gitHead":"f6be90020550a02ba14061a827e6977749c66643","scripts":{"test":"jest --passWithNoTests src","build":"rimraf dist && tsc --build ./tsconfig.json","watch":"tsc --watch","semantic-release":"semantic-release","test:integration":"jest --detectOpenHandles --forceExit -- integration-tests/**/*.spec.ts"},"_npmUser":{"name":"bkosm","email":"bartoshmen@gmail.com"},"repository":{"url":"git+https://github.com/bkosm/medusa-notification-ses.git","type":"git","directory":"."},"_npmVersion":"10.9.2","description":"AWS SES notification provider for Medusa","directories":{},"_nodeVersion":"22.17.0","dependencies":{"ajv":"^8.17.1","handlebars":"^4.7.8","nodemailer":"^6.9.12","ajv-formats":"^3.0.1","@aws-sdk/client-ses":"^3.821.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.0.3","rimraf":"^6.0.1","@swc/core":"^1.11.29","@swc/jest":"^0.2.38","typescript":"^5.8.3","semantic-release":"^24.2.5","@types/nodemailer":"^6.4.17","aws-sdk-client-mock":"^4.1.0","@semantic-release/git":"^10.0.1","@semantic-release/npm":"^12.0.1","@semantic-release/changelog":"^6.0.3"},"peerDependencies":{"@medusajs/framework":"^2.8.3"},"_npmOperationalInternal":{"tmp":"tmp/medusa-notification-ses_1.0.1_1752602788612_0.9017270935151855","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@bkosm/medusa-notification-ses","version":"1.1.0","keywords":["medusa-provider","medusa-provider-ses"],"author":{"name":"bkosm"},"license":"MIT","_id":"@bkosm/medusa-notification-ses@1.1.0","maintainers":[{"name":"bkosm","email":"bartoshmen@gmail.com"}],"homepage":"https://github.com/bkosm/medusa-notification-ses#readme","bugs":{"url":"https://github.com/bkosm/medusa-notification-ses/issues"},"dist":{"shasum":"4c7d5c3f72d3e778d3a441df1d5d41cb5e43ad6b","tarball":"https://registry.npmjs.org/@bkosm/medusa-notification-ses/-/medusa-notification-ses-1.1.0.tgz","fileCount":39,"integrity":"sha512-R1kbuP4hJOw8r/Bb+zQgkG6jiYp90eGlPzNKv/M02goqFFG5hxSxwtIO7Vbin7Uc/6euSQWdTfPSyH5BH20qIQ==","signatures":[{"sig":"MEUCIQDdILhknmGWCPbRiyABEKLbJsY7NIE7DCKt8oT/j3o8qwIgW5l7zJeoOhnC/wCP+5VoB/qCIlYNxMep+vSNIUzFY0M=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":58683},"main":"dist/index.js","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":"./dist/index.js","./template-providers":"./dist/template-providers/index.js"},"gitHead":"1c3bc0aacf2caf2105d05c3d5c0dbd56e170e33f","scripts":{"test":"jest src","build":"rimraf dist && tsc --build ./tsconfig.json","watch":"tsc --watch","semantic-release":"semantic-release","test:integration":"jest --detectOpenHandles --forceExit -- integration-tests/**/*.spec.ts"},"_npmUser":{"name":"bkosm","email":"bartoshmen@gmail.com"},"repository":{"url":"git+https://github.com/bkosm/medusa-notification-ses.git","type":"git","directory":"."},"_npmVersion":"10.9.2","description":"AWS SES notification provider for Medusa","directories":{},"_nodeVersion":"22.17.0","dependencies":{"ajv":"^8.17.1","handlebars":"^4.7.8","nodemailer":"^6.9.12","ajv-formats":"^3.0.1","@aws-sdk/client-s3":"^3.844.0","@aws-sdk/client-ses":"^3.821.0","aws-sdk-client-mock-jest":"^4.1.0"},"publishConfig":{"access":"public"},"typesVersions":{"*":{"template-providers":["./dist/template-providers/index.d.ts"]}},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.0.3","rimraf":"^6.0.1","@swc/core":"^1.11.29","@swc/jest":"^0.2.38","typescript":"^5.8.3","semantic-release":"^24.2.5","@types/nodemailer":"^6.4.17","aws-sdk-client-mock":"^4.1.0","@semantic-release/git":"^10.0.1","@semantic-release/npm":"^12.0.1","@semantic-release/changelog":"^6.0.3"},"peerDependencies":{"@medusajs/framework":"^2.8.3"},"_npmOperationalInternal":{"tmp":"tmp/medusa-notification-ses_1.1.0_1752687028126_0.3874957633230567","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@bkosm/medusa-notification-ses","version":"1.2.0","description":"AWS SES notification provider for Medusa","main":"dist/index.js","repository":{"type":"git","url":"git+https://github.com/bkosm/medusa-notification-ses.git","directory":"."},"publishConfig":{"access":"public"},"exports":{".":"./dist/index.js","./template-providers":"./dist/template-providers/index.js"},"typesVersions":{"*":{"template-providers":["./dist/template-providers/index.d.ts"]}},"engines":{"node":">=22"},"author":{"name":"bkosm"},"license":"MIT","scripts":{"test":"jest src","test:integration":"jest --detectOpenHandles --forceExit -- integration-tests/**/*.spec.ts","build":"rimraf dist && tsc --build ./tsconfig.json","watch":"tsc --watch","semantic-release":"semantic-release"},"devDependencies":{"@semantic-release/changelog":"^6.0.3","@semantic-release/git":"^10.0.1","@semantic-release/npm":"^12.0.1","@swc/core":"^1.11.29","@swc/jest":"^0.2.38","@types/nodemailer":"^6.4.17","aws-sdk-client-mock":"^4.1.0","jest":"^30.0.3","rimraf":"^6.0.1","semantic-release":"^24.2.5","typescript":"^5.8.3"},"peerDependencies":{"@medusajs/framework":"^2.8.3"},"keywords":["medusa-provider","medusa-provider-ses"],"dependencies":{"@aws-sdk/client-s3":"^3.844.0","@aws-sdk/client-ses":"^3.821.0","ajv":"^8.17.1","ajv-formats":"^3.0.1","aws-sdk-client-mock-jest":"^4.1.0","handlebars":"^4.7.8","nodemailer":"^6.9.12"},"_id":"@bkosm/medusa-notification-ses@1.2.0","gitHead":"6b248825c0e33c9464138db9af49aa0526c711c8","types":"./dist/index.d.ts","bugs":{"url":"https://github.com/bkosm/medusa-notification-ses/issues"},"homepage":"https://github.com/bkosm/medusa-notification-ses#readme","_nodeVersion":"22.18.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-qnZIU/eXBv6C369BoDUGckVQr25ond8DqnL5AAsseQDxM8J2X2foikhtqC2Y6LnfE5R+4y1ezZxAcsLrSMrTkQ==","shasum":"6702d6615b4035abf4f3191671c31bdce6000974","tarball":"https://registry.npmjs.org/@bkosm/medusa-notification-ses/-/medusa-notification-ses-1.2.0.tgz","fileCount":39,"unpackedSize":58683,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCzF6yfJ+aC/IGUPAMDJIRsIuZqhHA+VDTrugvaxFKXGgIhAI2URqgoy3VaPOUcZeY24EJm+laypk2z7KydZOj2mJ/k"}]},"_npmUser":{"name":"bkosm","email":"bartoshmen@gmail.com"},"directories":{},"maintainers":[{"name":"bkosm","email":"bartoshmen@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/medusa-notification-ses_1.2.0_1755020300942_0.9319872760692753"},"_hasShrinkwrap":false}},"time":{"created":"2025-06-25T14:25:40.069Z","modified":"2025-08-12T17:38:21.290Z","0.2.0":"2025-06-19T19:11:35.032Z","0.2.1":"2025-06-23T14:33:26.995Z","0.2.2":"2025-06-23T15:00:02.322Z","0.2.3":"2025-06-23T15:33:14.071Z","0.2.4":"2025-06-23T17:38:42.194Z","1.0.0":"2025-06-25T14:25:40.442Z","1.0.1":"2025-07-15T18:06:28.796Z","1.1.0":"2025-07-16T17:30:28.300Z","1.2.0":"2025-08-12T17:38:21.123Z"},"bugs":{"url":"https://github.com/bkosm/medusa-notification-ses/issues"},"author":{"name":"bkosm"},"license":"MIT","homepage":"https://github.com/bkosm/medusa-notification-ses#readme","keywords":["medusa-provider","medusa-provider-ses"],"repository":{"type":"git","url":"git+https://github.com/bkosm/medusa-notification-ses.git","directory":"."},"description":"AWS SES notification provider for Medusa","maintainers":[{"name":"bkosm","email":"bartoshmen@gmail.com"}],"readme":"# Medusa Provider - Notification SES\n\nSend emails from your Medusa application through AWS Simple Email Service.\nSupports SES sandbox, attachments and handlebars templates.\n\n## Installation\n\n```bash\nnpm install @bkosm/medusa-notification-ses\n```\n\n## Configuration\n\nRegister the provider in your Medusa project:\n\n```typescript\nimport { LocalTemplateProvider } from '@bkosm/medusa-notification-ses/template-providers'\n\nexport default defineConfig({\n  modules: [\n    {\n      resolve: \"@medusajs/medusa/notification\",\n      options: {\n        providers: [\n          {\n            resolve: \"@bkosm/medusa-notification-ses\",\n            id: \"notification-ses\",\n            options: {\n              channels: [\"email\"],\n              // Nodemailer send options, passed on each sent message\n              nodemailerConfig: {\n                from: \"noreply@yourdomain.com\",\n              },\n              // Use a template provider for email templates (see below)\n              templateProvider: new LocalTemplateProvider(\"./email-templates\"),\n              // Enables SES sandbox mode with automatic email address verification\n              sandboxConfig: {},\n            },\n          },\n        ],\n      },\n    },\n  ],\n});\n```\n\nSee the [example Medusa app](./examples/app/medusa-config.ts) how it looks in practice.\n\n## SES Sandbox Mode\n\nWhen using AWS SES in sandbox mode (common in development/staging environments), emails can only be sent to verified email addresses. This provider includes automatic email verification support that integrates seamlessly with Medusa's workflow retry mechanisms.\n\n### Configuration\n\nEnable sandbox mode by defining the `sandboxConfig` option.\n\n### How Sandbox Mode Works\n\n1. **Address Verification Check**: Before sending emails, all recipient addresses (to, cc, bcc) are checked against SES verification status\n2. **Automatic Verification**: Unverified addresses automatically trigger verification emails via `VerifyEmailIdentity` API\n3. **Retryable Errors**: Throws `MedusaError.Types.INVALID_DATA` for pending verifications, signaling Medusa workflows to retry\n\nTo re-request verification on every send, define `sandboxConfig.verifyOnEachSend: false` in the configuration.\n\n## Template Providers\n\nThe provider has built-in support for handlebars templates through a pluggable provider system. Two providers are included: `LocalTemplateProvider` and `S3TemplateProvider`.\n\nThe template system uses a directory-based structure where each template ID maps to a folder containing:\n\n1.  **`handlebars.template.html`** - Pre-compiled MJML template with Handlebars placeholders\n2.  **`data.schema.json`** - JSON schema for validating template data\n\n### `LocalTemplateProvider`\n\nThis provider loads templates from the local filesystem.\n\n#### Configuration\n\n```typescript\nimport { LocalTemplateProvider } from '@bkosm/medusa-notification-ses/template-providers'\n\n// ...\n  // Path to your templates directory\n  templateProvider: new LocalTemplateProvider(\"./email-templates\"),\n// ...\n```\n\n#### Example template setup\n\nWith the configuration above, your directory structure should look like this:\n\n##### `email-templates/welcome-email/handlebars.template.html`\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>Welcome to {{companyName}}</title>\n  </head>\n  <body>\n    <h1>Welcome {{firstName}}!</h1>\n    <p>\n      Thank you for joining {{companyName}}. We're excited to have you on board.\n    </p>\n    <p>Your email address is: {{email}}</p>\n    {{#if hasPromo}}\n    <p>\n      Use promo code <strong>{{promoCode}}</strong> for 20% off your first\n      order!\n    </p>\n    {{/if}}\n    <p>Best regards,<br />The {{companyName}} Team</p>\n  </body>\n</html>\n```\n\n##### `email-templates/welcome-email/data.schema.json`\n\n```json\n{\n  \"type\": \"object\",\n  \"properties\": {\n    \"firstName\": {\n      \"type\": \"string\",\n      \"minLength\": 1\n    },\n    \"email\": {\n      \"type\": \"string\",\n      \"format\": \"email\"\n    },\n    \"companyName\": {\n      \"type\": \"string\",\n      \"minLength\": 1\n    },\n    \"hasPromo\": {\n      \"type\": \"boolean\"\n    },\n    \"promoCode\": {\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\"firstName\", \"email\", \"companyName\"],\n  \"additionalProperties\": false,\n  \"if\": {\n    \"properties\": {\n      \"hasPromo\": { \"const\": true }\n    }\n  },\n  \"then\": {\n    \"required\": [\"promoCode\"]\n  }\n}\n```\n\n### `S3TemplateProvider`\n\nThis provider loads templates from an S3 bucket. This is useful for production environments where you might want to manage templates centrally without deploying new code.\n\n#### Configuration\n\n```typescript\nimport { S3TemplateProvider } from '@bkosm/medusa-notification-ses/template-providers'\n\n// ...\n  templateProvider: new S3TemplateProvider({\n    clientConfig: { region: 'us-east-1' }, // AWS S3 client config\n    bucket: 'your-s3-bucket-name',\n    prefix: 'email-templates/', // Optional prefix for your templates in the bucket\n  }),\n// ...\n```\n\nThe S3 bucket should have the same directory structure as the local provider. For example: `s3://your-s3-bucket-name/email-templates/welcome-email/handlebars.template.html`.\n\n### Template Processing Flow\n\n1.  **Startup**: Templates are loaded from the configured provider and validated when the service initializes.\n2.  **Runtime**: When sending emails with templates:\n    -   Template ID is validated against available templates.\n    -   Data is validated against the template's JSON schema.\n    -   Handlebars template is rendered with provided data.\n    -   Rendered HTML replaces the notification's HTML content.\n3.  **Caching**: Templates are cached in memory for optimal performance.\n\n## Usage\n\n### Basic Email Sending\n\nUse Medusa's notification module to send emails with raw HTML:\n\n```typescript\nimport { MedusaRequest, MedusaResponse } from \"@medusajs/framework/http\";\nimport { INotificationModuleService } from \"@medusajs/framework/types\";\nimport { Modules } from \"@medusajs/framework/utils\";\n\nexport async function POST(req: MedusaRequest, res: MedusaResponse) {\n  const notificationService: INotificationModuleService = req.scope.resolve(\n    Modules.NOTIFICATION\n  );\n\n  await notificationService.createNotifications({\n    to: \"customer@example.com\",\n    channel: \"email\",\n    content: {\n      subject: \"Order Confirmed\",\n      text: \"Your order has been confirmed\",\n      html: \"<p>Your order has been confirmed</p>\",\n    },\n    attachments: [\n      {\n        filename: \"receipt.pdf\",\n        content: pdfBufferBase64String,\n        content_type: \"application/pdf\",\n      },\n    ],\n  });\n\n  res.json({ success: true });\n}\n```\n\n### Template-Based Email Sending\n\nSend emails using pre-defined templates with dynamic data:\n\n```typescript\nawait notificationService.createNotifications({\n  to: \"customer@example.com\",\n  channel: \"email\",\n  template: \"order-confirmation\",\n  data: {\n    customerName: \"John Doe\",\n    orderNumber: \"ORD-123\",\n    items: [\n      { name: \"Product A\", quantity: 2, price: 29.99 },\n      { name: \"Product B\", quantity: 1, price: 15.5 },\n    ],\n    total: 75.48,\n    deliveryDate: \"2024-01-15\",\n  },\n  content: {\n    subject: \"Order Confirmation #ORD-123\",\n  },\n});\n```\n\n## Configuration Options\n\n### `sesClientConfig`\n\nAWS SES client configuration (optional). \n\nSee the full set of options here: https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-ses/Interface/SESClientConfig\n\n### `nodemailerConfig`\n\nNodemailer send options (`from` is required).\n\nSee the full set of options here: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/nodemailer/v3/index.d.ts#L104-L177\nOnly `subject`, `text` and `html` are substituted for runtime values at all times. Fields like `to`, `attachments` are concatenated with runtime values.\n\n### `templateProvider`\n\nAn instance of a template provider (optional). If not provided, the templating feature is disabled. This provider is responsible for loading and caching templates.\n\n- `LocalTemplateProvider`: Loads templates from the local filesystem.\n  - `directory`: path to a local directory with expected templates structure\n- `S3TemplateProvider`: Loads templates from an S3 bucket.\n  - `clientConfig`: AWS S3 client configuration.\n  - `bucket`: The S3 bucket name.\n  - `prefix`: An optional key prefix for the templates within the bucket.\n\n### `sandboxConfig`\n\nSES sandbox mode configuration (optional):\n\n- `verifyOnEachSend` (boolean, default: false) - When true, bypasses verification cache and checks SES on every send\n\nDisables sandbox feature if the object is not set (will fail on unverified addresses at runtime if the account uses SES sandbox).","readmeFilename":"README.md"}