In-Reply-To, References 헤더가 빠진 채로 수신되어,
서버의 1순위 매칭 키(emails.message_id ↔ in_reply_to)가 비어 작동하지 못했고,
email_replies 매핑 행이 생성되지 않아 inbox 에서 이전 발송 스레드와 연결되지 않았습니다.
이는 PR #7922
(multi-reply 덮어쓰기 버그) 와는 별개의 케이스이며, 코드 버그가 아닌 헤더 부재로 인한 알고리즘 한계입니다.
In-Reply-To 가 정상 파싱·저장되고 있으며,
본 9건의 raw_email 원문을 정규식으로 grep 한 결과 9건 모두 헤더 자체가 부재합니다
(raw_email ~* '^(in-reply-to|references):' → 0 hit).
"네이버만 유독" 도 아니며 도메인별 패턴이 명확합니다.
해당 lead 의 모든 메일 (created_at DESC):
| 시간 (KST) | 방향 | 제목 / 본문 | message_id | in_reply_to | thread_id |
|---|---|---|---|---|---|
| 05-26 19:38 | inbound | "제목 : 해외세일즈 자동화건" | <3fa93de7…@cmweb01.nm> | NULL | <3fa93de7…@cmweb01.nm> (자기 자신) |
| 05-26 19:35 | inbound | (제목 없음, 본문 "네~ !") | <f46a427a…@cmweb03.nm> | NULL | <f46a427a…@cmweb03.nm> (자기 자신) |
| 05-12 12:42 | outbound | (광고) 돛단배수산 대표님, K-Food 해외 수요 관련하여 공유드립니다 | <010c019e1a46…@amazonses.com> | — | <010c019dd6a8…@amazonses.com> |
| 04-30 25:17 | outbound | (광고) 돛단배수산 해외 영업 관련하여 한 번 더 연락드립니다 | <010c019ddf2e…@amazonses.com> | — | <010c019dd6a8…@amazonses.com> |
| 04-29 09:33 | outbound | (광고) 돛단배수산 해외 영업 관련하여 제안드립니다 | <010c019dd6a8…@amazonses.com> | — | <010c019dd6a8…@amazonses.com> (시퀀스 첫발송) |
SELECT * FROM email_replies WHERE reply_email_id IN (<5/26 inbound 2건>) OR original_email_id IN (<4/29–5/12 outbound 3건>); -- 결과: 0 rows
즉 우리 시스템은 두 inbound 를 "어떤 outbound 의 회신" 으로도 인식하지 못했고, 매핑 행 자체가 만들어지지 않았습니다.
@ap-northeast-2.amazonses.com010c019dd6a8…)@cmweb01.nm, @cmweb03.nm (네이버 발신 서버)in_reply_to: NULLreferences: 캡처되지 않음 (별도 컬럼 없음 + body 에도 인용 없음 추정)"네이버 메일 앱에서 보냈습니다." + In-Reply-To NULL 패턴 →
고객이 받은편지함에서 우리 메일을 보고 별도로 새 메일을 작성해 rinda@send.grinda.ai 로 직접 보냈을 가능성이 큼.
(네이버 앱이 정상 "답장" 으로 보낼 때는 In-Reply-To 를 채워서 보내는 것이 기준임 — 다른 회신 메일 케이스에서 확인됨.)
"우리가 파싱을 못하는 건지 / 네이버만 유독 그런 건지" 검증을 위한 모집단 분포:
| 도메인 | inbound | NULL | NULL % | 해석 |
|---|---|---|---|---|
naver.com | 182 | 9 | 4.9% | 정상 — 본 9건이 예외 케이스 |
gmail.com | 37 | 2 | 5.4% | 정상 |
qq.com, dooray.com, helenacoffee.vn, acb.com.vn, umma.io, diligencecertification.com, help.boots.com | 5~8 each | 0 | 0% | 완전 정상 (정상 클라이언트 답장) |
cosmoprofna.com, qogita.com, cxrd.co | 6~8 | 1~4 | 12~67% | 혼재 — 일부 직접 회신 |
ap-northeast-2.amazonses.com (SES 시스템 메일) | 5,111 | 4,800 | 93.9% | bounce/complaint/auto-reply — 답장 아님 (제외 모집단) |
hanmail.net (다음) | 20 | 20 | 100% | ⚠ 다음 웹메일이 헤더를 안 보내는 듯 — 별도 조사 필요 |
daum.net | 12 | 12 | 100% | ⚠ 동일 (다음 메일 인프라) |
자사 도메인 (fancl.co.jp, unilever.com, atlifestylestore.com, watsons.co.th, tsum.ru, mail.terravita.fr 등) | 5~11 each | 전수 | 100% | 회사 메일 시스템이 답장 시 새 스레드로 보냄 (또는 CRM/Zoho 등이 인입) |
raw_email 원문 grep 결과 헤더 자체가 부재 → 발신자가 새 메일로 보낸 것hanmail.net/daum.net) 은 100% NULL — 단독으로 별도 조사 가치 있음 (다음 웹메일이 답장 시 헤더를 의도적으로 제거하는지)SELECT COUNT(*) FILTER (WHERE raw_email ~* '^(in-reply-to|references)[[:space:]]*:') AS has_header,
COUNT(*) FILTER (WHERE raw_email !~* '^(in-reply-to|references)[[:space:]]*:') AS no_header
FROM emails WHERE id IN (<9개 ID>);
-- has_header: 0 | no_header: 9
즉 우리가 헤더를 받고도 무시한 게 아니라, 메일 원문에 헤더가 도착하지 않은 것이 확정.
→ Re:/RE:/회신: prefix 가 단 1건도 없음. 모두 "받은 광고에 대해 새 메일로 자기 소개를 시작하는" 한국 비즈니스 메일 패턴. 옵션 A(from_email + 시간 윈도우) 가 가장 효과적인 모집단.
| 우선순위 | 매칭 키 | 코드 위치 | 이번 케이스 결과 |
|---|---|---|---|
| 1 | In-Reply-To → emails.message_id |
webhook.service.ts:277, unipile-reply.service.ts |
❌ in_reply_to=NULL → 미실행 |
| 2 | from_email → lead.findLeadByEmail() |
webhook.service.ts:326 |
⚠ lead 식별은 가능하나 thread/sequence 연결은 아님 |
| 3 | leadId → sequence_enrollments |
webhook.service.ts:348-366 |
⚠ enrollment 추정은 되나 특정 outbound 와의 1:1 매핑은 못 만듦 → email_replies INSERT 조건 불충족 |
| — | Subject prefix (Re:/회신:) 매칭 | 미구현 | 설령 구현돼 있었어도 본 케이스는 prefix 없음 → fail |
| PR #7922 케이스 | 본 케이스 (kimgihan9895) | |
|---|---|---|
| In-Reply-To 헤더 | ✓ 있음 (정상 reply) | ✗ NULL (새 메일) |
| email_replies INSERT | ✓ 수행됨 (이후 UPDATE 가 덮어씀) | ✗ 아예 수행 안 됨 |
| 손실 메커니즘 | 같은 outbound 에 2번째 회신이 들어와 첫 회신 매핑이 UPDATE 로 덮어써짐 | 매칭 키 부재 → 매핑 미생성 |
| 버그 분류 | 코드 버그 (UPSERT 키 설계 오류) | 알고리즘 한계 (헤더 부재 fallback 부족) |
| 수정 | 완료 (734783db5, 5/27 머지) | 미해결 — 아래 옵션 참고 |
In-Reply-To 부재 시, 동일 from_email 의 lead 로 보낸 direction=outbound 중
가장 최근(예: 60일 이내)의 outbound 를 original_email_id 로 추정해 매핑.
reply_classification 에 "heuristic_match" 표시 + UI 에서 "추정 매칭" 라벨 노출 필요unipile-reply.service.ts 의 originalEmail 조회 분기 (현재 In-Reply-To 매칭 실패 시 그냥 lead-only fallback) 에 윈도우 쿼리 추가Re:, 회신:, 제목 :) 기반 매칭 보조본 케이스는 inbound subject 가 "제목 : 해외세일즈 자동화건" 으로 Re: prefix 가 없고 outbound subject 와도 직접 일치하지 않음 → 단독으로는 부족. 옵션 A의 tie-break 보조로만 유효.
본문 안에 인용된 outbound subject/snippet 을 grep 으로 찾아 매칭. 본 케이스의 본문은 "네~ !" 한 줄이라 적용 불가. 일반 케이스 보강용으로는 가치 있음.
발송 메일 푸터에 "이 메일에 직접 답장(Reply) 해주세요" 또는 회신 전용 mailto 링크 노출. 신규 회신만 개선, 본 케이스 같은 모바일 앱 새 메일 작성은 여전히 누락 가능. 옵션 A 와 병행 권장.
in_reply_to IS NULL 건수 / 전체 inbound 비율 (= 잠재 매칭 실패 모집단)