Guide

How to send email with Go

Send email from Go with net/http and the REST API.

In short

Create a Sendpository account, verify your domain, put your API key in SENDPOSITORY_API_KEY, and send with the code below - one HTTPS request per email, from server-side code only.

1. Verify your sending domain

Add your domain in the dashboard and publish the three DNS records it shows - SPF and a bounce record on an sp. subdomain, and a DKIM key on your apex. Your existing records are never edited. Verification usually lands in a few minutes, and you can set up the code below while you wait.

2. Create a key

Create an API key with the sending permission. It is shown once, so put it straight into your secrets. Read the key with os.Getenv("SENDPOSITORY_API_KEY").

3. Send an email

Go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"time"
)

func main() {
	body, _ := json.Marshal(map[string]any{
		"from":    "Your App <hello@mail.yourdomain.com>",
		"to":      []string{"customer@example.com"},
		"subject": "Your receipt",
		"html":    "<p>Thanks for your order.</p>",
	})
	req, _ := http.NewRequest("POST", "https://api.sendpository.com/v1/emails", bytes.NewReader(body))
	req.Header.Set("Authorization", "Bearer "+os.Getenv("SENDPOSITORY_API_KEY"))
	req.Header.Set("Content-Type", "application/json")

	res, err := (&http.Client{Timeout: 10 * time.Second}).Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	var out map[string]any
	json.NewDecoder(res.Body).Decode(&out)
	fmt.Println(res.StatusCode, out)
}

A success returns { "id": "..." } - the message’s id for looking it up later. A failure returns { "error": { "type", "message" } } with a 4xx or 5xx status.

Context and goroutines

Pass the request's `context.Context` into the call so a cancelled request cancels the send with it. A goroutine started with `context.Background()` outlives the request and keeps running after the client has gone.

If the caller should not wait, start a goroutine with a fresh context carrying its own timeout - never the request context, which is cancelled the moment the handler returns.

Testing it

Things to know

Questions

Which context should I pass?

The request's context if the caller is waiting, so a cancelled request cancels the send too. If you are sending in the background, start a fresh context with its own timeout - the request context is cancelled the moment the handler returns, which would kill the send.

How do I send email with Go?

Verify your sending domain, create an API key, put it in an environment variable, and POST the message as JSON to https://api.sendpository.com/v1/emails from server-side Go code. The example on this page runs as written once the domain is verified.

Can I send email with Go without SMTP?

Yes. This is plain HTTPS, so Go needs no mail library and no SMTP port - which matters on hosts that block outbound 25 and 587. Failures come back as a status code on the call instead of as a bounce message hours later.

More guides

Send your first email in minutes

6,000 emails a month (up to 200 a day), free forever. No card needed.