{"id":24201554,"url":"https://github.com/mstgnz/gomail","last_synced_at":"2025-08-27T22:30:18.647Z","repository":{"id":228411996,"uuid":"773903147","full_name":"mstgnz/gomail","owner":"mstgnz","description":"send email with smtp with go standart library","archived":false,"fork":false,"pushed_at":"2024-12-30T14:44:27.000Z","size":32,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-03T10:26:05.037Z","etag":null,"topics":["go","mail","smtp"],"latest_commit_sha":null,"homepage":"","language":"Go","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/mstgnz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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":"mstgnz"}},"created_at":"2024-03-18T15:46:53.000Z","updated_at":"2024-12-30T14:41:02.000Z","dependencies_parsed_at":"2024-06-21T03:57:52.945Z","dependency_job_id":"980af275-d631-4a7f-be6f-a0ffb758efc4","html_url":"https://github.com/mstgnz/gomail","commit_stats":null,"previous_names":["mstgnz/gomail"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/mstgnz/gomail","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mstgnz%2Fgomail","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mstgnz%2Fgomail/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mstgnz%2Fgomail/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mstgnz%2Fgomail/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mstgnz","download_url":"https://codeload.github.com/mstgnz/gomail/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mstgnz%2Fgomail/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272389491,"owners_count":24926287,"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","status":"online","status_checked_at":"2025-08-27T02:00:09.397Z","response_time":76,"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":["go","mail","smtp"],"created_at":"2025-01-13T21:16:20.952Z","updated_at":"2025-08-27T22:30:18.608Z","avatar_url":"https://github.com/mstgnz.png","language":"Go","funding_links":["https://github.com/sponsors/mstgnz"],"categories":[],"sub_categories":[],"readme":"# gomail\nThis is a Go package for sending emails. It provides functionality to send emails using the SMTP protocol with advanced features like connection pooling, rate limiting, and TLS support.\n\n## Installation\nTo use the package, you need to have Go installed and Go modules enabled in your project. Then you can add the package to your project by running the following command:\n\n```bash\ngo get -u github.com/mstgnz/gomail\n```\n\n## Features\n- SMTP protocol support\n- Connection pooling for performance optimization\n- HTML template support with custom functions\n- File attachments (regular and streaming)\n- Asynchronous email sending\n- Rate limiting\n- TLS support (STARTTLS and Direct TLS)\n- CC and BCC recipients\n- Email preview\n- Configurable timeouts and keep-alive\n- Template caching\n- Comprehensive error handling\n\n## Benchmarks\nPerformance benchmarks on Apple M1:\n\n```\nBenchmarkMailSend-8                    13111    83133 ns/op    14435 B/op    184 allocs/op\nBenchmarkMailSendWithAttachments-8     13074    87134 ns/op    19552 B/op    234 allocs/op\nBenchmarkMailSendAsync-8               12862    92055 ns/op    14660 B/op    187 allocs/op\n```\n\n- `MailSend`: Basic email sending without attachments\n- `MailSendWithAttachments`: Email sending with file attachments\n- `MailSendAsync`: Asynchronous email sending\n\nThe benchmarks show that:\n- Basic email sending takes ~83μs per operation\n- Adding attachments increases memory allocation by ~35% but only adds ~4μs to operation time\n- Async sending has minimal overhead (~9μs) compared to synchronous sending\n\nAll operations maintain efficient memory usage with relatively low allocations.\n\n## Basic Usage\n```go\npackage main\n\nimport (\n    \"github.com/mstgnz/gomail\"\n)\n\nfunc main() {\n    // Create a Mail struct and set the necessary fields\n    mail := \u0026Mail{\n        From:    \"sender@example.com\",\n        Name:    \"Sender Name\",\n        Host:    \"smtp.example.com\",\n        Port:    \"587\",\n        User:    \"username\",\n        Pass:    \"password\",\n    }\n\n    // Send a simple email\n    err := mail.SetSubject(\"Test Email\").\n        SetContent(\"This is a test email.\").\n        SetTo(\"recipient@example.com\").\n        Send()\n    if err != nil {\n        // Handle error\n    }\n}\n```\n\n## Advanced Features\n\n### Connection Pooling\n```go\nmail := \u0026Mail{\n    From:     \"sender@example.com\",\n    Name:     \"Sender Name\",\n    Host:     \"smtp.example.com\",\n    Port:     \"587\",\n    User:     \"username\",\n    Pass:     \"password\",\n}\n\n// Set connection pool size (default: 10)\nmail.SetPoolSize(20)\n```\n\n### HTML Templates with Custom Functions\n```go\n// Configure template engine\nengine := \u0026TemplateEngine{\n    BaseDir:    \"templates\",\n    DefaultExt: \".html\",\n    FuncMap: template.FuncMap{\n        \"upper\": strings.ToUpper,\n        \"formatDate\": func(t time.Time) string {\n            return t.Format(\"2006-01-02\")\n        },\n    },\n}\nmail.SetTemplateEngine(engine)\n\n// Render template with data\ndata := map[string]any{\n    \"Name\": \"John\",\n    \"Date\": time.Now(),\n}\nerr := mail.RenderTemplate(\"welcome\", data)\n```\n\nExample template (templates/welcome.html):\n```html\n\u003chtml\u003e\n\u003cbody\u003e\n    \u003ch1\u003eWelcome {{.Name}}!\u003c/h1\u003e\n    \u003cp\u003eToday is {{formatDate .Date}}\u003c/p\u003e\n    \u003cp\u003eYour name in uppercase: {{upper .Name}}\u003c/p\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n### TLS Configuration\n```go\n// STARTTLS configuration\nmail.SetTLSConfig(\u0026TLSConfig{\n    StartTLS:           true,\n    InsecureSkipVerify: false,\n    ServerName:         \"smtp.example.com\",\n})\n\n// Direct TLS configuration\nmail.SetTLSConfig(\u0026TLSConfig{\n    StartTLS:           false,\n    InsecureSkipVerify: false,\n    ServerName:         \"smtp.example.com\",\n})\n```\n\n### Rate Limiting\n```go\n// Limit to 10 emails per second\nmail.SetRateLimit(\u0026RateLimit{\n    Enabled:   true,\n    PerSecond: 10,\n})\n\n// Send multiple emails with rate limiting\nfor i := 0; i \u003c 100; i++ {\n    err := mail.SetSubject(fmt.Sprintf(\"Email %d\", i)).\n        SetContent(\"Rate limited email\").\n        SetTo(\"recipient@example.com\").\n        Send()\n    if err != nil {\n        log.Printf(\"Failed to send email %d: %v\", i, err)\n    }\n}\n```\n\n### Asynchronous Email Sending\n```go\n// Send email asynchronously\nresult := mail.SetSubject(\"Test Email\").\n    SetContent(\"This is a test email.\").\n    SetTo(\"recipient@example.com\").\n    SendAsync()\n\n// Check the result\nif err := \u003c-result; err != nil {\n    log.Printf(\"Failed to send email: %v\", err)\n}\n```\n\n### Large File Attachments (Streaming)\n```go\n// Stream a large file\nfile, err := os.Open(\"large-file.zip\")\nif err != nil {\n    log.Fatal(err)\n}\ndefer file.Close()\n\nfileInfo, err := file.Stat()\nif err != nil {\n    log.Fatal(err)\n}\n\nattachments := []AttachmentReader{\n    {\n        Name:   \"large-file.zip\",\n        Reader: file,\n        Size:   fileInfo.Size(),\n    },\n}\n\nerr = mail.SetSubject(\"Email with Large Attachment\").\n    SetContent(\"Please find the attached file.\").\n    SetTo(\"recipient@example.com\").\n    SetStreamAttachment(attachments).\n    Send()\n```\n\n### Email Preview\n```go\n// Preview email before sending\npreview, err := mail.PreviewEmail()\nif err != nil {\n    log.Printf(\"Preview error: %v\", err)\n    return\n}\nfmt.Println(\"Email Preview:\")\nfmt.Println(preview)\n```\n\n### Error Handling\n```go\n// Basic error handling\nerr := mail.Send()\nif err != nil {\n    switch {\n    case strings.Contains(err.Error(), \"connection refused\"):\n        log.Printf(\"SMTP server is not accessible: %v\", err)\n    case strings.Contains(err.Error(), \"invalid auth\"):\n        log.Printf(\"Authentication failed: %v\", err)\n    case strings.Contains(err.Error(), \"invalid recipient\"):\n        log.Printf(\"Invalid recipient address: %v\", err)\n    default:\n        log.Printf(\"Failed to send email: %v\", err)\n    }\n}\n\n// Async error handling with timeout\nresult := mail.SendAsync()\nselect {\ncase err := \u003c-result:\n    if err != nil {\n        log.Printf(\"Failed to send email: %v\", err)\n    }\ncase \u003c-time.After(30 * time.Second):\n    log.Printf(\"Email sending timed out\")\n}\n```\n\n### Template Usage Examples\n```go\n// 1. Basic Template\nengine := \u0026TemplateEngine{\n    BaseDir:    \"templates\",\n    DefaultExt: \".html\",\n}\nmail.SetTemplateEngine(engine)\n\n// Basic template usage\ndata := map[string]any{\n    \"Name\": \"John\",\n    \"Products\": []string{\"Product 1\", \"Product 2\"},\n    \"Total\": 99.99,\n}\nerr := mail.RenderTemplate(\"order-confirmation\", data)\n\n// 2. Custom Template Functions\nengine := \u0026TemplateEngine{\n    BaseDir:    \"templates\",\n    DefaultExt: \".html\",\n    FuncMap: template.FuncMap{\n        \"upper\": strings.ToUpper,\n        \"formatDate\": func(t time.Time) string {\n            return t.Format(\"2006-01-02\")\n        },\n        \"formatPrice\": func(price float64) string {\n            return fmt.Sprintf(\"$%.2f\", price)\n        },\n        \"safeHTML\": func(s string) template.HTML {\n            return template.HTML(s)\n        },\n    },\n}\nmail.SetTemplateEngine(engine)\n\n// 3. Template with Layouts\n// templates/layouts/base.html\n/*\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    \u003cheader\u003e{{template \"header\" .}}\u003c/header\u003e\n    \u003cmain\u003e{{template \"content\" .}}\u003c/main\u003e\n    \u003cfooter\u003e{{template \"footer\" .}}\u003c/footer\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n*/\n\n// templates/welcome.html\n/*\n{{define \"header\"}}\n    \u003ch1\u003eWelcome {{.Name}}\u003c/h1\u003e\n{{end}}\n\n{{define \"content\"}}\n    \u003cp\u003eToday is {{formatDate .Date}}\u003c/p\u003e\n    \u003cp\u003eYour total: {{formatPrice .Total}}\u003c/p\u003e\n{{end}}\n\n{{define \"footer\"}}\n    \u003cp\u003eContact us: support@example.com\u003c/p\u003e\n{{end}}\n*/\n```\n\n### TLS Configuration Examples\n```go\n// 1. STARTTLS with Gmail\nmail.SetTLSConfig(\u0026TLSConfig{\n    StartTLS:           true,\n    InsecureSkipVerify: false,\n    ServerName:         \"smtp.gmail.com\",\n})\n\n// 2. Direct TLS with custom certificates\ncert, err := tls.LoadX509KeyPair(\"cert.pem\", \"key.pem\")\nif err != nil {\n    log.Fatal(err)\n}\n\nmail.SetTLSConfig(\u0026TLSConfig{\n    StartTLS:           false,\n    InsecureSkipVerify: false,\n    ServerName:         \"smtp.example.com\",\n    Certificates:       []tls.Certificate{cert},\n})\n\n// 3. TLS with custom verification\nmail.SetTLSConfig(\u0026TLSConfig{\n    StartTLS:           true,\n    InsecureSkipVerify: false,\n    ServerName:         \"smtp.example.com\",\n    MinVersion:         tls.VersionTLS12,\n    MaxVersion:         tls.VersionTLS13,\n})\n\n// 4. Development/Testing TLS (insecure)\nmail.SetTLSConfig(\u0026TLSConfig{\n    StartTLS:           true,\n    InsecureSkipVerify: true, // Only for development!\n    ServerName:         \"localhost\",\n})\n```\n\n### Rate Limiting Examples\n```go\n// 1. Basic Rate Limiting\nmail.SetRateLimit(\u0026RateLimit{\n    Enabled:   true,\n    PerSecond: 10, // 10 emails per second\n})\n\n// 2. Burst Sending with Rate Limiting\nemails := []struct {\n    to      string\n    subject string\n    content string\n}{\n    {\"user1@example.com\", \"Subject 1\", \"Content 1\"},\n    {\"user2@example.com\", \"Subject 2\", \"Content 2\"},\n    // ... more emails\n}\n\n// Configure rate limiting\nmail.SetRateLimit(\u0026RateLimit{\n    Enabled:   true,\n    PerSecond: 5, // 5 emails per second\n})\n\n// Send emails with progress tracking\nfor i, email := range emails {\n    err := mail.SetSubject(email.subject).\n        SetContent(email.content).\n        SetTo(email.to).\n        Send()\n    \n    if err != nil {\n        log.Printf(\"Failed to send email %d: %v\", i+1, err)\n        continue\n    }\n    \n    log.Printf(\"Progress: %d/%d emails sent\", i+1, len(emails))\n}\n\n// 3. Async Sending with Rate Limiting\nresults := make(chan error, len(emails))\nfor _, email := range emails {\n    go func(e struct {\n        to      string\n        subject string\n        content string\n    }) {\n        results \u003c- mail.SetSubject(e.subject).\n            SetContent(e.content).\n            SetTo(e.to).\n            Send()\n    }(email)\n}\n\n// Collect results\nfor i := 0; i \u003c len(emails); i++ {\n    if err := \u003c-results; err != nil {\n        log.Printf(\"Email error: %v\", err)\n    }\n}\n```\n\n### Error Handling Examples\n```go\n// 1. Comprehensive Error Handling\nerr := mail.Send()\nif err != nil {\n    switch {\n    case strings.Contains(err.Error(), \"connection refused\"):\n        log.Printf(\"SMTP server is not accessible: %v\", err)\n        // Retry with backup server\n        mail.SetHost(\"backup-smtp.example.com\")\n        err = mail.Send()\n        \n    case strings.Contains(err.Error(), \"invalid auth\"):\n        log.Printf(\"Authentication failed: %v\", err)\n        // Refresh credentials and retry\n        mail.SetUser(\"new-user\").SetPass(\"new-pass\")\n        err = mail.Send()\n        \n    case strings.Contains(err.Error(), \"invalid recipient\"):\n        log.Printf(\"Invalid recipient address: %v\", err)\n        // Log invalid address for cleanup\n        logInvalidAddress(mail.To[0])\n        \n    case strings.Contains(err.Error(), \"timeout\"):\n        log.Printf(\"Connection timeout: %v\", err)\n        // Retry with increased timeout\n        mail.SetTimeout(30 * time.Second)\n        err = mail.Send()\n        \n    default:\n        log.Printf(\"Unexpected error: %v\", err)\n    }\n}\n\n// 2. Retry Logic\nmaxRetries := 3\nretryDelay := time.Second\n\nfor i := 0; i \u003c maxRetries; i++ {\n    err := mail.Send()\n    if err == nil {\n        break\n    }\n    \n    log.Printf(\"Attempt %d failed: %v\", i+1, err)\n    if i \u003c maxRetries-1 {\n        time.Sleep(retryDelay * time.Duration(i+1))\n    }\n}\n\n// 3. Async Error Handling with Context\nctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\ndefer cancel()\n\nresult := mail.SendAsync()\nselect {\ncase err := \u003c-result:\n    if err != nil {\n        log.Printf(\"Failed to send email: %v\", err)\n    }\ncase \u003c-ctx.Done():\n    log.Printf(\"Email sending timed out or cancelled\")\ncase \u003c-time.After(5 * time.Second):\n    log.Printf(\"Email sending took too long\")\n}\n\n// 4. Batch Error Handling\ntype EmailResult struct {\n    To    string\n    Error error\n}\n\nresults := make(chan EmailResult, len(recipients))\nfor _, to := range recipients {\n    go func(recipient string) {\n        err := mail.SetTo(recipient).Send()\n        results \u003c- EmailResult{To: recipient, Error: err}\n    }(to)\n}\n\n// Process results\nsuccessCount := 0\nfailureCount := 0\nfor i := 0; i \u003c len(recipients); i++ {\n    result := \u003c-results\n    if result.Error != nil {\n        failureCount++\n        log.Printf(\"Failed to send to %s: %v\", result.To, result.Error)\n    } else {\n        successCount++\n    }\n}\n\nlog.Printf(\"Sending complete: %d successful, %d failed\", successCount, failureCount)\n```\n\n## Contributing\nContributions are welcome! For any feedback, bug reports, or contributions, please submit an issue or pull request to the GitHub repository.\n\n## License\nThis package is licensed under the MIT License. See the LICENSE file for more information.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmstgnz%2Fgomail","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmstgnz%2Fgomail","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmstgnz%2Fgomail/lists"}