Documentation

Go SDK

Go 1.19+
Go Modules

Send emails with Go using the official Laneful Go SDK. Built for modern Go applications with comprehensive features and type safety.

Full Feature Support

Templates, attachments, tracking, webhooks

Type Safe

Built-in validation & error handling

Modern Go

Go 1.19+ with context support

Prerequisites

To get the most out of this guide, you'll need:

  • • Go 1.19 or higher
  • • Go modules enabled
  • • A Laneful account with API key
  • • Verified domain for sending emails

Installation

Go Modules

Add the following dependency to your go.mod:

go get github.com/lanefulhq/laneful-go

Quick Start

Send your first email in minutes:

Send Simple Text Email

package main

import (
    "context"
    "log"

    "github.com/lanefulhq/laneful-go"
)

func main() {
    // Create client
    client := laneful.NewLanefulClient(
        "https://your-endpoint.send.laneful.net",
        "your-auth-token",
    )

    // Create email
    email := laneful.Email{
        From: laneful.Address{
            Email: "sender@example.com",
            Name:  "Your Name",
        },
        To: []laneful.Address{
            {Email: "recipient@example.com", Name: "Recipient Name"},
        },
        Subject:     "Hello from Laneful!",
        TextContent: "This is a simple test email sent using the Laneful Go SDK.",
    }

    // Send email
    resp, err := client.SendEmail(context.Background(), email)
    if err != nil {
        log.Fatal("Failed to send email:", err)
    }

    log.Printf("✓ Email sent successfully! Status: %s", resp.Status)
}

Examples

Common use cases and patterns:

HTML Email with Tracking

// Create tracking settings
tracking := &laneful.TrackingSettings{
    Opens:  true,
    Clicks: true,
}

email := laneful.Email{
    From: laneful.Address{
        Email: "sender@example.com",
        Name:  "Your Name",
    },
    To: []laneful.Address{
        {Email: "recipient@example.com", Name: "Recipient Name"},
    },
    Subject:     "HTML Email with Tracking",
    HTMLContent: "<h1>Welcome!</h1><p>This is an <strong>HTML email</strong> with tracking enabled.</p>",
    TextContent: "Welcome! This is an HTML email with tracking enabled.",
    Tracking:    tracking,
    Tag:         "welcome-email",
}

resp, err := client.SendEmail(context.Background(), email)

Template Email

email := laneful.Email{
    From: laneful.Address{Email: "sender@example.com"},
    To:   []laneful.Address{{Email: "user@example.com"}},
    TemplateID: "welcome-template",
    TemplateData: map[string]interface{}{
        "name":         "John Doe",
        "company":      "Acme Corporation",
        "activation_link": "https://example.com/activate",
    },
}

resp, err := client.SendEmail(context.Background(), email)

Email with Attachments

import (
    "encoding/base64"
    "io/ioutil"
)

// Read file and encode as base64
fileData, err := ioutil.ReadFile("/path/to/document.pdf")
if err != nil {
    log.Fatal(err)
}

email := laneful.Email{
    From: laneful.Address{Email: "sender@example.com"},
    To:   []laneful.Address{{Email: "user@example.com"}},
    Subject:     "Document Attached",
    TextContent: "Please find the document attached.",
    Attachments: []laneful.Attachment{
        {
            FileName:    "document.pdf",
            Content:     base64.StdEncoding.EncodeToString(fileData),
            ContentType: "application/pdf",
        },
    },
}

resp, err := client.SendEmail(context.Background(), email)

Multiple Recipients with Reply-To

email := laneful.Email{
    From: laneful.Address{
        Email: "sender@example.com",
        Name:  "Your Name",
    },
    To: []laneful.Address{
        {Email: "user1@example.com", Name: "User One"},
        {Email: "user2@example.com", Name: "User Two"},
    },
    CC: []laneful.Address{
        {Email: "cc@example.com", Name: "CC Recipient"},
    },
    BCC: []laneful.Address{
        {Email: "bcc@example.com", Name: "BCC Recipient"},
    },
    ReplyTo: &laneful.Address{
        Email: "reply@example.com",
        Name:  "Reply To",
    },
    Subject:     "Email to Multiple Recipients",
    TextContent: "This email is being sent to multiple recipients.",
}

resp, err := client.SendEmail(context.Background(), email)

Scheduled Email

import "time"

// Schedule for 24 hours from now
sendTime := time.Now().Add(24 * time.Hour).Unix()

email := laneful.Email{
    From:      laneful.Address{Email: "sender@example.com"},
    To:        []laneful.Address{{Email: "user@example.com"}},
    Subject:   "Scheduled Email",
    TextContent: "This email was scheduled.",
    SendTime:  sendTime,
}

resp, err := client.SendEmail(context.Background(), email)

Batch Email Sending

emails := []laneful.Email{
    {
        From:        laneful.Address{Email: "sender@example.com"},
        To:          []laneful.Address{{Email: "user1@example.com"}},
        Subject:     "Email 1",
        TextContent: "First email content.",
    },
    {
        From:        laneful.Address{Email: "sender@example.com"},
        To:          []laneful.Address{{Email: "user2@example.com"}},
        Subject:     "Email 2",
        TextContent: "Second email content.",
    },
}

resp, err := client.SendEmails(context.Background(), emails)

Webhook Handler Example

import (
    "encoding/json"
    "net/http"
    "github.com/lanefulhq/laneful-go"
)

// Complete webhook handler implementation
func handleWebhook(w http.ResponseWriter, r *http.Request) {
    // Read the request body
    body, err := ioutil.ReadAll(r.Body)
    if err != nil {
        http.Error(w, "Failed to read body", http.StatusBadRequest)
        return
    }
    
    // Extract signature from headers
    signature := r.Header.Get("x-webhook-signature")
    if signature == "" {
        http.Error(w, "Missing signature", http.StatusUnauthorized)
        return
    }
    
    // Verify signature
    if !laneful.VerifyWebhookSignature(webhookSecret, string(body), signature) {
        http.Error(w, "Invalid signature", http.StatusUnauthorized)
        return
    }
    
    // Parse webhook data
    var webhookData struct {
        Events []map[string]interface{} `json:"events"`
    }
    
    if err := json.Unmarshal(body, &webhookData); err != nil {
        http.Error(w, "Invalid JSON", http.StatusBadRequest)
        return
    }
    
    // Process events
    for _, event := range webhookData.Events {
        eventType, _ := event["event"].(string)
        email, _ := event["email"].(string)
        
        switch eventType {
        case "delivery":
            log.Printf("Email delivered to: %s", email)
        case "open":
            log.Printf("Email opened by: %s", email)
        case "click":
            if url, ok := event["url"].(string); ok {
                log.Printf("Link clicked by %s: %s", email, url)
            }
        case "bounce":
            if isHard, ok := event["is_hard"].(bool); ok {
                log.Printf("Email bounced (%s) for: %s", 
                    map[bool]string{true: "hard", false: "soft"}[isHard], email)
            }
        }
    }
    
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("Webhook processed successfully"))
}

API Reference

LanefulClient

Constructors

  • NewLanefulClient(baseURL, authToken string) *LanefulClient - Creates a new client with default timeout (30 seconds)

Methods

  • SendEmail(ctx context.Context, email Email) (*ApiResponse, error) - Send single email
  • SendEmails(ctx context.Context, emails []Email) (*ApiResponse, error) - Send multiple emails

Email Struct

Required Fields

  • From Address - Sender address

Optional Fields

  • To []Address - Recipient addresses
  • CC []Address - CC recipient addresses
  • BCC []Address - BCC recipient addresses
  • ReplyTo *Address - Reply-to address
  • Subject string - Email subject
  • TextContent string - Plain text content
  • HTMLContent string - HTML content
  • TemplateID string - Template ID
  • TemplateData map[string]interface - Template data
  • Attachments []Attachment - File attachments
  • SendTime int64 - Scheduled send time (Unix timestamp)
  • Tracking *TrackingSettings - Email tracking configuration
  • Tag string - Email tag for categorization
  • Headers map[string]string - Custom headers
  • WebhookData map[string]string - Webhook metadata

Utility Structs

  • Address{Email, Name string} - Email address with optional name
  • Attachment{FileName, Content, ContentType, InlineID string} - File attachment
  • TrackingSettings{Opens, Clicks, Unsubscribes bool, UnsubscribeGroupID *int64} - Email tracking configuration
  • ApiResponse{Status string} - API response structure

Webhook Functions

Signature Verification

  • VerifyWebhookSignature(secret, payload, signature string) bool - Verifies webhook signature using HMAC-SHA256

Error Handling

Comprehensive error handling with Go's standard error interface:

import (
    "context"
    "fmt"
    "log"
    "github.com/lanefulhq/laneful-go"
)

func sendEmailWithErrorHandling(client *laneful.LanefulClient, email laneful.Email) {
    resp, err := client.SendEmail(context.Background(), email)
    if err != nil {
        // Handle different types of errors
        switch {
        case strings.Contains(err.Error(), "validation"):
            log.Printf("✗ Validation error: %v", err)
            log.Println("Please check your email configuration")
        case strings.Contains(err.Error(), "API error"):
            log.Printf("✗ API error: %v", err)
            log.Println("Please check your API credentials and endpoint")
        case strings.Contains(err.Error(), "failed to send request"):
            log.Printf("✗ Network error: %v", err)
            log.Println("Please check your network connection and endpoint URL")
        default:
            log.Printf("✗ Unexpected error: %v", err)
        }
        return
    }

    log.Printf("✓ Email sent successfully! Status: %s", resp.Status)
}

Error Types

  • Validation errors - Invalid input data
  • API errors - API returns error response
    Check error message for details
  • Network errors - HTTP communication fails
    Check connection and endpoint URL
  • JSON errors - Response parsing fails

Best Practices

  • • Always check errors from API calls
  • • Use context for request cancellation
  • • Log errors with context information
  • • Implement retry logic for transient failures
  • • Use structured logging for better debugging

Webhook Handling

Secure webhook handling with signature verification:

Basic Signature Verification

import (
    "net/http"
    "github.com/lanefulhq/laneful-go"
)

func webhookHandler(w http.ResponseWriter, r *http.Request) {
    // Read the request body
    body, err := ioutil.ReadAll(r.Body)
    if err != nil {
        http.Error(w, "Failed to read body", http.StatusBadRequest)
        return
    }
    
    // Get signature from headers
    signature := r.Header.Get("x-webhook-signature")
    secret := "your-webhook-secret"
    
    // Verify signature
    if laneful.VerifyWebhookSignature(secret, string(body), signature) {
        // Process webhook data
        processWebhookData(body)
        w.WriteHeader(http.StatusOK)
    } else {
        http.Error(w, "Invalid signature", http.StatusUnauthorized)
    }
}

Advanced Webhook Processing

import (
    "encoding/json"
    "net/http"
    "github.com/lanefulhq/laneful-go"
)

type WebhookEvent struct {
    Event string                 `json:"event"`
    Email string                 `json:"email"`
    Data  map[string]interface{} `json:"data"`
}

type WebhookPayload struct {
    Events []WebhookEvent `json:"events"`
}

func advancedWebhookHandler(w http.ResponseWriter, r *http.Request) {
    // Step 1: Read raw payload
    body, err := ioutil.ReadAll(r.Body)
    if err != nil {
        http.Error(w, "Failed to read body", http.StatusBadRequest)
        return
    }
    
    // Step 2: Extract signature
    signature := r.Header.Get("x-webhook-signature")
    if signature == "" {
        http.Error(w, "Missing signature", http.StatusUnauthorized)
        return
    }
    
    // Step 3: Verify signature
    if !laneful.VerifyWebhookSignature(webhookSecret, string(body), signature) {
        http.Error(w, "Invalid signature", http.StatusUnauthorized)
        return
    }
    
    // Step 4: Parse payload
    var payload WebhookPayload
    if err := json.Unmarshal(body, &payload); err != nil {
        http.Error(w, "Invalid JSON", http.StatusBadRequest)
        return
    }
    
    // Step 5: Process events
    for _, event := range payload.Events {
        switch event.Event {
        case "delivery":
            handleDeliveryEvent(event)
        case "open":
            handleOpenEvent(event)
        case "click":
            handleClickEvent(event)
        case "bounce":
            handleBounceEvent(event)
        case "drop":
            handleDropEvent(event)
        case "spam_complaint":
            handleSpamComplaintEvent(event)
        case "unsubscribe":
            handleUnsubscribeEvent(event)
        }
    }
    
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("Webhook processed successfully"))
}

Supported Webhook Events

Delivery Events

  • delivery - Email delivered successfully
  • bounce - Email bounced (hard or soft)
  • drop - Email dropped (spam, invalid, etc.)
  • spam_complaint - Recipient marked email as spam

Engagement Events

  • open - Email opened by recipient
  • click - Link clicked in email
  • unsubscribe - Recipient unsubscribed

Webhook Features

Security

  • • HMAC-SHA256 signature verification
  • • Constant-time comparison (timing attack protection)
  • • Standard HTTP header support

Integration

  • • Works with any HTTP framework
  • • Context-aware request handling
  • • Easy error handling with Go idioms

Ready to Get Started?

Start sending emails with Go in minutes. Check out the examples and integrate with your application.