sendamatic

package module
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 19, 2025 License: MIT Imports: 10 Imported by: 0

README

Sendamatic Go Client

Mirror on GitHub Go Reference Go Report Card

A Go client library for the Sendamatic email delivery API.

Features

  • Simple and idiomatic Go API
  • Context support for timeouts and cancellation
  • Fluent message builder interface
  • Support for HTML and plain text emails
  • File attachments with automatic base64 encoding
  • Custom headers
  • Multiple recipients (To, CC, BCC)
  • Comprehensive error handling

Installation

go get code.beautifulmachines.dev/jakoubek/sendamatic

Quick Start

package main

import (
    "context"
    "log"

    "code.beautifulmachines.dev/jakoubek/sendamatic"
)

func main() {
    // Create client
    client := sendamatic.NewClient("your-user-id", "your-password")

    // Build message
    msg := sendamatic.NewMessage().
        SetSender("[email protected]").
        AddTo("[email protected]").
        SetSubject("Hello from Sendamatic").
        SetTextBody("This is a test message.").
        SetHTMLBody("<h1>Hello!</h1><p>This is a test message.</p>")

    // Send email
    resp, err := client.Send(context.Background(), msg)
    if err != nil {
        log.Fatal(err)
    }

    log.Printf("Email sent successfully: %d", resp.StatusCode)
}

Usage Examples

Basic Email
msg := sendamatic.NewMessage().
    SetSender("[email protected]").
    AddTo("[email protected]").
    SetSubject("Hello World").
    SetTextBody("This is a plain text email.")

resp, err := client.Send(context.Background(), msg)
HTML Email with Multiple Recipients
msg := sendamatic.NewMessage().
    SetSender("[email protected]").
    AddTo("[email protected]").
    AddTo("[email protected]").
    AddCC("[email protected]").
    AddBCC("[email protected]").
    SetSubject("Monthly Newsletter").
    SetHTMLBody("<h1>Newsletter</h1><p>Your monthly update...</p>").
    SetTextBody("Newsletter - Your monthly update...")
Email with Attachments
// From file path
msg := sendamatic.NewMessage().
    SetSender("[email protected]").
    AddTo("[email protected]").
    SetSubject("Invoice").
    SetTextBody("Please find your invoice attached.")

err := msg.AttachFileFromPath("./invoice.pdf", "application/pdf")
if err != nil {
    log.Fatal(err)
}

// Or from byte slice
pdfData := []byte{...}
msg.AttachFile("invoice.pdf", "application/pdf", pdfData)
Custom Headers
msg := sendamatic.NewMessage().
    SetSender("[email protected]").
    AddTo("[email protected]").
    SetSubject("Custom Headers").
    SetTextBody("Email with custom headers").
    AddHeader("Reply-To", "[email protected]").
    AddHeader("X-Priority", "1")
With Timeout
client := sendamatic.NewClient(
    "user-id",
    "password",
    sendamatic.WithTimeout(45*time.Second),
)

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

resp, err := client.Send(ctx, msg)
Custom HTTP Client
httpClient := &http.Client{
    Timeout: 60 * time.Second,
    Transport: &http.Transport{
        MaxIdleConns: 10,
    },
}

client := sendamatic.NewClient(
    "user-id",
    "password",
    sendamatic.WithHTTPClient(httpClient),
)

Configuration Options

The client supports various configuration options via the functional options pattern:

client := sendamatic.NewClient(
    "user-id",
    "password",
    sendamatic.WithBaseURL("https://custom.api.url"),
    sendamatic.WithTimeout(60*time.Second),
    sendamatic.WithHTTPClient(customHTTPClient),
)

Response Handling

The SendResponse provides methods to check the delivery status:

resp, err := client.Send(ctx, msg)
if err != nil {
    log.Fatal(err)
}

// Check overall success
if resp.IsSuccess() {
    log.Println("Email sent successfully")
}

// Check individual recipient status
for email := range resp.Recipients {
    if status, ok := resp.GetStatus(email); ok {
        log.Printf("Recipient %s: status %d", email, status)
    }
    if msgID, ok := resp.GetMessageID(email); ok {
        log.Printf("Message ID: %s", msgID)
    }
}

Error Handling

The library provides typed errors for better error handling:

resp, err := client.Send(ctx, msg)
if err != nil {
    var apiErr *sendamatic.APIError
    if errors.As(err, &apiErr) {
        log.Printf("API error (status %d): %s", apiErr.StatusCode, apiErr.Message)
        if apiErr.ValidationErrors != "" {
            log.Printf("Validation: %s", apiErr.ValidationErrors)
        }
    } else {
        log.Printf("Other error: %v", err)
    }
}

Requirements

  • Go 1.22 or higher
  • Valid Sendamatic account with API credentials

API Credentials

Your API credentials consist of:

  • User ID: Your Mail Credential User ID
  • Password: Your Mail Credential Password

Find these in your Sendamatic dashboard under Mail Credentials.

Documentation

For detailed API documentation, visit:

License

MIT License - see LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

Author

Oliver Jakoubek ([email protected])

Documentation

Overview

Package sendamatic provides a Go client library for the Sendamatic email delivery API.

The library offers a simple and idiomatic Go API with context support, a fluent message builder interface, and comprehensive error handling for sending transactional emails.

Example usage:

client := sendamatic.NewClient("your-user-id", "your-password")
msg := sendamatic.NewMessage().
	SetSender("[email protected]").
	AddTo("[email protected]").
	SetSubject("Hello").
	SetTextBody("Hello World")
resp, err := client.Send(context.Background(), msg)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type APIError

type APIError struct {
	StatusCode       int    `json:"-"`
	Message          string `json:"error"`
	ValidationErrors string `json:"validation_errors,omitempty"`
	JSONPath         string `json:"json_path,omitempty"`
	Sender           string `json:"sender,omitempty"`
	SMTPCode         int    `json:"smtp_code,omitempty"`
}

APIError represents an error response from the Sendamatic API. It includes the HTTP status code, error message, and optional additional context such as validation errors, JSON path information, and SMTP codes.

func (*APIError) Error

func (e *APIError) Error() string

Error implements the error interface and returns a formatted error message. If validation errors are present, they are included with the JSON path context.

type Attachment

type Attachment struct {
	Filename string `json:"filename"`
	Data     string `json:"data"` // Base64-encoded file content
	MimeType string `json:"mimetype"`
}

Attachment represents an email attachment with its filename, MIME type, and base64-encoded data.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client represents a Sendamatic API client that handles authentication and HTTP communication with the Sendamatic email delivery service.

func NewClient

func NewClient(userID, password string, opts ...Option) *Client

NewClient creates and returns a new Client configured with the provided Sendamatic credentials. The userID and password are combined to form the API key used for authentication. Optional configuration functions can be provided to customize the client behavior.

Example:

client := sendamatic.NewClient("user-id", "password",
	sendamatic.WithTimeout(60*time.Second))

func (*Client) Send

func (c *Client) Send(ctx context.Context, msg *Message) (*SendResponse, error)

Send sends an email message through the Sendamatic API using the provided context. The message is validated before sending. If validation fails or the API request fails, an error is returned. On success, a SendResponse containing per-recipient delivery information is returned.

The context can be used to set deadlines, timeouts, or cancel the request.

type Header struct {
	Header string `json:"header"`
	Value  string `json:"value"`
}

Header represents a custom email header as a name-value pair.

type Message

type Message struct {
	To          []string     `json:"to"`
	CC          []string     `json:"cc,omitempty"`
	BCC         []string     `json:"bcc,omitempty"`
	Sender      string       `json:"sender"`
	Subject     string       `json:"subject"`
	TextBody    string       `json:"text_body,omitempty"`
	HTMLBody    string       `json:"html_body,omitempty"`
	Headers     []Header     `json:"headers,omitempty"`
	Attachments []Attachment `json:"attachments,omitempty"`
}

Message represents an email message with all its components including recipients, content, headers, and attachments. Messages are constructed using the fluent builder pattern provided by the setter methods.

func NewMessage

func NewMessage() *Message

NewMessage creates and returns a new empty Message with initialized slices for recipients, headers, and attachments. Use the setter methods to populate the message fields.

func (*Message) AddBCC

func (m *Message) AddBCC(email string) *Message

AddBCC adds a recipient email address to the BCC (blind carbon copy) field. Returns the message for method chaining.

func (*Message) AddCC

func (m *Message) AddCC(email string) *Message

AddCC adds a recipient email address to the CC (carbon copy) field. Returns the message for method chaining.

func (*Message) AddHeader

func (m *Message) AddHeader(name, value string) *Message

AddHeader adds a custom email header with the specified name and value. Common examples include "Reply-To", "X-Priority", or custom application headers. Returns the message for method chaining.

func (*Message) AddTo

func (m *Message) AddTo(email string) *Message

AddTo adds a recipient email address to the To field. Returns the message for method chaining.

func (*Message) AttachFile

func (m *Message) AttachFile(filename, mimeType string, data []byte) *Message

AttachFile adds a file attachment to the message from a byte slice. The data is automatically base64-encoded for transmission. Returns the message for method chaining.

func (*Message) AttachFileFromPath

func (m *Message) AttachFileFromPath(path, mimeType string) error

AttachFileFromPath reads a file from the filesystem and adds it as an attachment. The filename is extracted from the path. Returns an error if the file cannot be read. The file data is automatically base64-encoded for transmission.

func (*Message) SetHTMLBody

func (m *Message) SetHTMLBody(body string) *Message

SetHTMLBody sets the HTML body of the email. Returns the message for method chaining.

func (*Message) SetSender

func (m *Message) SetSender(email string) *Message

SetSender sets the sender email address for the message. Returns the message for method chaining.

func (*Message) SetSubject

func (m *Message) SetSubject(subject string) *Message

SetSubject sets the email subject line. Returns the message for method chaining.

func (*Message) SetTextBody

func (m *Message) SetTextBody(body string) *Message

SetTextBody sets the plain text body of the email. Returns the message for method chaining.

func (*Message) Validate

func (m *Message) Validate() error

Validate checks whether the message meets all required criteria for sending. It returns an error if any validation rules are violated:

  • At least one recipient is required
  • Maximum of 255 recipients allowed
  • Sender must be specified
  • Subject must be specified
  • Either TextBody or HTMLBody (or both) must be provided

type Option

type Option func(*Client)

Option is a function type that modifies a Client during initialization. Options follow the functional options pattern for configuring client behavior.

func WithBaseURL

func WithBaseURL(baseURL string) Option

WithBaseURL returns an Option that sets a custom API base URL for the client. Use this to point to a different Sendamatic API endpoint or a testing environment.

Example:

client := sendamatic.NewClient("user", "pass",
	sendamatic.WithBaseURL("https://custom.api.url"))

func WithHTTPClient

func WithHTTPClient(client *http.Client) Option

WithHTTPClient returns an Option that replaces the default HTTP client with a custom one. This allows full control over HTTP behavior such as transport settings, connection pooling, and custom middleware.

Example:

customClient := &http.Client{
	Timeout: 60 * time.Second,
	Transport: customTransport,
}
client := sendamatic.NewClient("user", "pass",
	sendamatic.WithHTTPClient(customClient))

func WithTimeout

func WithTimeout(timeout time.Duration) Option

WithTimeout returns an Option that sets the HTTP client timeout duration. This determines how long the client will wait for a response before timing out. The default timeout is 30 seconds.

Example:

client := sendamatic.NewClient("user", "pass",
	sendamatic.WithTimeout(60*time.Second))

type SendResponse

type SendResponse struct {
	StatusCode int
	Recipients map[string][2]interface{} // Email address -> [status code, message ID]
}

SendResponse represents the response from a send email request. It contains the overall HTTP status code and per-recipient delivery information including individual status codes and message IDs.

func (*SendResponse) GetMessageID

func (r *SendResponse) GetMessageID(email string) (string, bool)

GetMessageID returns the message ID for a specific recipient email address. The message ID can be used to track the email in logs or with the email provider. Returns the message ID and true if found, or empty string and false if not found.

func (*SendResponse) GetStatus

func (r *SendResponse) GetStatus(email string) (int, bool)

GetStatus returns the delivery status code for a specific recipient email address. The status code indicates whether the email was accepted for delivery to that recipient. Returns the status code and true if found, or 0 and false if not found.

Note: The API returns status codes as JSON numbers which are decoded as float64, so this method performs the necessary type conversion to int.

func (*SendResponse) IsSuccess

func (r *SendResponse) IsSuccess() bool

IsSuccess returns true if the email send request was successful (HTTP 200). Note that this checks the overall request status; individual recipients may still have failed. Use GetStatus to check per-recipient delivery status.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL