49354
phpでメールを受信した際に、受信したメールから「差出人」「件名」「本文」を抽出してDBに保存する処理を作成しました。  
テストして正常に動作することを確認したのですが、特定の差出人からメールのみ「本文」が文字化けして保存されてしまいます。メーラーソフトで見るぶんには文字化けは発生しないので、メールそのものには問題がないかと考えているのですが・・・

文字化けするメールの文字コードは「utf-8」なのですが、  
「utf-8」のメールすべてが文字化けするのではなく、現状一部のメールのみ文字化けします。  
文字化けするのはあくまで「本文」のみで「件名」は日本語であっても文字化けは発生しません。

文字化けする原因はどのようなことが考えられるでしょうか？

▼以下のようなコードを書いています。

```

    // メールの処理開始
    mb_language('ja');
    mb_internal_encoding("utf-8");
    
    // メール取得
    if ( ($stdin=fopen("php://stdin",'r')) == true ){
        while( !feof($stdin) ){
            $line .= fgets($stdin,4096);
        }
    }
    fclose($stdin);
    
    
    // PEAR を使った処理
    $decoder = & new Mail_mimeDecode( $line ); // MIMEを分解
    $parts = $decoder->getSendArray();
    list( $recipients, $headers, $body ) = $parts;
    
    $subject = mb_decode_mimeheader( $headers['Subject'] ) ;
    $from = mb_decode_mimeheader( $headers['From'] ) ;
    $m_body = trim(mb_convert_encoding( $body, "UTF-8", 'ASCII, JIS, UTF-8, SJIS' ));
    
    //以下DBに保存する処理
    
```

▼文字化けしたメールの一部です

```

      =E2=96=BC=E9=80=A3=E7=B5=A1=E5=B8=8C=E6=9C=9B=
     =E6=97=A5/=E6=99=82=E9=96=93=E5=B8=AF
    
    
     =E2=96=BC=E8=BB=8A=E6=A4=
     =9C=E6=BA=80=E4=BA=86=E6=97=A5
     2018-10-17
    
```
CC BY-SA 4.0
2018-10-16T02:49:08.747
49330
2018-10-17T08:59:20.070
2018-10-16T07:30:38.697
26236
26236
question
php 文字化け 文字コード
受信したメールをDBに保存する際に特定のメールのみ文字化けが発生する
コメントに書いた通りですが、Mail_mimeDecodeは`getSendArray()`を呼んでも、quoted-
printableやbase64でエンコードされたメール本文をデコードしてくれません。正しくデコードさせてやるには`decode()`メソッドを呼ぶ必要があります。

`// PEAR を使った処理`以下の行を、次のように書き換えてください。

```

    // PEAR を使った処理
    $decoder = & new Mail_mimeDecode( $line ); // MIMEを分解
    $decoded = $decoder->decode(
        'include_bodies' => true,
        'decode_bodies' => true,
        'decode_headers' => false, //<-(1)
    ]);
    
    $subject = mb_decode_mimeheader( $decoded->headers['subject'] ) ; //<-(2)
    $from = mb_decode_mimeheader( $decoded->headers['from'] ) ; //<-(2)
    $m_body = trim(mb_convert_encoding( $decoded->body, "UTF-8", 'ASCII, JIS, UTF-8, SJIS' ));
    
    //以下DBに保存する処理
    
```

最近のメールクライアントでは、UTF-8メールを送信するのにquoted-
pritableもbase64も使わないものが多いので、文字化けするものの方が少なかったかもしれませんが、一般的には対応しておかないとまずいものです。

他の種類の文字化けまでは保証できませんが、少なくとも`=`がやたら出てくるquoted-
printableの文字列がそのまま登録されることはなくなるはずです。コメントに書いたように一部修正していただかないといけないかもしれませんが、お試しください。

* * *

と言うわけで、質問者の @たーとるず さんのお力もお借りして上記のコードを修正しました。

(1) `'decode_headers' =>
true,`を指定した元のコードでは、ヘッダー内容のデコード処理がMail_mimeDecode側と、`mb_decode_mimeheader`によるものと二重に走っていました。Mail_mimeDecode側のデコード処理はいまいちあてにできなさそうなので、`mb_decode_mimeheader`だけで処理するよう、値を`false`に変更しました。

(2)
MIMEのヘッダー名は大文字小文字無視が原則ですが、PHPの連想配列はそのような「大文字小文字無視」した検索ができないので、なんらかの方法で表記を統一してやる必要があります。Mail_mimeDecodeではMIMEの仕様にあるような「頭字大文字」ではなく「全部小文字」と言う動作になっていたので、キー文字列をそれに合わせて変更しました。
CC BY-SA 4.0
2018-10-16T12:22:08.470
49354
2018-10-17T08:59:20.070
2018-10-17T08:59:20.070
13972
13972
49330
answer