Skip to content
/ postal Public

A simple worker pool which makes sending email easy and efficient. Supports SMTP and MailGun.

License

Notifications You must be signed in to change notification settings

tsawler/postal

Repository files navigation

Built with GoLang Version License Go Report Card

Postal

Postal is a simple package which allows you to send email messages, either via an SMTP server or using MailGun's api. Postal implements a simple worker pool to make sending messages both easy and efficient. Postal uses standard Go templates (html/template).

Installation

Install it the usual way:

go get -u github.com/tsawler/postal

Usage

To create a worker pool to send email, first define a postal.Service object with settings appropriate for your environment. This is the postal.Service type:

// Service is the type used to create a MailDispatcher.
type Service struct {
    Method        int                           // How to send the message: postal.SMTP or postal.MailGun.
    ServerURL     string                        // The URL of the server mail is sent from.
    SMTPServer    string                        // The SMTP server.
    SMTPPort      int                           // The SMTP server's port.
    SMTPUser      string                        // The username for the SMTP server.
    SMTPPassword  string                        // The password for the SMTP server.
    ErrorChan     chan error                    // A channel to send errors (or nil) to.
    MaxWorkers    int                           // Maximum number of workers in the pool.
    MaxMessages   int                           // How big the buffer should be for the JobQueue.
    Domain        string                        // The domain used to send mail.
    APIKey        string                        // The API key for mailgun.
    SendingFromEU bool                          // If using mailgun and sending from EU, set to true.
    TemplateDir   string                        // Where templates are stored.
    templateMap   map[string]*template.Template // The map of preprocessed html templates.
}

Then, create a postal.MailDispatcher by calling postal.New with your postal.Service as the parameter:

dispatcher, _ := postal.Service(myService)

Create a mail message by defining a postal.MailData object. This is the type for postal.MailData:

// MailData holds all information for a given message.
type MailData struct {
	ToName       string         // The name of the recipient.
	ToAddress    string         // The email address of the recipient.
	FromName     string         // The name of the sender.
	FromAddress  string         // The email address of the sender.
	AdditionalTo []string       // Additional TO recipients.
	Subject      string         // The subject of the email message.
	Content      template.HTML  // The content of the message, as HTML.
	Template     string         // The template to use. If not specified, will use a simple default template.
	CC           []string       // A slice of CC recipient emails.
	BCC          []string       // A slice of BCC recipient emails.
	Attachments  []string       // A slice of attachments, which must exist on disk (i.e. []string{"./files/myfile.pdf"}).
	Data         map[string]any // Data which is to be passed to the Go template.
	InlineImages []string       // A slice of images to be inlined in the email. PNG is preferred.
	ServerURL    string         // The URL of the server (for backlinks in message).
}

Finally, to send the message, call the Send() method on your dispatcher. Errors will be sent back on the Service.ErrorChan, and nil will be sent back if the mail was queued successfully.

dispatcher.Send(msg)

// Wait for a response.
err := <-service.ErrorChan

An example of sending via SMTP:

package main

import (
	"fmt"
	"github.com/tsawler/postal"
)

func main() {
	// Define a postal.Service variable with values appropriate for your environment.
	service := postal.Service{
		Method:         postal.SMTP,       // Method to send. Options are postal.SMTP or postal.MailGun.
		ServerURL:     "http://localhost", // The URL of the server (for backlinks in mail).
		SMTPServer:    "localhost",        // The name of the SMTP server you are sending through.
		SMTPPort:      1025,               // The port the SMTP server listens on.
		SMTPUser:      "",                 // SMTP username.
		SMTPPassword:  "",                 // SMTP password.
		ErrorChan:     make(chan error),   // A channel to receive errors (or nil for success).
		MaxWorkers:    2,                  // Number of workers in our pool.
		MaxMessages:   10,                 // Buffer size for send channel.
		TemplateDir:   "./templates",      // The directory where mail templates live.
	}
	
	// Get a dispatcher by calling postal.New(service).
	dispatcher, _ := postal.New(service)

	// Run the worker pool.
	dispatcher.Run()

	// Create a mail message.
	msg := postal.MailData{
		ToName:      "Me",
		ToAddress:   "me@here.com",
		FromName:    "Jack",
		FromAddress: "jack@there.com",
		Subject:     "Test subject",
		Content:     "Hello, world!",
		CC:          []string{"you@here.com", "him@here.com"},
		//Template:    "my-template.gohtml", // You can specify your own template, or leave this out and use the default.
	}

	// Send the message by calling dispatcher.Send.
	fmt.Println("Sending mail")
	dispatcher.Send(msg)

	// Wait for something back from ErrorChan.
	fmt.Println("Waiting for response")
	err := <-service.ErrorChan
	fmt.Println("Error", err)
}

An example sending through MailGun's api:

package main

import (
	"fmt"
	"github.com/tsawler/postal"
)

func main() {
	
	// Define a postal.Service variable with values appropriate for your environment.
	service := postal.Service{
		Method:        postal.MailGun,     // Method to send. Options are postal.SMTP or postal.MailGun.
		ServerURL:    "http://localhost",  // The URL of your server, in case you want backlinks in your message.
		ErrorChan:     make(chan error),   // A channel to receive error messages (or nil for successful sends).
		MaxWorkers:    2,                  // The number of workers you want in the worker pool.
		MaxMessages:   10,                 // The size of the job queue (a buffered channel).
		SendingFromEU: false,              // Set to true if sending from European Union (mailgun only).
		TemplateDir:   "./templates",      // The directory where mail templates live.
		Domain:        "yourdomain.com",   // The domain you are sending from (mailgun only).
		APIKey:        "your-mailgun-api", // The mailgun api key (mailgun only).
	}
	
	// Call postal.New with your service to get a message dispatcher.
	dispatcher, _ := postal.New(service)

	// Run the worker pool associated with the dispatcher.
	dispatcher.Run()

	// Create a mail message, of postal.MailData type.
	msg := postal.MailData{
		ToName:        "Me",
		ToAddress:     "me@here.com",
		FromName:      "Jack",
		FromAddress:   "jack@there.com",
		Subject:       "Test subject",
		Content:       "Hello, world!",
		CC:            []string{"you@here.com", "him@here.com"},
	}

	// Send the message.
	fmt.Println("Sending mail")
	dispatcher.Send(msg)

	
	// Wait for a response.
	fmt.Println("Waiting for response")
	err := <-service.ErrorChan
	
	// If err is nil, then the message was sent.
	fmt.Println("Error", err)
}

About

A simple worker pool which makes sending email easy and efficient. Supports SMTP and MailGun.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages