{"id":27621789,"url":"https://github.com/productdevbook/unemail","last_synced_at":"2025-12-30T09:27:11.222Z","repository":{"id":286253101,"uuid":"960861988","full_name":"productdevbook/unemail","owner":"productdevbook","description":"📫 Lightweight, zero-dependency TypeScript email library with pluggable providers and MailCrab support for local development.","archived":false,"fork":false,"pushed_at":"2025-04-17T18:51:00.000Z","size":245,"stargazers_count":74,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-18T08:09:12.548Z","etag":null,"topics":["email","unpkg","unplugin"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/productdevbook.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["productdevbook"]}},"created_at":"2025-04-05T08:12:35.000Z","updated_at":"2025-04-18T07:10:01.000Z","dependencies_parsed_at":"2025-04-05T09:35:02.618Z","dependency_job_id":null,"html_url":"https://github.com/productdevbook/unemail","commit_stats":null,"previous_names":["productdevbook/unemail"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/productdevbook%2Funemail","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/productdevbook%2Funemail/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/productdevbook%2Funemail/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/productdevbook%2Funemail/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/productdevbook","download_url":"https://codeload.github.com/productdevbook/unemail/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250395281,"owners_count":21423400,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["email","unpkg","unplugin"],"created_at":"2025-04-23T08:04:05.629Z","updated_at":"2025-12-30T09:27:11.217Z","avatar_url":"https://github.com/productdevbook.png","language":"TypeScript","readme":"# unemail\n\n[![npm version][npm-version-src]][npm-version-href]\n[![npm downloads][npm-downloads-src]][npm-downloads-href]\n[![bundle][bundle-src]][bundle-href]\n[![JSDocs][jsdocs-src]][jsdocs-href]\n[![License][license-src]][license-href]\n\nA modern, TypeScript-first email sending library with support for multiple providers and ESM-only architecture.\n\n## Supported Email Services\n\n- **SMTP** - Any standard SMTP server including Gmail, Outlook, Office 365, etc.\n- **AWS SES** - Amazon Simple Email Service\n- **Resend** - Modern email API for developers\n- **HTTP API** - Custom HTTP API endpoints for email delivery\n- **MailCrab** - Local development email testing (via SMTP provider)\n\n\u003e 📢 **Want to add a provider?** We welcome pull requests for new providers! See the [Creating Custom Email Providers](#creating-custom-email-providers) section for guidance.\n\n## Features\n\n- 📦 **Multiple Providers** - Support for various email services including AWS SES, MailCrab, HTTP APIs, and more\n- 🔌 **Provider Pattern** - Easily extend with custom providers\n- 🔄 **Type-safe** - Full TypeScript support with generics and strict typing\n- 📤 **ESM Only** - Modern ES modules architecture\n- 🧪 **Well-tested** - Comprehensive test suite for all components\n- 📄 **Zero External Dependencies** - Core functionality has no runtime dependencies\n- 🔒 **Error Handling** - Consistent error handling across all providers\n\n## Installation\n\n```bash\n# Using pnpm\npnpm add unemail\n\n# Using npm\nnpm install unemail\n\n# Using yarn\nyarn add unemail\n```\n\n## Quick Start\n\n```typescript\nimport { createEmailService } from 'unemail'\nimport httpProvider from 'unemail/providers/http'\n\n// Create a service with your preferred provider\nconst emailService = createEmailService({\n  provider: httpProvider({\n    endpoint: 'https://api.example.com/email',\n    apiKey: 'your-api-key'\n  })\n})\n\n// Send an email\nconst result = await emailService.sendEmail({\n  from: { email: 'sender@example.com', name: 'Sender Name' },\n  to: { email: 'recipient@example.com', name: 'Recipient Name' },\n  subject: 'Hello from unemail',\n  text: 'This is a test email sent using unemail library',\n  html: '\u003cp\u003eThis is a test email sent using \u003cstrong\u003eunemail\u003c/strong\u003e library\u003c/p\u003e'\n})\n\nif (result.success) {\n  console.log('Email sent successfully!', result.data.messageId)\n}\nelse {\n  console.error('Failed to send email:', result.error)\n}\n```\n\n## Available Providers\n\n### AWS SES Provider\n\n```typescript\nimport { createEmailService } from 'unemail'\nimport awsSesProvider from 'unemail/providers/aws-ses'\n\nconst emailService = createEmailService({\n  provider: awsSesProvider({\n    accessKeyId: 'AWS_ACCESS_KEY',\n    secretAccessKey: 'AWS_SECRET_KEY',\n    region: 'us-east-1'\n  })\n})\n```\n\n### HTTP Provider\n\n```typescript\nimport { createEmailService } from 'unemail'\nimport httpProvider from 'unemail/providers/http'\n\nconst emailService = createEmailService({\n  provider: httpProvider({\n    endpoint: 'https://api.yourservice.com/send',\n    apiKey: 'your-api-key',\n    method: 'POST', // optional, defaults to POST\n    headers: { // optional, additional headers\n      'X-Custom-Header': 'custom-value'\n    }\n  })\n})\n```\n\n### MailCrab Provider (for development)\n\n```typescript\nimport { createEmailService } from 'unemail'\nimport smtpProvider from 'unemail/providers/smtp'\n\nconst emailService = createEmailService({\n  provider: smtpProvider({\n    host: 'localhost',\n    port: 1025, // default MailCrab port\n    secure: false // typically false for development\n  })\n})\n```\n\n### SMTP Provider\n\n```typescript\nimport { createEmailService } from 'unemail'\nimport smtpProvider from 'unemail/providers/smtp'\n\n// Basic configuration\nconst emailService = createEmailService({\n  provider: smtpProvider({\n    host: 'smtp.example.com',\n    port: 587,\n    secure: false, // use TLS\n    user: 'username',\n    password: 'password'\n  })\n})\n\n// Advanced configuration with enhanced security and features\nconst advancedEmailService = createEmailService({\n  provider: smtpProvider({\n    host: 'smtp.example.com',\n    port: 587,\n    secure: false,\n    user: 'username',\n    password: 'password',\n\n    // TLS options\n    rejectUnauthorized: true, // Verify SSL certificates (set to false to ignore certificate errors)\n\n    // Connection pooling for sending multiple emails efficiently\n    pool: true,\n    maxConnections: 5,\n\n    // Enhanced authentication\n    authMethod: 'CRAM-MD5', // 'LOGIN', 'PLAIN', 'CRAM-MD5', or 'OAUTH2'\n\n    // OAuth2 authentication (if using OAUTH2 authMethod)\n    oauth2: {\n      user: 'user@example.com',\n      clientId: 'client-id',\n      clientSecret: 'client-secret',\n      refreshToken: 'refresh-token',\n      accessToken: 'access-token',\n      expires: 1714939200000\n    },\n\n    // DKIM signing to improve deliverability\n    dkim: {\n      domainName: 'example.com',\n      keySelector: 'mail',\n      privateKey: '-----BEGIN PRIVATE KEY-----\\n...\\n-----END PRIVATE KEY-----'\n    }\n  })\n})\n\n// Basic email sending\nawait emailService.sendEmail({\n  from: { email: 'sender@example.com', name: 'Sender' },\n  to: { email: 'recipient@example.com' },\n  subject: 'Test email',\n  text: 'Plain text content',\n  html: '\u003cp\u003eHTML content\u003c/p\u003e'\n})\n\n// Advanced email sending with SMTP-specific options\nawait advancedEmailService.sendEmail({\n  from: { email: 'sender@example.com', name: 'Sender' },\n  to: { email: 'recipient@example.com' },\n  subject: 'Test email',\n  text: 'Plain text content',\n  html: '\u003cp\u003eHTML content\u003c/p\u003e',\n\n  // Basic SMTP-specific options\n  priority: 'high', // 'high', 'normal', or 'low'\n  dsn: {\n    success: true, // Request successful delivery notification\n    failure: true, // Request failure notification\n    delay: true // Request delay notification\n  },\n\n  // Threading and references\n  inReplyTo: '\u003cprevious-message-id@example.com\u003e',\n  references: ['\u003cref1@example.com\u003e', '\u003cref2@example.com\u003e'],\n\n  // Email management\n  listUnsubscribe: 'mailto:unsubscribe@example.com',\n\n  // Gmail-specific features\n  googleMailHeaders: {\n    promotionalContent: true, // Mark as promotional content\n    feedbackId: 'campaign:12345:user:123', // For engagement tracking\n    category: 'promotions' // 'primary', 'social', 'promotions', 'updates', or 'forums'\n  },\n\n  // Control DKIM signing per email\n  useDkim: true\n})\n```\n\n### Resend Provider\n\n```typescript\nimport { createEmailService } from 'unemail'\nimport resendProvider from 'unemail/providers/resend'\n\nconst emailService = createEmailService({\n  provider: resendProvider({\n    apiKey: 'your-resend-api-key'\n  })\n})\n```\n\n## Email Options\n\nSend emails with a variety of options:\n\n```typescript\nimport { Buffer } from 'node:buffer'\nimport fs from 'node:fs'\n\nconst result = await emailService.sendEmail({\n  // Required fields\n  from: { email: 'sender@example.com', name: 'Sender Name' },\n  to: [\n    { email: 'recipient1@example.com', name: 'Recipient One' },\n    { email: 'recipient2@example.com', name: 'Recipient Two' }\n  ],\n  subject: 'Test Email with Attachments',\n\n  // Content - at least one of text or html is required\n  text: 'Plain text version of the email',\n  html: '\u003cp\u003eHTML version of the email\u003c/p\u003e',\n\n  // Optional fields\n  cc: { email: 'cc@example.com', name: 'CC Recipient' },\n  bcc: { email: 'bcc@example.com', name: 'BCC Recipient' },\n\n  // Custom headers\n  headers: {\n    'X-Custom-Header': 'custom-value'\n  },\n\n  // Attachments\n  attachments: [\n    {\n      filename: 'document.pdf',\n      content: Buffer.from('...'), // Can be Buffer or Base64 string\n      contentType: 'application/pdf'\n    },\n    {\n      filename: 'image.png',\n      content: fs.readFileSync('path/to/image.png'),\n      contentType: 'image/png'\n    }\n  ],\n\n  // Reply-to address\n  replyTo: { email: 'reply@example.com', name: 'Reply Handler' }\n})\n```\n\n## Creating Custom Email Providers\n\nYou can easily create custom providers for any email service:\n\n```typescript\nimport type { EmailOptions, EmailResult, Result } from 'unemail/types'\nimport { createEmailService, defineProvider } from 'unemail'\n\n// Define your provider\nconst myCustomProvider = defineProvider((options = {}) =\u003e {\n  // Provider initialization\n  const apiKey = options.apiKey\n  const apiUrl = options.apiUrl || 'https://api.default-service.com'\n\n  // Method implementations\n  return {\n    name: 'my-custom-provider',\n\n    features: {\n      attachments: true,\n      html: true,\n      templates: false,\n      tracking: false\n    },\n\n    options,\n\n    async initialize() {\n      // Initialize your provider if needed\n      // e.g. validate credentials, set up connections, etc.\n    },\n\n    async isAvailable() {\n      // Check if the provider is available\n      // e.g. test connection, validate credentials, etc.\n      return true\n    },\n\n    async sendEmail(options: EmailOptions): Promise\u003cResult\u003cEmailResult\u003e\u003e {\n      try {\n        // Implementation of email sending logic\n\n        // On success\n        return {\n          success: true,\n          data: {\n            messageId: 'generated-or-returned-message-id',\n            sent: true,\n            timestamp: new Date(),\n            provider: 'my-custom-provider'\n          }\n        }\n      }\n      catch (error) {\n        // On error\n        return {\n          success: false,\n          error: error as Error\n        }\n      }\n    }\n  }\n})\n\nconst emailService = createEmailService({\n  provider: myCustomProvider({\n    apiKey: 'your-api-key',\n    apiUrl: 'https://api.your-service.com'\n  })\n})\n```\n\n## Error Handling\n\nAll provider methods return a standardized `Result` type:\n\n```typescript\ninterface Result\u003cT = any\u003e {\n  success: boolean\n  data?: T\n  error?: Error\n}\n```\n\nThis allows for consistent error handling:\n\n```typescript\nconst result = await emailService.sendEmail({\n  // email options...\n})\n\nif (result.success) {\n  // Handle success\n  console.log(`Email sent with ID: ${result.data.messageId}`)\n}\nelse {\n  // Handle error\n  console.error(`Failed to send email: ${result.error.message}`)\n}\n```\n\n## Development Setup\n\n### Prerequisites\n\n- Node.js 20.11.1 or higher\n- pnpm\n\n### Local Development\n\n```bash\n# Clone the repository\ngit clone https://github.com/your-username/unemail.git\ncd unemail\n\n# Install dependencies\npnpm install\n\n# Build the package\npnpm build\n\n# Run tests\npnpm test\n```\n\n### Testing with MailCrab\n\nFor local development, you can use MailCrab, a local SMTP server:\n\n```bash\n# Run the MailCrab setup script\npnpm mailcrab\n\n# Test with the example script\npnpm example\n```\n\n#### unemail-mailcrab CLI\n\nThe package includes a CLI tool called `unemail-mailcrab` that helps you set up and manage a MailCrab container for local email testing:\n\n```bash\n# Install globally to use the CLI from anywhere\nnpm install -g unemail\n\n# Run the CLI\nunemail-mailcrab\n```\n\nThe CLI tool:\n\n- Checks if Docker is installed\n- Verifies if ports 1025 (SMTP) and 1080 (Web UI) are available\n- Pulls the MailCrab Docker image if not already available\n- Manages existing MailCrab containers (start/stop/create new)\n- Sets up a Docker container running MailCrab\n- Provides detailed instructions for using MailCrab with unemail\n\nAfter running the CLI, you can:\n- Send emails to localhost:1025 using the MailCrab provider\n- View all sent emails in the MailCrab web UI at http://localhost:1080\n- Stop/start the container with `docker stop unemail-mailcrab` and `docker start unemail-mailcrab`\n\n## Credits\n\nThis project's architecture and provider pattern was inspired by [unjs/unstorage](https://github.com/unjs/unstorage), which uses a similar approach for storage drivers.\n\n## License\n\nPublished under the [MIT](https://github.com/productdevbook/unemail/blob/main/LICENSE) license.\nMade by [@productdevbook](https://github.com/productdevbook) and [community](https://github.com/productdevbook/unemail/graphs/contributors) 💛\n\n\u003c!-- Badges --\u003e\n\n[npm-version-src]: https://img.shields.io/npm/v/unemail?style=flat\u0026colorA=080f12\u0026colorB=1fa669\n[npm-version-href]: https://npmjs.com/package/unemail\n[npm-downloads-src]: https://img.shields.io/npm/dm/unemail?style=flat\u0026colorA=080f12\u0026colorB=1fa669\n[npm-downloads-href]: https://npmjs.com/package/unemail\n[bundle-src]: https://deno.bundlejs.com/badge?q=unemail@0.0.4\n[bundle-href]: https://deno.bundlejs.com/badge?q=unemail@0.0.4\n[license-src]: https://img.shields.io/github/license/productdevbook/unemail.svg?style=flat\u0026colorA=080f12\u0026colorB=1fa669\n[license-href]: https://github.com/productdevbook/unemail/blob/main/LICENSE\n[jsdocs-src]: https://img.shields.io/badge/jsdocs-reference-080f12?style=flat\u0026colorA=080f12\u0026colorB=1fa669\n[jsdocs-href]: https://www.jsdocs.io/package/unemail\n","funding_links":["https://github.com/sponsors/productdevbook"],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fproductdevbook%2Funemail","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fproductdevbook%2Funemail","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fproductdevbook%2Funemail/lists"}