{"id":51169595,"url":"https://github.com/nurulislamrimon/sendora","last_synced_at":"2026-06-26T23:03:42.611Z","repository":{"id":358536038,"uuid":"1181484076","full_name":"nurulislamrimon/sendora","owner":"nurulislamrimon","description":"A developer-first email service library for Node.js with SMTP support, Handlebars templates, and queue management","archived":false,"fork":false,"pushed_at":"2026-03-14T07:42:30.000Z","size":43,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-17T22:07:26.179Z","etag":null,"topics":["mail","mail-integration","mail-package","mailchimp","mailer","mailgun","mailtrap","node-mail","nodemailer","npm","npm-package","npmjs"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nurulislamrimon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-14T07:41:10.000Z","updated_at":"2026-03-14T07:44:44.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/nurulislamrimon/sendora","commit_stats":null,"previous_names":["nurulislamrimon/sendora"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/nurulislamrimon/sendora","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nurulislamrimon%2Fsendora","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nurulislamrimon%2Fsendora/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nurulislamrimon%2Fsendora/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nurulislamrimon%2Fsendora/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nurulislamrimon","download_url":"https://codeload.github.com/nurulislamrimon/sendora/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nurulislamrimon%2Fsendora/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34835782,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-26T02:00:06.560Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["mail","mail-integration","mail-package","mailchimp","mailer","mailgun","mailtrap","node-mail","nodemailer","npm","npm-package","npmjs"],"created_at":"2026-06-26T23:03:42.130Z","updated_at":"2026-06-26T23:03:42.586Z","avatar_url":"https://github.com/nurulislamrimon.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# sendora\n\n[![npm version](https://img.shields.io/npm/v/sendora)](https://www.npmjs.com/package/sendora)\n[![license](https://img.shields.io/npm/l/sendora)](LICENSE)\n[![author](https://img.shields.io/badge/author-Nurul%20Islam%20Rimon-blue)](https://github.com/nurulislamrimon)\n[![repo](https://img.shields.io/badge/repo-github.com%2Fnurulislamrimon%2Fsendora-lightgrey)](https://github.com/nurulislamrimon/sendora)\n\nA developer-first email service library for Node.js that simplifies sending emails with templates, multiple providers, and excellent developer experience.\n\n## Features\n\n- **Simple API** - Intuitive interface for sending emails\n- **Multiple Providers** - SMTP support with Nodemailer (SendGrid, Resend, Mailgun coming soon)\n- **Template Engine** - Handlebars-based templates with layouts and partials\n- **Type-safe** - Full TypeScript support with strong typing\n- **Queue Support** - Built-in queue for background email processing\n- **Developer-friendly Logging** - Powered by pino\n- **Configuration Validation** - Zod-powered validation\n\n## Installation\n\n```bash\nnpm install sendora\n```\n\n## Quick Start\n\n```typescript\nimport { Sendora } from 'sendora';\n\nconst mail = new Sendora({\n  provider: 'smtp',\n  smtp: {\n    host: 'smtp.gmail.com',\n    port: 587,\n    secure: false,\n    auth: {\n      user: process.env.MAIL_USER,\n      pass: process.env.MAIL_PASS,\n    },\n  },\n});\n\nawait mail.initialize();\n\nawait mail.send({\n  to: 'user@example.com',\n  subject: 'Welcome',\n  html: '\u003ch1\u003eHello World!\u003c/h1\u003e',\n});\n```\n\n## Configuration\n\n### SMTP Configuration\n\n```typescript\nconst mail = new Sendora({\n  provider: 'smtp',\n  smtp: {\n    host: 'smtp.gmail.com',\n    port: 587,\n    secure: false,\n    auth: {\n      user: 'your-email@gmail.com',\n      pass: 'your-app-password',\n    },\n  },\n  from: 'Your App \u003cnoreply@yourapp.com\u003e',\n});\n```\n\n### Full Configuration Options\n\n```typescript\nconst mail = new Sendora({\n  provider: 'smtp',\n  smtp: {\n    host: 'smtp.gmail.com',\n    port: 587,\n    secure: false,\n    auth: {\n      user: process.env.MAIL_USER,\n      pass: process.env.MAIL_PASS,\n    },\n  },\n  from: 'Sender \u003csender@example.com\u003e',\n  templates: {\n    dir: './templates',\n    ext: '.hbs',\n    layouts: {\n      dir: './templates/layouts',\n      default: 'main',\n    },\n    partials: {\n      dir: './templates/partials',\n    },\n    defaultData: {\n      company: 'My Company',\n      year: new Date().getFullYear(),\n    },\n  },\n  queue: {\n    enabled: true,\n    concurrency: 5,\n    delay: 1000,\n  },\n  logger: {\n    enabled: true,\n    level: 'debug',\n    prettyPrint: true,\n  },\n  defaultHeaders: {\n    'X-Mailer': 'Sendora',\n  },\n});\n```\n\n## Email Options\n\n```typescript\nawait mail.send({\n  from: 'Sender \u003csender@example.com\u003e',\n  to: ['user1@example.com', 'user2@example.com'],\n  cc: 'cc@example.com',\n  bcc: 'bcc@example.com',\n  subject: 'Email Subject',\n  text: 'Plain text version',\n  html: '\u003ch1\u003eHTML version\u003c/h1\u003e',\n  replyTo: 'reply@example.com',\n  attachments: [\n    {\n      filename: 'document.pdf',\n      path: '/path/to/file.pdf',\n    },\n  ],\n  headers: {\n    'X-Custom-Header': 'value',\n  },\n});\n```\n\n## Templates\n\n### Creating Templates\n\nCreate your templates in the configured templates directory:\n\n```handlebars\n{{!-- templates/welcome.hbs --}}\n\u003ch2\u003eHello {{name}}!\u003c/h2\u003e\n\u003cp\u003eWelcome to {{company}}.\u003c/p\u003e\n```\n\n### Using Templates\n\n```typescript\nawait mail.send({\n  to: 'user@example.com',\n  subject: 'Welcome!',\n  template: 'welcome',\n  data: {\n    name: 'John',\n    company: 'Acme Inc',\n  },\n});\n```\n\n### Layouts\n\n```handlebars\n{{!-- templates/layouts/main.hbs --}}\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n  \u003ctitle\u003e{{title}}\u003c/title\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n  {{{body}}}\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n### Partials\n\n```handlebars\n{{!-- templates/partials/button.hbs --}}\n\u003ca href=\"{{url}}\" class=\"btn\"\u003e{{text}}\u003c/a\u003e\n```\n\n```handlebars\n{{!-- Usage in template --}}\n{{\u003e button url=\"https://example.com\" text=\"Click Me\" }}\n```\n\n### Custom Helpers\n\n```typescript\nconst mail = new Sendora({\n  provider: 'smtp',\n  smtp: { /* ... */ },\n  templates: {\n    helpers: {\n      uppercase: (str: string) =\u003e str.toUpperCase(),\n      formatDate: (date: Date) =\u003e date.toLocaleDateString(),\n    },\n  },\n});\n```\n\n## Queue Support\n\nEnable the built-in queue for background email processing:\n\n```typescript\nconst mail = new Sendora({\n  provider: 'smtp',\n  smtp: { /* ... */ },\n  queue: true,\n});\n\nawait mail.initialize();\n\nawait mail.send({\n  to: 'user@example.com',\n  subject: 'Welcome',\n  template: 'welcome',\n  data: { name: 'John' },\n});\n\nconsole.log(mail.getQueueSize());\n```\n\n## Logging\n\n```typescript\nconst mail = new Sendora({\n  provider: 'smtp',\n  smtp: { /* ... */ },\n  logger: {\n    enabled: true,\n    level: 'info',\n    prettyPrint: true,\n  },\n});\n```\n\nLog levels: `trace`, `debug`, `info`, `warn`, `error`, `fatal`\n\n## Error Handling\n\n```typescript\nimport { Sendora, TemplateNotFoundError, ProviderError } from 'sendora';\n\ntry {\n  await mail.send({\n    to: 'user@example.com',\n    template: 'nonexistent',\n  });\n} catch (error) {\n  if (error instanceof TemplateNotFoundError) {\n    console.error('Template not found:', error.message);\n  } else if (error instanceof ProviderError) {\n    console.error('Provider error:', error.message);\n  }\n}\n```\n\n## Type Safety\n\n```typescript\ninterface WelcomeData {\n  name: string;\n  company: string;\n}\n\nawait mail.send\u003cWelcomeData\u003e({\n  to: 'user@example.com',\n  template: 'welcome',\n  data: {\n    name: 'John',\n    company: 'Acme',\n  },\n});\n```\n\n## API Reference\n\n### `new Sendora(config)`\n\nCreates a new Sendora instance.\n\n**Parameters:**\n- `config` - Configuration object\n\n### `mail.send(options)`\n\nSends an email.\n\n**Parameters:**\n- `options` - Email options\n\n**Returns:** `Promise\u003cSendEmailResponse\u003e`\n\n### `mail.sendBulk(emails)`\n\nSends multiple emails.\n\n**Parameters:**\n- `emails` - Array of email options\n\n**Returns:** `Promise\u003cSendEmailResponse[]\u003e`\n\n### `mail.initialize()`\n\nInitializes the template engine.\n\n**Returns:** `Promise\u003cvoid\u003e`\n\n### `mail.close()`\n\nCloses the provider connection.\n\n**Returns:** `Promise\u003cvoid\u003e`\n\n### `mail.getQueueSize()`\n\nReturns the number of queued emails.\n\n**Returns:** `number`\n\n### `mail.clearQueue()`\n\nClears all queued emails.\n\n## License\n\nMIT © [Nurul Islam Rimon](https://github.com/nurulislamrimon)\n\n## Contributing\n\nContributions are welcome! This project is open source and we invite developers to contribute.\n\n### Ways to Contribute\n\n- **Bug Reports** - Open an issue with clear steps to reproduce\n- **Feature Requests** - Suggest new features or improvements\n- **Pull Requests** - Submit patches or new features\n- **Documentation** - Improve docs, examples, or add translations\n- **Testing** - Add more test cases\n\n### Getting Started\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n### Development Setup\n\n```bash\n# Clone the repo\ngit clone https://github.com/nurulislamrimon/sendora.git\ncd sendora\n\n# Install dependencies\nnpm install\n\n# Run tests\nnpm test\n\n# Build\nnpm run build\n```\n\nWe appreciate all contributions, no matter how small!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnurulislamrimon%2Fsendora","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnurulislamrimon%2Fsendora","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnurulislamrimon%2Fsendora/lists"}