• v1.0.0 bfec1761d0

    Rene Nochebuena released this 2026-05-29 10:05:22 -06:00 | 0 commits to main since this release

    v1.0.0

    code.nochebuena.dev/einherjar/smtp


    Architecture Decisions Resolved

    Decision Outcome
    No-op when Host empty New returns a silent no-op — SMTP absence never blocks a transaction (account creation, order placement)
    Interface name Sender (N-4 agent noun) — single Send method; not Provider
    BCC handling In SMTP envelope only (RCPT TO) — never written to message headers; RFC 5321/5322 compliant
    Attachment encoding base64 with multipart/mixed; body in quoted-printable
    Template rendering Separate from Send — caller renders to string, assigns to Message.Body; no coupling between rendering and transport
    External dependencies None — pure stdlib (net/smtp, mime/multipart, html/template)
    Health priority LevelDegraded — email delivery failure degrades but does not halt the service

    API

    import "code.nochebuena.dev/einherjar/smtp"
    
    // Interfaces
    type Sender interface {
        Send(ctx context.Context, msg Message) error
    }
    type Component interface {
        lifecycle.Component
        observability.Checkable
        observability.Identifiable
        Sender
    }
    
    // Value types
    type Message struct {
        To          []string
        CC          []string
        BCC         []string    // in SMTP envelope only; never in headers
        ReplyTo     string
        Subject     string
        Body        string
        ContentType string      // defaults to "text/plain"
        Attachments []Attachment
    }
    type Attachment struct {
        Name        string
        ContentType string      // defaults to "application/octet-stream"
        Data        io.Reader   // consumed once on Send; must not be reused
    }
    
    // Config
    type Config struct {
        Host     string `env:"EINHERJAR_SMTP_HOST"`
        Port     int    `env:"EINHERJAR_SMTP_PORT"     envDefault:"587"`
        User     string `env:"EINHERJAR_SMTP_USER"`
        Password string `env:"EINHERJAR_SMTP_PASSWORD"`
        From     string `env:"EINHERJAR_SMTP_FROM"`
    }
    func DefaultConfig() Config
    
    // Constructor — returns no-op Component when cfg.Host is empty
    func New(logger logging.Logger, cfg Config) Component
    
    // Template rendering (separate from Send)
    type Template struct { /* unexported */ }
    func ParseFS(fsys fs.FS, patterns ...string) (*Template, error)
    func (t *Template) Render(name string, data any) (string, error)
    

    Install

    go get code.nochebuena.dev/einherjar/smtp@v1.0.0
    

    Dependencies

    Module Version Role
    code.nochebuena.dev/einherjar/contracts v1.0.0 lifecycle.Component, observability.Checkable, logging.Logger
    code.nochebuena.dev/einherjar/core v1.0.0 xerrors
    Downloads