Repository navigation
Releases
Releases · goldnead/statamic-inbox
0.2.4
Changed
- Settings: the addon now declares
settingsNavParent()([section, name]of its own Control Panel navigation entry). With statamic-brand-context 1.16 or newer its settings show as the sub-item "Einstellungen" under that entry; addons without a navigation of their own share one "Addon-Suite" page under Settings. Older brand-context versions ignore the method and keep the previous layout. - Settings: the sub-item carries the same name as the navigation entry, also when the entry shows a counter.
Upgrading
- No migration, no new config key.
0.2.3
Added
- [new]
inbox:summaryfor agents over SSH: per mailbox (name, address, brand) the numbers new,
open and of those unread, waiting longer than--wartetdays (default 7), snoozed and snoozed
until today, plus fetch problems (last_error, folder errors, messages given up on).--json
for a fixed JSON shape,--detailsfor the first five conversations behind each number
(subject, other side, age; never a body),--brandto narrow to one brand. Read only: no
write, no event, no log line, andunreadstays as it was. See "For agents / CLI" in the
README.
Changed
- The tab logic moved from
ConversationsControllerintoSupport\ConversationQuery, which the
listing, the unread badge in the nav andinbox:summarynow share. The tab counts and the
badge are unchanged.
0.2.2
Signatures, and the mails your website sends through the mailbox no longer count as yours.
Added
- [new] Signatures. Several per mailbox, set up in the new "Signaturen" tab of the mailbox form: a
name, plain text (line breaks stay, web addresses become links), one of them the default, and
optionally LeadHub tags. For a contact with one of those tags that signature is preselected; the
first one from the top wins, without a match the default. Placeholders:{{ sender.name }}and
{{ mailbox.email }}. The reply form has a picker with a preview underneath, "Keine" included.
The signature goes under the text and above the quote, after--in the text part. - [new] Replies are sent with an HTML part next to the text: everything escaped, links clickable, the
quote as a blockquote. - [new] With a signature chosen, the AI draft ends without a closing line carrying a name.
Changed
- The Migadu and All-Inkl presets send over port 587 with STARTTLS instead of 465. Many hosts block outbound
465, and the connection test then times out. Sites that publishedconfig/inbox.phpkeep their
own value; existing mailboxes keep their saved port. - Mails the website sends through the mailbox are system mails. Order and booking
confirmations, invoices, access mails in Sent no longer make a conversation relevant, no longer
set it to "waiting", and no longer make the recipient a known correspondent. On their own they
open no conversation (skip reasonsystem); inside one that exists anyway they show folded and
marked "automatisch". Recognised byAuto-Submitted,X-Auto-Response-SuppressorX-Suite-*
headers; otherwise never when a person clearly wrote it (a reply from the inbox, Gmail's
webmail, a mail program inUser-Agent/X-Mailersuch as Roundcube, Thunderbird, Apple Mail or
Outlook, or a mail that answers another); then by subject (inbox.system_mail.subjects, by
default the subjects the suite sends, in both forms of address), or by a Symfony/Laravel
Message-ID together with a sender name frominbox.system_mail.senders. The Message-ID alone
never decides: Roundcube builds the same shape. info+anything@domainis one of your own addresses wheninfo@domainis the mailbox address
or an alias: mail to or from it makes no conversation.inbox:reclassifyapplies both to what is stored: conversations made only of system mails or
only of mail to your own (plus) addresses are deleted with skip records, system mails in the
others are marked. It prints "only system mails" and "marked as automatic".
Fixed
- [fix] A reply sent from the inbox gets its IMAP UID once the fetch meets it in Sent, so
inbox:reclassifycan read its headers later.
Security
- The clean-up that deletes conversations (hiding a sender,
inbox:reclassify) took a reason
given as text for a callable when the text named a PHP function. In 0.2.1 only the fixed
reasonsselfandblockedreached it, never outside input, so it was not reachable; the
reasonsystemof this release would have been. A reason is now only ever called when it is a
closure.
Upgrading
php artisan migrate(addsinbox_mailboxes.signaturesandinbox_messages.automatic), then
php artisan inbox:reclassify --dry-run, then without--dry-run.
0.2.1
The filter could hide or delete real leads. Fixed, with a way to get back what 0.2.0 skipped.
Fixed
- [fix] Hiding a sender or domain deletes first contacts only. Conversations you answered, with a
LeadHub contact, or taken over stay, your own sent mails in them included. Hiding works only from
a conversation in "Neu", and the dialog says beforehand how many conversations will be deleted.
A contact, someone you have written to before, or a reply in an existing conversation now also
gets through a hidden sender or domain. - [fix] Sent is read before INBOX. A reply that arrived in INBOX in the same fetch as your mail found
no thread yet and could be taken for bulk mail (an out-of-office answer, a ticket system).
Someone you have written to before is now an exception from the bulk filter as well. - [fix] Contact forms and booking tools. A mail from
noreply@with a person inReply-Tois that
person: they become the other side of the conversation, the exceptions apply to them, and the
no-reply rule does not fire. - [fix] Skip records keep less. The Message-ID only as a SHA-256 hash, the sender only for hidden
senders (where removing the rule needs it). A migration clears the sender of the others. - [fix] Removing a hidden sender needs
reply inbox, like hiding it; before, it needed
manage inbox mailboxes. - [fix]
inbox:reclassifytakes a conversation out of "Neu" once it has become relevant, applies
relevance even when headers cannot be read (archived mail), and reads headers stored by 0.2.0
again because they lackReply-To. - [fix] A conversation that starts with your reply is titled without
Re:.
Added
- [new]
inbox:reclassify --reconsider-skipped [--dry-run]looks at every skip record again (except
hidden senders): headers by PEEK at the recorded folder and UID, or, when the UID is gone, a
search by Message-ID in INBOX and All Mail. What no longer counts as bulk mail is imported; the
records left are hashed.
Upgrading
php artisan migrate, thenphp artisan inbox:reclassify --reconsider-skipped --dry-run, then
without--dry-run, thenphp artisan inbox:reclassify --dry-runto check nothing is left.
0.2.0
Only relevant mail. The inbox is for conversations with leads and customers; newsletters and
invoices stay in your mail program.
Added
- [new] Bulk mail is not taken over. A mail with
List-Unsubscribe,List-IdorList-Post,
Precedence: bulk/list/junk,Auto-Submitted(other thanno), typical mailing-service headers
(Feedback-ID,X-Campaign,X-Mailchimp-*,X-SES-Outgoing,X-MC-Userand more, extendable
viainbox.filter.bulk_headers), a no-reply sender or an emptyReturn-Path(bounces) is not
stored at all. Only a skip record is kept (Message-ID, folder, UID, reason), so it is not fetched
twice. A LeadHub contact and a reply in an existing conversation always come through. Sent mail
to more than ten people or by Bcc list counts as a circular and is skipped too. Switch per
mailbox: "Massenmails überspringen", on by default. - [new] First contacts in their own tab "Neu". A conversation is relevant when the other side is a
LeadHub contact, when you answered or started it, or when you have written to that address from
this mailbox before. Everything else is filed asnew: shown only in "Neu", with its own count,
not in the menu badge. Actions there: "Übernehmen", "Kontakt anlegen", "Absender ausblenden",
"Domain ausblenden". A reply takes a conversation out of "Neu" by itself. - [new] Hidden senders and domains. Hiding deletes the existing conversations in Statamic
(attachments included) and keeps future mail out; the mails stay in Gmail or your mailbox.
Freemail domains (gmail.com, gmx.de, web.de and others) can only be hidden sender by sender. The
mailbox page lists the rules with "Entfernen". - [new] Own addresses. Aliases per mailbox; mail between your own addresses makes no conversation.
- [new]
inbox:reclassify {--mailbox=} {--dry-run}applies the filter to mail imported before: reads the
headers again over IMAP (headers only, PEEK, nothing is marked read), deletes bulk and
to-yourself conversations with their files, files unknown people under "Neu". Always run
--dry-runfirst. - [new] The mailbox page shows the bulk mail skipped in the last 30 days.
- [new] New messages store the headers the filter decides on (
filter_headers), so a rule change can be
applied again without asking the server.
Changed
- A first contact from someone unknown now arrives as
new, notopen.
Fixed
- [fix] The mailbox form now saves the sender name ("Absendername"); since 0.1.0 it was shown but not
sent.
Upgrading
- Run
php artisan migrate, thenphp artisan inbox:reclassify --dry-runand, when the numbers
look right,php artisan inbox:reclassify.
0.1.1
Fixed
- [fix] The addon list no longer calls the addon "Postfach-Einstellungen". The settings entry gets its name from
settingsTitle()(brand-context 1.15), not from a global translation of the addon name "Inbox". With an older brand-context the entry reads "Inbox".
0.1.0
First release.
- Control Panel: the inbox as core's Listing (tabs Offen, Wartet, Erledigt, Geschlummert, search,
mailbox filter, unread dot, failed sends), fetch problems per mailbox above it, an empty state
that leads to connecting a mailbox. - Conversation screen: thread with older messages and quoted text folded, HTML in a sandboxed
frame without scripts, remote images only on click, inline images and attachments through the
permission-checked route, LeadHub contact card or "Kontakt anlegen", status and snooze, reply
form with template and AI draft that only fill the text. - Mailbox screens: list, create and edit with provider presets, write-only password that is asked
for again when server, port or login change, connection test before or after saving. - German translations (
lang/de.json),scripts/setup-playground.shwith seed data from the
IMAP fake. - Package skeleton: service provider, per-brand settings through brand-context, permissions
view inbox,reply inbox,manage inbox mailboxes. - Fetching over IMAP (directorytree/imapengine): INBOX and Sent, UID cursor per folder, first run
fromimport_since(90 days), dedupe by Message-ID per mailbox,inbox:fetchevery minute with
a lock per mailbox, each mailbox inside its brand. - Threading by In-Reply-To, References, then counterpart plus normalised subject within 30 days.
- Parsing with zbateson/mail-mime-parser, HTML through symfony/html-sanitizer with remote images
held back (data-inbox-src), quoted replies stripped (own marker, then email-reply-parser). - Replies over the mailbox's own SMTP with Message-ID, In-Reply-To and References, APPEND to Sent
except on Gmail, queued, failures kept on the message (send_error). - Suppression: hard bounce, complaint and invalid address block a reply; fail-closed.
- LeadHub: contact linking (never creating), timeline entries deduped by
inbox:{message_id}. - AI draft (Claude Messages API,
ANTHROPIC_API_KEY), templates from email-templates, activity
producer and an automations trigger; all optional and detected at runtime. - Host guard against private, loopback and link-local IMAP/SMTP hosts.
- CP JSON endpoints and Inertia pages (
inbox::…); the Vue screens follow. - Hardening after review: a message that cannot be stored no longer freezes a mailbox (ledger
inbox_fetch_failures, three attempts, then given up visibly); overlong fields are cut, overlong
Message-IDs indexed by hash; errors per folder (folder_errors) apart from a broken mailbox;
UIDVALIDITY per folder; future Date headers clamped;srcsetand<source>blocked as remote
images;cid:images mapped to the attachment route; APPEND failures kept asfiled_error;
password required again when host, port or login change (also for the connection test);
Gmail and Sent folder re-detected on a host change; contact links checked against LeadHub. - Nav item "Postfach" with the unread count, "E-Mails" panel on the LeadHub contact, and
"Kontakt anlegen" from a conversation. The unuseddefault_mailboxsetting is gone. - AI drafts default to
claude-sonnet-5.