mail

package
v1.3.1 Latest Latest
Warning

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

Go to latest
Published: Aug 31, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package mail reads the places HEY keeps postings — a box, a label, a collection — through one Source type and one page read, so a caller never has to know which endpoint a source is served by.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func TopicIDIn

func TopicIDIn(appURL string) int64

TopicIDIn reads the thread out of a posting's URL, which is the only place HEY's posting JSON says which topic a posting is: `_posting.jbuilder` serves no topic and no topic_id, and the web app follows the URL. A URL that addresses something else — a contact page, a bundle view — has no topic and answers zero.

func TopicIDOf added in v1.0.0

func TopicIDOf(posting generated.Posting) int64

TopicIDOf resolves the thread a posting opens: its own app_url, or — for a bundle, whose app_url is its sender's contact page — its app_bundle_url. HEY points that at a topic exactly when the bundle holds one unseen thread (haystack's `bundle_posting` route), which is the thread the bundle row opens in the web app. A bundle with several unseen threads opens a bundle view of its own, and one with none opens the contact, so neither names a topic and both answer zero.

Types

type Collection

type Collection struct {
	ID   int64
	Name string
}

Collection is a collection a posting's topic belongs to.

type Contact

type Contact struct {
	ID           int64
	Name         string
	EmailAddress string
}

Contact is who a posting came from.

type Entry

type Entry struct {
	ID                    int64
	CreatedAt             time.Time
	Creator               Contact
	AlternativeSenderName string
	Summary               string
	Body                  htmlutil.Markdown
	BodyHTML              string
	// BodyState is what became of the body when the entry came through threadload:
	// hydrated, bodyless, over_limit or failed. Empty for an entry read another way.
	BodyState string
}

Entry is one message in a thread. CreatedAt is the time HEY served, not a string of it, for the reason Posting gives: a date formatted and parsed back is a date a reader east of UTC reads as yesterday's.

Body is Markdown, converted once here at the edge, and BodyHTML keeps the HTML HEY served so the image and attachment extractors still have the attributes Markdown drops.

func LoadedEntry

func LoadedEntry(loaded threadload.Entry) Entry

LoadedEntry describes an entry threadload read: the message when there is one, and what became of the body either way.

func NewEntry

func NewEntry(entry generated.Entry, message generated.Message) Entry

NewEntry describes a thread's entry against the message HEY served for it. A topic lists its entries and each message is read on its own, and the two disagree about what they carry: an entry read as part of a bundle has no creator and no timestamp of its own, and a message read directly has a subject where the entry has a summary.

type Extenzion

type Extenzion struct {
	ID   int64
	Name string
}

Extenzion is the HEY extension — a group address — a posting arrived through.

type Folder

type Folder struct {
	ID   int64
	Name string
}

Folder is a label a posting is filed under.

type Kind

type Kind string

Kind is which of HEY's posting endpoints a Source is served by.

const (
	KindBox        Kind = "box"
	KindFolder     Kind = "folder"
	KindCollection Kind = "collection"
)

type Page

type Page struct {
	Postings []generated.Posting
	Cursor   string
	Total    int
}

Page is one page of a source's postings. Cursor is whatever the next read needs to carry on where this page stopped — a geared_pagination cursor for a label or a collection, HEY's own next_history_url for a box — and is empty at the end of the list. Total is HEY's count of everything in the source, zero where it does not say.

func ReadPage

func ReadPage(ctx context.Context, client *hey.Client, source Source, cursor string) (Page, error)

ReadPage reads the page of a source that begins at cursor. An empty cursor reads the first page.

func ReadSeenPage added in v1.3.0

func ReadSeenPage(ctx context.Context, client *hey.Client, cursor string) (Page, error)

ReadSeenPage reads a page of the Imbox's Previously Seen postings, which HEY serves on their own route ordered by when they were seen — the Imbox's own pages order seen postings last, which is why the box cannot stand in for this. There is no Source parameter: the route is account-scoped and names the Imbox itself. An empty cursor reads the first page.

type Posting

type Posting struct {
	ID                    int64
	TopicID               int64
	CreatedAt             time.Time
	Name                  string
	Summary               string
	AlternativeSenderName string
	Seen                  bool
	// IsBundle marks a row that is a bundle of one contact's unseen threads. It comes
	// from the posting's kind — HEY's `bundled` flag means filed *inside* a bundle.
	IsBundle          bool
	BubbledUp         bool
	Muted             bool
	VisibleEntryCount int32
	Creator           Contact
	Extenzions        []Extenzion
	Folders           []Folder
	Collections       []Collection
}

Posting is one row of a source: a thread, a bundle or a single entry as HEY lists it. The timestamps are the ones HEY served, so whatever shows one decides how it reads — formatting a time into a string and parsing it back is how a reader east of UTC ends up looking at yesterday's date.

func NewPosting

func NewPosting(posting generated.Posting) Posting

NewPosting describes one posting HEY answered with. Its text is sanitized here, once, so that every row, picker and notice that shows a posting shows it inert.

func Postings

func Postings(postings []generated.Posting) []Posting

Postings describes a page of postings HEY answered with.

type Source

type Source struct {
	Kind      Kind
	ID        int64
	Name      string
	BoxKind   string
	AppURL    string
	CreatedAt time.Time
	UpdatedAt time.Time
}

Source is a place postings are read from. BoxKind carries HEY's own kind for a box (hey.BoxKindImbox and friends), which is what tells the named box routes apart; it is empty for a label or a collection.

func BoxSource

func BoxSource(box *generated.BoxShowResponse) Source

BoxSource describes the box HEY answered with.

func CollectionSource

func CollectionSource(collection *generated.CollectionWithPostings) Source

CollectionSource describes the collection HEY answered with.

func FolderSource

func FolderSource(folder *generated.FolderWithPostings) Source

FolderSource describes the label HEY answered with.

func ListedBoxSource

func ListedBoxSource(box generated.Box) Source

ListedBoxSource describes a box from HEY's list of them, which names the boxes without serving any of their postings or URLs.

func (Source) Coverable

func (s Source) Coverable() bool

Coverable reports whether cover art belongs over this source's seen postings. Only the Imbox is coverable, which is haystack's rule in Box::Imbox#coverable?.

Jump to

Keyboard shortcuts

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