Transactional Email

Sending Email with the Go SDK

Install the official Go module and queue a transactional email from a verified workspace sender.

The official github.com/LeadPush/leadpush-go module provides a standard-library-only, context-aware client for the Leadpush API. Use this guide when a Go service, worker, or application needs to send password resets, verification codes, receipts, account alerts, or other application-triggered email.

Before you start

Make sure you have:

  • Go 1.25 or newer
  • a Leadpush API key for the correct workspace
  • a verified sending domain and sender address
  • workspace delivery set to Normal when you are ready to deliver real email

Create and copy an API key from Workspace Settings → Developer Keys. The Email API uses this bearer API key, not an SMTP username and password. See API Keys for the complete dashboard workflow.

Install the SDK

Add the released v1.0.0 module to your Go project:

Go modules
go get github.com/LeadPush/leadpush-go@v1.0.0

The SDK uses only the Go standard library. Package documentation is available on pkg.go.dev.

Configure the API key

Store the key in an environment variable or secret manager. Never commit it to source control or expose it in browser code.

Example .env
LEADPUSH_API_KEY=your_workspace_api_key

Send a transactional email

Every network operation accepts context.Context as its first argument. The example below sets a 30-second SDK request timeout and a longer caller deadline, sends both HTML and plain-text bodies, and prints each tracked message UUID.

send_email.go
package main

import (
    "context"
    "errors"
    "fmt"
    "log"
    "os"
    "time"

    leadpush "github.com/LeadPush/leadpush-go"
)

func main() {
    client, err := leadpush.New(
        os.Getenv("LEADPUSH_API_KEY"),
        leadpush.WithTimeout(30*time.Second),
    )
    if err != nil {
        log.Fatal(err)
    }

    ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
    defer cancel()

    send, err := client.Emails.Send(ctx, leadpush.SendEmailParams{
        From:    "alerts@example.com",
        To:      []string{"customer@example.com"},
        Subject: "Your verification code",
        HTML:    leadpush.Ptr("<p>Your code is 482910</p>"),
        Text:    leadpush.Ptr("Your code is 482910"),
        ReplyTo: leadpush.Ptr("support@example.com"),
        Headers: map[string]string{
            "X-Correlation-ID": "verification-482910",
        },
    })
    if err != nil {
        handleError(err)
        return
    }

    fmt.Println("accepted:", send.Accepted)
    fmt.Println("messages:", send.MessageCount)
    for _, message := range send.Messages {
        fmt.Println(message.Recipient, message.UUID)
    }
}

func handleError(err error) {
    switch {
    case leadpush.IsUnauthorized(err):
        log.Println("Check LEADPUSH_API_KEY.")
    case leadpush.IsForbidden(err):
        log.Println("The API key cannot access this workspace resource.")
    case leadpush.IsValidation(err):
        log.Println("Review the sender, recipients, subject, and message body.")
    case leadpush.IsNotFound(err):
        log.Println("The requested Leadpush resource was not found.")
    }

    var apiError *leadpush.APIError
    if errors.As(err, &apiError) {
        log.Printf("Leadpush API status %d: %v", apiError.StatusCode, apiError.Payload)
    }

    var timeoutError *leadpush.TimeoutError
    if errors.As(err, &timeoutError) {
        log.Printf("Leadpush request timed out: %v", timeoutError)
    }

    if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
        log.Printf("Caller context ended: %v", err)
    }
}

Replace alerts@example.com with a verified sender from the API key's workspace. Provide HTML, Text, or both, and include at least one recipient across To and BCC.

Understand contexts and timeouts

Use a request context to connect Leadpush calls to an incoming HTTP request, worker job, shutdown signal, or application deadline.

  • leadpush.WithTimeout controls the SDK-owned request timeout. When it expires, the SDK returns *leadpush.TimeoutError.
  • A canceled caller context remains context.Canceled.
  • A caller deadline remains context.DeadlineExceeded.
  • Transport errors unrelated to a deadline are returned unchanged.

The SDK does not retry requests automatically in v1. Add application-level retries only where the operation and your idempotency strategy make them safe.

Understand the response

A successful send request means Leadpush accepted and queued the message; it does not guarantee final delivery.

  • Accepted confirms that the request was accepted.
  • MessageCount reports how many unique recipient messages were created.
  • Messages contains the tracked message UUID and status for each recipient.

Store the returned UUIDs when your application needs to connect a send with delivery troubleshooting or support activity. See the Send Email API reference for request fields, recipient normalization, response data, and queue behavior.

Troubleshooting

Explore this topic

Continue exploring this topic

Connect this guide to relevant product capabilities, implementation details, and practical email workflows.