Go SDK

Idiomatic Go email client

The official Mailpipe Go SDK follows idiomatic Go conventions: context-aware requests, typed errors, and a clean interface that composes well with the standard library. It has zero required external dependencies beyond the standard library.

Installation

Fetch the module with go get:

terminal
go get github.com/mailpipe/mailpipe-go

Then import the package in your Go code:

main.go
import "github.com/mailpipe/mailpipe-go"

Requires Go 1.21 or later. The module uses only the Go standard library — no third-party dependencies.

Configuration

Create a client using functional options:

client.go
package main

import (
    "os"
    mailpipe "github.com/mailpipe/mailpipe-go"
)

func main() {
    // Basic client — reads MAILPIPE_API_KEY from environment by default
    client := mailpipe.NewClient(os.Getenv("MAILPIPE_API_KEY"))

    // Or pass options explicitly
    client := mailpipe.NewClient(
        os.Getenv("MAILPIPE_API_KEY"),
        mailpipe.WithBaseURL("https://api.mailpipe.dev/v1"),
        mailpipe.WithTimeout(30 * time.Second),
        mailpipe.WithMaxRetries(3),
        mailpipe.WithHTTPClient(myCustomHTTPClient),
    )
}

For long-lived services, create a single client at startup and share it across goroutines. The client is safe for concurrent use:

app.go
package app

import (
    "os"
    mailpipe "github.com/mailpipe/mailpipe-go"
)

// Shared client — initialize once
var Mail = mailpipe.NewClient(os.Getenv("MAILPIPE_API_KEY"))

Send Email

Send a transactional email. All methods accept a context.Context as their first argument:

send.go
package main

import (
    "context"
    "fmt"
    "log"
    "os"

    mailpipe "github.com/mailpipe/mailpipe-go"
)

func main() {
    client := mailpipe.NewClient(os.Getenv("MAILPIPE_API_KEY"))
    ctx := context.Background()

    msg, err := client.Messages.Send(ctx, mailpipe.SendEmailParams{
        From:    "noreply@yourdomain.com",
        To:      []string{"user@example.com"},
        Subject: "Welcome to our platform!",
        HTML:    "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
        Text:    "Welcome! Thanks for signing up.",
    })
    if err != nil {
        log.Fatalf("send failed: %v", err)
    }

    fmt.Printf("Sent: %s
", msg.ID)
}

Send with CC, BCC, and a named sender:

send_advanced.go
msg, err := client.Messages.Send(ctx, mailpipe.SendEmailParams{
    From: mailpipe.Address{
        Email: "invoices@acme.com",
        Name:  "Acme Billing",
    },
    To:      []string{"customer@example.com"},
    CC:      []string{"accountant@acme.com"},
    BCC:     []string{"archive@acme.com"},
    ReplyTo: "billing@acme.com",
    Subject: "Your invoice #INV-2024-001",
    HTML:    invoiceHTML,
    Text:    invoiceText,
    Headers: map[string]string{
        "X-Invoice-Id": "INV-2024-001",
    },
    Tags: []string{"invoice", "billing"},
})
if err != nil {
    return fmt.Errorf("send invoice: %w", err)
}

List Mailboxes

Retrieve all mailboxes and list messages with filtering:

mailboxes.go
// List all mailboxes
resp, err := client.Mailboxes.List(ctx, nil)
if err != nil {
    return err
}

for _, mb := range resp.Data {
    fmt.Printf("%s — %d unread
", mb.Email, mb.UnreadCount)
}

// List unread messages in a specific mailbox
msgs, err := client.Messages.List(ctx, &mailpipe.ListMessagesParams{
    MailboxID: "mbx_01hx7k3abc",
    Unread:    mailpipe.Bool(true),
    Limit:     25,
})
if err != nil {
    return err
}

fmt.Printf("Found %d unread messages (total: %d)
",
    len(msgs.Data), msgs.Meta.Total)

for _, msg := range msgs.Data {
    fmt.Printf("  [%s] %s
", msg.ReceivedAt.Format(time.RFC3339), msg.Subject)
}

Error Handling

The SDK returns typed errors that implement the standard error interface. Use errors.As to inspect specific error types:

errors.go
import (
    "errors"
    mailpipe "github.com/mailpipe/mailpipe-go"
)

_, err := client.Messages.Send(ctx, params)
if err != nil {
    var apiErr *mailpipe.APIError
    var rateLimitErr *mailpipe.RateLimitError
    var authErr *mailpipe.AuthenticationError

    switch {
    case errors.As(err, &rateLimitErr):
        fmt.Printf("Rate limited — retry after %ds
", rateLimitErr.RetryAfter)
    case errors.As(err, &authErr):
        fmt.Println("Invalid API key — check MAILPIPE_API_KEY")
    case errors.As(err, &apiErr):
        fmt.Printf("API error %d: %s (request: %s)
",
            apiErr.StatusCode, apiErr.Message, apiErr.RequestID)
    default:
        return fmt.Errorf("unexpected error: %w", err)
    }
}

Context and Timeouts

All SDK methods respect context cancellation and deadlines, enabling precise timeout and cancellation control across your application:

context.go
// Per-request timeout using context
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

msg, err := client.Messages.Send(ctx, params)
if err != nil {
    if errors.Is(err, context.DeadlineExceeded) {
        log.Println("Request timed out after 5s")
    }
    return err
}

Propagate cancellation from HTTP request handlers — the SDK will abort the in-flight API call when the client disconnects:

http_handler.go
func SendWelcomeHandler(w http.ResponseWriter, r *http.Request) {
    // r.Context() is cancelled when the HTTP client disconnects
    ctx := r.Context()

    _, err := app.Mail.Messages.Send(ctx, mailpipe.SendEmailParams{
        From:    "welcome@acme.com",
        To:      []string{r.FormValue("email")},
        Subject: "Welcome!",
        HTML:    welcomeHTML,
    })
    if err != nil {
        if errors.Is(err, context.Canceled) {
            // Client disconnected — no need to respond
            return
        }
        http.Error(w, "Failed to send email", http.StatusInternalServerError)
        return
    }

    w.WriteHeader(http.StatusCreated)
    json.NewEncoder(w).Encode(map[string]string{"status": "sent"})
}

For background jobs and workers, use a base context with global timeout:

worker.go
func processEmailQueue(client *mailpipe.Client, queue []SendJob) error {
    // Give the entire batch 2 minutes
    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
    defer cancel()

    g, ctx := errgroup.WithContext(ctx)

    for _, job := range queue {
        job := job // capture loop var
        g.Go(func() error {
            _, err := client.Messages.Send(ctx, job.Params)
            return err
        })
    }

    return g.Wait()
}

API Reference

Explore the full REST API documentation with all available endpoints.

View API Reference

Webhooks

Receive real-time email events with webhook signature verification.

Webhook Guide

Need Help?

Our team is here to help. Reach out if you have any questions.

Contact Support