Skip to main content
This guide covers the fundamental operations for sending emails with the Resend Go SDK.

Initialize the Client

First, create a Resend client with your API key:
import (
	"context"
	"os"

	"github.com/resend/resend-go/v3"
)

func main() {
	ctx := context.TODO()
	apiKey := os.Getenv("RESEND_API_KEY")

	client := resend.NewClient(apiKey)
}

Send a Basic Email

The simplest way to send an email:
params := &resend.SendEmailRequest{
	To:      []string{"[email protected]"},
	From:    "[email protected]",
	Text:    "hello world",
	Subject: "Hello from Golang",
}

sent, err := client.Emails.SendWithContext(ctx, params)
if err != nil {
	panic(err)
}
fmt.Printf("Sent email: %s\n", sent.Id)

Email with HTML Content

Send rich HTML emails:
params := &resend.SendEmailRequest{
	To:      []string{"[email protected]"},
	From:    "[email protected]",
	Html:    "<strong>Welcome to our service!</strong>",
	Text:    "Welcome to our service!",
	Subject: "Welcome",
}

sent, err := client.Emails.SendWithContext(ctx, params)
if err != nil {
	panic(err)
}
Providing both Html and Text ensures your email renders properly in all email clients.

Advanced Recipients

Add CC, BCC, and ReplyTo addresses:
params := &resend.SendEmailRequest{
	To:      []string{"[email protected]"},
	From:    "[email protected]",
	Text:    "hello world",
	Subject: "Hello from Golang",
	Cc:      []string{"[email protected]"},
	Bcc:     []string{"[email protected]"},
}

sent, err := client.Emails.SendWithContext(ctx, params)

Send with Idempotency Key

Prevent duplicate emails by using an idempotency key:
params := &resend.SendEmailRequest{
	To:      []string{"[email protected]"},
	From:    "[email protected]",
	Text:    "hello world",
	Subject: "Hello from Golang",
}

options := &resend.SendEmailOptions{
	IdempotencyKey: "unique-idempotency-key",
}

sent, err := client.Emails.SendWithOptions(ctx, params, options)
if err != nil {
	panic(err)
}
fmt.Printf("Sent email with idempotency key: %s\n", sent.Id)
If you send the same request with the same idempotency key within 24 hours, Resend will return the original response instead of sending a duplicate email.

Send with Attachments

Attach files from local paths or remote URLs:
import "os"

// Read attachment file
pwd, _ := os.Getwd()
fileContent, err := os.ReadFile(pwd + "/invoice.pdf")
if err != nil {
	panic(err)
}

attachment := &resend.Attachment{
	Content:     fileContent,
	Filename:    "invoice.pdf",
	ContentType: "application/pdf",
}

params := &resend.SendEmailRequest{
	To:          []string{"[email protected]"},
	From:        "[email protected]",
	Text:        "Please find your invoice attached",
	Subject:     "Your Invoice",
	Attachments: []*resend.Attachment{attachment},
}

sent, err := client.Emails.SendWithContext(ctx, params)

Retrieve Email Details

Get information about a sent email:
// Get email by ID
email, err := client.Emails.GetWithContext(ctx, sent.Id)
if err != nil {
	panic(err)
}

fmt.Printf("Email ID: %s\n", email.Id)
fmt.Printf("Subject: %s\n", email.Subject)
fmt.Printf("To: %v\n", email.To)
fmt.Printf("From: %s\n", email.From)

List Sent Emails

Retrieve a list of sent emails with pagination:
listResp, err := client.Emails.ListWithContext(ctx)
if err != nil {
	panic(err)
}

fmt.Printf("Found %d emails\n", len(listResp.Data))
fmt.Printf("Has more emails: %v\n", listResp.HasMore)

for _, email := range listResp.Data {
	fmt.Printf("ID: %s, Subject: %s, To: %v\n",
		email.Id, email.Subject, email.To)
}

Manage Attachments

List and retrieve email attachments:
// List all attachments for an email
attachments, err := client.Emails.ListAttachmentsWithContext(ctx, emailId)
if err != nil {
	panic(err)
}

fmt.Printf("Found %d attachments\n", len(attachments.Data))
for _, att := range attachments.Data {
	fmt.Printf("- ID: %s, Filename: %s, ContentType: %s\n",
		att.Id, att.Filename, att.ContentType)
}

// Get a specific attachment
if len(attachments.Data) > 0 {
	attachmentId := attachments.Data[0].Id
	attachment, err := client.Emails.GetAttachment(emailId, attachmentId)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Retrieved: %s (%s)\n", attachment.Filename, attachment.ContentType)
}

Complete Example

Here’s a complete example from examples/send_email.go:
examples/send_email.go
package main

import (
	"context"
	"fmt"
	"os"

	"github.com/resend/resend-go/v3"
)

func main() {
	ctx := context.TODO()
	apiKey := os.Getenv("RESEND_API_KEY")

	client := resend.NewClient(apiKey)

	// Send params
	params := &resend.SendEmailRequest{
		To:      []string{"[email protected]"},
		From:    "[email protected]",
		Text:    "hello world",
		Subject: "Hello from Golang",
		Cc:      []string{"[email protected]"},
		Bcc:     []string{"[email protected]"},
		ReplyTo: "[email protected]",
	}

	sent, err := client.Emails.SendWithContext(ctx, params)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Sent email: %s\n", sent.Id)

	// Get email details
	email, err := client.Emails.GetWithContext(ctx, sent.Id)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Email details: %+v\n", email)
}

Next Steps

Templates

Use email templates with dynamic variables

Error Handling

Handle rate limits and validation errors

Custom Client

Configure HTTP client with custom timeouts and retry logic

API Reference

View complete API documentation

Build docs developers (and LLMs) love