{"id":51349058,"url":"https://github.com/slashdevops/mailer","last_synced_at":"2026-07-02T14:40:26.509Z","repository":{"id":290046786,"uuid":"973179155","full_name":"slashdevops/mailer","owner":"slashdevops","description":"Mailer go library","archived":false,"fork":false,"pushed_at":"2026-06-24T20:15:09.000Z","size":46,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-24T22:07:27.687Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/slashdevops.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-04-26T12:40:14.000Z","updated_at":"2026-06-24T20:15:15.000Z","dependencies_parsed_at":"2025-04-26T15:19:54.716Z","dependency_job_id":"538d1fe5-18bd-42d3-aaa1-0fb41c92a35d","html_url":"https://github.com/slashdevops/mailer","commit_stats":null,"previous_names":["p2p-b2b/mailer","slashdevops/mailer"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/slashdevops/mailer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slashdevops%2Fmailer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slashdevops%2Fmailer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slashdevops%2Fmailer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slashdevops%2Fmailer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/slashdevops","download_url":"https://codeload.github.com/slashdevops/mailer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slashdevops%2Fmailer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35051883,"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-07-02T02:00:06.368Z","response_time":173,"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":[],"created_at":"2026-07-02T14:40:25.736Z","updated_at":"2026-07-02T14:40:26.497Z","avatar_url":"https://github.com/slashdevops.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mailer\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/slashdevops/mailer.svg)](https://pkg.go.dev/github.com/slashdevops/mailer)\n![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/slashdevops/mailer?style=plastic)\n[![Go Report Card](https://goreportcard.com/badge/github.com/slashdevops/mailer)](https://goreportcard.com/report/github.com/slashdevops/mailer)\n\nThis package provides a robust and concurrent email sending service for Go applications. It allows queueing emails and sending them asynchronously using a pool of workers via a configurable backend (e.g., SMTP).\n\n## Features\n\n* **Concurrent Sending:** Uses a worker pool to send emails concurrently.\n* **Buffering:** Queues emails in a buffered channel, sized according to the worker count.\n* **Graceful Shutdown:** Supports context cancellation for stopping workers and waits for them to finish processing enqueued items.\n* **Pluggable Backend:** Uses a `MailerService` interface, allowing different sending mechanisms (e.g., SMTP, API-based services). An SMTP implementation (`MailerSMTP`) is included.\n* **Content Validation:** Includes a builder (`MailContentBuilder`) for creating validated `MailContent` with checks for field lengths and allowed MIME types.\n* **Context Propagation:** Leverages `context.Context` for cancellation and timeout propagation throughout the sending process.\n* **Structured Logging:** Uses the standard `log/slog` package for informative logging.\n* **Error Handling:** Provides specific error types (`MailerError`, `MailQueueError`) for better error management.\n* **Customizable Worker Count:** Allows configuring the number of concurrent workers within defined limits.\n* **MIME Type Support:** Supports `text/plain` and `text/html` MIME types.\n* **Sender and Recipient Details:** Allows specifying sender and recipient names along with email addresses.\n\n## Installation\n\nTo use this library in your project, install it using `go get`:\n\n```sh\ngo get github.com/slashdevops/mailer@latest\n````\n\n## Components\n\n* **`MailService`**: The main service that manages the email queue and worker pool.\n* **`MailContent` / `MailContentBuilder`**: Struct and builder for defining email content (sender, recipient, subject, body, MIME type).\n* **`MailerService`**: Interface for the actual email sending logic.\n* **`MailerSMTP`**: An implementation of `MailerService` using standard SMTP.\n\n## Configuration\n\n### `MailService`\n\nConfigure the `MailService` using `MailServiceConfig`:\n\n```go\ntype MailServiceConfig struct {\n    Ctx         context.Context // Optional: Parent context for cancellation.\n    WorkerCount int             // Number of concurrent sending workers (1-100).\n    Timeout     time.Duration   // Optional: Timeout for operations (currently unused in core service logic but available).\n    Mailer      MailerService   // The backend mailer implementation (e.g., MailerSMTP).\n}\n```\n\n### `MailerSMTP`\n\nConfigure the `MailerSMTP` backend using `MailerSMTPConf`:\n\n```go\ntype MailerSMTPConf struct {\n    SMTPHost string // SMTP server hostname.\n    SMTPPort int    // SMTP server port (e.g., 587, 465, 25).\n    Username string // SMTP username for authentication.\n    Password string // SMTP password for authentication.\n}\n```\n\n## Usage Example\n\n```go\npackage main\n\nimport (\n  \"context\"\n  \"fmt\"\n  \"log/slog\"\n  \"os\"\n  \"os/signal\"\n  \"syscall\"\n  \"time\"\n\n  \"github.com/slashdevops/mailer\" // Assuming this is the module path\n)\n\nfunc main() {\n  // --- Configuration ---\n  smtpConf := mailer.MailerSMTPConf{\n    SMTPHost: \"smtp.example.com\", // Replace with your SMTP host\n    SMTPPort: 587,                // Replace with your SMTP port\n    Username: \"user@example.com\", // Replace with your SMTP username\n    Password: \"your_password\",    // Replace with your SMTP password\n  }\n\n  smtpMailer, err := mailer.NewMailerSMTP(smtpConf)\n  if err != nil {\n    slog.Error(\"Failed to configure SMTP mailer\", \"error\", err)\n    os.Exit(1)\n  }\n\n  // Create a context that can be cancelled\n  appCtx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)\n  defer cancel()\n\n  mailServiceConf := \u0026mailer.MailServiceConfig{\n    Ctx:         appCtx,     // Use the cancellable context\n    WorkerCount: 5,          // Number of concurrent workers\n    Mailer:      smtpMailer, // Use the configured SMTP mailer\n  }\n\n  mailService, err := mailer.NewMailService(mailServiceConf)\n  if err != nil {\n    slog.Error(\"Failed to create mail service\", \"error\", err)\n    os.Exit(1)\n  }\n\n  // --- Start the Service ---\n  // Start the service with the application context\n  mailService.Start(appCtx)\n  slog.Info(\"Mail service started. Press Ctrl+C to stop.\")\n\n  // --- Enqueue Emails ---\n  go func() {\n    // Example of enqueuing emails\n    for i := 0; i \u003c 10; i++ {\n      subject := fmt.Sprintf(\"Test Email %d\", i+1)\n      body := fmt.Sprintf(\"This is the body of test email #%d.\", i+1)\n\n      content, err := (\u0026mailer.MailContentBuilder{}).\n        WithFromName(\"Sender Name\").\n        WithFromAddress(\"sender@example.com\").\n        WithToName(\"Recipient Name\").\n        WithToAddress(\"recipient@example.com\"). // Replace with a valid recipient\n        WithMimeType(\"text/plain\").\n        WithSubject(subject).\n        WithBody(body).\n        Build()\n\n      if err != nil {\n        slog.Error(\"Failed to build mail content\", \"error\", err)\n        continue // Skip this email\n      }\n\n      err = mailService.Enqueue(content)\n      if err != nil {\n        // This might happen if the context is cancelled while enqueuing\n        slog.Error(\"Failed to enqueue email\", \"error\", err)\n        // If context is cancelled, we should probably stop trying to enqueue\n        if appCtx.Err() != nil {\n          break\n        }\n      } else {\n        slog.Info(\"Email enqueued\", \"subject\", subject)\n      }\n      time.Sleep(500 * time.Millisecond) // Simulate some delay between emails\n    }\n    slog.Info(\"Finished enqueuing sample emails.\")\n  }()\n\n  // --- Wait for Shutdown Signal ---\n  \u003c-appCtx.Done() // Block until context is cancelled (Ctrl+C)\n\n  slog.Info(\"Shutdown signal received.\")\n\n  // --- Stop the Service Gracefully ---\n  // Stop accepting new emails and wait for workers to finish\n  // Note: Stop() closes the channel. If context cancellation is the primary\n  // shutdown mechanism, workers will stop based on \u003c-ctx.Done().\n  // Calling Stop() ensures the channel is closed if not already done by context cancellation propagation.\n  // Depending on exact needs, you might just rely on context cancellation and use Wait().\n  // Using Stop() here is generally safer for ensuring cleanup.\n  mailService.Stop() // This also calls Wait() internally after closing the channel\n\n  slog.Info(\"Mail service stopped gracefully.\")\n}\n```\n\n## Contributing\n\nContributions are welcome! Please feel free to submit pull requests or open issues.\n\n## License\n\nThis project is licensed under the Apache License 2.0. See the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslashdevops%2Fmailer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fslashdevops%2Fmailer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslashdevops%2Fmailer/lists"}