Golang package for send email. Support keep alive connection, TLS and SSL. Easy for bulk SMTP.

Go Simple Mail

The best way to send emails in Go with SMTP Keep Alive and Timeout for Connect and Send.

Go Report Card go.dev

IMPORTANT

Examples in this README are for v2.2.0 and above. Examples for older versions can be found here.

The minimum Go version is 1.13, for Go 1.12 and older use branch go1.12.

Breaking change in 2.2.0: The signature of SetBody and AddAlternative used to accept strings ("text/html" and "text/plain") and not require on of the contentType constants (TextHTML or TextPlain). Upgrading, while not quite following semantic versioning, is quite simple:

  email := mail.NewMSG()
- email.SetBody("text/html", htmlBody)
- email.AddAlternative("text/plain", plainBody)
+ email.SetBody(mail.TextHTML, htmlBody)
+ email.AddAlternative(mail.TextPlain, plainBody)

Introduction

Go Simple Mail is a simple and efficient package to send emails. It is well tested and documented.

Go Simple Mail can only send emails using an SMTP server. But the API is flexible and it is easy to implement other methods for sending emails using a local Postfix, an API, etc.

This package contains (and is based on) two packages by Joe Grasse:

A lot of changes in Go Simple Mail were sent with not response.

Features

Go Simple Mail supports:

  • Multiple Attachments with path
  • Multiple Attachments in base64
  • Multiple Attachments from bytes (since v2.6.0)
  • Inline attachments from file, base64 and bytes (bytes since v2.6.0)
  • Multiple Recipients
  • Priority
  • Reply to
  • Set sender
  • Set from
  • Allow sending mail with different envelope from (since v2.7.0)
  • Embedded images
  • HTML and text templates
  • Automatic encoding of special characters
  • SSL and TLS
  • Unencrypted connection (not recommended)
  • Sending multiple emails with the same SMTP connection (Keep Alive or Persistent Connection)
  • Timeout for connect to a SMTP Server
  • Timeout for send an email
  • Return Path
  • Alternative Email Body
  • CC and BCC
  • Add Custom Headers in Message
  • Send NOOP, RESET, QUIT and CLOSE to SMTP client
  • PLAIN, LOGIN and CRAM-MD5 Authentication (since v2.3.0)
  • Custom TLS Configuration (since v2.5.0)

Documentation

https://pkg.go.dev/github.com/xhit/go-simple-mail/v2?tab=doc

Download

This package uses go modules.

$ go get github.com/xhit/go-simple-mail/v2

Usage

package main

import (
	"log"

	"github.com/xhit/go-simple-mail/v2"
)

const htmlBody = `<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<title>Hello Gophers!</title>
	</head>
	<body>
		<p>This is the <b>Go gopher</b>.</p>
		<p><img src="cid:Gopher.png" alt="Go gopher" /></p>
		<p>Image created by Renee French</p>
	</body>
</html>`

func main() {
	server := mail.NewSMTPClient()

	// SMTP Server
	server.Host = "smtp.example.com"
	server.Port = 587
	server.Username = "[email protected]"
	server.Password = "examplepass"
	server.Encryption = mail.EncryptionTLS

	// Since v2.3.0 you can specified authentication type:
	// - PLAIN (default)
	// - LOGIN
	// - CRAM-MD5
	// server.Authentication = mail.AuthPlain

	// Variable to keep alive connection
	server.KeepAlive = false

	// Timeout for connect to SMTP Server
	server.ConnectTimeout = 10 * time.Second

	// Timeout for send the data and wait respond
	server.SendTimeout = 10 * time.Second

	// Set TLSConfig to provide custom TLS configuration. For example,
	// to skip TLS verification (useful for testing):
	server.TLSConfig = &tls.Config{InsecureSkipVerify: true}

	// SMTP client
	smtpClient,err := server.Connect()

	if err != nil{
		log.Fatal(err)
	}

	// New email simple html with inline and CC
	email := mail.NewMSG()
	email.SetFrom("From Example <[email protected]>").
		AddTo("[email protected]").
		AddCc("[email protected]").
		SetSubject("New Go Email")

	email.SetBody(mail.TextHTML, htmlBody)

	email.AddInline("/path/to/image.png", "Gopher.png")

	// Call Send and pass the client
	err = email.Send(smtpClient)
	if err != nil {
		log.Println(err)
	} else {
		log.Println("Email Sent")
	}
}

Send multiple emails in same connection

	//Set your smtpClient struct to keep alive connection
	server.KeepAlive = true

	for _, to := range []string{
		"[email protected]",
		"[email protected]",
		"[email protected]",
	} {
		// New email simple html with inline and CC
		email := mail.NewMSG()
		email.SetFrom("From Example <[email protected]>").
			AddTo(to).
			SetSubject("New Go Email")

		email.SetBody(mail.TextHTML, htmlBody)
		email.AddInline("/path/to/image.png", "Gopher.png")

		// Call Send and pass the client
		err = email.Send(smtpClient)
		if err != nil {
			log.Println(err)
		} else {
			log.Println("Email Sent")
		}
	}

More examples

See example/example_test.go.

Owner
Santiago De la Cruz
Doing some private stuffs.
Santiago De la Cruz
Comments
  • Unify attachment handling API

    Unify attachment handling API

    Currently we have the following function signatures for adding attachments to an Email struct:

    func (email *Email) AddAttachment(file string, name ...string) *Email
    func (email *Email) AddAttachmentBase64(b64File, name string) *Email
    func (email *Email) AddAttachmentData(data []byte, filename, mimeType string) *Email
    func (email *Email) AddInline(file string, name ...string) *Email
    func (email *Email) AddInlineBase64(b64File, name, mimeType string) *Email
    func (email *Email) AddInlineData(data []byte, filename, mimeType string) *Email
    

    For some reason AddAttachment and AddInline are variadic but only accept one name:

            if len(name) > 1 {
                    email.Error = errors.New("Mail Error: Attach can only have a file and an optional name")
                    return email
            }
    

    Other functions take name as parameter and possibly also mimeType.

    I propose we modify all these functions to accept name and mimeType. So the API would become:

    func (email *Email) AddAttachment(file, name, mimeType string) *Email
    func (email *Email) AddAttachmentBase64(b64Data, name, mimeType string) *Email
    func (email *Email) AddAttachmentData(data []byte, name, mimeType string) *Email
    func (email *Email) AddInline(file, name, mimeType string) *Email
    func (email *Email) AddInlineBase64(b64Data, name, mimeType string) *Email
    func (email *Email) AddInlineData(data []byte, name, mimeType string) *Email
    

    edit. I changed argument name b64File -> b64Data so it is consistent with file and data arguments.

  • Create interface from type to improve the testability of this library

    Create interface from type to improve the testability of this library

    It is very hard to test the usage of this library in other projects.

    With these interfaces, it will be easy to mock this library.

    When developing other projects, the functionality of external libraries should not have to be tested as well.

  • Get encrypted function

    Get encrypted function

    Please provide a function that can get the encryption, For example: SMTP = > encryption TLS

    const (
    	// EncryptionNone uses no encryption when sending email
    	EncryptionNone encryption = iota
    	// EncryptionSSL sets encryption type to SSL when sending email
    	EncryptionSSL
    	// EncryptionTLS sets encryption type to TLS when sending email
    	EncryptionTLS
    )
    
  • Allow sending mail with different envelope from.

    Allow sending mail with different envelope from.

    It's often necessary to send mails where the 'From' header and the SMTP envelope email address differ. The new function 'SendEnvelopeFrom' allows this.

  • Rfc1870 fix

    Rfc1870 fix

    As i'm see client not support SIZE as expected. I add message SIZE as it described in RFC 1870.

    Can you check my propose for extend mail command in smtp.go ? I also need this extensions

    • CHECKPOINT RFC 1845
    • BINARYMIME RFC 3030
    • CHUNKING RFC 3030

    CHECKPOINT also need extend mail from command like this PR for size

    And CHUNKING and BINARYMIME need additional command and disable break commands on lines limit by 80

  • Client does not reconnect on network failure, even with KeepAlive

    Client does not reconnect on network failure, even with KeepAlive

    I had a smtp connexion OK (with keepalive), when suddently the remote server closed it. Since this event no mail were sent, event if the remote server is back online.

    Here is the log i have each time i send a mail since the event.

    write tcp 127.0.0.1:60591->127.0.0.1:25: wsasend: An existing connection was forcibly closed by the remote host.  
    

    The only way to get my mails sent again, was by killing/starting my app.

    You can easily reproduce this case with mailHog, by activating "JIM" with -invite-jim -jim-disconnect "1"

  • Discarding duplicate email address and setting error

    Discarding duplicate email address and setting error

    Hi Thanks for creating this package, great work 👍

    I wanted to know if is there any specific reason why you are not adding a duplicate email address in recipients and setting error on email also?

    email.recipients, err = addAddress(email.recipients, address.Address)
    	if err != nil {
    		email.Error = errors.New("Mail Error: " + err.Error() + "; Header: [" + header + "] Address: [" + addresses[i] + "]")
    		return email
    
  • MISSING_MIMEOLE Message has X-MSMail-Priority, but no X-MimeOLE

    MISSING_MIMEOLE Message has X-MSMail-Priority, but no X-MimeOLE

    I got this message in mailtrap.io "Spam check": MISSING_MIMEOLE Message has X-MSMail-Priority, but no X-MimeOLE

    image

    Is all good with this header?

    SpamAssassin Rule: MISSING_MIMEOLE
    
    Standard description: Message has X-MSMail-Priority, but no X-MimeOLE
    
    Explanation
    
    The message is pretending to be generated by a Microsoft email program which uses the extension header X-MSMail-Priority, but is missing the extension header X-MimeOLE which is characteristic of Microsoft email.
    
    This suggests that the sender is using badly-written mailout software, rather than a genuine Microsoft email program.
    
  • Add golangci-lint action

    Add golangci-lint action

    Add golangci-lint action

    Use permissive configuration to ease follow up of changes, fixes reported by the linter

    Applied fixes:

    • Fix deadcode, unused and varcheck lint errors
    • Fix govet lint errors

    Signed-off-by: Alex Szakaly [email protected]

  • go-simple-mail can send email from a RFC822 formatted message.

    go-simple-mail can send email from a RFC822 formatted message.

    Hello,

    This a PR which allow go-simple-mail to send email from a RFC822 message. I have 2 usecases which needed this change

    Usecase 1 : Delayed delivery my app creates mail.Mail messages but send them only 3 or 4 days after ;

    • it save the Message(RFC822) got with *Email.GetMessage() into DB
    • 3 or 4 days later, it takes it and send them to smtp server.

    Usecase 2 : S/MIME Encrypted mail After retrieving the RFC822 message, i envelope it with S/MIME and get a new RFC822 message.

    Hope it helps.

    Changes

    • new function mail.SendMessage(from, recipients, msg, client) error
    • Email exports a GetRecipients() function to get all recipients emails
  • Can't go get

    Can't go get

    $ go get -u github.com/xhit/go-simple-mail/v2
    cannot find package "github.com/xhit/go-simple-mail/v2" in any of:
            ...\github.com\xhit\go-simple-mail\v2 (from $GOROOT)
            ...\github.com\xhit\go-simple-mail\v2 (from $GOPATH)
    

    I guess this is related to go modules?

  • Implement reconnect or reconnect helper from #23

    Implement reconnect or reconnect helper from #23

    I ended up spending several hours trying to make a type that would wrap the SMTPClient type and do the NOOP sending to implement the suggestion in this comment before I realized there was no easy way to track the last time an email was sent for the timer, and you cannot do that by wrapping a SMTPClient because the email type is what sends the email in Email.Send, by calling an an unexported internal function. This means that I need to create a special EmailProvider which returns a new type embedding Email so that I can wrap Email.Send and Email.SendEnvelopeFrom to track the SMTPClient with a mutex and reset the loop. Also SMTPClient has an exported Client field, which returns the unexported internal smtpClient type, which is unfortunately useless. So I cannot have the SMTPServer reconnect the internal smtpClient, and I must use EmailProvider to do that. It's a bit convoluted and not nearly as easy as the solution in #23 would suggest.

    It would be nice if there was a way to do this in the library, or if you could provide a type like my EmailProvider that wraps the client and server objects to re-create it when necessary.

  • OAuth2.0

    OAuth2.0

    Hello there,

    is there any interest or maybe already any ongoing development (though i did not see anything in the branches) regarding a generic OAuth2.0 implementation? Microsoft seems to force everyone from BasicAuthentication to OAuth2.0

    I am a big fan of this package due to its simplicity and i was wondering if anyone else stumbled across this?

    I noticed you are aware that OAuth2 is not working in this issue Are you interested in adding OAuth2 as this will be the next Generation of Authentications? I probably could help implementing it, if you are interested.

    Best regards, LarsTi

  • Mail not reciving to Yahoo Accounts

    Mail not reciving to Yahoo Accounts

    Hi, Mails not receiving to yahoo accounts. Getting the error message 5.6.7(destination does not support SMTPUTF8 required for message delivery).
    Please give a soulution

  • V3 help

    V3 help

    Hello, I hope you are happy using this package :)

    Currently I'm too busy, and I know this package needs some features proposed in this discussion https://github.com/xhit/go-simple-mail/discussions/53

    I left a branch here for V3 https://github.com/xhit/go-simple-mail/tree/v3, feel free to add some features, breaking changes, enhancement, etc... that you think is needed, I will check all PRs.

    The PR destination should be v3 branch.

    Also, If you want to be a maintainer, please respond this issue :)

  • Improvement: Reuse Connection (or unclear documentation)

    Improvement: Reuse Connection (or unclear documentation)

    Hey, first things first: nice package, thank you for that. But it seems that it is not really possible to keep one connection open?

    I want to run this in the background and from time to time send a mail. As far as I understood the documentation (or sadly/more precisely the code 😬) right, it is not intended to reuse a client? Instead I should create a new client for each message (or hope that the connection is still open/use client.noop and maybe re-create the client)? This seems a bit wasteful to open a new connection for every message.

    Maybe this could be an improvement for v3? 😁

:incoming_envelope: Simple email interface across multiple service providers (ses, postmark, mandrill, smtp)
:incoming_envelope: Simple email interface across multiple service providers (ses, postmark, mandrill, smtp)

go-mail Lightweight email package with multi-provider support (ses, mandrill, postmark) Table of Contents Installation Documentation Examples & Tests

Dec 10, 2022
envio de email via SMTP com anexo usando Go

gosendmail - SMTP This repo is a simple net/smtp abstraction for sending emails using SMTP. With it we can send emails With copy, with blind copy and

Aug 18, 2022
Pretty wrapper for sending email using go net/smtp

Emailer A pretty wrapper around go net/smtp send multiple email using single client func main() { var client *emailer.Client var clientX sync.Mute

Mar 23, 2022
Simple tool to test SMTP mail send with various settings including TLS1.1 downgrade

smtptest Simple tool to test SMTP mail send with various settings including TLS1.1 downgrade All settings are configurable in the config.yaml file ser

Sep 19, 2022
Email-searcher - Given a domain name and real name, attempt to find an existing email for that user.

email-searcher Given a domain name and real name, attempt to find an existing email for that user. Using Run it with both the domain and name flags, l

Jan 2, 2022
VMail - check the markup (HTML, CSS) of HTML email template compatibility with email clients
VMail - check the markup (HTML, CSS) of HTML email template compatibility with email clients

VMail - check the markup (HTML, CSS) of HTML email template compatibility with email clients Email clients use different rendering standards. This is

Dec 17, 2022
golang honeypot smtp server
golang honeypot smtp server

honeygogo-smtp standalone honeypot A lightweight SMTP honeypot server written in Go, leveraging go-smtp. A stand alone version of a module from honeyg

May 4, 2022
📮 Simple (but useful) email sender written in pure Go v1.17. Support HTML templates and attachments.

?? Go Email Sender Simple (but useful) email sender written in pure Go v1.17. Yes, yet another email package here! ?? Support HTML templates and attac

Dec 31, 2021
Web and API based SMTP testing
Web and API based SMTP testing

MailHog Inspired by MailCatcher, easier to install. Download and run MailHog Configure your outgoing SMTP server View your outgoing email in a web UI

Jan 4, 2023
Lightweight SMTP client written in Go

Hectane Hectane is both a Go package providing an SMTP queue for sending emails and a standalone application that exposes this functionality via an HT

Nov 23, 2022
MailHog SMTP Protocol

MailHog SMTP Protocol github.com/mailhog/smtp implements an SMTP server state machine. It attempts to encapsulate as much of the SMTP protocol (plus i

Oct 27, 2022
Disposable webmail server (similar to Mailinator) with built in SMTP, POP3, RESTful servers; no DB required.
Disposable webmail server (similar to Mailinator) with built in SMTP, POP3, RESTful servers; no DB required.

Disposable webmail server (similar to Mailinator) with built in SMTP, POP3, RESTful servers; no DB required.

Jan 1, 2023
Simple SMTP Server for Testing

go-smtptester Simple SMTP Server for Testing. How it works All received mails are saved in a sync.Map with a key: From+Recipient1+Recipient2 Mails to

Nov 18, 2021
An easy way to send emails with attachments in Go

PROJECT DISCONTINUED This repository only exists for archival purposes. email An easy way to send emails with attachments in Go Install go get github.

Dec 12, 2022
Hxgomail - Gomail - a simple and efficient package to send emails

Gomail Introduction Gomail is a simple and efficient package to send emails. It

Jan 4, 2022
An email MIME artist for golang

Marcel is a tool to generate IETF compliant emails in raw MIME format. I mainly use this for generating emails with attachments and sending them via amazon SES. If that's what you're doing too, you may want notifications

Nov 7, 2022
EMail Searcher By Golang
EMail Searcher By Golang

GiveMeMail ▄████ ██▓ ██▒ ██▓ ▓██████ ███▄ ▄███▓▓██████ ███▄ ▄███▓ ██ ██▓ ██▓ ██▒ ▀█▒ ▓██▒ ▓██░ █▒ ▓█ ▀ ▓██▒▀█▀ ██▒▓█

Dec 4, 2021
An email service written in Golang
An email service written in Golang

furion An email service written in Go. Architecture Diagram

Dec 19, 2021
Email - Emailing with limitator for golang

email Emailing with optional limiter. It will send no more then limiterMax email

Jan 3, 2022