PhoenixKitInbox.Schemas.Message (PhoenixKitInbox v0.2.0)

Copy Markdown View Source

The message body — stored once, regardless of how many mailboxes receive it. Per-recipient state (which folder it's in, whether it's been read, starred, trashed) lives on PhoenixKitInbox.Schemas.Delivery, one row per recipient mailbox.

This is the same split Gmail and every other webmail uses, and it's why "mark as read in my mailbox" doesn't mark it read for the four other people on the thread.

Threading

thread_uuid groups a conversation. A brand-new message gets thread_uuid == uuid (it is the root); a reply inherits the parent's thread_uuid and sets parent_uuid. That's enough for Messages.list_thread/2 to return a conversation in one indexed query, and it leaves room for a threaded reading pane later without a migration.

Drafts

A draft is a message with status: "draft" and no sent_at. It gets exactly one delivery row — into the author's own "drafts" folder. Sending flips status to "sent", stamps sent_at, and fans out the recipient deliveries.

Tables are created by PhoenixKitInbox.Migrations, never by this schema.

Summary

Functions

Valid values for the body_format column.

Changeset for creating or updating a draft.

Changeset applied at send time. A sent message must carry a subject or a body — an entirely blank message is never worth delivering to anyone.

Valid values for the status column.

Types

t()

@type t() :: %PhoenixKitInbox.Schemas.Message{
  __meta__: term(),
  body: term(),
  body_format: term(),
  inserted_at: term(),
  metadata: term(),
  parent_uuid: term(),
  sender_mailbox_uuid: term(),
  sender_user_uuid: term(),
  sent_at: term(),
  status: term(),
  subject: term(),
  thread_uuid: term(),
  updated_at: term(),
  uuid: term()
}

Functions

body_formats()

@spec body_formats() :: [String.t()]

Valid values for the body_format column.

changeset(message, attrs)

Changeset for creating or updating a draft.

Deliberately lenient about subject/body: an empty draft is a legitimate thing to autosave. sent_changeset/2 is where the real requirements land.

sent_changeset(message, attrs)

Changeset applied at send time. A sent message must carry a subject or a body — an entirely blank message is never worth delivering to anyone.

statuses()

@spec statuses() :: [String.t()]

Valid values for the status column.