goat

package module
v1.2.2 Latest Latest
Warning

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

Go to latest
Published: Jun 30, 2026 License: MIT Imports: 13 Imported by: 0

README

PkgGoDev Go Version Go Report Card GitHub License

GitHub Release GitHub Actions Workflow Status codecov

go-at

Go library for streamlining email delivery with templating capabilities.

go-at is an email delivery library designed to make sending emails from Go applications effortless. It combines email delivery capabilities with a robust templating system, allowing you to create beautiful, responsive emails with ease.

Features
  • Easy integration: Minimal setup with sensible defaults
  • Email delivery: Send emails via SendGrid or Brevo with an extensible interface for other providers
  • Templating: Create dynamic content using Go's template syntax
  • Styling: Add styles through your template definitions
  • Attachments: Attach files such as PDFs or calendar invites, including inline images

Installation

go get github.com/Zapharaos/go-at

Note: Goat uses Go Modules to manage dependencies.

Usage Examples

Note : This example Sendgrid credential is for demonstration purposes only. Please replace it with your own Sendgrid API key and email address.

package main

import (
    "log"
    "github.com/Zapharaos/go-at"
)

func main() {
    // 1. Set up SendGrid service
    service := goat.NewSendgridService(
        "your-sendgrid-api-key",
        "Your Company",
        "no-reply@yourcompany.com",
    )
    restore := goat.SetSenderService(service)
    defer restore()

    // 2. Create a simple template
    template := goat.Template{
        Name:       "welcome",
        ContentRaw: "Hello {{.Name}}! Welcome to {{.Company}}.",
        Data: map[string]string{
            "Name":    "John Doe",
            "Company": "Acme Corp",
        },
    }

    // 3. Render the template
    content, err := template.Render()
    if err != nil {
        log.Fatal(err)
    }

    // 4. Send the email
	err = goat.Send(goat.NewEmailMessage(
		"user@example.com",
		"Welcome to Acme Corp!",
		content, // plain text
		content, // HTML (same as plain text in this simple example)
    ))
    if err != nil {
        log.Fatal(err)
    }
}

For comprehensive usage examples including template variables, pluralization, and fallback behavior, see the examples package.

Attachments

Attach files by passing their raw bytes — go-at base64-encodes them for the provider. Use WithAttachment for standard files (PDF, .ics, etc.) and WithInlineAttachment to embed an image referenced from the HTML body via cid:<contentID>:

pdf, _ := os.ReadFile("invoice.pdf")
logo, _ := os.ReadFile("logo.png")

msg := goat.NewEmailMessage(
    "user@example.com",
    "Your invoice",
    "Please find your invoice attached.",            // plain text
    `<p>Invoice attached</p><img src="cid:logo">`,   // HTML referencing the inline image
).
    WithAttachment("invoice.pdf", "application/pdf", pdf).
    WithInlineAttachment("logo.png", "image/png", logo, "logo")

err := goat.Send(msg)

Note: Inline embedding and explicit MIME types are fully supported on SendGrid. Brevo (brevo-go v1.1.3) infers the MIME type from the filename and has no Content-ID field, so an inline attachment is delivered as a regular attachment.

Using Brevo instead of SendGrid

go-at also ships with a Brevo implementation of the sender interface. Swap the service creation for NewBrevoService and the rest of the API stays the same:

service := goat.NewBrevoService(
    "your-brevo-api-key",
    "Your Company",
    "no-reply@yourcompany.com",
)
restore := goat.SetSenderService(service)
defer restore()

Development

Install dependencies:

make dev-deps

Run unit tests and generate coverage report:

make test-unit

Run linters:

make lint

Some linter violations can automatically be fixed:

make fmt

Contributing

We welcome contributions to the go-at library! If you have a bug fix, feature request, or improvement, please open an issue or pull request on GitHub. We appreciate your help in making go-at better for everyone. If you are interested in contributing to the go-at library, please check out our contributing guidelines for more information on how to get started.

License

The project is licensed under the MIT License.

Documentation

Overview

Package goat provides email delivery with templating capabilities.

go-at simplifies sending emails from Go applications with built-in templating and support for multiple delivery providers (SendGrid and Brevo).

Basic usage:

service := goat.NewSendgridService("api-key", "Your Name", "you@company.com")
restore := goat.SetSenderService(service)
defer restore()

template := goat.Template{
	Name:       "welcome",
	ContentRaw: "Hello {{.Name}}!",
	Data:       map[string]string{"Name": "John"},
}
content, _ := template.Render()
err := goat.Send("user@example.com", "Welcome", content, content)

To use Brevo instead of SendGrid, create the service with NewBrevoService:

service := goat.NewBrevoService("api-key", "Your Name", "you@company.com")

Attach files (e.g. a PDF or calendar invite) with WithAttachment, or embed an image inline via WithInlineAttachment and reference it from HTML as cid:<ContentID>:

pdf, _ := os.ReadFile("invoice.pdf")
msg := goat.NewEmailMessage("user@example.com", "Your invoice", content, content).
	WithAttachment("invoice.pdf", "application/pdf", pdf)
err := goat.Send(msg)

For more details, see README.md.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsEmailValid

func IsEmailValid(email string) bool

func Send

func Send(message *EmailMessage) error

Send directly exposes the current sender service Send function.

func SetSenderService

func SetSenderService(service SenderService) func()

SetSenderService affect a new repository to the global service singleton

Types

type Attachment added in v1.2.1

type Attachment struct {
	Filename    string
	ContentType string // MIME type, e.g. "application/pdf", "text/calendar"
	Content     []byte // raw bytes (not base64)
	ContentID   string // optional; when set, the attachment is inline
}

Attachment represents a file attached to an email. Content holds the raw (un-encoded) bytes; the library base64-encodes it per provider. Set ContentID to embed the attachment inline (referenced from HTML as cid:<ContentID>). Note: Brevo (brevo-go v1.1.3) ignores ContentType and ContentID — it infers the MIME type from Filename and cannot embed inline; such attachments are sent as regular attachments.

type BrevoClient added in v1.1.0

type BrevoClient interface {
	SendTransacEmail(ctx context.Context, sendSmtpEmail brevo.SendSmtpEmail) (brevo.CreateSmtpEmail, *http.Response, error)
}

BrevoClient is an interface for sending emails

type BrevoService added in v1.1.0

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

BrevoService implements the SenderService interface using Brevo

func (*BrevoService) Send added in v1.1.0

func (s *BrevoService) Send(message *EmailMessage) error

Send sends an email using Brevo.

It returns only an error and is kept for backward compatibility; use SendWithResult when you need the message ID returned by Brevo.

func (*BrevoService) SendWithResult added in v1.2.2

func (s *BrevoService) SendWithResult(message *EmailMessage) (SendResult, error)

SendWithResult sends an email using Brevo and returns the message ID from the API response.

The returned SendResult.MessageID is the raw value of the response messageId field, kept verbatim including the surrounding chevrons (e.g. "<xxx@smtp-relay.mailin.fr>"). Brevo webhooks echo this same value in their message-id field, so it is the join key used to track delivery status.

type EmailMessage added in v1.2.0

type EmailMessage struct {
	To               string
	Subject          string
	PlainTextContent string
	HTMLContent      string
	ReplyTo          *ReplyTo
	Headers          map[string]string
	Attachments      []Attachment
}

EmailMessage represents an email to be sent. Build one with NewEmailMessage and chain With* methods for optional fields.

func NewEmailMessage added in v1.2.0

func NewEmailMessage(to, subject, plainTextContent, htmlContent string) *EmailMessage

NewEmailMessage creates a new EmailMessage with the required fields.

func (*EmailMessage) WithAttachment added in v1.2.1

func (m *EmailMessage) WithAttachment(filename, contentType string, content []byte) *EmailMessage

WithAttachment adds a standard file attachment and returns the message for chaining.

func (*EmailMessage) WithAttachments added in v1.2.1

func (m *EmailMessage) WithAttachments(attachments ...Attachment) *EmailMessage

WithAttachments appends pre-built attachments and returns the message for chaining.

func (*EmailMessage) WithHeader added in v1.2.0

func (m *EmailMessage) WithHeader(key, value string) *EmailMessage

WithHeader adds a single custom header and returns the message for chaining.

func (*EmailMessage) WithHeaders added in v1.2.0

func (m *EmailMessage) WithHeaders(headers map[string]string) *EmailMessage

WithHeaders sets all custom headers at once and returns the message for chaining.

func (*EmailMessage) WithInlineAttachment added in v1.2.1

func (m *EmailMessage) WithInlineAttachment(filename, contentType string, content []byte, contentID string) *EmailMessage

WithInlineAttachment adds an inline attachment referenced from HTML as cid:<contentID> and returns the message for chaining.

func (*EmailMessage) WithReplyTo added in v1.2.0

func (m *EmailMessage) WithReplyTo(name, address string) *EmailMessage

WithReplyTo sets the reply-to address and returns the message for chaining.

type ReplyTo added in v1.0.1

type ReplyTo struct {
	Name    string
	Address string
}

ReplyTo holds the reply-to name and address for an email.

type SendResult added in v1.2.2

type SendResult struct {
	// MessageID is the provider message identifier, kept verbatim
	// (e.g. Brevo returns it wrapped in chevrons: "<xxx@smtp-relay.mailin.fr>").
	MessageID string
}

SendResult holds metadata returned by a provider after sending an email.

func SendWithResult added in v1.2.2

func SendWithResult(message *EmailMessage) (SendResult, error)

SendWithResult directly exposes the current sender service SendWithResult function.

type SenderService

type SenderService interface {
	Send(message *EmailMessage) error
	SendWithResult(message *EmailMessage) (SendResult, error)
}

SenderService defines the interface for handling emails

func GetSenderService

func GetSenderService() SenderService

GetSenderService is used to access the global service singleton

func NewBrevoService added in v1.1.0

func NewBrevoService(apiKey, senderName, senderEmail string) SenderService

NewBrevoService returns a new instance of BrevoService

func NewSendgridService

func NewSendgridService(apiKey, senderName, senderEmail string) SenderService

NewSendgridService returns a new instance of SendgridService

type SendgridClient

type SendgridClient interface {
	Send(email *mail.SGMailV3) (*rest.Response, error)
	SendWithContext(ctx context.Context, email *mail.SGMailV3) (*rest.Response, error)
}

SendgridClient is an interface for sending emails

type SendgridService

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

SendgridService implements the SenderService interface using SendGrid

func (*SendgridService) Send

func (s *SendgridService) Send(message *EmailMessage) error

Send sends an email using SendGrid.

It returns only an error and is kept for backward compatibility; use SendWithResult when you need the message ID returned by SendGrid.

func (*SendgridService) SendWithResult added in v1.2.2

func (s *SendgridService) SendWithResult(message *EmailMessage) (SendResult, error)

SendWithResult sends an email using SendGrid and returns the message ID from the response.

SendGrid returns the message ID in the X-Message-Id response header rather than the body; the returned SendResult.MessageID holds that value (empty if the header is absent).

type Template

type Template struct {
	Name       string      // Name of the template
	ContentRaw string      // Raw HTML content with potential template variables
	Data       interface{} // Data containing the template variables values
}

Template represents an email template

func (Template) Render

func (t Template) Render() (string, error)

Render renders a template with the given data

Directories

Path Synopsis