{"id":13412682,"url":"https://github.com/xhit/go-simple-mail","last_synced_at":"2026-01-16T18:22:44.032Z","repository":{"id":39911768,"uuid":"208547678","full_name":"xhit/go-simple-mail","owner":"xhit","description":"Golang package for send email. Support keep alive connection, TLS and SSL. Easy for bulk SMTP.","archived":false,"fork":false,"pushed_at":"2024-07-20T13:14:15.000Z","size":209,"stargazers_count":672,"open_issues_count":16,"forks_count":100,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-05-16T10:46:33.359Z","etag":null,"topics":["bulk-email","bulk-email-sender","email","go","golang","golang-package","keep-alive","mail","persistent","persistent-connections","send-email","send-email-with-attachment","smtp","smtp-client","smtp-mail","timeout"],"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/xhit.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":["xhit"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":["https://paypal.me/hit"]}},"created_at":"2019-09-15T05:38:54.000Z","updated_at":"2025-05-16T08:26:09.000Z","dependencies_parsed_at":"2024-10-26T08:36:26.937Z","dependency_job_id":"bbb89b2d-9732-412e-ab15-8ca400e9a707","html_url":"https://github.com/xhit/go-simple-mail","commit_stats":{"total_commits":121,"total_committers":29,"mean_commits":4.172413793103448,"dds":0.5702479338842975,"last_synced_commit":"a5ceaf25bef4f7f306c3eddaab1232afa4c15f9c"},"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/xhit/go-simple-mail","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xhit%2Fgo-simple-mail","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xhit%2Fgo-simple-mail/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xhit%2Fgo-simple-mail/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xhit%2Fgo-simple-mail/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xhit","download_url":"https://codeload.github.com/xhit/go-simple-mail/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xhit%2Fgo-simple-mail/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28480636,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["bulk-email","bulk-email-sender","email","go","golang","golang-package","keep-alive","mail","persistent","persistent-connections","send-email","send-email-with-attachment","smtp","smtp-client","smtp-mail","timeout"],"created_at":"2024-07-30T20:01:27.775Z","updated_at":"2026-01-16T18:22:43.992Z","avatar_url":"https://github.com/xhit.png","language":"Go","funding_links":["https://github.com/sponsors/xhit","https://paypal.me/hit"],"categories":["Email","电子邮件","Go","邮件库","邮件库`邮件管理和发送的go语言库`","Relational Databases"],"sub_categories":["Search and Analytic Databases","检索及分析资料库","Advanced Console UIs","SQL 查询语句构建库"],"readme":"# Go Simple Mail\n\nThe best way to send emails in Go with SMTP Keep Alive and Timeout for Connect and Send.\n\n\u003ca href=\"https://goreportcard.com/report/github.com/xhit/go-simple-mail/v2\"\u003e\u003cimg src=\"https://goreportcard.com/badge/github.com/xhit/go-simple-mail\" alt=\"Go Report Card\"\u003e\u003c/a\u003e\n\u003ca href=\"https://pkg.go.dev/github.com/xhit/go-simple-mail/v2?tab=doc\"\u003e\u003cimg src=\"https://img.shields.io/badge/go.dev-reference-007d9c?logo=go\u0026logoColor=white\" alt=\"go.dev\"\u003e\u003c/a\u003e\n\n\n# IMPORTANT\n\nExamples in this README are for v2.2.0 and above. Examples for older versions\ncan be found [here](https://gist.github.com/xhit/54516917473420a8db1b6fff68a21c99).\n\nGo 1.13+ is required.\n\nBreaking change in 2.2.0: The signature of `SetBody` and `AddAlternative` used\nto accept strings (\"text/html\" and \"text/plain\") and not require on of the\n`contentType` constants (`TextHTML` or `TextPlain`). Upgrading, while not\nquite following semantic versioning, is quite simple:\n\n```diff\n  email := mail.NewMSG()\n- email.SetBody(\"text/html\", htmlBody)\n- email.AddAlternative(\"text/plain\", plainBody)\n+ email.SetBody(mail.TextHTML, htmlBody)\n+ email.AddAlternative(mail.TextPlain, plainBody)\n```\n\n# Introduction\n\nGo Simple Mail is a simple and efficient package to send emails. It is well tested and\ndocumented.\n\nGo Simple Mail can only send emails using an SMTP server. But the API is flexible and it\nis easy to implement other methods for sending emails using a local Postfix, an API, etc.\n\nThis package contains (and is based on) two packages by **Joe Grasse**:\n\n- https://github.com/joegrasse/mail (unmaintained since Jun 29, 2018), and\n- https://github.com/joegrasse/mime (unmaintained since Oct 1, 2015).\n\nA lot of changes in Go Simple Mail were sent with not response.\n\n## Features\n\nGo Simple Mail supports:\n\n- Multiple Attachments with path\n- Multiple Attachments in base64\n- Multiple Attachments from bytes (since v2.6.0)\n- Inline attachments from file, base64 and bytes (bytes since v2.6.0)\n- Multiple Recipients\n- Priority\n- Reply to\n- Set sender\n- Set from\n- Allow sending mail with different envelope from (since v2.7.0)\n- Embedded images\n- HTML and text templates\n- Automatic encoding of special characters\n- SSL/TLS and STARTTLS\n- Unencrypted connection (not recommended)\n- Sending multiple emails with the same SMTP connection (Keep Alive or Persistent Connection)\n- Timeout for connect to a SMTP Server\n- Timeout for send an email\n- Return Path\n- Alternative Email Body\n- CC and BCC\n- Add Custom Headers in Message\n- Send NOOP, RESET, QUIT and CLOSE to SMTP client\n- PLAIN, LOGIN and CRAM-MD5 Authentication (since v2.3.0)\n- AUTO Authentication (since v2.14.0)\n- Allow connect to SMTP without authentication (since v2.10.0)\n- Custom TLS Configuration (since v2.5.0)\n- Send a RFC822 formatted message (since v2.8.0)\n- Send from localhost (yes, Go standard SMTP package cannot do that because... WTF Google!)\n- Support text/calendar content type body (since v2.11.0)\n- Support add a List-Unsubscribe header (since v2.11.0)\n- Support to add a DKIM signarure (since v2.11.0)\n- Support to send using custom connection, ideal for proxy (since v2.15.0)\n- Support Delivery Status Notification (DSN) (since v2.16.0)\n- Support text/x-amp-html content type body (since v2.16.0)\n\n## Documentation\n\nhttps://pkg.go.dev/github.com/xhit/go-simple-mail/v2?tab=doc\n\nNote 1: by default duplicated recipients throws an error, from `v2.13.0` you can use `email.AllowDuplicateAddress = true` to avoid the check.\n\nNote 2: by default Bcc header is not set in email. From `v2.14.0` you can use `email.AddBccToHeader = true` to add this.\n\nNote 3: by default all addresses are validated against RFC5322. Setting `email.UseProvidedAddress = true` skips this validation, but requires you to ensure a valid address is sent.\n\n## Download\n\nThis package uses go modules.\n\n```console\n$ go get github.com/xhit/go-simple-mail/v2\n```\n\n# Usage\n\n```go\npackage main\n\nimport (\n\t\"log\"\n\n\tmail \"github.com/xhit/go-simple-mail/v2\"\n\t\"github.com/toorop/go-dkim\"\n)\n\nconst htmlBody = `\u003chtml\u003e\n\t\u003chead\u003e\n\t\t\u003cmeta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /\u003e\n\t\t\u003ctitle\u003eHello Gophers!\u003c/title\u003e\n\t\u003c/head\u003e\n\t\u003cbody\u003e\n\t\t\u003cp\u003eThis is the \u003cb\u003eGo gopher\u003c/b\u003e.\u003c/p\u003e\n\t\t\u003cp\u003e\u003cimg src=\"cid:Gopher.png\" alt=\"Go gopher\" /\u003e\u003c/p\u003e\n\t\t\u003cp\u003eImage created by Renee French\u003c/p\u003e\n\t\u003c/body\u003e\n\u003c/html\u003e`\n\nconst privateKey = `-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAwGrscUxi9zEa9oMOJbS0kLVHZXNIW+EBjY7KFWIZSxuGAils\nwBVl+s5mMRrR5VlkyLQNulAdNemg6OSeB0R+2+8/lkHiMrimqQckZ5ig8slBoZhZ\nwUoL/ZkeQa1bacbdww5TuWkiVPD9kooT/+TZW1P/ugd6oYjpOI56ZjsXzJw5pz7r\nDiwcIJJaaDIqvvc5C4iW94GZjwtmP5pxhvBZ5D6Uzmh7Okvi6z4QCKzdJQLdVmC0\nCMiFeh2FwqMkVpjZhNt3vtCo7Z51kwHVscel6vl51iQFq/laEzgzAWOUQ+ZEoQpL\nuTaUiYzzNyEdGEzZ2CjMMoO8RgtXnUo2qX2FDQIDAQABAoIBAHWKW3kycloSMyhX\nEnNSGeMz+bMtYwxNPMeebC/3xv+shoYXjAkiiTNWlfJ1MbbqjrhT1Pb1LYLbfqIF\n1csWum/bjHpbMLRPO++RH1nxUJA/BMqT6HA8rWpy+JqiLW9GPf2DaP2gDYrZ0+yK\nUIFG6MfzXgnju7OlkOItlvOQMY+Y501u/h6xnN2yTeRqXXJ1YlWFPRIeFdS6UOtL\nJ2wSxRVdymHbGwf+D7zet7ngMPwFBsbEN/83KGLRjkt8+dMQeUeob+nslsQofCZx\niokIAvByTugmqrB4JqhNkAlZhC0mqkRQh7zUFrxSj5UppMWlxLH+gPFZHKAsUJE5\nmqmylcECgYEA8I/f90cpF10uH4NPBCR4+eXq1PzYoD+NdXykN65bJTEDZVEy8rBO\nphXRNfw030sc3R0waQaZVhFuSgshhRuryfG9c1FP6tQhqi/jiEj9IfCW7zN9V/P2\nr16pGjLuCK4SyxUC8H58Q9I0X2CQqFamtkLXC6Ogy86rZfIc8GcvZ9UCgYEAzMQZ\nWAiLhRF2MEmMhKL+G3jm20r+dOzPYkfGxhIryluOXhuUhnxZWL8UZfiEqP5zH7Li\nNeJvLz4pOL45rLw44qiNu6sHN0JNaKYvwNch1wPT/3/eDNZKKePqbAG4iamhjLy5\ngjO1KgA5FBbcNN3R6fuJAg1e4QJCOuo55eW6vFkCgYEA7UBIV72D5joM8iFzvZcn\nBPdfqh2QnELxhaye3ReFZuG3AqaZg8akWqLryb1qe8q9tclC5GIQulTInBfsQDXx\nMGLNQL0x/1ylsw417kRl+qIoidMTTLocUgse5erS3haoDEg1tPBaKB1Zb7NyF8QV\n+W1kX2NKg5bZbdrh9asekt0CgYA6tUam7NxDrLv8IDo/lRPSAJn/6cKG95aGERo2\nk+MmQ5XP+Yxd+q0LOs24ZsZyRXHwdrNQy7khDGt5L2EN23Fb2wO3+NM6zrGu/WbX\nnVbAdQKFUL3zZEUjOYtuqBemsJH27e0qHXUls6ap0dwU9DxJH6sqgXbggGtIxPsQ\npQsjEQKBgQC9gAqAj+ZtMXNG9exVPT8I15reox9kwxGuvJrRu/5eSi6jLR9z3x9P\n2FrgxQ+GCB2ypoOUcliXrKesdSbolUilA8XQn/M113Lg8oA3gJXbAKqbTR/EgfUU\nkvYaR/rTFnivF4SL/P4k/gABQoJuFUtSKdouELqefXB+e94g/G++Bg==\n-----END RSA PRIVATE KEY-----`\n\nfunc main() {\n\tserver := mail.NewSMTPClient()\n\n\t// SMTP Server\n\tserver.Host = \"smtp.example.com\"\n\tserver.Port = 587\n\tserver.Username = \"test@example.com\"\n\tserver.Password = \"examplepass\"\n\tserver.Encryption = mail.EncryptionSTARTTLS\n\n\t// You can specified authentication type:\n\t// - AUTO (default)\n\t// - PLAIN\n\t// - LOGIN\n\t// - CRAM-MD5\n\t// - None\n\t// server.Authentication = mail.AuthAuto\n\n\t// Variable to keep alive connection\n\tserver.KeepAlive = false\n\n\t// Timeout for connect to SMTP Server\n\tserver.ConnectTimeout = 10 * time.Second\n\n\t// Timeout for send the data and wait respond\n\tserver.SendTimeout = 10 * time.Second\n\n\t// Set TLSConfig to provide custom TLS configuration. For example,\n\t// to skip TLS verification (useful for testing):\n\tserver.TLSConfig = \u0026tls.Config{InsecureSkipVerify: true}\n\n\t// SMTP client\n\tsmtpClient,err := server.Connect()\n\n\tif err != nil{\n\t\tlog.Fatal(err)\n\t}\n\n\t// New email simple html with inline and CC\n\temail := mail.NewMSG()\n\temail.SetFrom(\"From Example \u003cnube@example.com\u003e\").\n\t\tAddTo(\"xhit@example.com\").\n\t\tAddCc(\"otherto@example.com\").\n\t\tSetSubject(\"New Go Email\").\n\t\tSetListUnsubscribe(\"\u003cmailto:unsubscribe@example.com?subject=https://example.com/unsubscribe\u003e\")\n\n\temail.SetBody(mail.TextHTML, htmlBody)\n\n\t// also you can add body from []byte with SetBodyData, example:\n\t// email.SetBodyData(mail.TextHTML, []byte(htmlBody))\n\t// or alternative part\n\t// email.AddAlternativeData(mail.TextHTML, []byte(htmlBody))\n\n\t// add inline\n\temail.Attach(\u0026mail.File{FilePath: \"/path/to/image.png\", Name:\"Gopher.png\", Inline: true})\n\n\t// also you can set Delivery Status Notification (DSN) (only is set when server supports DSN)\n\temail.SetDSN([]mail.DSN{mail.SUCCESS, mail.FAILURE}, false)\n\n\t// you can add dkim signature to the email. \n\t// to add dkim, you need a private key already created one.\n\tif privateKey != \"\" {\n\t\toptions := dkim.NewSigOptions()\n\t\toptions.PrivateKey = []byte(privateKey)\n\t\toptions.Domain = \"example.com\"\n\t\toptions.Selector = \"default\"\n\t\toptions.SignatureExpireIn = 3600\n\t\toptions.Headers = []string{\"from\", \"date\", \"mime-version\", \"received\", \"received\"}\n\t\toptions.AddSignatureTimestamp = true\n\t\toptions.Canonicalization = \"relaxed/relaxed\"\n\n\t\temail.SetDkim(options)\n\t}\n\n\t// always check error before send\n\tif email.Error != nil{\n\t\tlog.Fatal(email.Error)\n\t}\n\n\t// Call Send and pass the client\n\terr = email.Send(smtpClient)\n\tif err != nil {\n\t\tlog.Println(err)\n\t} else {\n\t\tlog.Println(\"Email Sent\")\n\t}\n}\n```\n\n## Send multiple emails in same connection\n\n```go\n\t//Set your smtpClient struct to keep alive connection\n\tserver.KeepAlive = true\n\n\tfor _, to := range []string{\n\t\t\"to1@example1.com\",\n\t\t\"to3@example2.com\",\n\t\t\"to4@example3.com\",\n\t} {\n\t\t// New email simple html with inline and CC\n\t\temail := mail.NewMSG()\n\t\temail.SetFrom(\"From Example \u003cnube@example.com\u003e\").\n\t\t\tAddTo(to).\n\t\t\tSetSubject(\"New Go Email\")\n\n\t\temail.SetBody(mail.TextHTML, htmlBody)\n\n\t\t// add inline\n\t\temail.Attach(\u0026mail.File{FilePath: \"/path/to/image.png\", Name:\"Gopher.png\", Inline: true})\n\n\t\t// always check error before send\n\t\tif email.Error != nil{\n\t\t\tlog.Fatal(email.Error)\n\t\t}\n\n\t\t// Call Send and pass the client\n\t\terr = email.Send(smtpClient)\n\t\tif err != nil {\n\t\t\tlog.Println(err)\n\t\t} else {\n\t\t\tlog.Println(\"Email Sent\")\n\t\t}\n\t}\n```\n\n# Send with custom connection\n\nIt's possible to use a custom connection with custom dieler, like a dialer that uses a proxy server, etc...\n\nWith this, these servers params are ignored: `Host`, `Port`. You have total control of the connection.\n\nExample using a conn for proxy:\n\n```go\npackage main\n\nimport (\n\t\"crypto/tls\"\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\n\tmail \"github.com/xhit/go-simple-mail/v2\"\n\t\"golang.org/x/net/proxy\"\n)\n\nfunc main() {\n\tserver := mail.NewSMTPClient()\n\n\thost := \"smtp.example.com\"\n\tport := 587\n\tproxyAddr := \"proxy.server\"\n\n\tconn, err := getCustomConnWithProxy(proxyAddr, host, port)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tserver.Username = \"test@example.com\"\n\tserver.Password = \"examplepass\"\n\tserver.Encryption = mail.EncryptionSTARTTLS\n\tserver.CustomConn = conn\n\n\tsmtpClient, err := server.Connect()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\temail := mail.NewMSG()\n\n\terr = email.SetFrom(\"From Example \u003cnube@example.com\u003e\").AddTo(\"xhit@example.com\").Send(smtpClient)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n}\n\nfunc getCustomConnWithProxy(proxyAddr, host string, port int) (net.Conn, error) {\n\tdial, err := proxy.SOCKS5(\"tcp\", proxyAddr, nil, proxy.Direct)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tdialer, err := dial.Dial(\"tcp\", fmt.Sprintf(\"%s:%d\", host, port))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tconf := \u0026tls.Config{ServerName: host}\n\tconn := tls.Client(dialer, conf)\n\n\treturn conn, nil\n}\n\n```\n\n## More examples\n\nSee [example/example_test.go](example/example_test.go).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxhit%2Fgo-simple-mail","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxhit%2Fgo-simple-mail","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxhit%2Fgo-simple-mail/lists"}