mail

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Oct 13, 2026 License: Apache-2.0 Imports: 28 Imported by: 0

Documentation

Overview

Package mail parses MIME messages and sanitizes HTML bodies. It is pure: no storage, network or UI dependencies.

Index

Constants

View Source
const (
	MaxBodyBytes = 2 << 20
	MaxMIMEDepth = 20
)

Variables

This section is empty.

Functions

func AddrKey

func AddrKey(s string) string

AddrKey is the lowercased bare address of an address string ("Bob <b@x>" → "b@x").

func Blank

func Blank(src string) bool

Blank reports whether HTML has no content at all: only whitespace and the editor's empty placeholders (p, div, br). An image, a rule or a table is content.

func Build

func Build(o Outgoing, now time.Time) (raw []byte, messageID string, err error)

Build renders o as RFC 5322 bytes. Bcc is never written to the headers (the sender uses it only as envelope recipients). messageID is returned without angle brackets, matching Parsed.MessageID.

func CIDs

func CIDs(src string) []string

CIDs are the Content-IDs src's images refer to as cid:, in order.

func DecodePart

func DecodePart(data []byte, encoding, cs string) ([]byte, error)

DecodePart decodes a separately fetched MIME part body using its recorded transfer encoding and (for text) charset.

func FormatAddress

func FormatAddress(name, addr string) string

FormatAddress renders a display name and address as one header address that net/mail parses back to the same parts. The name stays readable UTF-8 and is quoted (with \ and " escaped) unless it is a plain run of words; so is a local part that is not a dot-atom ("a b"@example.com).

func ForwardSubject

func ForwardSubject(s string) string

func HTMLToText

func HTMLToText(src string) string

HTMLToText converts HTML to plain text: block elements become line breaks, list items get a "- " prefix, links render as "text (url)".

func JoinDraft

func JoinDraft(editable, quote, signature string) string

JoinDraft is the draft body of its parts, as SplitDraft returns them.

func ParseStructure

func ParseStructure(bs imap.BodyStructure) (textParts []Attachment, atts []Attachment)

ParseStructure walks an IMAP BODYSTRUCTURE and reports the displayable body parts to fetch and the attachment metadata, with IMAP part paths. ponytail: message/rfc822 children are treated as one attachment, not descended into.

func QuoteHTML

func QuoteHTML(orig *Parsed) string

QuoteHTML returns the "on {date}, {from} wrote:" line plus the original in a blockquote.

func RemoteImages

func RemoteImages(safe string) []string

RemoteImages are the http(s) image sources of a sanitized body (kept by Sanitize with loadRemote): its <img> sources and CSS background images, in order, each once.

func ReplaceImages

func ReplaceImages(src string, f func(s string) string) string

ReplaceImages returns src with every <img> source s replaced by f(s); an empty result drops the source. It does not sanitize.

func ReplyRecipients

func ReplyRecipients(orig *Parsed, self string, all bool) (to, cc []string)

ReplyRecipients picks reply targets: Reply-To if set, else From. With all, the original To/Cc are added to cc. self and duplicates are dropped.

func ReplySubject

func ReplySubject(s string) string

func Sanitize

func Sanitize(src string, inline map[string]Attachment, loadRemote bool) (safe string, blockedRemote int)

Sanitize cleans received HTML. inline is keyed by Content-ID. Links become data-href (not navigable); remote images are dropped unless loadRemote. blockedRemote counts remote resources found in the original HTML.

func SanitizeCompose

func SanitizeCompose(src string) string

SanitizeCompose cleans pasted content in the composer: same whitelist, no remote resources. data-godwit survives only as a draft marker: "quote" or "signature".

func SanitizeDraft

func SanitizeDraft(src string, cids map[string]bool) string

SanitizeDraft is SanitizeCompose keeping the images whose src is cid: of a Content-ID in cids (the draft account's signature images); any other cid, data: or remote source is dropped.

func Snippet

func Snippet(text string) string

Snippet returns the first 200 characters with whitespace collapsed and the invisible characters gone: mail pads its preview text with zero-width and joiner characters between spaces (a preheader), which would fill the line with nothing to see. They are dropped, not made spaces, so none splits a word (a soft hyphen); the joiners only at a word's ends, as inside one they shape it (Persian's non-joiner, an emoji's joiner).

func SplitDraft

func SplitDraft(src string) (editable, quote, signature string)

SplitDraft splits a sanitized draft body into its editable part, its quote and its signature: the first top-level elements marked "quote" and "signature"; everything else is editable. JoinDraft puts them back together.

func StripMarkers

func StripMarkers(src string) string

StripMarkers removes every data-godwit attribute, in any letter case (the parser lowercases names), so marked HTML from a model or another mail becomes ordinary content.

func ThreadKeys

func ThreadKeys(p *Parsed) (ids []string, subjectKey string)

ThreadKeys returns the conversation keys of p: ids is its own Message-ID plus In-Reply-To and References (deduplicated), subjectKey the lowercased subject without Re/Fwd/回复/转发 prefixes and with whitespace collapsed.

Types

type Attachment

type Attachment struct {
	Part, Encoding, Charset, Filename, ContentType, ContentID string
	Inline                                                    bool
	Size                                                      int
	Data                                                      []byte
}

Attachment Part is the IMAP-style 1-based dot path ("1", "2.1"). Data is empty when produced by ParseStructure.

type Outgoing

type Outgoing struct {
	From, ReplyTo string
	To, Cc, Bcc   []string
	Subject, HTML string
	InReplyTo     string
	References    []string
	Attachments   []Attachment // Data must be filled
	// Related are images the HTML may show as cid:<ContentID> (the account's
	// signature images): sent inline, in multipart/related, when it does.
	Related []Attachment
}

Outgoing is a message to be built. Addresses are "Name <addr>" or bare addresses.

type Parsed

type Parsed struct {
	MessageID, Subject, From, ReplyTo, InReplyTo string
	To, Cc, References                           []string
	Date                                         time.Time
	Text, HTML                                   string
	Truncated                                    bool
	Damaged                                      bool     // best-effort result: some part failed to read or decode
	Warnings                                     []string // what went wrong, for logs
	Attachments                                  []Attachment
}

func Parse

func Parse(raw []byte) (*Parsed, error)

Parse parses a full RFC 5322 message.

Jump to

Keyboard shortcuts

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