【SwiftMailer】件名の文字化けを調査してみた話

# 目次
<!-- TOC -->
- [はじめに](#はじめに)
- [したいこと](#したいこと)
- [やったこと](#やったこと)
    - [とりあえずソースを確認](#とりあえずソースを確認)
    - [文字化けした部分の文字コードを調べる](#文字化けした部分の文字コードを調べる)
    - [メールのソースを読む](#メールのソースを読む)
    - [初心に戻ってみる](#初心に戻ってみる)
- [結論](#結論)

<!-- /TOC -->

# はじめに
- PHPのSwiftMailerライブラリを使って送信したメールの件名の一部が文字化けする現象を、素人なりに調査してみた話です
- 他の人が書いたソースを利用しているため処理内容はざっくりとしか把握できていません
- エンコードはShiftJis
- メーラーはThunderbird

# したいこと
`ほげほげシステムふがふが機能ぴよぴよ確認結果(NG)`
という件名にしたいが、受信したメールでは
`ほげほげシステムふがふが機能ぴよぴよ灰hﾈｸ惠比x?`
になっている

「ぴよぴよ」の後ろから文字化けしているためこれを直したい

※ここでの件名は例なので適当です

# やったこと
## とりあえずソースを確認

```php:文字コードを指定してるところを確認
Swift::init(function () {
    Swift_DependencyContainer::getInstance()
        ->register('mime.qpheaderencoder')
        ->asAliasOf('mime.base64headerencoder');

    Swift_Preferences::getInstance()->setCharset('shift_jis');
});
```

メール送信について調べていると文字コードは`iso-2022-jp`で送信するのが主流のようでしたが、ここでは`shift_jis`で貫きます。

※この時点では`SwiftMailer`というものを知らないのでSwift~と書かれているものが何なのかはわかっておらず、雰囲気で読んでいました。

## 文字化けした部分の文字コードを調べる

**予想**

ShiftJisでは「確」は「8A6D」だが何故か別のエンコードになってしまっている。
例えばutf8の「8A6D」は「灰」なのかもしれない。

**やってみる**

文字化けしてない方(確認結果)と、文字化けした方(灰hﾈｸ惠比x?)の文字コードを書き出してみた。

|JIS|SJIS|EUC|UTF-8|UTF-16|字|
|--:|--:|--:|--:|--:|--:|
|334E|8A6D|B3CE|E7A2BA|78BA|確|
|4727|9446|C7A7|E8AA8D|8A8D|認|
|376B|8C8B|B7EB|E7B590|7D50|結|
|324C|89CA|B2CC|E69E9C|679C|果|

|JIS|SJIS|EUC|UTF-8|UTF-16|字|
|--:|--:|--:|--:|--:|--:|
|3325|8A44|B3A5|E781B0|7070|灰|
|68|68|68|68|0068|h|
|48|C8|8EC8|EFBE88|FF88|ﾈ|
|38|B8|8EB8|EFBDB8|FF78|ｸ|
|582A|9CA8|D8AA|E683A0|60E0|惠|
|16|16|16|16|16||
|4866|94E4|C8E6|E6AF94|6BD4|比|
|78|78|78|78||x|
|16|16|16|16|16||
||||||?|

文字コード間違っていたらすみません

**結果**

関係性が見えてこなかったので文字コードが変わってしまってるとかではなさそう。
まぁ件名の途中から文字コードが変わって文字化けするなんて現象が実際にあり得るのかはわかりませんが...

## メールのソースを読む
なんで最初に気づかなかったのか謎ですが、ソース見れば何か書いてあるんじゃねと思ったので見てみる

**やってみる**
1. ソースを見たいメールを開く
2. 右上のボタン群から「その他」>「ソースを表示(V)」を選択<br>![2019-08-21-13-51-16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199895/e85a52bf-6d8f-03f4-852a-c5cc6e161fbb.png)
3. 別ウィンドウでソースが開くので「Subject:」という文言を探してその後ろを参照する

「From:」や「To:」の後ろを見てみると普通にメールアドレスや差出人などが書かれている一方で、「Subject:」の後ろにはハッシュ値のような言葉が並び、`=?shift_jis?`という言葉が含まれていました。Subjectは件名のことです。

何がなんだかさっぱりでしたがなんとなく関係ありそうな`=?shift_jis?`で検索してみたら日本語の件名をShiftJisでエンコードしたってことみたい？

ネットに転がってたデコードツールで「Subject:」の後ろをコピペしたものをデコードしてみたら文字化けした件名(～ぴよぴよ灰hﾈｸ惠比x?)が出てきたので多分そういうことかな。

**結果**

関係がありそうなところは見つからなかった

## 初心に戻ってみる

```php:冒頭に載せたソースを再掲
Swift::init(function () {
    Swift_DependencyContainer::getInstance()
        ->register('mime.qpheaderencoder')
        ->asAliasOf('mime.base64headerencoder');

    Swift_Preferences::getInstance()->setCharset('shift_jis');
});
```

文字コードのことは一旦忘れてソースを理解してみようと思い、Swiftなんたらを調べることに。

**やってみる**

普通に`Swift`って打つとiOSアプリを作るのに役立ちそうな情報が出てきそうだったので「Swift php メール」とかで検索してみると、[Swift Mailer](https://gray-code.com/php/swift-mailer-vol1/)というライブラリがあるらしい

なるほどそれならと「Swift Mailer Subject 文字化け」で調べてみたところそれっぽい記事を発見([symfony1.4の「SwiftMailer」を日本語対応(iso-2022-jp)してみた](https://www.kuzilla.co.jp/20100301symfony))

> どうも、Subjectが長いと文字化けするみたい。<br>ググって見ると、どうも前のバージョンのSwift Mailerも長い日本語は文字化けするという情報が。

とのこと。まじか。

ということで件名をいじいじして実験してみる

|これが|こうなる|結果|
|:--|:--|:--|
|ほげほげシステムふがふが機能ぴよぴよ確認結果(NG)|ほげほげシステムふがふが機能ぴよぴよ灰hﾈｸ惠比x?|×|
|ぴよぴよ確認結果(NG)|ぴよぴよ確認結果(NG)|○|
|あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほ|あいうえおかきくけこさしすせそたちつH,h,�,�,ｨ,ｸ,ﾈ,ﾘ--8-h|×|
|ｱｲｳｴｵｶｷｸｹｺｻｼｽｾｿﾀﾁﾂﾃﾄﾅﾆﾇﾈﾉﾊﾋﾌﾍﾎﾏﾐﾑﾒﾓﾔﾕﾖﾗﾘﾙﾚﾛﾜｦﾝ|ｱｲｳｴｵｶｷｸｹｺｻｼｽｾｿﾀﾁﾂﾃﾄﾅﾆﾇﾈﾉﾊﾋﾌﾍﾎﾏﾐﾑﾒﾓﾔm}狛ｭｽﾊmﾐ|×|
|ａａａａａｂｂｂｂｂｃｃｃｃｃｄｄｄｄｄｅｅｅｅｅ|ａａａａａｂｂｂｂｂｃｃｃｃｃｄｄｄH(H(X(X(X(X(X(|×|
|aaaaabbbbbccc...zzzzz|aaaaabbbbbccc...zzzzz|○|

**結果**

- 全角日本語
    - 18文字目まで正常に表示
- 半角日本語
    - 36文字目まで正常に表示
- 全角英字
    - 18文字目まで正常に表示
- 半角英字
    - 36文字を超えても正常に表示(130文字まで確認)

# 結論
下記のどれかで対応できそう

- 件名を短くする
- 件名を半角英字にする
- SwiftMailer以外の方法でメール送信を行う

もし「こうすれば長めの日本語件名にできるよ！」とか「ここ間違ってない？」とかあれば教えてください！