Files
Z User e45b68bb8b 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
2026-10-27 22:50:50 +00:00

441 lines
12 KiB
HTML
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>春日松弛感生活提案 · 小红书封面</title>
<style>
:root {
--mint: #cfe1cd; /* 顶部薄荷 */
--mint-soft: #e3edd9; /* 中部柔薄荷 */
--cream: #f1ebd9; /* 底部奶油 */
--grass: #8ab28a; /* 草绿 */
--ink: #2d4a3e; /* 深墨绿 */
--ink-soft: #557565; /* 灰墨绿 */
--line: #b8cdb5;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body {
background: #2a2a2a;
font-family: 'Songti SC', 'STSong', 'Source Han Serif SC', 'Noto Serif SC', 'Heiti SC', serif;
-webkit-font-smoothing: antialiased;
color: var(--ink);
}
body {
display: flex;
justify-content: center;
align-items: flex-start;
padding: 40px 0;
}
/* ===== 画布 1242×1660 ===== */
.cover {
width: 1242px;
height: 1660px;
position: relative;
background: var(--cream);
overflow: hidden;
box-shadow: 0 30px 80px rgba(0,0,0,.4);
}
/* 顶部薄荷绿渐变天空 */
.sky {
position: absolute;
top: 0; left: 0; right: 0;
height: 900px;
background: linear-gradient(180deg,
var(--mint) 0%,
var(--mint-soft) 55%,
var(--cream) 100%);
z-index: 0;
}
/* 顶部条:左上日期 + 右上品牌 */
.top-bar {
position: absolute;
top: 60px;
left: 60px;
right: 60px;
z-index: 5;
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.date-eng {
font-family: 'Times New Roman', 'Songti SC', serif;
font-style: italic;
font-weight: 400;
font-size: 32px;
color: var(--ink);
letter-spacing: 0.04em;
}
.brand-cn {
text-align: right;
color: var(--ink);
}
.brand-cn .line {
font-family: 'Songti SC', 'Source Han Serif SC', serif;
font-weight: 500;
font-size: 34px;
letter-spacing: 0.1em;
border-bottom: 1.5px solid var(--ink);
padding-bottom: 4px;
display: inline-block;
}
.brand-cn .sub {
font-size: 20px;
margin-top: 8px;
letter-spacing: 0.15em;
color: var(--ink-soft);
}
/* 英文大标题 */
.eng-title {
position: absolute;
top: 130px;
left: 60px;
z-index: 5;
font-family: 'Times New Roman', 'Georgia', serif;
font-weight: 400;
font-style: italic;
font-size: 92px;
line-height: 1.0;
letter-spacing: -0.01em;
color: var(--ink);
}
.eng-title .spaced {
letter-spacing: 0.18em;
}
.eng-title .l2 { display: block; margin-top: 6px; }
/* 中文大标题 */
.cn-title {
position: absolute;
top: 340px;
left: 60px;
right: 60px;
z-index: 5;
font-family: 'Songti SC', 'STSong', 'Source Han Serif SC', 'Noto Serif SC', serif;
font-weight: 700;
font-size: 108px;
line-height: 1.05;
letter-spacing: 0.04em;
color: var(--ink);
}
/* ===== 中部:云朵 + 主图 ===== */
.scene {
position: absolute;
top: 590px;
left: 0; right: 0;
height: 640px;
z-index: 1;
overflow: hidden;
}
/* SVG 云朵层(在主图之上,做"插画式"遮罩) */
.clouds {
position: absolute;
top: 0; left: 0; right: 0;
height: 360px;
z-index: 3;
pointer-events: none;
}
.clouds svg { display: block; width: 100%; height: 100%; }
/* 主图:Pexels 春日草甸,带柔光滤镜 */
.hero-img {
position: absolute;
bottom: 0; left: 0; right: 0;
height: 520px;
overflow: hidden;
z-index: 2;
/* 顶部柔化:用 mask 让上沿和云朵区融合 */
-webkit-mask-image: linear-gradient(180deg, transparent 0%, rgba(0,0,0,.7) 18%, #000 35%, #000 100%);
mask-image: linear-gradient(180deg, transparent 0%, rgba(0,0,0,.7) 18%, #000 35%, #000 100%);
}
.hero-img img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center 55%;
filter: saturate(0.85) brightness(1.05) contrast(0.95);
display: block;
}
/* 主图上的薄荷绿色彩叠加,让照片更接近插画调 */
.hero-tint {
position: absolute;
bottom: 0; left: 0; right: 0;
height: 520px;
background: linear-gradient(180deg,
rgba(207, 225, 205, 0.35) 0%,
rgba(180, 210, 175, 0.18) 40%,
rgba(241, 235, 217, 0.0) 100%);
z-index: 4;
pointer-events: none;
}
/* 草地装饰:底部一条小草丛剪影 */
.grass-deco {
position: absolute;
bottom: 0; left: 0; right: 0;
height: 80px;
z-index: 5;
pointer-events: none;
}
.grass-deco svg { display: block; width: 100%; height: 100%; }
/* Pexels 标注 */
.photo-credit {
position: absolute;
right: 24px;
bottom: 18px;
z-index: 6;
font-family: 'Helvetica Neue', sans-serif;
font-size: 14px;
color: rgba(255,255,255,0.85);
letter-spacing: 0.12em;
text-shadow: 0 1px 3px rgba(0,0,0,.5);
}
/* ===== 底部:提案块 ===== */
.proposals {
position: absolute;
top: 1255px;
left: 60px;
right: 60px;
z-index: 6;
display: grid;
grid-template-columns: 1fr 1fr;
column-gap: 56px;
row-gap: 22px;
}
.prop h4 {
font-family: 'Songti SC', 'STSong', 'Source Han Serif SC', serif;
font-weight: 700;
font-size: 28px;
color: var(--ink);
margin-bottom: 6px;
letter-spacing: 0.02em;
}
.prop h4 .num {
font-family: 'Times New Roman', serif;
font-style: italic;
font-weight: 400;
color: var(--grass);
margin-right: 8px;
font-size: 26px;
}
.prop p {
font-family: 'Songti SC', 'Source Han Serif SC', serif;
font-size: 17px;
line-height: 1.55;
color: var(--ink-soft);
letter-spacing: 0.02em;
max-height: 53px;
overflow: hidden;
}
/* ===== 最底栏:日期 / 地点 / 品牌 ===== */
.footer {
position: absolute;
bottom: 50px;
left: 60px;
right: 60px;
z-index: 10;
display: flex;
justify-content: space-between;
align-items: flex-end;
border-top: 1px solid var(--line);
padding-top: 18px;
background: var(--cream);
}
.footer-left {
color: var(--ink);
}
.footer-left .date {
font-family: 'Times New Roman', serif;
font-style: italic;
font-weight: 400;
font-size: 40px;
color: var(--grass);
line-height: 1;
}
.footer-left .loc {
font-family: 'Songti SC', serif;
font-size: 19px;
margin-top: 8px;
letter-spacing: 0.06em;
color: var(--ink);
}
.footer-left .loc b {
font-family: 'Helvetica Neue', sans-serif;
font-weight: 600;
margin-right: 6px;
color: var(--ink-soft);
font-size: 17px;
letter-spacing: 0.1em;
}
.footer-right {
text-align: right;
color: var(--ink);
}
.footer-right .brand {
font-family: 'Songti SC', 'Source Han Serif SC', serif;
font-weight: 700;
font-size: 22px;
letter-spacing: 0.18em;
}
.footer-right .brand .sep {
margin: 0 10px;
color: var(--grass);
}
.footer-right .tag {
font-family: 'Helvetica Neue', sans-serif;
font-size: 14px;
margin-top: 6px;
letter-spacing: 0.18em;
color: var(--ink-soft);
}
</style>
</head>
<body>
<div class="cover">
<!-- 天空背景 -->
<div class="sky"></div>
<!-- 顶部条 -->
<div class="top-bar">
<div class="date-eng">Apr. 2026</div>
<div class="brand-cn">
<span class="line">春和景明</span>
<div class="sub">春日生活提案</div>
</div>
</div>
<!-- 英文标题 -->
<div class="eng-title">
<span>Soft</span> <span class="spaced">S p r i n g</span>
<span class="l2">&amp; Slow Days</span>
</div>
<!-- 中文标题 -->
<div class="cn-title">春日松弛感<br>生活提案</div>
<!-- 中部场景 -->
<div class="scene">
<!-- 云朵 -->
<div class="clouds">
<svg viewBox="0 0 1242 360" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
<!-- 三朵云 -->
<g fill="#f1ebd9">
<path d="M -40,200
C 60,120 180,110 240,160
C 290,90 410,80 470,150
C 540,100 660,120 700,180
C 760,130 870,140 900,210
C 980,180 1100,200 1160,260
C 1220,240 1300,280 1320,360
L 1320,400 L -40,400 Z" opacity="0.92"/>
<path d="M 100,100
C 180,40 320,40 380,100
C 440,60 560,80 600,140
C 660,100 780,110 830,170
C 920,140 1020,160 1080,220
L 1080,260 L 100,260 Z" opacity="0.5"/>
</g>
<!-- 远山轮廓线 -->
<path d="M 0,340 L 200,280 L 380,310 L 560,260 L 780,300 L 980,270 L 1242,320"
stroke="#8ab28a" stroke-width="1.5" fill="none" opacity="0.55"/>
</svg>
</div>
<!-- 主图 -->
<div class="hero-img">
<img src="https://images.pexels.com/photos/32893151/pexels-photo-32893151.jpeg?auto=compress&cs=tinysrgb&w=1600"
alt="dreamy meadow with spring wildflowers from Pexels">
</div>
<div class="hero-tint"></div>
<!-- 草地装饰 -->
<div class="grass-deco">
<svg viewBox="0 0 1242 80" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
<g stroke="#557565" stroke-width="1.6" fill="none" opacity="0.55" stroke-linecap="round">
<path d="M 30 80 Q 28 50 32 30"/>
<path d="M 38 80 Q 42 55 36 38"/>
<path d="M 90 80 Q 92 52 88 30"/>
<path d="M 96 80 Q 94 55 102 35"/>
<path d="M 180 80 Q 178 50 184 28"/>
<path d="M 188 80 Q 192 52 186 32"/>
<path d="M 260 80 Q 258 50 264 30"/>
<path d="M 270 80 Q 274 56 268 36"/>
<path d="M 340 80 Q 336 48 342 26"/>
<path d="M 348 80 Q 352 55 346 32"/>
<path d="M 420 80 Q 418 50 424 28"/>
<path d="M 430 80 Q 434 55 428 32"/>
<path d="M 510 80 Q 506 48 512 26"/>
<path d="M 518 80 Q 522 55 516 32"/>
<path d="M 600 80 Q 598 50 604 28"/>
<path d="M 608 80 Q 612 55 606 32"/>
<path d="M 690 80 Q 688 48 694 26"/>
<path d="M 700 80 Q 704 55 698 32"/>
<path d="M 780 80 Q 776 50 782 28"/>
<path d="M 788 80 Q 792 55 786 32"/>
<path d="M 870 80 Q 866 50 872 28"/>
<path d="M 878 80 Q 882 55 876 32"/>
<path d="M 960 80 Q 958 50 964 28"/>
<path d="M 968 80 Q 972 55 966 32"/>
<path d="M 1050 80 Q 1046 50 1052 28"/>
<path d="M 1058 80 Q 1062 55 1056 32"/>
<path d="M 1140 80 Q 1138 50 1144 28"/>
<path d="M 1150 80 Q 1154 56 1148 32"/>
<path d="M 1200 80 Q 1196 50 1202 28"/>
</g>
</svg>
</div>
<div class="photo-credit">PHOTO · PEXELS / FARHAAN PARIMOO</div>
</div>
<!-- 提案列表 -->
<div class="proposals">
<div class="prop">
<h4><span class="num">01</span>城市公园野餐</h4>
<p>带一块格子布、半盒草莓,<br>坐到云挪了又挪。</p>
</div>
<div class="prop">
<h4><span class="num">02</span>周末山野徒步</h4>
<p>8 公里以内的小路,不打卡,<br>把节奏交还给身体。</p>
</div>
<div class="prop">
<h4><span class="num">03</span>阳台花园种植</h4>
<p>从一盆薄荷开始,把"等待"<br>重新放回每一天。</p>
</div>
<div class="prop">
<h4><span class="num">04</span>樱花树下夜读</h4>
<p>一本薄薄的随笔,<br>读到天色变蓝,读到困。</p>
</div>
</div>
<!-- 底栏 -->
<div class="footer">
<div class="footer-left">
<div class="date">4.04 — 5.20</div>
<div class="loc"><b>WHERE</b>城市 · 山野 · 阳台 · 任何有春风的地方</div>
</div>
<div class="footer-right">
<div class="brand">慢 <span class="sep">·</span> 生 <span class="sep">·</span> 活</div>
<div class="tag">SLOW LIVING JOURNAL &nbsp;/&nbsp; VOL.04</div>
</div>
</div>
</div>
</body>
</html>