Skip to content

v2.0.0

Choose a tag to compare

@YouSysAdmin YouSysAdmin released this 02 Oct 11:55
· 202 commits to devel since this release
893f7f7

Breaking

  • API field naming conventions: request and response bodies say sender and
    recipients, headers come only through the headers map
  • The email and inbound logs page by one opaque cursor: GET /api/v1/emails
    and GET /api/v1/inbound-emails take cursor and answer next_cursor, the
    before and before_id parameters are gone
  • The page alias on offset-paged lists is gone, limit and offset are the
    only paging parameters
  • A new email status, cancelled, and a new webhook event, email.cancelled:
    a client switching on the status has one more value to expect
  • Go SDK: ListEmails returns the next cursor and EmailFilter carries the
    new filters, Statuses and Cursor replace Status and Before

Features

  • Sender addresses sign their mail, S/MIME or PGP, inside the message under DKIM,
    and a campaign can decline the sender's signature
  • One rulebook for custom headers: project defaults, campaign headers, per-message
    headers, submission forwards the client's own and drops the project's list
  • A campaign carries its own headers and can send with no unsubscribe links or headers
  • A campaign one-click unsubscribes from every campaign, the hosted page offers
    the list alone, per-list opt-outs are visible on the list, the subscriber and the API
  • Preview a campaign as one subscriber, from the campaign page with a subscriber picker
  • Subscriber search matches the name and is indexed, a subscriber lists the static
    lists it is on, members are added to lists by search
  • Pick an unsubscribe list on the send page
  • Search by from/to in inbound and the sandbox, clear sandbox inboxes by sender
  • Every /api/v1 answer names the credential that authenticated it
  • Rotate a domain's DKIM key under a second selector
  • rekey re-encrypts every sealed column under a new encryption key, keeps the
    retired tracking key so delivered unsubscribe links keep working, and refuses
    to run against a schema other than the binary's
  • Additional filtersmatch=exact on sender and recipient across the three message lists, whole addresses matched as mailboxes, email= on accounts and campaign messages

API

  • A scheduled or still queued message can be cancelled, from the API and the
    console, and a webhook hears email.cancelled
  • A send carries tags and metadata, the log filters by tag, and an
    Idempotency-Key header makes a retried send answer with the message the
    first request queued
  • The email log filters by sender, recipient, a list of statuses, a from/to
    window, after for a poller, template, API key and SMTP server
  • The inbound log searches the subject
  • The sandbox list takes subject and since, clear takes recipients and
    older_than
  • One whole address looks up suppressions, bounces, subscribers and contacts
    with email=, and every search in the API ignores case
  • /emails/stats, /inbound-emails/stats and a campaign's analytics take a
    from/to window, the audit trail filters by type, actor and window
  • Campaigns, templates and accounts filter by status or name and page on
    request, with a total
  • Webhooks: read one, edit it, disable it by hand, post a test event, send a
    delivery again, and narrow the delivery log by outcome and event. Every
    attempt keeps the body it posted
  • API keys, SMTP credentials, sandbox credentials and senders can be read one
    at a time and edited
  • A suppression block list is imported whole
  • Every query parameter a route reads is in the OpenAPI document, and a guard
    keeps it so

Fixes

Sending and delivery

  • SES: the From header keeps its display name, the return path is not sent as FromEmailAddress
  • Every outbound SMTP conversation is bounded and cut on stop
  • Outcome writes are fenced on the claim that produced them, the worker's first
    poll waits for the pool to report in
  • Relay completion is fenced on the hand-off claim, revocation runs on resumed
    sessions, node-asserted fields are bounded, enrolment is serialised and locks
    only after the token is checked
  • Attachment content types are parsed, parameters survive
  • An SNS notification is filed once inside its window
  • Inbound RCPT remembers domain lookups and caps refusals per session
  • Webhook slots are held per attempt, bounded per project, released when the post panics
  • DKIM rotation is offered on verified domains only
  • The email log's recipient search ignores case, like the subject search beside it

Templates and campaigns

  • Template execution is bounded in iterations and printf padding, not only
    output, and template bodies count toward the budget
  • A lenient render leaves a blank, not the no-value marker
  • The campaign preview renders the campaign's own data, never the template's sample

Auth and sessions

  • A bearer decides the request: only a bearer exempts it from the cross-site
    check, logout judges it before the cookie, HSTS follows the public URL,
    object-src none
  • Over HTTPS the session cookie carries the __Host- prefix and only that cookie is read
  • A revoked session is dropped from every node's cache at once
  • The login lock is held against the addresses that earned it, caps fresh
    addresses, and judges IPv6 by its /64
  • Reset and verification mail budgets are spent per address, IPv6 by its /64
  • Enrolling a second factor proves the password first, and a second-factor
    change ends the other sessions
  • Confirming an email address no longer signs the account in
  • Passkey sign-in admits what password sign-in admits
  • set-password is a targeted write that keeps the new hash, ends sessions and
    reset links
  • The last administrator survives demotion and deletion, and the last
    administrator and the first user are decided under a lock
  • A request naming no credential gets the ordinary body ceiling
  • Tracking links are keyed on the encryption key, old ones keep verifying

Platform

  • HTTP is drained before the audit trail closes, cron jobs outlive the
    scheduler and are cut by Wait
  • The event stream recovers its own panic through the configured logger
  • The http-01 responder follows the current ACME manager
  • Sandbox clear refuses a selection naming no address
  • The example config passes validation, worker timeouts are documented
  • The Go SDK core carries the new inbound and suppression fields

Console

  • The subscribers page searches and pages on the server
  • The header editor is always on the send page, the template's Settings button is Edit
  • The builder's mobile view, preview exit, font list and typography toggles