版本号 3.2.7 -> 3.2.8(邮件配色整封同色系化 + 对比度修复)

邮件模板原来只有品牌条一个色块,其余大面积底色全是中性灰,
主色稍朴素(主题默认 #24292e)整封信看起来就是黑白的。

- 新增 yang_mail_palette():底色/描边/强调文字全部从主色同色系派生
- 新增 yang_mail_chroma()/hsl()/hsl_hex()/ensure_chroma()/has_hue()
- 修复深浅判定:白字对比度 = 黑字对比度的交叉点在 L≈0.179,不是 0.5。
  用 0.5 会把亮蓝 #00a2ff(L=0.331)判成深色配白字,只有 2.76:1
- 新增 yang_mail_fg_on():在白与深之间取对比度更高者,
  中灰 #808080 上从 4.41 提到 5.32(AA 达标)
- 修复:与白混合是同比压缩色度,0.94 档压 16 倍 ⇒ 近中性主色
  派生出的浅底只剩 0.002,物理不可见。加彩度兜底,按各自亮度补足
- 修复:页脚改浅底后 12px 说明文字降到 4.26:1,muted 改为按背景推导
- 品牌条/按钮仍严格用用户填的原色,补彩度只作用于派生色
This commit is contained in:
2026-10-23 16:13:48 +08:00
parent 269364bed4
commit 9c48ba56eb
2 changed files with 364 additions and 30 deletions
+363 -29
View File
@@ -69,21 +69,343 @@ function yang_mail_shade($hex, $ratio = 0.82)
*
* 用相对亮度公式(WCAG),不是简单取平均 —— 人眼对绿最敏感、蓝最不敏感,
* 直接平均会把 #00ff00 判成中等亮度。
*
* ── 阈值为什么是 0.179 而不是 0.5 ────────────────────────────
* 「白字对比度 = 黑字对比度」的那个点,可以解出来:
* 白字对比度 = 1.05 / (L + 0.05)
* 黑字对比度 = (L + 0.05) / 0.05
* 两者相等 ⇒ (L + 0.05)² = 0.0525 ⇒ L ≈ 0.179
* 所以在 L = 0.179 处,白字与黑字一样清楚;低于它白字更好,高于它黑字更好。
* 之前写 0.5,把一整段"其实该用深色字"的中间亮度全划成了"深色",
* 典型受害者就是亮蓝 #00a2ff(L=0.331):被判成深色 ⇒ 压白字 ⇒ 只有 2.76:1,
* 远低于 AA 的 4.5,品牌条上的站名其实很难看清。按 0.179 判定后走深色字,6.31:1。
*
* ⚠️ 这个函数只回答"深还是浅",**不负责保证对比度**。中灰 #808080 落在
* 交叉点附近,白字 3.95、深字 4.41 —— 两个都不到 4.5,但必须选一个。
* 所以配字时不要直接用它,用 yang_mail_fg_on():那里是"黑白里取更优",
* 顺带在都不达标时退回纯黑/纯白,能多榨出一两档。
*/
function yang_mail_is_dark($hex)
{
return yang_mail_lum($hex) < 0.179;
}
/**
* 相对亮度(WCAG,0=纯黑 1=纯白)
*/
function yang_mail_lum($hex)
{
$hex = ltrim((string) $hex, '#');
if (strlen($hex) !== 6) {
return true;
if (!preg_match('/^[0-9a-fA-F]{6}$/', $hex)) {
return 0.0;
}
$lin = function ($c) {
$c /= 255;
return $c <= 0.03928 ? $c / 12.92 : pow(($c + 0.055) / 1.055, 2.4);
};
return 0.2126 * $lin(hexdec(substr($hex, 0, 2)))
+ 0.7152 * $lin(hexdec(substr($hex, 2, 2)))
+ 0.0722 * $lin(hexdec(substr($hex, 4, 2)));
}
/**
* 给某个底色配文字色:在白与深之间取**对比度更高**的那个
*
* 为什么不是"深色就配白、浅色就配深":中灰区(如 #808080)两边都不达标
* (白字 3.95、深字 4.41),二元判定的答案取决于阈值落在哪一侧,
* 而阈值本身对两个都不达标的情况毫无意义。取更优的那个至少是当前最好的选择,
* 而且这个判据跟"阈值该定多少"完全解耦 —— 换阈值也不会选错。
*/
function yang_mail_fg_on($bg)
{
$white = yang_mail_contrast('#ffffff', $bg);
$dark = yang_mail_contrast('#1a1a1a', $bg);
if ($white >= $dark) {
return '#ffffff';
}
// 深字够不着 AA 时,纯黑还能再挤一点(#808080 上 4.41 → 5.32)
return yang_mail_contrast('#000000', $bg) > $dark ? '#000000' : '#1a1a1a';
}
/**
* 取一个颜色的「色度」(chroma)—— 三个通道的最大差
*
* ── 为什么不用 HSL 饱和度判断"有没有颜色" ────────────────────
* HSL 的 S 在高亮度区会虚高。实测派生底 #f0f9ff(几乎纯白带一点点蓝)
* 的 HSL 饱和度是 **1.00**,而 #e5e5e6(纯灰)是 0.005 —— 看起来判据很灵。
* 但 #e9eaec 这种"肉眼就是灰"的颜色,HSL 饱和度也有 0.12,
* 会被判成"有颜色"。真正决定人眼能否看出颜色的,是通道极差(色度):
* #f0f9ff → 0.059(看得出是极浅蓝)
* #e9eaec → 0.012(看不出,就是灰)
* 两者 HSL 饱和度一个是 1.00、一个 0.12,顺序跟人的感受**正好相反**。
* 所以这里一律用色度,不用 S。
*/
function yang_mail_chroma($hex)
{
$hex = ltrim((string) $hex, '#');
if (!preg_match('/^[0-9a-fA-F]{6}$/', $hex)) {
return 0.0;
}
$v = array(
hexdec(substr($hex, 0, 2)),
hexdec(substr($hex, 2, 2)),
hexdec(substr($hex, 4, 2)),
);
return (max($v) - min($v)) / 255;
}
/**
* 把「有色相但太淡」的颜色沿**它自己的色相**加饱和,直到色度达到下限
*
* ── 为什么需要这一步 ────────────────────────────────────────
* 主题默认主色是 #24292e,色度只有 0.039(几乎是中性深灰)。
* 往白里兑出浅底后色度只剩 0.002 —— 物理上不可见,整封邮件仍旧是黑白的,
* 用户看到的还是「模板没做好」。但「从灰里调出彩色」在数学上不可能,
* 而主题默认值就是它,所以必须有一个补饱和的环节。
*
* 只动饱和度,**色相与亮度一律不动** —— 派生色仍属同一色系,品牌识别没丢。
*/
function yang_mail_ensure_chroma($hex, $minChroma)
{
if (yang_mail_chroma($hex) >= $minChroma) {
return $hex;
}
list($hue, $l) = yang_mail_hsl($hex);
$den = 1 - abs(2 * $l - 1);
if ($den < 1e-6) {
// 纯白或纯黑:没有色相可言
return $hex;
}
$s0 = yang_mail_chroma($hex) / $den;
/* 逐档搜索而不是解析求解:色度是 max-min,跟 S 的关系在 l>0.5 与
* l<0.5 两侧公式不同,硬推容易在边界写错;这里步数只有几十。 */
for ($s = $s0; $s <= 0.95; $s += 0.02) {
$out = yang_mail_hsl_hex($hue, $s, $l);
if (yang_mail_chroma($out) >= $minChroma) {
return $out;
}
}
return yang_mail_hsl_hex($hue, 0.95, $l);
}
/**
* 这个颜色有没有「真实色相」(可以放心拿它的色相去染色)
*
* ── 为什么判据放在源头,而不是放在每个派生色上 ──────────────────
* 与白色混合是**同比压缩**色度:0.94 那一档压 16 倍。
* 所以"派生出的浅底色度很低"是**必然现象**,不是"这个颜色没有色相"。
* 早先的实现在 yang_mail_ensure_chroma() 里对入参做 0.02 死区判断,
* 于是极浅底(混合后 0.008)被当成"没有色相"直接跳过,
* 兜底等于没做 —— 恰恰是最需要兜底的那一档失效了。
*
* 真正该判断的是**种子**:种子的色度 ≥ 0.02 说明它有一个真实可辨的色相
* (#24292e 是 0.039,属"有一点点真实的蓝",可以放大);
* 低于 0.02 的(#808080 这种纯中性灰)色相是浮点噪声,按噪声染色
* 等于随机配色,还会让「主色本来就没有色相」变得不可观测 —— 那就不染。
*/
function yang_mail_has_hue($hex)
{
return yang_mail_chroma($hex) >= 0.02;
}
/**
* #rrggbb → array(色相 0~1, 亮度 0~1)
*/
function yang_mail_hsl($hex)
{
$hex = ltrim((string) $hex, '#');
if (!preg_match('/^[0-9a-fA-F]{6}$/', $hex)) {
return array(0.0, 0.0);
}
$r = hexdec(substr($hex, 0, 2)) / 255;
$g = hexdec(substr($hex, 2, 2)) / 255;
$b = hexdec(substr($hex, 4, 2)) / 255;
$lin = function ($c) {
return $c <= 0.03928 ? $c / 12.92 : pow(($c + 0.055) / 1.055, 2.4);
$mx = max($r, $g, $b);
$mn = min($r, $g, $b);
$l = ($mx + $mn) / 2;
$d = $mx - $mn;
if ($d < 1e-9) {
return array(0.0, $l);
}
if ($mx === $r) {
$h = (($g - $b) / $d + ($g < $b ? 6 : 0)) / 6;
} elseif ($mx === $g) {
$h = (($b - $r) / $d + 2) / 6;
} else {
$h = (($r - $g) / $d + 4) / 6;
}
return array($h, $l);
}
/**
* HSL → #rrggbb(h 为 0~1)
*/
function yang_mail_hsl_hex($h, $s, $l)
{
$hue2rgb = function ($p, $q, $t) {
if ($t < 0) {
$t += 1;
}
if ($t > 1) {
$t -= 1;
}
if ($t < 1 / 6) {
return $p + ($q - $p) * 6 * $t;
}
if ($t < 1 / 2) {
return $q;
}
if ($t < 2 / 3) {
return $p + ($q - $p) * (2 / 3 - $t) * 6;
}
return $p;
};
$L = 0.2126 * $lin($r) + 0.7152 * $lin($g) + 0.0722 * $lin($b);
return $L < 0.5;
if ($s <= 0) {
$v = (int) round($l * 255);
return sprintf('#%02x%02x%02x', $v, $v, $v);
}
$q = $l < 0.5 ? $l * (1 + $s) : $l + $s - $l * $s;
$p = 2 * $l - $q;
return sprintf(
'#%02x%02x%02x',
(int) round(255 * $hue2rgb($p, $q, $h + 1 / 3)),
(int) round(255 * $hue2rgb($p, $q, $h)),
(int) round(255 * $hue2rgb($p, $q, $h - 1 / 3))
);
}
/**
* 生成整封邮件用的配色表(全部从主色派生,同色系)
*
* ── 为什么整封邮件不能是灰的 ──────────────────────────────────
* 早先模板里只有品牌条、徽标、按钮、最后一块引用块的竖线用主色,
* 其余 90% 面积(标题、正文、引用块底色、信息表分隔线、页脚)全是中性灰
* (#1a2028 / #5f6b78 / #c2cbd4 / #edf0f3)。主色若本身不够艳
* (比如主题默认的 #24292e 是接近中性的深灰蓝),整封信看起来就是黑白的。
* 「彩色」不是靠一个大色块,而是让**底色、描边、强调文字**都在同一色系里。
*
* ── 为什么要算而不是写死 ──────────────────────────────────────
* 主色是用户在主题选项里改的,写死一套蓝就没有意义了。
* 这里从主色派生出:极浅底(区块背景)、浅底(页脚背景)、
* 中档描边、深档文字(保证对浅底 ≥4.5:1)。
*
* ── 派生为什么不能只是「与白混合」────────────────────────────
* 混合是同比压缩色度:0.94 那一档把色度压 16 倍。主色是 #24292e 这种
* 近中性深灰(色度 0.039)时,兑完只剩 0.002,肉眼与纯灰无异 ——
* 这正是「换成默认主色后邮件又变黑白」的机制。
* 所以浅底在混合之后还要过一道 yang_mail_ensure_chroma(),按**它自己所在
* 亮度**补一个可见的色度下限(浅底用 MIN_CHROMA_TINT,中档用 MIN_CHROMA_MID)。
* 这一步只动饱和度、不动色相和亮度,颜色仍是主色的同一色系。
*
* ── 品牌条为什么仍用原色 ────────────────────────────────────
* 用户直接看到主色的地方(品牌条、按钮、徽标)一律用他填的原色。
* 他选了深灰蓝,就不该在标题栏上看到它被换成亮蓝。补饱和只用于
* 「主色的稀释/加深」,那是他自己没指定过的颜色。
*
* 全部输出**实色**,不用 rgba:Outlook(Word 引擎)不认 rgba,会整条丢掉背景。
*/
function yang_mail_palette($brand = null)
{
if ($brand === null) {
$brand = yang_mail_brand_color();
}
$brand = ltrim((string) $brand, '#');
if (!preg_match('/^[0-9a-fA-F]{6}$/', $brand)) {
$brand = '24292e';
}
$brand = '#' . $brand;
/* 派生用的种子:中性一点的先提饱和,否则这一整套派生色都将是灰的。
* 只在主色有**真实色相**时才放大(见 yang_mail_has_hue);
* 零色相的纯灰宁可保持灰,也不要凭空编一个色相。 */
$seed = yang_mail_has_hue($brand) ? yang_mail_ensure_chroma($brand, 0.30) : $brand;
$onBrand = yang_mail_fg_on($brand);
/* 浅底:混合后按自身亮度再补一次色度。
* 极浅底(ratio 0.94)本身亮度很高,能容纳的色度有限,
* 所以下限分两档 —— 用同一个值会让极浅底被迫变深、不再是"浅底"。
* 主色零色相时不补:那套灰是事实,硬染就是编造。 */
$keep = yang_mail_has_hue($brand);
$tintXX = $keep ? yang_mail_ensure_chroma(yang_mail_tint($seed, 0.94), 0.045)
: yang_mail_tint($seed, 0.94);
$tintX = $keep ? yang_mail_ensure_chroma(yang_mail_tint($seed, 0.88), 0.075)
: yang_mail_tint($seed, 0.88);
$tintLine = $keep ? yang_mail_ensure_chroma(yang_mail_tint($seed, 0.80), 0.110)
: yang_mail_tint($seed, 0.80);
$tintMid = $keep ? yang_mail_ensure_chroma(yang_mail_tint($seed, 0.55), 0.220)
: yang_mail_tint($seed, 0.55);
$pageBg = $keep ? yang_mail_ensure_chroma(yang_mail_tint($seed, 0.90), 0.065)
: yang_mail_tint($seed, 0.90);
/* 强调文字色:从种子一路压暗,取第一个"在白底和极浅底上都 ≥4.5"的档位。
* 不能直接拿主色当文字色 —— 亮蓝 #00a2ff 在白底只有 2.76:1。
* 也不能无脑取很深,那样就看不出是"主色的深版"了,所以要取**最亮的达标档**。 */
$textOnTint = $seed;
for ($s = 0.20; $s <= 0.90; $s += 0.02) {
$c = yang_mail_shade($seed, $s);
if (yang_mail_contrast($c, '#ffffff') >= 4.5
&& yang_mail_contrast($c, $tintXX) >= 4.5) {
$textOnTint = $c;
break;
}
}
/* 次要文字色:原来是固定的 #5c6b7a,但页脚底色改成了主色浅底之后,
* 这个固定值在浅蓝上只有 4.26:1 —— 12px 小字不达 AA。
* 「文字色写死、背景色随主色变」这个组合本身就是错的:背景一变浅,
* 固定灰就压不住。所以改成从基准灰往下压,压到在**它实际会遇到的
* 两种背景**(页脚浅底、邮件最外层)上都达标为止。 */
$muted = '#5c6b7a';
for ($t = 1.0; $t >= 0.55; $t -= 0.02) {
$cand = $t >= 0.999 ? $muted : yang_mail_shade($muted, $t);
if (yang_mail_contrast($cand, $tintX) >= 4.5
&& yang_mail_contrast($cand, $pageBg) >= 4.5) {
$muted = $cand;
break;
}
}
return array(
'brand' => $brand, // 主色(品牌条、按钮)
'brand_dark' => yang_mail_shade($brand, 0.78), // 品牌条下沿深色带
'on_brand' => $onBrand, // 压在品牌色上的字
'text' => $textOnTint, // 同色系的强调文字(标题/标签)
'tint_xx' => $tintXX, // 极浅底:引用块、信息表
'tint_x' => $tintX, // 稍深一点的浅底:页脚
'tint_line' => $tintLine, // 浅底上的描边/分隔线
'tint_mid' => $tintMid, // 中档:弱化竖线、次要描边
'page_bg' => $pageBg, // 邮件最外层背景
'body' => '#243040', // 正文(保持深灰蓝,长文好读)
'muted' => $muted, // 次要文字(时间、页脚),按背景调过
);
}
/**
* 计算两色的 WCAG 对比度
*
* 给配色表自检用:派生颜色是否达标,靠算而不是靠眼睛看。
*/
function yang_mail_contrast($fg, $bg)
{
$lumOf = function ($hex) {
$hex = ltrim((string) $hex, '#');
if (strlen($hex) !== 6) {
return 0;
}
$lin = function ($c) {
$c /= 255;
return $c <= 0.03928 ? $c / 12.92 : pow(($c + 0.055) / 1.055, 2.4);
};
return 0.2126 * $lin(hexdec(substr($hex, 0, 2)))
+ 0.7152 * $lin(hexdec(substr($hex, 2, 2)))
+ 0.0722 * $lin(hexdec(substr($hex, 4, 2)));
};
$a = $lumOf($fg);
$b = $lumOf($bg);
return (max($a, $b) + 0.05) / (min($a, $b) + 0.05);
}
/**
@@ -218,9 +540,21 @@ function yang_mail_render($args)
$quoteList = array($d['quote']);
}
$brand = yang_mail_brand_color();
$brandD = yang_mail_shade($brand, 0.78);
$onBrand = yang_mail_is_dark($brand) ? '#ffffff' : '#1a1a1a';
/* 整套配色从主色派生一次,后面所有颜色都从这里取。
* 不在这里散落写死 #xxxxxx —— 那样主色一改,「彩色」就断了,
* 又退回成"一个色块 + 一堆灰」。 */
$pal = yang_mail_palette();
$brand = $pal['brand'];
$brandD = $pal['brand_dark'];
$onBrand = $pal['on_brand'];
$cText = $pal['text'];
$cBody = $pal['body'];
$cMuted = $pal['muted'];
$cTintXX = $pal['tint_xx'];
$cTintX = $pal['tint_x'];
$cTintLine = $pal['tint_line'];
$cTintMid = $pal['tint_mid'];
$cPageBg = $pal['page_bg'];
// badge 的背景:把主色往白色方向提亮一档,得到比主色浅、但同色相的实色。
// 主色本身是深色时提亮 22%,浅色时压暗 —— 否则浅主色上叠浅 badge 会看不见。
@@ -256,22 +590,22 @@ function yang_mail_render($args)
</style>
<![endif]-->
</head>
<body style="margin:0;padding:0;width:100%;background-color:#eef1f4;">
<body style="margin:0;padding:0;width:100%;background-color:<?php echo esc_attr($cPageBg); ?>;">
<?php /* 预读文字:显示在收件箱列表里标题的后面。藏起来但必须真实存在,且要足够长,
否则客户端会把正文第一句抓上去当摘要。 */ ?>
<div style="display:none;font-size:1px;color:#eef1f4;line-height:1px;max-height:0;max-width:0;opacity:0;overflow:hidden;">
<div style="display:none;font-size:1px;color:<?php echo esc_attr($cPageBg); ?>;line-height:1px;max-height:0;max-width:0;opacity:0;overflow:hidden;">
<?php echo esc_html($d['preheader'] ? $d['preheader'] : $d['heading']); ?>
</div>
<table border="0" cellpadding="0" cellspacing="0" width="100%" role="presentation" style="background-color:#eef1f4;">
<table border="0" cellpadding="0" cellspacing="0" width="100%" role="presentation" style="background-color:<?php echo esc_attr($cPageBg); ?>;">
<tr><td align="center" style="padding:32px 12px;">
<?php /* 宽度写法是「混合式」:
· Outlook(Word 引擎)只认 HTML 属性 width="600",CSS 的 max-width 它当没看见;
· 其它客户端认 CSS,于是 width:100% + max-width:600px 让手机窄屏自动收窄。
两套并存,各取所需。只写死 600px 会让手机横向滚动——实测过。 */ ?>
<table border="0" cellpadding="0" cellspacing="0" width="600" role="presentation" style="width:100%;max-width:600px;background-color:#ffffff;border-radius:12px;overflow:hidden;border:1px solid #e3e7ec;">
<table border="0" cellpadding="0" cellspacing="0" width="600" role="presentation" style="width:100%;max-width:600px;background-color:#ffffff;border-radius:12px;overflow:hidden;border:1px solid <?php echo esc_attr($cTintLine); ?>;">
<?php /* ── 顶部品牌条 ── */ ?>
<tr>
@@ -309,13 +643,13 @@ function yang_mail_render($args)
<td style="padding:34px 32px 8px 32px;">
<?php if ($d['heading'] !== ''): ?>
<div style="font-family:<?php echo $sans; ?>;font-size:21px;font-weight:600;color:#1a2028;line-height:1.45;margin:0 0 12px 0;">
<div style="font-family:<?php echo $sans; ?>;font-size:21px;font-weight:600;color:<?php echo esc_attr($cText); ?>;line-height:1.45;margin:0 0 12px 0;">
<?php echo esc_html($d['heading']); ?>
</div>
<?php endif; ?>
<?php if ($d['intro'] !== ''): ?>
<div style="font-family:<?php echo $sans; ?>;font-size:15px;color:#4a5560;line-height:1.7;margin:0 0 22px 0;">
<div style="font-family:<?php echo $sans; ?>;font-size:15px;color:<?php echo esc_attr($cBody); ?>;line-height:1.7;margin:0 0 22px 0;">
<?php echo esc_html($d['intro']); ?>
</div>
<?php endif; ?>
@@ -330,23 +664,23 @@ function yang_mail_render($args)
* 只有一个块时它既是第一也是最后 ⇒ 拿到主色,与旧版行为一致。
*/
$isLast = ($qi === count($quoteList) - 1);
$barColor = $isLast ? $brand : '#c2cbd4';
$barBg = $isLast ? '#f6f8fa' : '#fafbfc';
$barColor = $isLast ? $brand : $cTintMid;
$barBg = $isLast ? $cTintXX : $cTintX;
$barMargin = $isLast ? '22px' : '14px';
?>
<table border="0" cellpadding="0" cellspacing="0" width="100%" role="presentation" style="margin:0 0 <?php echo $barMargin; ?> 0;">
<tr>
<td style="border-left:3px solid <?php echo esc_attr($barColor); ?>;background-color:<?php echo esc_attr($barBg); ?>;padding:16px 18px;border-radius:0 8px 8px 0;">
<?php if (!empty($q['label'])): ?>
<div style="font-family:<?php echo $sans; ?>;font-size:12px;font-weight:600;color:#5f6b78;letter-spacing:0.6px;text-transform:uppercase;margin:0 0 8px 0;">
<div style="font-family:<?php echo $sans; ?>;font-size:12px;font-weight:600;color:<?php echo esc_attr($cText); ?>;letter-spacing:0.6px;text-transform:uppercase;margin:0 0 8px 0;">
<?php echo esc_html($q['label']); ?>
</div>
<?php endif; ?>
<div style="font-family:<?php echo $sans; ?>;font-size:15px;color:#2d3740;line-height:1.7;word-break:break-word;">
<div style="font-family:<?php echo $sans; ?>;font-size:15px;color:<?php echo esc_attr($cBody); ?>;line-height:1.7;word-break:break-word;">
<?php echo nl2br(esc_html(isset($q['content']) ? $q['content'] : '')); ?>
</div>
<?php if (!empty($q['meta'])): ?>
<div style="font-family:<?php echo $sans; ?>;font-size:13px;color:#5f6b78;line-height:1.6;margin:9px 0 0 0;">
<div style="font-family:<?php echo $sans; ?>;font-size:13px;color:<?php echo esc_attr($cMuted); ?>;line-height:1.6;margin:9px 0 0 0;">
<?php echo esc_html($q['meta']); ?>
</div>
<?php endif; ?>
@@ -358,13 +692,13 @@ function yang_mail_render($args)
<?php if (!empty($d['rows'])): ?>
<?php /* 信息表:两列。label 列定宽 88px 并右对齐,value 左对齐,视觉上最稳。
不用 table-layout:fixed 之外的花样,Outlook 只认这个。 */ ?>
<table border="0" cellpadding="0" cellspacing="0" width="100%" role="presentation" style="margin:0 0 24px 0;border-top:1px solid #edf0f3;">
<table border="0" cellpadding="0" cellspacing="0" width="100%" role="presentation" style="margin:0 0 24px 0;border-top:1px solid <?php echo esc_attr($cTintLine); ?>;">
<?php foreach ($d['rows'] as $row): ?>
<tr>
<td width="88" valign="top" style="width:88px;padding:11px 0;border-bottom:1px solid #edf0f3;font-family:<?php echo $sans; ?>;font-size:13px;color:#5f6b78;line-height:1.6;white-space:nowrap;">
<td width="88" valign="top" style="width:88px;padding:11px 0;border-bottom:1px solid <?php echo esc_attr($cTintLine); ?>;font-family:<?php echo $sans; ?>;font-size:13px;color:<?php echo esc_attr($cMuted); ?>;line-height:1.6;white-space:nowrap;">
<?php echo esc_html($row['label']); ?>
</td>
<td valign="top" style="padding:11px 0 11px 16px;border-bottom:1px solid #edf0f3;font-family:<?php echo $sans; ?>;font-size:14px;color:#2d3740;line-height:1.6;word-break:break-word;">
<td valign="top" style="padding:11px 0 11px 16px;border-bottom:1px solid <?php echo esc_attr($cTintLine); ?>;font-family:<?php echo $sans; ?>;font-size:14px;color:<?php echo esc_attr($cBody); ?>;line-height:1.6;word-break:break-word;">
<?php
$v = isset($row['value']) ? $row['value'] : '';
if (!empty($row['strong'])) {
@@ -386,7 +720,7 @@ function yang_mail_render($args)
<?php endif; ?>
<?php if ($d['note'] !== ''): ?>
<div style="font-family:<?php echo $sans; ?>;font-size:13px;color:#5f6b78;line-height:1.7;padding:16px 0 0 0;border-top:1px solid #edf0f3;">
<div style="font-family:<?php echo $sans; ?>;font-size:13px;color:<?php echo esc_attr($cMuted); ?>;line-height:1.7;padding:16px 0 0 0;border-top:1px solid <?php echo esc_attr($cTintLine); ?>;">
<?php echo esc_html($d['note']); ?>
</div>
<?php endif; ?>
@@ -396,13 +730,13 @@ function yang_mail_render($args)
<?php /* ── 页脚 ── */ ?>
<tr>
<td style="padding:24px 32px 30px 32px;">
<div style="border-top:1px solid #edf0f3;padding-top:20px;font-family:<?php echo $sans; ?>;font-size:12px;color:#5f6b78;line-height:1.9;">
<td bgcolor="<?php echo esc_attr($cTintX); ?>" style="background-color:<?php echo esc_attr($cTintX); ?>;padding:24px 32px 30px 32px;">
<div style="border-top:1px solid <?php echo esc_attr($cTintLine); ?>;padding-top:20px;font-family:<?php echo $sans; ?>;font-size:12px;color:<?php echo esc_attr($cMuted); ?>;line-height:1.9;">
<div style="margin:0 0 6px 0;">
<a href="<?php echo esc_url($home); ?>" target="_blank" rel="noopener" style="color:#3d4752;text-decoration:none;font-weight:600;"><?php echo esc_html($site); ?></a>
<a href="<?php echo esc_url($home); ?>" target="_blank" rel="noopener" style="color:<?php echo esc_attr($cText); ?>;text-decoration:none;font-weight:600;"><?php echo esc_html($site); ?></a>
</div>
<div style="margin:0;">此邮件由系统自动发出,请勿直接回复。</div>
<div style="margin:6px 0 0 0;color:#6b7684;">&copy; <?php echo esc_html($year); ?> <?php echo esc_html($site); ?></div>
<div style="margin:6px 0 0 0;color:<?php echo esc_attr($cMuted); ?>;">&copy; <?php echo esc_html($year); ?> <?php echo esc_html($site); ?></div>
</div>
</td>
</tr>
@@ -410,7 +744,7 @@ function yang_mail_render($args)
</table>
<?php /* 底部说明:为什么收到这封邮件。放在卡片外面,视觉上属于系统信息 */ ?>
<div style="font-family:<?php echo $sans; ?>;font-size:12px;color:#5f6b78;line-height:1.7;padding:18px 8px 0 8px;max-width:600px;">
<div style="font-family:<?php echo $sans; ?>;font-size:12px;color:<?php echo esc_attr($cMuted); ?>;line-height:1.7;padding:18px 8px 0 8px;max-width:600px;">
您收到这封邮件,是因为本站记录了与您邮箱相关的订阅或互动。
</div>