mailfold

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 4, 2026 License: MIT Imports: 10 Imported by: 0

README

mailfold-go

Official Go client SDK for Mailfold, a self-hosted webmail/admin backend. This package wraps Mailfold's per-mailbox REST API (send/read/search/delete mail, manage flags, fetch attachments) using only the Go standard library — zero third-party runtime dependencies.

This is the official client SDK for the main project: https://github.com/isi1988/Mailfold

Install

go get github.com/isi1988/mailfold-go

Quickstart

package main

import (
	"errors"
	"fmt"
	"log"

	mailfold "github.com/isi1988/mailfold-go"
)

func main() {
	client := mailfold.New("https://your-mailfold-instance.example", "mf_live_...")

	// Send a message.
	if _, err := client.Send(mailfold.SendRequest{
		To:      []string{"friend@example.com"},
		Subject: "Hello from mailfold-go",
		Text:    "This was sent via the Mailfold API.",
	}); err != nil {
		log.Fatal(err)
	}

	// List folders.
	folders, err := client.Folders()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(folders)

	// List recent message headers.
	headers, err := client.Messages(mailfold.MessagesOptions{Folder: "INBOX", Limit: 10})
	if err != nil {
		log.Fatal(err)
	}

	uid := int(headers[0].UID)

	// Fetch a full message.
	msg, err := client.Message("INBOX", uid)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(msg.Subject, msg.Text)

	// Search a folder.
	results, err := client.Search("INBOX", "invoice")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(len(results), "matches")

	// Download an attachment's raw bytes.
	if len(msg.Attachments) > 0 {
		att, err := client.Attachment("INBOX", uid, 0)
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(att.Filename, len(att.Data), "bytes")
	}

	// Flag a message as seen.
	if err := client.SetFlag(mailfold.SetFlagRequest{
		Folder: "INBOX",
		UID:    uid,
		Flag:   mailfold.FlagSeen,
		Set:    true,
	}); err != nil {
		log.Fatal(err)
	}

	// Delete a message.
	if err := client.DeleteMessage("INBOX", uid); err != nil {
		var apiErr *mailfold.APIError
		if errors.As(err, &apiErr) {
			fmt.Println("status:", apiErr.StatusCode, "message:", apiErr.Message)
			if apiErr.HasRetryAfter {
				fmt.Println("retry after:", apiErr.RetryAfter, "seconds")
			}
			return
		}
		log.Fatal(err)
	}
}

A complete runnable version of this example lives in example/main.go.

Authentication

Every request is authenticated with a per-mailbox API key sent as Authorization: Bearer <token>. Tokens look like mf_live_<kid>_<secret> — treat them as opaque strings; never parse them.

Errors

Non-2xx responses are returned as *mailfold.APIError, which exposes:

  • StatusCode — the HTTP status code
  • Message — the server's {"error": "..."} message
  • RetryAfter / HasRetryAfter — populated from the Retry-After header on 429 responses

License

MIT — see LICENSE.

Documentation

Overview

Package mailfold is the official Go client SDK for Mailfold (https://github.com/isi1988/Mailfold), a self-hosted webmail/admin backend. It wraps Mailfold's per-mailbox REST API using only the standard library (net/http, encoding/json) — no third-party dependencies.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type APIError

type APIError struct {
	StatusCode    int
	Message       string
	RetryAfter    int
	HasRetryAfter bool
}

APIError is returned whenever the Mailfold server responds with a non-2xx status code. It exposes the HTTP status, the server's error message, and (when the server set the header, typically on 429) the Retry-After value in seconds.

func (*APIError) Error

func (e *APIError) Error() string

type Address

type Address struct {
	Name  string `json:"name"`
	Email string `json:"email"`
}

Address is a single email participant (name may be empty).

type Attachment

type Attachment struct {
	Filename    string `json:"filename"`
	ContentType string `json:"content_type"`
	Size        int    `json:"size"`
}

Attachment describes metadata about a message attachment (not its bytes; use Client.Attachment to fetch the bytes).

type AttachmentData

type AttachmentData struct {
	Data        []byte
	ContentType string
	Filename    string
}

AttachmentData is the raw bytes of an attachment plus whatever metadata the server exposed via response headers.

The attachment endpoint returns the file's raw bytes directly (not JSON), so this is a plain struct assembled from the HTTP response rather than an unmarshaled body.

type Client

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

Client is a Mailfold API client bound to a single base URL and API key. Construct one with New and reuse it; it is safe for concurrent use.

func New

func New(baseURL, apiKey string) *Client

New creates a Client for the given Mailfold instance base URL (e.g. "https://real.mailfold.site" or a self-hosted URL) and API key (a "mf_live_..." bearer token). The token is sent verbatim and is never parsed or validated client-side.

func (*Client) Attachment

func (c *Client) Attachment(folder string, uid int, index int) (*AttachmentData, error)

Attachment downloads a single attachment's raw bytes by folder, message UID, and attachment index. Requires the mail:read scope.

Unlike every other endpoint, this one returns raw binary bytes rather than a JSON envelope, so it is handled outside of Client.do.

func (*Client) DeleteMessage

func (c *Client) DeleteMessage(folder string, uid int) error

DeleteMessage deletes (or marks \Deleted, per server semantics) the message at folder/uid. Requires the mail:write scope.

func (*Client) Folders

func (c *Client) Folders() ([]Folder, error)

Folders lists the mailbox's IMAP folders. Requires the mail:read scope.

func (*Client) Message

func (c *Client) Message(folder string, uid int) (*Message, error)

Message fetches a single full message (body + attachment metadata) by folder and UID. Requires the mail:read scope.

func (*Client) Messages

func (c *Client) Messages(opts MessagesOptions) ([]MessageHeader, error)

Messages lists message headers in a folder, newest first. Requires the mail:read scope.

func (*Client) Search

func (c *Client) Search(folder, q string) ([]MessageHeader, error)

Search searches a folder for messages matching q. Requires the mail:read scope.

func (*Client) Send

func (c *Client) Send(req SendRequest) (*SendResponse, error)

Send sends an email from the mailbox the API key is bound to. Requires the mail:send scope.

func (*Client) SetFlag

func (c *Client) SetFlag(req SetFlagRequest) error

SetFlag sets or clears a single IMAP flag on a message. Requires the mail:write scope.

func (*Client) WithHTTPClient

func (c *Client) WithHTTPClient(hc *http.Client) *Client

WithHTTPClient overrides the underlying *http.Client (e.g. to set a custom timeout or transport). Returns the same Client for chaining.

type Flag

type Flag string

Flag is one of the flag names accepted by Client.SetFlag.

const (
	FlagSeen     Flag = "seen"
	FlagFlagged  Flag = "flagged"
	FlagAnswered Flag = "answered"
	FlagDeleted  Flag = "deleted"
	FlagDraft    Flag = "draft"
)

type Folder

type Folder struct {
	Name       string   `json:"name"`
	Attributes []string `json:"attributes"`
}

Folder describes a single IMAP mailbox folder.

type Message

type Message struct {
	MessageHeader
	Text        string       `json:"text"`
	HTML        string       `json:"html"`
	Attachments []Attachment `json:"attachments"`
}

Message is the full message body, as returned by GET .../mail/message.

type MessageHeader

type MessageHeader struct {
	UID     uint32    `json:"uid"`
	Subject string    `json:"subject"`
	From    []Address `json:"from"`
	To      []Address `json:"to"`
	Date    string    `json:"date"`
	Flags   []string  `json:"flags"`
	Seen    bool      `json:"seen"`
	Size    uint32    `json:"size"`
	Preview string    `json:"preview"`
}

MessageHeader is a summary of a message, as returned by the listing and search endpoints.

type MessagesOptions

type MessagesOptions struct {
	Folder string
	Limit  int
}

MessagesOptions configures Client.Messages. Zero values mean "use the server default" (folder defaults to INBOX, limit defaults to 50).

type SendRequest

type SendRequest struct {
	To      []string `json:"to,omitempty"`
	Cc      []string `json:"cc,omitempty"`
	Bcc     []string `json:"bcc,omitempty"`
	Subject string   `json:"subject,omitempty"`
	Text    string   `json:"text,omitempty"`
	HTML    string   `json:"html,omitempty"`
}

SendRequest is the payload for Client.Send. From is not included: the server always forces the From address to the mailbox the API key is bound to.

type SendResponse

type SendResponse struct {
	Status string `json:"status"`
}

SendResponse is returned by POST /api/v1/mail/send.

type SetFlagRequest

type SetFlagRequest struct {
	Folder string `json:"folder"`
	UID    int    `json:"uid"`
	Flag   Flag   `json:"flag"`
	Set    bool   `json:"set"`
}

SetFlagRequest is the payload for Client.SetFlag.

type StatusResponse

type StatusResponse struct {
	Status string `json:"status"`
}

StatusResponse is the generic {"status": "..."} response body returned by the delete and flag endpoints.

Directories

Path Synopsis
Command example demonstrates every method of the mailfold client.
Command example demonstrates every method of the mailfold client.

Jump to

Keyboard shortcuts

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