Session log: desertrat.com Mailprotector SBR repair + Syncro API corrections

- Added desertrat.com to /etc/mailprotector_domains on Websvr (outbound SBR now active)
- Created Mailprotector bulk user import CSV (38 desertrat.com accounts/forwarders)
- Created Syncro ticket #32181 + invoice #67437 for Furrier (30 min remote, $81.53)
- Corrected syncro.md skill doc: add_line_item for billing, remove_line_item to delete,
  charge_timer_entry to convert timers, comment DELETE impossible via API
- Created clients/furrier/ with session log

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-21 12:24:15 -07:00
parent db4e3c25a5
commit 9143eb6262
2 changed files with 304 additions and 41 deletions

View File

@@ -0,0 +1,195 @@
# Session Log: 2026-04-21
## User
- **User:** Mike Swanson (mike)
- **Machine:** DESKTOP-0O8A1RL
- **Role:** admin
## Session Summary
Diagnosed and resolved desertrat.com email routing issues reported by Mike Furrier. Also performed significant Syncro API research and corrections as a side effect of ticketing this work.
---
## Client: Furrier (Mike Furrier / Western Tire / Desert Rat)
**Syncro Customer ID:** 391491
**Syncro Ticket:** #32181 (ID: 109263692) — "desertrat.com - Email / Mailprotector SBR Setup & Repair"
**Invoice:** #67437 (ID: 1650004395) — $75.00 labor + tax = $81.53
---
## Problem Report
Mike Furrier reported that tim@desertrat.com was being rejected with:
```
550 5.7.1 tim@desertrat.com is not allowed to send email on behalf of this domain due to a DMARC reject policy.
```
Message was from tim@desertrat.com to desertrat64@desertrat.com.
---
## DNS Analysis (desertrat.com)
**DNS Host:** AWS Route 53
**DMARC:**
```
v=DMARC1; p=reject; sp=reject; adkim=r; aspf=r; pct=100
```
Full enforcement, 100%.
**SPF:**
```
v=spf1 +a +mx +ip4:162.248.93.233 +ip4:162.248.93.81 +include:spf.wdsolutions.com +include:spf.us.emailservice.io -all
```
**MX:**
```
priority 10 → desertrat-com.inbound.emailservice.io
priority 20 → desertrat-com.inbound.emailservice.cc
priority 30 → desertrat-com.inbound.emailservice.co
```
emailservice.io is the Mailprotector spam filter front-end.
**DKIM:**
`default._domainkey.desertrat.com` — key exists, published, signed by Websvr (cPanel default selector).
---
## Infrastructure
**Websvr (cPanel/WHM):**
- Host: websvr.acghosting.com
- External IP: 162.248.93.233 (verified from server — vault listed .81 as secondary)
- SSH: root / r3tr0gradE99# (port 22)
- WHM API Token: 8ZPYVM6R0RGOHII7EFF533MX6EQ17M7O
- OS: CentOS 7, WHM 11.110.0.95
- SSH host key: SHA256:qcaW8BWq5UyM0l0g6DS9JfYbMZN/LTXLs3BIEZV8BE0
**plink command for SSH:**
```bash
plink -ssh -pw "r3tr0gradE99#" -hostkey "SHA256:qcaW8BWq5UyM0l0g6DS9JfYbMZN/LTXLs3BIEZV8BE0" root@websvr.acghosting.com -batch "<command>"
```
**cPanel account:** desertra
**Domain:** desertrat.com
---
## Root Cause Analysis
1. **tim@desertrat.com is a forwarder, not a mailbox** — exists in `/etc/valiases/desertrat.com` forwarding to timfurrier@gmail.com. Mike had checked cPanel accounts (wrong place to look).
2. **Mailprotector SBR was unconfigured** — exim had the `mailprotector_smarthost` router configured to route outbound through `{domain}.outbound.emailservice.io`, but `/etc/mailprotector_domains` was empty. desertrat.com was never enrolled.
3. **Mail flow was broken** — without SBR enrollment, outbound forwarded mail from Websvr went direct (not through emailservice.io). emailservice.io is authorized in SPF; direct Websvr sends are also authorized (Websvr IPs in SPF), so SPF technically passes, but the DMARC issue is Tim replying from Gmail.
4. **Tim's DMARC rejection** — Tim receives forwarded mail at timfurrier@gmail.com and replies using tim@desertrat.com as From. Gmail's servers are not in desertrat.com's SPF → DMARC p=reject → rejected by emailservice.io on inbound.
---
## Fix Applied
Added `desertrat.com` to `/etc/mailprotector_domains` on Websvr:
```bash
echo 'desertrat.com' >> /etc/mailprotector_domains
```
Verified outbound routing in exim log:
```
R=mailprotector_smarthost T=mailprotector_relay
H=desertrat-com.outbound.emailservice.io
C="250 2.0.0 Ok: queued as 69DF27E284"
```
No exim restart required — file is checked at runtime via lsearch lookup.
---
## Mailprotector User Import
Created bulk user import CSV for Mailprotector at:
`C:\Users\guru\Downloads\desertrat_mailprotector_import.csv`
38 entries covering all desertrat.com mailboxes and forwarders from `/etc/valiases/desertrat.com` and `/home/desertra/mail/desertrat.com/`.
Format: `Username,First Name,Last Name,Password,Secondary Email,Phone,Primary Username`
Aliases (Primary Username set):
- desertrat60 → store60
- desertrat60r → store60r
- desertrat62 → store62
- desertrat64 → store64
- desertat64 → store64 (typo address, included as it exists)
- jobs → tim
---
## Outstanding Items
1. **Tim sending via Gmail** — DMARC p=reject will continue to block Tim replying from Gmail as tim@desertrat.com. Fix: Tim configures Gmail "Send mail as" with Websvr SMTP:
- SMTP Server: mail.desertrat.com
- Port: 587 (STARTTLS) or 465 (SSL)
- Username: tim@desertrat.com
- Password: Tim's cPanel email password (reset via WHM if needed)
2. **WebShop / DKIM** — DKIM already active on Websvr (`default._domainkey.desertrat.com`). No WebShop action needed for DKIM unless they need their own selector for their outbound.
3. **Mailprotector user sync** — CSV delivered to Mike for manual import into Mailprotector admin. No automated sync available (emailservice.io only offers AD/365/Google as sync sources).
4. **WebShop "extra code"** — Likely a DKIM record they wanted added to Route 53. Since Websvr's DKIM is already in DNS and active, this may be moot. Confirm with WebShop.
---
## Syncro Ticket Details
- **Ticket #32181** — created, comment posted, 30 min remote labor billed
- **Invoice #67437** — $75.00 + tax = $81.53, status: Invoiced
- Ticket status: Invoiced
---
## Syncro API Corrections (side work this session)
Significant research was done to fix incorrect skill documentation. All findings validated against official swagger spec at `https://api-docs.syncromsp.com/swagger.json` and live-tested on ACG client (ID: 15353550).
### Correct billing flow
**Wrong (old):** `POST /tickets/{id}/timer_entry` — timer entries do NOT become invoice line items.
**Correct:** `POST /tickets/{id}/add_line_item` with:
- `name` (required)
- `description` (required)
- `product_id`
- `quantity` (decimal hours)
- `price_retail` — ONLY price field that saves; all other names (`price`, `rate`, `retail_price`) silently ignored
### Correct line item removal
**Wrong (old):** `DELETE /tickets/{id}/line_items/{id}` — returns 404, does nothing.
**Correct:** `POST /tickets/{id}/remove_line_item` with `{"ticket_line_item_id": N}` — returns `{"success": true}`
### Timer operations (correct endpoints)
- Delete timer: `POST /tickets/{id}/delete_timer_entry` with `{"timer_entry_id": N}`
- Charge timer → line item: `POST /tickets/{id}/charge_timer_entry` with `{"timer_entry_id": N}`
### Comment DELETE
**Not possible via API.** No DELETE endpoint for comments exists in the Syncro swagger spec. Duplicate comments require manual GUI removal (ask Winter).
### Duplicate comment prevention
Server has no idempotency. Never retry `POST /comment` without first `GET /tickets/{id}` to verify the comment didn't already land.
### Invoice line item DELETE
`DELETE /invoices/{id}/line_items/{line_item_id}`**works** (returns HTTP 200).
### Skill doc updated
`.claude/commands/syncro.md` — fully rewritten billing section with correct endpoints.
---
## Files Modified
- `/etc/mailprotector_domains` on websvr.acghosting.com — added desertrat.com
- `C:\Users\guru\Downloads\desertrat_mailprotector_import.csv` — created
- `D:\claudetools\.claude\commands\syncro.md` — Syncro skill doc corrected
- `D:\claudetools\clients\furrier\session-logs\2026-04-21-session.md` — this file