0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Markdown→HTMLメールがGmailで崩れる原因と実務的な対策

Posted at

業務システムや通知メールで、

  • Markdown で本文を書く
  • サーバー側で HTML に変換してメール送信する

という構成を採用している方は多いと思います。

しかし、

管理画面や他のメーラーでは問題ないのに Gmail だけ表示が崩れる

という現象に遭遇したことはありませんか?

この記事は、Markdown でメール本文を書き、サーバー側で HTML 変換して送信しているエンジニア向けに、
Markdown → HTML → Gmail の流れで発生するスタイル崩れの原因と、
実務で有効だった対策を整理します。


結論(先に)

  • Gmail は 一部の HTML タグのスタイルを自動的に上書きする
  • <p> / <strong> / <em> などは特に影響を受けやすい
  • CSS はほぼ無効、インラインスタイル前提で設計する必要がある
  • Markdown の出力 HTML をそのまま使うのは危険

よくある構成

多くの現場で、以下のような流れになっています。

Markdown
  ↓(パーサー)
HTML
  ↓(メール送信)
Gmail / Outlook / Apple Mail

Markdown パーサーは次のような HTML を生成します。

<p>本文テキスト <strong>強調</strong></p>

一見すると正しく、管理画面のプレビューでも問題ありません。


問題:Gmail による「スタイルの標準化」

Gmail は セキュリティ・可読性の観点から、
HTML メールに対して独自の処理を行います。

Gmail が行う主な処理

  • <style> タグの削除・無視
  • 一部 CSS プロパティの無効化
  • HTML タグごとの デフォルトスタイル強制

その結果、以下のようなことが起こります。

  • <p>margin が勝手に付く / 消える
  • <strong>font-weight が意図しない値になる
  • フォントサイズが Gmail 標準に引き戻される

※ これらの挙動は 予告なく変更されることがあり、「以前は大丈夫だった」が普通に起こります。


具体例:管理画面では正常、Gmail では崩れる

管理画面(期待通り)

  • フォントサイズ:14px
  • 行間:1.6
  • 太字:少し強調

Gmail

  • フォントサイズが 16px 相当に拡大
  • <p> の上下に余白が入る
  • 太字が想定より強くなる

原因は、Markdown パーサーが生成した素の HTML タグが Gmail の上書き対象になっているためです。


対策①:インラインスタイルを前提にする(最重要)

Gmail で最も安定するのは インラインスタイル です。

❌ NG(ほぼ無視される)

<style>
  p { font-size:14px; line-height:1.6; }
</style>

⭕ OK(比較的安全)

<p style="font-size:14px; line-height:1.6; margin:0;">
  本文テキスト
</p>

対策②:Markdown 出力 HTML を後処理する

Markdown → HTML 変換後、そのまま送らないのがポイントです。

やること

  • <p>style を強制付与
  • <strong> / <em> にも font-weight / font-style を明示
  • 不要なタグは <span> に置き換える

例(Laravel / PHP イメージ)

$html = convertMarkdownToHtml($markdown);

$html = str_replace(
    '<p>',
    '<p style="font-size:14px; line-height:1.6; margin:0;">',
    $html
);

※ 正規表現ではなく DOM パーサーで安全に処理するのが理想です。


対策③:メール用 HTML と割り切る

Web 用 HTML の常識は メールでは通用しません

メール HTML の割り切り

  • CSS 設計は最小限
  • table レイアウトも許容
  • モダン CSS は使わない

Markdown は 入力補助ツールと割り切り、
最終形は「メール特化 HTML」に変換するのが現実解です。


対策④:HTMLメール用の HTML クリーンアップ

Markdown → HTML 変換後に、
「HTMLメールとして安全な状態に整える工程」 を必ず挟みます。

ここで重要なのは、

  • Web 用 HTML を期待しない
  • Gmail に解釈されやすい形に寄せる
  • 表示が変わりやすい要素を明示的に固定する

という考え方です。

Markdown はあくまで「入力を楽にするための記法」であり、
最終的に送信するのは メール特化 HTML です。

クリーンアップで行うこと

最低限、以下のような処理を行うと Gmail での表示が安定します。

  • <p>font-size / line-height / margin を明示
  • <strong>font-weight を明示
  • <em>font-style を明示
  • <style> / <script> タグの削除
  • Gmail で解釈が不安定な属性の除去

特に <p> / <strong> / <em>
Gmail 側でスタイルを上書きされやすいタグなので、
意図した見た目をインラインスタイルで固定します。

実装イメージ(例)

以下は PHP / Laravel を想定した一例です。
言語やフレームワークが違っても、考え方は同じです。

libxml_use_internal_errors(true);

$dom = new DOMDocument('1.0', 'UTF-8');
$dom->loadHTML(
    mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'),
    LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD
);

$xpath = new DOMXPath($dom);

// <p>
foreach ($xpath->query('//p') as $p) {
    $p->setAttribute(
        'style',
        'font-size:14px; line-height:1.6; margin:0 0 12px 0;'
    );
}

// <strong>
foreach ($xpath->query('//strong') as $strong) {
    $strong->setAttribute('style', 'font-weight:600;');
}

// <em>
foreach ($xpath->query('//em') as $em) {
    $em->setAttribute('style', 'font-style:italic;');
}

// <style> / <script> 削除
foreach ($xpath->query('//style | //script') as $node) {
    $node->parentNode->removeChild($node);
}

$html = $dom->saveHTML();

※ 正規表現ではなく DOM 操作で行うのが安全です。

なぜクリーンアップ工程が必要か

Markdown パーサーの出力 HTML は、

  • ブラウザ表示を前提としている
  • メールクライアント特有の挙動を考慮していない
  • Gmail の仕様変更に弱い

という前提があります。

そのため、
「変換結果をそのまま送る」こと自体が不安定です。

  • HTMLメール用のクリーンアップを挟むことで
  • 表示ルールを一箇所に集約できる
  • Gmail 以外のメーラー差分にも対応しやすくなる
  • 「一部のメールだけ崩れる」事故を防げる

というメリットがあります。


まとめ

  • Gmail は HTML メールのスタイルを 積極的に上書きする
  • Markdown パーサーの素の出力は Gmail と相性が悪い
  • インラインスタイル前提 + 後処理が安定解

Markdown で書ける快適さと、
Gmail で崩れない現実的な設計の間をどう取るかが重要です。

同じ問題で悩んでいる方の参考になれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?