# Postwell — Product Requirements (v4.1)

Postwell is a web email client with a folder and label sidebar showing unread counts, threaded conversations, star and flag markers, bulk actions, search operators, a compose window with recipient chips, Cc/Bcc, attachments, draft autosave and a 5-second undo-send, snooze with presets and a date picker, and settings for signature, vacation responder and labels. The product clock is fixed at Monday 19 Oct 2026 09:30 UTC.

**Problem.** People who handle a busy inbox need to triage quickly, find mail precisely and send messages with confidence, and must be able to trust the unread counts, the folder contents and who actually sees a message.

## Users
- **Busy professional** — Triage the inbox with bulk actions, snooze and keyboard shortcuts.
- **Sender** — Compose, attach, save drafts and retract a message within the undo window.
- **Organiser** — Keep mail sorted with labels and find anything with search operators.

## Goals
- Badges and unread counts always match the number of unread conversations they describe.
- Every selected conversation is acted on; none is silently skipped.
- Blind-copied recipients are never revealed to other recipients.
- Invalid input is rejected with a specific message before anything is sent or saved.

## Sign-in (AUTH)

Access to the mailbox.

- **FR-AUTH-01** (Must) Valid credentials open the Inbox with the seeded folder counts.
  - The sign-in page is headed "Sign in to Postwell" with Email and Password fields
  - After sign-in the URL is /mail/inbox, the heading is "Inbox" with "9 unread"
  - Sidebar badges: Inbox 9, Drafts 2, Spam 1
  - The browser tab title starts with "Inbox (9)" and ends with "Postwell"
- **FR-AUTH-02** (Should) Empty or wrong credentials are rejected without leaving the sign-in page.
  - Empty form: "Enter your email and password"
  - Wrong password: "Invalid email or password" and the form stays

## Folders and lists (LST)

Sidebar folders, list rows and paging.

- **FR-LST-01** (Should) Every sidebar folder opens its own URL and lists its seeded conversations.
  - Sent (/mail/sent): 6 conversations including "Meeting notes follow-up"
  - Drafts: "Thank you for the intro" and one with no subject
  - Archive: "Signed: office lease addendum" and "Trip recap: Lisbon"
  - Spam: "You have won a free cruise!!!" and "Limited offer: cheap watches"
  - Trash: "Old newsletter: September edition" and an "Empty Trash now" button
  - Starred: "Re: Vendor shortlist for the print run", "Photos from Saturday", "Dinner reservation confirmed"
- **FR-LST-02** (Could) List rows show unread (bold), important marker, label chips, attachment paperclip, message count, filled star and a date that is a time for today, "Yesterday" or a weekday label.
  - "Daniel Moss, Q4 roadmap review — agenda": bold, important marker, "Work" chip, count 2
  - "Stayfold Billing, Invoice 4471 for October hosting": paperclip and "Receipts" chip, time not weekday
  - "Re: Vendor shortlist for the print run": not bold, star filled
- **FR-LST-03** (Should) The Inbox pages in groups of 25.
  - "Page 1 of 2 · 27 conversations" with the older-page button enabled
  - Page 2 shows 2 rows and the next button is disabled
- **FR-LST-04** (Could) Direct URLs open the right folder after sign-in; browser Back and Forward work inside the app.

## Reading and markers (RD)

Open conversations, read state, star and flag.

- **FR-RD-01** (Must) Opening an unread conversation marks it read and lowers the Inbox badge and the header unread count by one each time.
  - Opening "Lunch on Thursday?": row no longer bold; Inbox badge and header go from 9 to 8
  - Opening "Contract draft needs your signature" next gives 7
  - The pane shows Reply, Reply all and Forward
- **FR-RD-02** (Should) Mark as unread / Mark as read change the Inbox badge by one per conversation.
  - Mark "Photos from Saturday" unread: row bold, badge and header 10; Mark as read: 9
  - Marking "Lunch on Thursday?" read: 8
- **FR-RD-03** (Could) Starring a conversation adds it to Starred and unstarring removes it.
  - Starring "Receipt for your coffee order" makes Starred 4; unstarring "Photos from Saturday" leaves 3

## Archive, spam and trash (ACT)

Move conversations between folders, singly or in bulk.

- **FR-ACT-01** (Must) Archive removes the row from the Inbox with the toast "Conversation archived" and an Undo that restores it.
  - Archiving "Parking permit renewal", then Undo, restores the row; archiving again leaves Archive with 3 conversations
- **FR-ACT-02** (Must) A bulk action applies to every selected conversation.
  - Selecting "Library books due soon", "Weekend plans" and "Parking permit renewal" and archiving removes all three from the Inbox
  - Archive then lists 5 conversations (the 3 plus the 2 seeded)
- **FR-ACT-03** (Must) Move to Trash holds mail until Empty Trash is confirmed; cancelling keeps it.
  - Toast "Conversation moved to Trash"; Trash lists "Weekend plans" and "Old newsletter: September edition"
  - "Empty Trash now" opens a confirmation; Cancel keeps both
  - Confirming empties Trash and shows its empty-state message; "Weekend plans" is not in the Inbox
- **FR-ACT-04** (Should) Report spam moves the conversation to Spam with toast "Marked as spam"; Spam badge counts only unread items.
  - "Receipt for your coffee order" leaves the Inbox; Spam lists 3 while its badge stays 1

## Snooze (SNZ)

Hide a conversation until a chosen time.

- **FR-SNZ-01** (Should) Snoozing with a preset hides the row until the chosen time and lists it under Snoozed.
  - The menu offers presets and "Pick date and time (UTC)"
  - Toast starts "Snoozed until" and ends "UTC"
  - Snoozed lists "Passport renewal form" (due Wed, Oct 21, 8:00 AM) and the new item
- **FR-SNZ-02** (Should) A snooze time must be in the future relative to the product clock.
  - 2026-10-18 08:00 shows "Snooze time must be in the future" and the row stays in the Inbox

## Labels (LBL)

Apply labels and manage them in Settings.

- **FR-LBL-01** (Should) Labels are applied and removed from the "Label as" menu and filter the list from the sidebar.
  - Menu lists Work, Personal, Receipts, Travel and Team
  - Choosing Personal adds a green chip; the Personal sidebar list includes the conversation; removing it deletes the chip
- **FR-LBL-02** (Should) Labels can be created with a colour and deleted after confirmation.
  - Settings > Labels lists Work, Personal, Receipts, Travel, Team
  - Creating "Clients" in Red shows toast "Label created" and it is the sixth label
  - Delete opens "Delete label?" (the label will be removed from all conversations); confirming shows "Label deleted" and five labels remain
- **FR-LBL-03** (Could) Label names are required, unique (case-insensitive) and at most 20 characters.
  - Empty: "Label name is required"
  - "work": A label named "work" already exists
  - A 23-character name: "Label name can be at most 20 characters"

## Search (SRC)

Free text and operators from:, to:, subject:, label:, has:attachment, is:unread.

- **FR-SRC-01** (Must) Search operators narrow the mailbox to exactly the matching conversations, and operators combine.
  - from:priya: "Q4 roadmap review — agenda", "Budget v3 — comments inside", "Welcome aboard, Lucas"
  - is:unread: 9 conversations
  - subject:invoice: "Invoice 4471 for October hosting"
  - Free text "budget": "Budget v3 — comments inside" and "Re: Hiring plan for Q1"
- **FR-SRC-02** (Could) A search with no matches shows an empty state, not an error; clearing the box restores the Inbox of 27 conversations.
- **FR-SRC-03** (Must) has:attachment returns only conversations that have an attachment.
  - 7 conversations, each with a paperclip, including "Floor plan v3 for the new studio" and "Signed: office lease addendum"; "Lunch on Thursday?" is not listed
  - from:leo has:attachment returns only "Team offsite photos (zip)"

## Compose and send (CMP)

New messages, undo send, validation, attachments, drafts, reply and Bcc.

- **FR-CMP-01** (Must) A composed message is sent after a 5-second undo countdown and appears in Sent with the signature.
  - Compose (button or "c") opens with the body ending "-- " and the signature name
  - Send shows a toast counting down 5 seconds with Undo
  - After the countdown the message is the newest in Sent and Sent grows from 6 to 7; the body has the typed text and the signature
- **FR-CMP-02** (Should) Undo within the countdown cancels the send and returns to the compose window with the same content.
  - No conversation with that subject appears in Sent; Sent still has 6
- **FR-CMP-03** (Must) Sending is refused with a specific message when recipients, content or addresses are invalid.
  - No recipient: "Add at least one recipient"
  - Malformed chip text: “not-an-email” is not a valid email address
  - No subject and no body: "Add a subject or a message before sending"
- **FR-CMP-04** (Should) Attachments over 10 MB or more than 5 files at once are refused.
  - A large file shows that it "is larger than 10.0 MB" and is not attached
  - Six files show "You can attach at most 5 files"
- **FR-CMP-05** (Should) Typing autosaves a draft after about 2 seconds; the draft can be reopened and discarded.
  - Status reads "Draft saved"; "Save and close" adds the draft so Drafts shows 3 and its badge is 3
  - Reopening shows the saved subject; "Discard draft" returns Drafts to 2
- **FR-CMP-06** (Must) Reply addresses the sender and adds the message to the same conversation.
  - Reply to "Lunch on Thursday?" opens a box addressed to Hana Kobayashi with subject "Re: Lunch on Thursday?"
  - After sending, the conversation has 2 messages and the latest is from the signed-in user
- **FR-CMP-07** (Must) Bcc recipients receive the message but are never shown to other recipients.
  - In Sent the To line lists only the To recipients; the Bcc address does not appear there

## Settings (SET)

Signature and vacation responder.

- **FR-SET-01** (Should) The signature is saved, appended to new messages, and limited to 200 characters.
  - Settings (/mail/settings/general) shows the Signature tab and a counter "n / 200"
  - Saving shows toast "Signature saved"; new Compose bodies end with "-- " and the new signature
  - 201 characters turns the counter red and shows "Signature can be at most 200 characters"
- **FR-SET-02** (Must) An enabled vacation responder requires a subject, a message and a first day, and the last day must not be before the first day.
  - Messages in order: "Vacation subject is required", "Vacation message is required", "Choose the first day"
  - First day 2026-10-30 with last day 2026-10-26 shows "Last day must be on or after the first day" and nothing is saved
  - First 2026-10-26 and last 2026-10-30 saves with toast "Vacation responder is on"

## Keyboard shortcuts (KEY)

Act on the list without a mouse.

- **FR-KEY-01** (Should) "?" opens "Keyboard shortcuts"; j moves down, o opens, e archives, c composes.
  - j three times then o opens the third conversation "Lunch on Thursday?"; e shows "Conversation archived"

## Non-functional requirements

- **NFR-01** (Could) At 800 px width the sidebar narrows or collapses and nothing overflows horizontally; the account menu (name, email, Sign out) stays in the viewport; dark mode keeps the teal accent and unread rows stand out.
- **NFR-02** (Must) Unread badges, header counts and the tab title always equal the number of unread conversations in the folder they describe.

## Glossary and rules

- **Conversation** — A thread of one or more messages shown as one row.
- **Undo window** — The 5 seconds after Send during which the message can still be cancelled.
- **Product clock** — Time is fixed at Mon 19 Oct 2026 09:30 UTC for every date rule.

## Out of scope

- Real mail delivery
- Mobile apps
