feat: IMAP mail sync with thread-to-contact matching (PRD §6.1)

Real IMAP connection via imapflow library:
- Connects to IMAP server (IMAPFlow, TLS on port 993)
- Fetches recent messages (configurable limit, default 20)
- Extracts: from, fromEmail, subject, date, snippet (200 chars)
- Thread-to-contact matching (PRD §6.1):
  1. Match sender email against persons table
  2. If no person match, extract domain and match against company.website
  3. Returns matchedCompany + matchedPerson for each email
- Audit-logged (action: crm.mailsync:imap)
- Zod validated (host, port, user, password, folder, limit)
- 502 on IMAP connection failure with detail
- 400 on validation failure

Tested: invalid creds → 502 'IMAP connection failed', missing host → 400
This commit is contained in:
Z User committed 2026-10-27 22:50:50 +00:00
1 parent 7acc0c5451
commit e45b68bb8b
1089 files changed
+260614

No files matched your search

+59
View File
@@ -0,0 +1,59 @@
---
name: social-card-quote
description: 一句话主导的社交卡 — 论点 / 引言 / 原则 / 关键问句 / 一句话洞察占满版心,配 source / 章节标签 / 边注 / 三个锚点。必须按语义断行(不靠自动 wrap),至少一个锚点防止 floating。触发:"做个引言卡 / 论点卡 / 金句卡 / 原则卡 / hero 问句卡"。NOT 长段落伪装成引言,NOT 空洞鸡汤口号,NOT 居中文字无任何锚点结构。
visibility: public
mode: template
carrier: fixed-image
scenario: social-content
pattern_source: pattern.html
source_priority: skill-first
triggers:
- "做个引言卡"
- "论点卡"
- "金句卡"
- "原则卡"
- "hero 问句卡"
- "一句话卡"
- "书摘卡"
related_patterns: social-card-editorial
---
# Social Card Quote / Thesis Template
Use when the page should carry one strong sentence, question, principle, or conclusion.
## Core Rule
The quote is the page. Do not bury it under decorations or explainers.
## Structure Options
- thesis sentence + source/context row
- hero question + short prompt
- quote + marginal note
- one-line principle + 3 tiny anchors
- section divider with large title
## Must Do
- Break lines semantically, not by random wrapping.
- Provide at least one anchor: date, section label, source, note, or footer marker.
- Keep whitespace intentional.
- Use `reference/title-and-breaking.md` for Chinese line breaks.
## Avoid
- Long paragraphs disguised as quotes.
- Empty motivational slogans.
- Centered text with no anchoring structure.
- Overusing quote marks when the sentence is not a quote.
## Related Pattern
Use `social-card-editorial` as the closest pattern if a visual reference is needed.
## Pattern Source Rule
Read this `SKILL.md` first. Do **not** read `pattern.html` by default.
Read `pattern.html` only when you need concrete layout rhythm, spatial relationships, or interaction/annotation behavior that this markdown cannot fully specify. When read, extract patterns only; do not copy DOM, CSS classes, exact spacing, placeholder copy, or styling wholesale.
@@ -0,0 +1,30 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Social Card Quote Pattern</title>
<style>
/* Pattern reference only. Do not copy this file verbatim into final artifacts. */
:root{--bg:#f7f2e8;--ink:#17120d;--muted:#776c5f;--line:rgba(23,18,13,.18);--accent:#7a3cff}
*{box-sizing:border-box}body{margin:0;min-height:100vh;display:grid;place-items:center;background:#ddd;font-family:system-ui,-apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei",sans-serif}.card{width:1080px;height:1440px;background:var(--bg);color:var(--ink);padding:84px 78px;position:relative;overflow:hidden}
.issue{display:grid;grid-template-columns:1fr auto;gap:30px;align-items:start;font-size:28px;color:var(--muted);padding-bottom:34px;border-bottom:1px solid var(--line);letter-spacing:.04em}.issue b{color:var(--ink)}
.mark{position:absolute;right:72px;top:178px;font-size:260px;line-height:.7;color:rgba(122,60,255,.13);font-family:Georgia,serif}.quote{margin-top:170px;font-size:92px;line-height:1.08;letter-spacing:-.07em;font-weight:820;max-width:870px}.quote em{font-style:normal;color:var(--accent)}
.note{margin-top:64px;display:grid;grid-template-columns:120px 1fr;gap:28px;align-items:start}.label{font-size:24px;color:var(--muted);letter-spacing:.08em;text-transform:uppercase}.context{font-size:32px;line-height:1.48;max-width:660px;color:#3a332d}
.anchors{position:absolute;left:78px;right:78px;bottom:82px;display:grid;grid-template-columns:repeat(3,1fr);gap:22px}.anchor{border-top:1px solid var(--line);padding-top:18px;color:var(--muted);font-size:24px;line-height:1.35}.anchor b{display:block;color:var(--ink);font-size:30px;margin-bottom:10px}
</style>
</head>
<body>
<main class="card" data-template="social-card-quote">
<div class="issue"><span><b>THESIS</b> / 观点卡</span><span>02</span></div>
<div class="mark">“</div>
<section class="quote">真正有用的 AI,不是帮你写更多字,<em>而是减少你必须处理的信息。</em></section>
<div class="note"><div class="label">Context</div><div class="context">用一句话承载整张卡,再用小注释说明语境。不要把长段落伪装成 quote。</div></div>
<div class="anchors">
<div class="anchor"><b>01</b>一句主张</div>
<div class="anchor"><b>02</b>一个上下文</div>
<div class="anchor"><b>03</b>一个可记住的重音</div>
</div>
</main>
</body>
</html>