mail

package module
v0.0.0-...-fe48e8a Latest Latest
Warning

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

Go to latest
Published: Jul 17, 2026 License: BSD-3-Clause Imports: 18 Imported by: 0

README

go-ruby-mail/mail

mail — go-ruby-mail

Docs License Go Coverage

A pure-Go (no cgo) reimplementation of Ruby's mail gem — the RFC 5322 / MIME message parser and generator. It builds and reads email messages: header fold/unfold, structured address fields, RFC 2047 encoded-words, and RFC 2045 MIME (multipart, boundaries, nested parts, attachments, and base64 / quoted-printable transfer encodings) — without any Ruby runtime.

It is the message backend for go-embedded-ruby, but is a standalone, reusable module — a sibling of go-ruby-yaml and go-ruby-regexp.

Parsing, generating and delivery. Parsing and generating the on-the-wire form of a message (RFC 5322 grammar, MIME structure, transfer encodings) is fully deterministic and needs no interpreter, so it lives here as pure Go. Delivery and retrieval — sending over SMTP/sendmail and fetching over POP3/IMAP — are implemented here too, in pure Go, mirroring the gem's delivery and retriever methods. Every transport reaches its server through an injectable dialer seam, so the package stays CGO-free and is driven in tests by in-process SMTP/POP3/IMAP servers — never a real mail server.

Features

Faithful port of the gem's parse + generate, validated against the mail gem on every supported platform:

  • RFC 5322 headers — fold/unfold of continuation lines, ordered multi-valued fields, and the standard fields From / To / Cc / Bcc / Reply-To / Subject / Date / Message-ID / In-Reply-To / References / MIME-Version / Content-Type / Content-Transfer-Encoding / Content-Disposition / Content-ID.
  • Structured addresses — display-name / angle-addr / bare addr-spec / parenthesised comments / RFC 5322 group syntax, with quoted and RFC 2047 encoded display names (Mail::Address, Mail::AddressList).
  • RFC 2047 encoded-words=?charset?B?…?= and ?Q?…?= decode (UTF-8, US-ASCII, ISO-8859-1) and encode, with the §6.2 adjacent-word whitespace fold.
  • RFC 2045 MIMEmultipart/{mixed,alternative,related} with boundaries and nested parts, .parts, .attachments (filename from Content-Disposition or Content-Type; name=, content-id), and body decode of base64 / quoted-printable / 7bit / 8bit.
  • GenerateEncoded() / String() re-emit the message, RFC 2047 encoding non-ASCII unstructured fields and folding long headers at 78 columns.
  • Delivery — the gem's delivery methods: SMTP (STARTTLS / implicit TLS, PLAIN / LOGIN / CRAM-MD5 auth), Sendmail, TestDelivery, FileDelivery and LoggerDelivery, plus the SMTP envelope (Return-Path / Sender / From sender, To+Cc+Bcc recipients, Bcc stripped from the transmitted message).
  • Retrieval — POP3 and IMAP retrievers (Find / First / Last / All with the gem's what/order/count selection; IMAP mailbox select/search/fetch), both pure-Go clients over an injectable dialer seam.

CGO-free, dependency-free, 100% test coverage, gofmt + go vet clean, and green across the six 64-bit Go targets (amd64, arm64, riscv64, loong64, ppc64le, s390x).

Install

go get github.com/go-ruby-mail/mail

Usage

package main

import (
	"fmt"

	"github.com/go-ruby-mail/mail"
)

func main() {
	// Parse a raw message (Mail.new).
	m := mail.New("From: John <john@example.com>\r\n" +
		"To: a@x.com, b@y.com\r\n" +
		"Subject: =?utf-8?B?SGVsbG8=?=\r\n\r\n" +
		"Body text\r\n")

	fmt.Println(m.From())               // [john@example.com]
	fmt.Println(m.To())                 // [a@x.com b@y.com]
	fmt.Println(m.Subject())            // Hello   (encoded-word decoded)
	fmt.Println(m.Body().DecodedString())

	// Build a message (Mail.new { … }).
	out := mail.New("", func(m *mail.Message) {
		m.SetFrom("me@here.com").
			SetTo("you@there.com").
			SetSubject("Héllo").      // RFC 2047 encoded on emit
			SetBody("Hello body")
	})
	fmt.Print(out.Encoded())
}

API

func New(raw string, builders ...func(*Message)) *Message // Mail.new / Mail.new { … }
func Read(path string) (*Message, error)                  // Mail.read

// Accessors (gem-faithful)
func (m *Message) From/To/Cc/Bcc/ReplyTo() []string
func (m *Message) Subject() string
func (m *Message) MessageID/InReplyTo() string
func (m *Message) References() []string
func (m *Message) Date() (time.Time, bool)
func (m *Message) Body() *Body
func (m *Message) Multipart() bool
func (m *Message) Parts() []*Part
func (m *Message) Attachments() []*Part
func (m *Message) TextPart/HTMLPart() *Part
func (m *Message) ContentType/MimeType/Charset() string
func (m *Message) Header() *Header

// MIME part / attachment
func (m *Message) Filename/ContentID/ContentDisposition() string
func (m *Message) IsAttachment() bool
func (m *Message) Decoded() []byte

// Generate
func (m *Message) Encoded() string // == String() ; Mail#encoded / #to_s

// Structured types
type Address struct { DisplayName, Local, Domain string; Comments []string }
func NewAddress(s string) *Address
func NewAddressList(s string) *AddressList
type Body struct { Raw, Encoding string }
type Field struct { Name, Value string }
type Header struct { /* ordered fields + case-insensitive lookup */ }
type Part = Message

// Delivery (Mail.defaults { delivery_method … } / message.deliver)
func Defaults(fn func(*Config))                     // configure delivery + retriever
func (m *Message) Deliver() error                   // via the configured method
func (m *Message) DeliverWith(d DeliveryMethod) error
type DeliveryMethod interface { Deliver(m *Message) error }
type SMTP struct { Address, Port, Domain, UserName, Password, Authentication,
    OpenSSLVerifyMode string; EnableStartTLSAuto, SSL, TLS bool; Dial Dialer; … }
type Sendmail struct { Location string; Arguments []string; Run … }
type TestDelivery struct{ … }   // records deliveries, like Mail::TestMailer
type FileDelivery struct{ Location, Extension string }
type LoggerDelivery struct{ Logger Logger }
type Dialer func(network, address string) (net.Conn, error) // the transport seam

// Retrieval (retriever_method :pop3 / :imap ; Mail.find/first/last/all)
func Find(opts FindOptions) ([]*Message, error)
func First() (*Message, error); func Last() (*Message, error); func All() ([]*Message, error)
type RetrieverMethod interface { Find(opts FindOptions) ([]*Message, error) }
type POP3 struct { Address, UserName, Password string; Port int; EnableSSL bool; Dial Dialer; … }
type IMAP struct { Address, UserName, Password string; Port int; EnableSSL, EnableStartTLS bool; Dial Dialer; … }

Sending and retrieving

// Configure a delivery method, then deliver (Mail.defaults + message.deliver).
mail.Defaults(func(c *mail.Config) {
    c.SetDeliveryMethod(&mail.SMTP{
        Address: "smtp.example.com", Port: 587,
        UserName: "me", Password: "secret", Authentication: "plain",
        EnableStartTLSAuto: true,
    })
})
msg := mail.New("", func(m *mail.Message) {
    m.SetFrom("me@example.com").SetTo("you@example.com").
        SetSubject("Hi").SetBody("Hello")
})
_ = msg.Deliver()

// Retrieve over POP3 or IMAP (Mail.find/first/all).
mail.Defaults(func(c *mail.Config) {
    c.SetRetrieverMethod(&mail.IMAP{
        Address: "imap.example.com", Port: 993, EnableSSL: true,
        UserName: "me", Password: "secret",
    })
})
inbox, _ := mail.All()

Tests & coverage

The suite pairs deterministic, ruby-free tests (which alone hold coverage at 100%, so the qemu cross-arch and Windows lanes pass the gate) with a differential mail-gem oracle (version-gated to Ruby ≥ 4.0): a corpus of folded-header / encoded-word / address-group / multipart / attachment messages is parsed here and in the gem and the accessors compared, and a message built here is re-parsed by the gem. The oracle scripts $stdout.binmode so Windows text-mode never pollutes the bytes, and skip themselves where ruby / the gem is absent.

Delivery and retrieval are driven by in-process fake SMTP / POP3 / IMAP servers reached through the injectable dialer seam — no real mail server is contacted — and the delivery path is additionally differential-tested against the gem: the same message is delivered to an in-process SMTP sink from both the gem and this package, and the envelope and DATA put on the wire are compared.

COVERPKG=$(go list ./... | paste -sd, -)
go test -race -coverpkg="$COVERPKG" -coverprofile=cover.out ./...
go tool cover -func=cover.out | tail -1   # 100.0%

Deferred RFC edge cases

Documented honestly for future work; none affect the corpus above:

  • RFC 2231 continued/extended parameters (name*0*=…, charset-tagged parameter values) are not yet decoded — plain and quoted filename= / name= are.
  • Charsets beyond UTF-8 / US-ASCII / ISO-8859-1 in encoded-words are passed through byte-for-byte rather than transcoded (no data loss).

License

BSD-3-Clause — see LICENSE. Copyright the go-ruby-mail/mail authors.

WebAssembly

Being pure Go (CGO=0), this library also compiles to WebAssembly — both GOOS=js GOARCH=wasm (browser / Node.js) and GOOS=wasip1 GOARCH=wasm (WASI). CI builds both targets on every push, alongside the six 64-bit native/qemu arches.

GOOS=js     GOARCH=wasm go build ./...   # browser / Node
GOOS=wasip1 GOARCH=wasm go build ./...   # WASI (wasmtime, wasmer, wasmedge, …)

Documentation

Overview

Delivery — sending a Message over a transport — mirroring the Ruby `mail` gem's delivery methods (Mail.defaults { delivery_method … } + message.deliver).

Every transport is modelled behind an injectable seam: SMTP dials through a Dialer (defaulting to net.Dial), sendmail runs through a swappable runner, and the file/logger sinks go through overridable openers. This keeps the code pure-Go (CGO-free) yet fully drivable by in-process fake servers in tests — no real mail server is ever contacted.

Package mail is a pure-Go (CGO-free) reimplementation of Ruby's `mail` gem — the RFC 5322 / MIME message parser and generator. It builds and reads email messages: header fold/unfold, structured address fields, RFC 2047 encoded-words, RFC 2045 MIME (multipart, boundaries, nested parts, attachments, and base64 / quoted-printable transfer encodings) — all without any Ruby runtime.

API shape

New parses a raw message (or, given a builder function, constructs one); Read reads a message from a file. The resulting Message exposes the gem-faithful accessors From/To/Cc/Bcc/ReplyTo/Subject/Body/Date/MessageID and the MIME view Parts/Attachments/Multipart/ContentType, plus Message.Encoded / Message.String to serialise it back.

Delivery and retrieval

Sending and fetching are implemented here too, mirroring the gem's delivery and retriever methods: configure them with Defaults and send with Message.Deliver, or fetch with Find / First / Last / All. The delivery methods are SMTP (net/smtp, with STARTTLS/implicit-TLS and PLAIN/ LOGIN/CRAM-MD5 auth), Sendmail, TestDelivery, FileDelivery and LoggerDelivery; the retrievers are POP3 and IMAP, both pure-Go clients. Every transport reaches its server through an injectable Dialer seam, so it stays CGO-free and fully testable against in-process servers.

Retrieval — fetching messages from a mailbox — mirroring the Ruby `mail` gem's retriever methods (Mail.defaults { retriever_method … } + Mail.find/first/ last/all). Two transports are implemented in pure Go: POP3 and IMAP, each dialing through the same injectable Dialer seam so an in-process fake server can drive the exchange in tests.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Defaults

func Defaults(fn func(*Config))

Defaults configures the process-wide delivery/retriever methods, mirroring Mail.defaults do … end. The block receives a Config to set the methods on.

Types

type Address

type Address struct {
	// DisplayName is the phrase before the angle-addr (unquoted), or "" when the
	// address is a bare addr-spec.
	DisplayName string
	// Local is the local-part (before "@").
	Local string
	// Domain is the domain (after "@"), or "" for an addr with no domain.
	Domain string
	// Comments holds any parenthesised comments found in the mailbox.
	Comments []string
	// contains filtered or unexported fields
}

Address is a single RFC 5322 mailbox, mirroring Ruby's Mail::Address. It is parsed from a mailbox token such as `John Doe <john@example.com>`, `john@example.com (Johnny)`, or a bare `john@example.com`.

func NewAddress

func NewAddress(s string) *Address

NewAddress parses a single mailbox token into an Address, mirroring Mail::Address.new. Surrounding whitespace is ignored.

func (*Address) Address

func (a *Address) Address() string

Address returns the addr-spec ("local@domain", or just "local" when there is no domain), matching Mail::Address#address.

func (*Address) Format

func (a *Address) Format() string

Format renders the address for a header: `Display Name <addr>` when a display name is present (quoting it if needed), else the bare addr-spec. Mirrors Mail::Address#format / #to_s.

func (*Address) String

func (a *Address) String() string

String implements fmt.Stringer as Format.

type AddressList

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

AddressList is an ordered collection of addresses parsed from an address field (To/Cc/…), mirroring Mail::AddressList. Group syntax (`name: a@x, b@x;`) is flattened: the members appear in Addresses tagged with their group name.

func NewAddressList

func NewAddressList(s string) *AddressList

NewAddressList parses a comma-separated address field, honouring RFC 5322 group syntax and quoted display names, into an AddressList.

func (*AddressList) Addresses

func (al *AddressList) Addresses() []*Address

Addresses returns the parsed addresses in order.

type Body

type Body struct {
	Raw      string
	Encoding string
}

Body holds a message or part body, mirroring Mail::Body. Raw is the body exactly as it appeared on the wire (still transfer-encoded); Encoding names the Content-Transfer-Encoding used to decode it.

func (*Body) Decoded

func (b *Body) Decoded() []byte

Decoded returns the body decoded according to its Content-Transfer-Encoding, matching Mail::Body#decoded. Unknown or identity encodings (7bit/8bit/binary) return the raw bytes unchanged.

func (*Body) DecodedString

func (b *Body) DecodedString() string

DecodedString is Decoded as a string, for convenience.

func (*Body) Encode

func (b *Body) Encode(encoding string) string

Encode returns b's decoded content re-encoded for the named Content-Transfer-Encoding (base64 / quoted-printable / identity), the form a host uses when serialising a body it built from decoded bytes. Mirrors Mail::Body#encoded.

type Config

type Config struct{}

Config is the receiver of a Defaults block, mirroring the object yielded by Ruby's Mail.defaults. Set the process-wide delivery and retriever methods on it.

func (*Config) SetDeliveryMethod

func (c *Config) SetDeliveryMethod(d DeliveryMethod)

SetDeliveryMethod installs d as the process-wide delivery method used by Message.Deliver, mirroring `delivery_method :smtp, …`.

func (*Config) SetRetrieverMethod

func (c *Config) SetRetrieverMethod(r RetrieverMethod)

SetRetrieverMethod installs r as the process-wide retriever used by Find / First / Last / All, mirroring `retriever_method :pop3, …`.

type DeliveryMethod

type DeliveryMethod interface {
	// Deliver sends m, returning any transport or validation error.
	Deliver(m *Message) error
}

DeliveryMethod is a transport that sends a Message, mirroring the gem's delivery-method objects (each responds to deliver!). Implementations: SMTP, Sendmail, TestDelivery, FileDelivery and LoggerDelivery.

type Dialer

type Dialer func(network, address string) (net.Conn, error)

Dialer establishes a transport connection to address (host:port), mirroring the signature of net.Dial. It is the seam through which every socket-opening delivery/retrieval method reaches its server; tests inject a Dialer that returns one end of an in-process net.Pipe so a fake server can drive the exchange without any real network.

type Field

type Field struct {
	Name  string // canonical field name, e.g. "Subject"
	Value string // unfolded raw value (whitespace-collapsed continuation)
}

Field is a single header field (a name and its unfolded value), mirroring the role of Mail::Field. The stored Value is already unfolded but not yet encoded-word decoded; Decoded returns the human-readable form.

func (*Field) Decoded

func (f *Field) Decoded() string

Decoded returns the field value with RFC 2047 encoded-words decoded, matching Mail::Field#decoded for unstructured fields.

func (*Field) String

func (f *Field) String() string

String returns "Name: Value" without folding, for debugging.

type FileDelivery

type FileDelivery struct {
	// Location is the output directory (default "./mails").
	Location string
	// Extension is appended to each recipient-derived filename.
	Extension string
}

FileDelivery writes the message to one file per unique recipient under Location, appending if the file exists, mirroring Mail::FileDelivery.

func (*FileDelivery) Deliver

func (f *FileDelivery) Deliver(m *Message) error

Deliver writes m into Location, one file per unique recipient.

type FindOptions

type FindOptions struct {
	// What is "first" or "last" (default "first").
	What string
	// Order is "asc" or "desc" (default "asc").
	Order string
	// Count caps how many messages are returned (default 10); ignored when All.
	Count int
	// All returns every message, mirroring Mail.all / count => :all.
	All bool
	// DeleteAfterFind deletes each retrieved message from the server.
	DeleteAfterFind bool
	// Mailbox is the IMAP mailbox to open (default "INBOX"). Ignored by POP3.
	Mailbox string
	// Keys are the IMAP SEARCH criteria (default ["ALL"]). Ignored by POP3.
	Keys []string
	// ReadOnly opens the IMAP mailbox with EXAMINE instead of SELECT.
	ReadOnly bool
}

FindOptions selects which messages a RetrieverMethod returns, mirroring the options hash of Mail.find. The zero value is completed with the gem's defaults (what=first, order=asc, count=10, mailbox=INBOX, keys=[ALL]).

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

Header is an ordered list of fields plus a case-insensitive lookup, mirroring Mail::Header. Multiple fields with the same name are preserved in order.

func (*Header) Fields

func (h *Header) Fields() []*Field

Fields returns the header's fields in order.

func (*Header) Get

func (h *Header) Get(name string) *Field

Get returns the first field whose name matches (case-insensitively), or nil.

func (*Header) GetAll

func (h *Header) GetAll(name string) []*Field

GetAll returns every field whose name matches (case-insensitively).

type IMAP

type IMAP struct {
	// Address is the IMAP server host (default "localhost").
	Address string
	// Port is the IMAP server port (default 143).
	Port int
	// UserName / Password are the login credentials.
	UserName string
	Password string
	// EnableSSL requests an implicit-TLS (IMAPS) connection.
	EnableSSL bool
	// EnableStartTLS upgrades a plaintext connection via STARTTLS before login.
	EnableStartTLS bool
	// Dial is the connection seam; nil means net.Dial.
	Dial Dialer
	// TLSConfig, when set, overrides the default (verify-none) TLS config.
	TLSConfig *tls.Config
}

IMAP retrieves messages from an IMAP mailbox, mirroring `retriever_method :imap` with mailbox select/search/fetch. It speaks IMAP in pure Go over a connection from IMAP.Dial (net.Dial by default).

func (*IMAP) All

func (p *IMAP) All() ([]*Message, error)

All returns every IMAP message.

func (*IMAP) Find

func (p *IMAP) Find(opts FindOptions) ([]*Message, error)

Find retrieves messages from the IMAP mailbox per opts.

func (*IMAP) First

func (p *IMAP) First() (*Message, error)

First returns the oldest IMAP message.

func (*IMAP) Last

func (p *IMAP) Last() (*Message, error)

Last returns the newest IMAP message.

type Logger

type Logger interface {
	Print(v ...any)
}

Logger is the sink for LoggerDelivery; *log.Logger satisfies it.

type LoggerDelivery

type LoggerDelivery struct {
	// Logger is the destination; nil logs to stdout.
	Logger Logger
}

LoggerDelivery "delivers" a message by logging its wire form, mirroring Mail::LoggerDelivery. Useful for development.

func (*LoggerDelivery) Deliver

func (l *LoggerDelivery) Deliver(m *Message) error

Deliver logs m's envelope message.

type Message

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

Message is a parsed or constructed email message, mirroring Ruby's Mail message object. Build one with New; read it back with the accessors, or serialise it with Message.Encoded.

func All

func All() ([]*Message, error)

All returns every message from the configured retriever, mirroring Mail.all.

func Find

func Find(opts FindOptions) ([]*Message, error)

Find returns messages from the process-wide retriever configured with Defaults, mirroring Mail.find.

func First

func First() (*Message, error)

First returns the oldest message from the configured retriever, mirroring Mail.first (nil when the mailbox is empty).

func Last

func Last() (*Message, error)

Last returns the newest message from the configured retriever, mirroring Mail.last (nil when the mailbox is empty).

func New

func New(raw string, builders ...func(*Message)) *Message

New parses raw as an RFC 5322 message, mirroring Mail.new(raw). If raw is empty and builders are supplied, it constructs a message by running each builder against the fresh message instead (mirroring the `Mail.new { … }` block form).

func Read

func Read(path string) (*Message, error)

Read reads a message from the file at path, mirroring Mail.read(path).

func (*Message) AddHeader

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

AddHeader appends a header field without removing existing same-named fields.

func (*Message) AddPart

func (m *Message) AddPart(p *Part) *Message

AddPart appends a child part and marks the message multipart if it is not already (the caller is expected to set the multipart Content-Type/boundary, or rely on the default applied at emission).

func (*Message) Attachments

func (m *Message) Attachments() []*Part

Attachments returns the parts that are attachments (see Message.IsAttachment), recursing into nested multipart parts, mirroring Mail#attachments.

func (*Message) Bcc

func (m *Message) Bcc() []string

Bcc returns the Bcc addresses, mirroring Mail#bcc.

func (*Message) Body

func (m *Message) Body() *Body

Body returns the message's Body, mirroring Mail#body. For a multipart message this is the raw wrapper body; use Message.Parts for the children.

func (*Message) Cc

func (m *Message) Cc() []string

Cc returns the Cc addresses, mirroring Mail#cc.

func (*Message) Charset

func (m *Message) Charset() string

Charset returns the charset parameter of the Content-Type, or "".

func (*Message) ContentDisposition

func (m *Message) ContentDisposition() string

ContentDisposition returns the Content-Disposition media value (e.g. "attachment" / "inline"), or "".

func (*Message) ContentID

func (m *Message) ContentID() string

ContentID returns the Content-ID header value with any surrounding angle brackets removed, mirroring Mail#content_id.

func (*Message) ContentType

func (m *Message) ContentType() string

ContentType returns the part's Content-Type header value with its parameters preserved (e.g. `text/plain; charset=UTF-8`), or "" when absent — mirroring Mail::Part#content_type.

func (*Message) ContentTypeParameters

func (m *Message) ContentTypeParameters() map[string]string

ContentTypeParameters returns the parsed parameters of the Content-Type header (keys lower-cased), mirroring Mail#content_type_parameters.

func (*Message) Date

func (m *Message) Date() (time.Time, bool)

Date returns the parsed Date header. The bool reports whether a Date was present and parseable, mirroring the fact that Mail#date returns nil when absent.

func (*Message) Decoded

func (m *Message) Decoded() []byte

Decoded returns the part's body decoded per its Content-Transfer-Encoding, mirroring Mail::Part#decoded.

func (*Message) Deliver

func (m *Message) Deliver() error

Deliver sends the message via the process-wide delivery method configured with Defaults, mirroring Mail::Message#deliver. It errors if no delivery method has been configured.

func (*Message) DeliverWith

func (m *Message) DeliverWith(d DeliveryMethod) error

DeliverWith sends the message via the given delivery method, mirroring assigning a per-message delivery_method then calling deliver.

func (*Message) Encoded

func (m *Message) Encoded() string

Encoded serialises the message back to its RFC 5322 / MIME wire form, mirroring Mail#encoded / Mail#to_s. Header fields are emitted in insertion order (so a parsed message round-trips its field order), unstructured values carrying non-ASCII bytes are RFC 2047 encoded, and long fields are folded at 78 columns. A multipart message re-emits its parts between the boundary delimiters.

func (*Message) Field

func (m *Message) Field(name string) string

Field returns the unfolded raw value of the named header field, or "".

func (*Message) Filename

func (m *Message) Filename() string

Filename returns the attachment filename from the Content-Disposition (filename=) or the Content-Type (name=) parameter, mirroring how Mail derives an attachment's filename; "" when the part is not a named attachment.

func (*Message) From

func (m *Message) From() []string

From returns the From addresses as addr-specs, mirroring Mail#from.

func (*Message) HTMLPart

func (m *Message) HTMLPart() *Part

HTMLPart returns the first text/html part, mirroring Mail#html_part.

func (*Message) Header

func (m *Message) Header() *Header

Header returns the message's header for direct field access, mirroring Mail#header.

func (*Message) InReplyTo

func (m *Message) InReplyTo() string

InReplyTo returns the In-Reply-To msg-id without angle brackets. When multiple ids are present it returns the first (as the gem does for a scalar accessor).

func (*Message) IsAttachment

func (m *Message) IsAttachment() bool

IsAttachment reports whether the part is an attachment: either an explicit `Content-Disposition: attachment`, or any part that carries a filename.

func (*Message) MIMEVersion

func (m *Message) MIMEVersion() string

MIMEVersion returns the MIME-Version header value, or "".

func (*Message) MessageID

func (m *Message) MessageID() string

MessageID returns the Message-ID with angle brackets stripped, mirroring Mail#message_id (which returns the msg-id without the angle brackets).

func (*Message) MimeType

func (m *Message) MimeType() string

MimeType returns just the media type of the Content-Type (e.g. "text/plain"), lower-cased, mirroring Mail#mime_type.

func (*Message) Multipart

func (m *Message) Multipart() bool

Multipart reports whether the message is multipart (has a multipart/* Content-Type and at least one parsed part), mirroring Mail#multipart?.

func (*Message) Parts

func (m *Message) Parts() []*Part

Parts returns the child MIME parts, mirroring Mail#parts (empty for a non-multipart message).

func (*Message) References

func (m *Message) References() []string

References returns the References msg-ids (angle brackets stripped), in order, mirroring Mail#references.

func (*Message) ReplyTo

func (m *Message) ReplyTo() []string

ReplyTo returns the Reply-To addresses, mirroring Mail#reply_to.

func (*Message) SetBcc

func (m *Message) SetBcc(v string) *Message

SetBcc sets the Bcc field.

func (*Message) SetBody

func (m *Message) SetBody(v string) *Message

SetBody sets the body content (decoded/plain form).

func (*Message) SetCc

func (m *Message) SetCc(v string) *Message

SetCc sets the Cc field.

func (*Message) SetContentTransferEncoding

func (m *Message) SetContentTransferEncoding(v string) *Message

SetContentTransferEncoding sets the Content-Transfer-Encoding field and keeps the body's decode encoding in sync.

func (*Message) SetContentType

func (m *Message) SetContentType(v string) *Message

SetContentType sets the Content-Type field.

func (*Message) SetContentTypeParams

func (m *Message) SetContentTypeParams(mediaType string, order []string, params map[string]string) *Message

SetContentTypeParams sets the Content-Type field from a media type plus parameters, emitting them in the given key order (each value quoted when required). Mirrors building a Content-Type with content_type_parameters.

func (*Message) SetDate

func (m *Message) SetDate(t time.Time) *Message

SetDate sets the Date field to the RFC 5322 rendering of t.

func (*Message) SetDateString

func (m *Message) SetDateString(v string) *Message

SetDateString sets the Date field to a raw string (already formatted).

func (*Message) SetFrom

func (m *Message) SetFrom(v string) *Message

SetFrom sets the From field.

func (*Message) SetHeader

func (m *Message) SetHeader(name, v string) *Message

SetHeader sets an arbitrary header field by name.

func (*Message) SetInReplyTo

func (m *Message) SetInReplyTo(v string) *Message

SetInReplyTo sets the In-Reply-To field.

func (*Message) SetMessageID

func (m *Message) SetMessageID(v string) *Message

SetMessageID sets the Message-ID field, adding angle brackets if the caller passed a bare id.

func (*Message) SetReferences

func (m *Message) SetReferences(v string) *Message

SetReferences sets the References field.

func (*Message) SetReplyTo

func (m *Message) SetReplyTo(v string) *Message

SetReplyTo sets the Reply-To field.

func (*Message) SetSubject

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

SetSubject sets the Subject field. The value is stored raw; header emission RFC 2047 encodes it when it contains non-ASCII bytes.

func (*Message) SetTo

func (m *Message) SetTo(v string) *Message

SetTo sets the To field.

func (*Message) String

func (m *Message) String() string

String is an alias for Encoded, mirroring Mail#to_s.

func (*Message) Subject

func (m *Message) Subject() string

Subject returns the decoded Subject, mirroring Mail#subject.

func (*Message) TextPart

func (m *Message) TextPart() *Part

TextPart returns the first text/plain part of a multipart message (or the message itself when it is a plain text message), mirroring Mail#text_part.

func (*Message) To

func (m *Message) To() []string

To returns the To addresses, mirroring Mail#to.

type POP3

type POP3 struct {
	// Address is the POP3 server host (default "localhost").
	Address string
	// Port is the POP3 server port (default 110).
	Port int
	// UserName / Password are the login credentials.
	UserName string
	Password string
	// EnableSSL requests an implicit-TLS (POP3S) connection.
	EnableSSL bool
	// Dial is the connection seam; nil means net.Dial.
	Dial Dialer
	// TLSConfig, when set, overrides the default (verify-none) TLS config.
	TLSConfig *tls.Config
}

POP3 retrieves messages from a POP3 mailbox, mirroring `retriever_method :pop3`. It speaks POP3 in pure Go over a connection from POP3.Dial (net.Dial by default).

func (*POP3) All

func (p *POP3) All() ([]*Message, error)

All returns every POP3 message.

func (*POP3) Find

func (p *POP3) Find(opts FindOptions) ([]*Message, error)

Find retrieves messages from the POP3 mailbox per opts.

func (*POP3) First

func (p *POP3) First() (*Message, error)

First returns the oldest POP3 message.

func (*POP3) Last

func (p *POP3) Last() (*Message, error)

Last returns the newest POP3 message.

type Part

type Part = Message

Part is one MIME part of a multipart message, mirroring Mail::Part. It shares the Message shape (a part is itself a message-like entity with its own header and body, and may nest further parts).

type RetrieverMethod

type RetrieverMethod interface {
	// Find returns the messages selected by opts.
	Find(opts FindOptions) ([]*Message, error)
}

RetrieverMethod fetches messages from a mailbox, mirroring the gem's retriever objects. Implementations: POP3 and IMAP.

type SMTP

type SMTP struct {
	// Address is the SMTP server host (default "localhost").
	Address string
	// Port is the SMTP server port (default 25).
	Port int
	// Domain is the argument to EHLO/HELO; when empty the client's default is
	// used and no explicit HELO is sent.
	Domain string
	// UserName / Password are the AUTH credentials.
	UserName string
	Password string
	// Authentication selects the AUTH mechanism: "plain", "login" or "cram_md5"
	// (empty means no authentication).
	Authentication string
	// EnableStartTLSAuto upgrades a plaintext connection to TLS via STARTTLS when
	// the server advertises it, mirroring :enable_starttls_auto.
	EnableStartTLSAuto bool
	// OpenSSLVerifyMode of "none" disables certificate verification (maps to
	// InsecureSkipVerify), mirroring :openssl_verify_mode => 'none'.
	OpenSSLVerifyMode string
	// SSL / TLS request an implicit-TLS (SMTPS) connection, mirroring :ssl/:tls.
	SSL bool
	TLS bool
	// Dial is the connection seam; nil means net.Dial.
	Dial Dialer
	// TLSConfig, when set, overrides the config built from OpenSSLVerifyMode.
	TLSConfig *tls.Config
}

SMTP delivers a message over SMTP, mirroring the gem's `delivery_method :smtp` with its address/port/user_name/password/authentication/enable_starttls_auto/ openssl_verify_mode settings. Sending is done with the standard library's net/smtp over a connection obtained from SMTP.Dial (net.Dial by default), so tests can substitute an in-process server.

func (*SMTP) Deliver

func (s *SMTP) Deliver(m *Message) error

Deliver sends m over SMTP.

type Sendmail

type Sendmail struct {
	// Location is the sendmail binary path (default "/usr/sbin/sendmail").
	Location string
	// Arguments are the fixed arguments (default ["-i"]).
	Arguments []string
	// Run is the execution seam; nil runs the real binary.
	Run func(path string, args []string, stdin []byte) error
}

Sendmail delivers a message by piping it to a local sendmail binary, mirroring `delivery_method :sendmail`. The command is built as `location arguments… -f <from> -- <recipients…>` and the LF-normalised message is written to its stdin.

func (*Sendmail) Deliver

func (s *Sendmail) Deliver(m *Message) error

Deliver pipes m to the sendmail binary.

type TestDelivery

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

TestDelivery is a no-op delivery method that records every delivered message, mirroring Mail::TestMailer for use in tests. It still builds (and thus validates) the SMTP envelope, so envelope errors surface as they would over a real transport.

func (*TestDelivery) Clear

func (t *TestDelivery) Clear()

Clear empties the recorded deliveries, mirroring TestMailer.deliveries.clear.

func (*TestDelivery) Deliver

func (t *TestDelivery) Deliver(m *Message) error

Deliver records m after validating its envelope.

func (*TestDelivery) Deliveries

func (t *TestDelivery) Deliveries() []*Message

Deliveries returns a snapshot of the recorded messages, mirroring Mail::TestMailer.deliveries.

Jump to

Keyboard shortcuts

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