anthropics / anthropics/claude-plugins-official
imessage: self-chat silently dropped when self-chat handle (phone) differs from Apple ID account (email)
- Ngôn ngữ chính
- Python
- Star
- 36.3k
- Fork
- 4.1k
- Merge trung bình
- 2 ngày 14 giờ
- Pull request đã merge (30 ngày)
- 539
Mô tả
## Summary
The iMessage plugin silently drops **all** self-chat (Note-to-Self) messages when your self-chat is keyed by your **phone number** but your iMessage `account` identity is an **email** (the normal case for iPhone users). The README promises "self-chat bypasses access control," but in this configuration self-chat never bypasses anything — every message is dropped by the DM gate.
`external_plugins/imessage/server.ts`, v0.1.0, macOS.
## Root cause
`SELF` is built only from the `account` column of your sent messages:
```
// server.ts ~L181
SELECT DISTINCT account AS addr FROM message WHERE is_from_me = 1 AND account IS NOT NULL AND account != '' LIMIT 50
```
The `account` column holds your Apple ID **sending** identity, which for most people is an email (e.g. `E:you@example.com`). But a Note-to-Self chat is very commonly keyed by your **phone number** (`+1XXXXXXXXXX`), and that number never appears in `account`. So:
```
// server.ts L804
const isSelfChat = !isGroup && SELF.has(sender.toLowerCase()) // sender = "+1XXXXXXXXXX", SELF = {"you@example.com"} -> false
```
`isSelfChat` is `false`, so the message falls through to the DM gate, and with the default empty allowlist it is dropped:
```
// server.ts ~L333-335
if (!input.isGroup) {
if (access.allowFrom.includes(input.senderId)) return { action: 'deliver' }
if (access.dmPolicy === 'allowlist') return { action: 'drop' } // <- every self-chat message dies here
```
## Reproduction
1. On an iPhone-linked Mac where your self-chat thread is addressed by phone number (Messages shows a "You" thread keyed to your number) and your Apple ID is an email.
2. Launch with `claude --channels plugin:imessage@claude-plugins-official`.
3. Text yourself anything. It reaches `chat.db` but never injects into the session.
Verified against `chat.db`:
- The received (`is_from_me=0`) self-echo row has `handle_id -> +1XXXXXXXXXX` (phone), while `account = E:you@example.com` (email). These never match after `SELF.has(sender.toLowerCase())`.
- (Separately confirmed the body decodes fine via `parseAttributedBody` — `text` is NULL, content is in `attributedBody`. So decoding is not the problem; identity matching is.)
There is no structural way in `chat.db` to tie the phone-number handle back to "you" via `account`, so the current single-source `SELF` can't self-correct.
## Why a plain allowlist entry is not the fix
Adding your own number to `allowFrom` delivers the messages, but echo suppression (`consumeEcho`, L805) only runs under `isSelfChat`. Since it would still be `false`, the plugin's own outbound replies (which come back as `is_from_me=0` echoes on the self-chat) would loop back in as commands. The correct fix must make `isSelfChat` true.
## Proposed fix (two parts)
**1. Auto-detect self-chat handles (fixes the common case, no config).**
In addition to the `account` query, add to `SELF` the handle of any 1:1 chat that contains a *self-echo* — a message present as **both** `is_from_me=1` and `is_from_me=0` with matching text/`attributedBody` and near-identical timestamp. That duplication is characteristic of Note-to-Self chats and does not occur in normal DMs, so it reliably identifies your own phone/email handles without any configuration. (Can be scoped to recent messages for performance.)
**2. Explicit escape hatch (idiomatic, deterministic).**
Honor an `IMESSAGE_SELF_IDS` env var (comma-separated handles), appended to `SELF`, matching the existing `IMESSAGE_ACCESS_MODE` / `IMESSAGE_ALLOW_SMS` / `IMESSAGE_DB_PATH` convention. Covers multi-number setups, aliases, and CI. Sketch:
```ts
// after the existing SELF-building block
for (const id of (process.env.IMESSAGE_SELF_IDS ?? '')
.split(',')
.map((s) => s.trim().replace(/^[A-Za-z]:/, '').toLowerCase())
.filter(Boolean)) SELF.add(id)
```
Plus a note in README.md / ACCESS.md.
I've been running (2) locally as a patch and it fully resolves it. Happy to help validate a maintainer's implementation of (1).
Hướng dẫn đóng góp
Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này
Hướng nghiên cứu
Start in external_plugins/imessage/server.ts with the SELF-building query around L181, the DM gate around L333-335, and isSelfChat/consumeEcho around L804-805. Reproduce the phone-versus-email identity mismatch against chat.db, then verify that self-chat handles are recognized, echo suppression still works, and IMESSAGE_SELF_IDS plus the README.md/ACCESS.md documentation cover the explicit configuration path.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- macos, sqlite, typescript
- Lĩnh vực
- authentication, backend, databases
- Loại issue
- Lỗi
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức độ hoạt động
- Ít trao đổi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức phù hợp với người mới
- 55/100