toga-ai 1.0.309 → 1.0.310
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -7,7 +7,7 @@ client: shared
|
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
9
|
updated: 2026-07-09
|
|
10
|
-
owners: ["jcardinal", "dfranks"]
|
|
10
|
+
owners: ["jcardinal", "dfranks", "mhammontree"]
|
|
11
11
|
files:
|
|
12
12
|
- crons/tickets.php
|
|
13
13
|
- crons/tickets_prod.php
|
|
@@ -40,6 +40,19 @@ TOGa Desk ingests support email into tickets through a cron-driven IMAP poller
|
|
|
40
40
|
3. **Parse & route (`emailToTicket()`):** extract from/to/cc/subject/body (with encoding fixes);
|
|
41
41
|
match an existing ticket via `In-Reply-To` + `Message-ID` headers and **plus-addressing**
|
|
42
42
|
(`support+<ticketnum>@…`). Matched ⇒ `addReply()`; otherwise ⇒ `add()`.
|
|
43
|
+
- **Noise suppression (before any ticket/attachment is created):** both feeders drop known
|
|
44
|
+
automated no-noise mail via the shared helper
|
|
45
|
+
`Ticket::isSuppressedNoiseEmail(?string $from, ?string $subject): bool` (static, in
|
|
46
|
+
`class.ticket.php`). It returns true only when the sender matches `/^no-?reply@/` **AND**
|
|
47
|
+
the subject starts with `staples po ` — both required so a real person is never blocked, and
|
|
48
|
+
the sender check is **domain-agnostic** (matches `noreply@togatech.com` /
|
|
49
|
+
`noreply@goagilant.com` and survives future sender-domain flips; the Staples PO alert sender
|
|
50
|
+
flipped `goagilant.com → togatech.com` on 2026-06-02). Wired into BOTH intake feeders:
|
|
51
|
+
`crons/tickets.php` adds it as one more `&&`-clause in the existing IMAP intake guard
|
|
52
|
+
(alongside the delivery-status / `MAILER-DAEMON` / Compass auto-reply filters);
|
|
53
|
+
`crons/pipe.php` uses it as an early guard-and-`exit(0)` right after the `$from`/`$subject`
|
|
54
|
+
parse. Each feeder logs a "suppressed" line. (TRUE-79975 — ~815 such alerts since Jun 2024,
|
|
55
|
+
~704 of them landing in the dept-1 "Support Desk" catch-all and being closed by hand.)
|
|
43
56
|
4. **Side effects:** auto-create a user when the sender domain maps to an existing client; assign
|
|
44
57
|
to a department via the department email lookup; save attachments locally then push to **S3**
|
|
45
58
|
(`App_Cloud::copyFileToS3()`, bucket `asifiles`); optionally generate Talos/TogaIQ summaries.
|
|
@@ -49,7 +62,12 @@ TOGa Desk ingests support email into tickets through a cron-driven IMAP poller
|
|
|
49
62
|
## Data model
|
|
50
63
|
Writes `tickets`, `tickets_replies`, attachment `files`; reads config from the `config` table
|
|
51
64
|
(`tickets_defaultdepartment`, `tickets_defaultclient`, `auto_close_tickets`,
|
|
52
|
-
`email_from_address`, `timezone`). Department routing keys on `tickets_departments.email
|
|
65
|
+
`email_from_address`, `timezone`). Department routing keys on a `tickets_departments.email`
|
|
66
|
+
`LIKE` match against the To/CC addresses; **anything unmatched falls through to config
|
|
67
|
+
`tickets_defaultdepartment` (= dept 1 "Support Desk" catch-all) and `tickets_defaultclient`** —
|
|
68
|
+
which is why unrouted/automated mail piles into "Support Desk". There is **no allowlist/blocklist
|
|
69
|
+
config framework**: noise filtering is ad-hoc inline guards in the crons (the hardcoded Compass
|
|
70
|
+
"Automatic reply:" filter and now `isSuppressedNoiseEmail`).
|
|
53
71
|
|
|
54
72
|
## Gotchas / known issues
|
|
55
73
|
- **`$processName` guard:** `tickets.php` throws if executed directly instead of via an env
|
|
@@ -59,7 +77,13 @@ Writes `tickets`, `tickets_replies`, attachment `files`; reads config from the `
|
|
|
59
77
|
- **Loop prevention** only excludes FROM==department-TO addresses; CC/reply-all across multiple
|
|
60
78
|
department addresses can still loop.
|
|
61
79
|
- **Auto-reply filters** are partly hardcoded (e.g. ignore `TechHub@compass-usa.com`
|
|
62
|
-
"Automatic reply:" messages)
|
|
80
|
+
"Automatic reply:" messages), and now the `isSuppressedNoiseEmail` Staples-PO filter — there
|
|
81
|
+
is no config-driven allow/block list, so each new noise source is another inline guard.
|
|
82
|
+
- **`Ticket::extractEmail()` returned an undefined offset on a no-match** (bare `$matches[0]`).
|
|
83
|
+
With a sender-less/malformed email this codebase promotes the warning to a thrown error
|
|
84
|
+
(`E_ALL` + `App_Error::handleError`), so an intake cron could **halt**. Hardened to
|
|
85
|
+
`return $matches[0] ?? '';` (TRUE-79975) — important because `isSuppressedNoiseEmail` routes
|
|
86
|
+
nullable/malformed sender input through `extractEmail`, putting this latent bug on the hot path.
|
|
63
87
|
- Attachments are deleted locally immediately after the S3 upload with **no retry** if S3 fails.
|
|
64
88
|
- **`adminid` clobber on reply routing:** after `emailToTicket()` sets `$data['adminid']` from
|
|
65
89
|
the FROM address (~line 1407), an asset lookup (~line 1437-1442) overwrites it with the
|
|
@@ -69,6 +93,10 @@ Writes `tickets`, `tickets_replies`, attachment `files`; reads config from the `
|
|
|
69
93
|
classification. See the ticket-lifecycle doc.
|
|
70
94
|
|
|
71
95
|
## Change history
|
|
96
|
+
- 2026-07-09 — added `Ticket::isSuppressedNoiseEmail()` noise suppression (no-reply sender + "Staples PO"
|
|
97
|
+
subject) wired into both feeders before ticket creation; hardened `extractEmail()` no-match to
|
|
98
|
+
`''`; documented the `tickets_defaultdepartment` → "Support Desk" catch-all fall-through
|
|
99
|
+
(TRUE-79975) (mhammontree)
|
|
72
100
|
- 2026-07-09 — documented the `emailToTicket()` adminid-overwrite reply misclassification
|
|
73
101
|
(TRUE-80114 planning investigation) (dfranks)
|
|
74
102
|
- 2026-06-15 — documented from a source read of `crons/tickets*.php` and `emailToTicket()` (jcardinal)
|
package/package.json
CHANGED