1行1000バイトを超えると文字化けするメール

1行あたり1000バイトを超えると文字化け

送信メールの本文が1行あたり1000バイトを超えた場合、本文が部分的に文字化けすることがあります。

(日本語の1文字は3バイト)

ある環境では1行あたり334文字、1002バイトで文字化けの事象が確認出来ました。


(文字化けだけでなく全体的に体裁がおかしくなっている現象も確認)

これは元々RFCというインターネットの技術仕様によってメール本文中1行の最大長は1000バイトと定められているため、1000バイトを超えた場合にメール送信サーバが自動的に※改行文字を割り込ませることが文字化けの原因となっているようです。

※マルチバイトを考慮しない改行の仕方になっている

【解決策】必要な箇所で改行が入るようにする

最大長1000バイトを超えないように必要な箇所で改行が入るようにします。

PHPのwordwrap関数を使う

環境: PHP 7.1.6

PHPの場合、文字列分割を行うためのwordwrapという標準の関数を利用し、
分割用の文字に改行文字を使うことで自動的な改行を実現します。

ただし、wordwrapは標準ではマルチバイト文字非対応のため日本語用に使うことが出来ないので、
PHPの公式ドキュメント内に有志で用意されているマルチバイト対応のmb_wordwrapを利用します。

mb_wordwrap(対象の文字列, 分割する文字数, 分割文字, 常に分割するか)

  • 第1引数 改行を入れるための対象の文字列
  • 第2引数 分割する文字数(改行を入れる場合はここで指定した数が1行ごとの文字数となる)
  • 第3引数 分割するための文字列(改行を行うので改行文字:バックスラッシュエヌを指定する)
  • 第4引数 trueを指定した場合、第2で指定した文字数よりも長い単語があっても分割する (改行を目的とするのでtrueでよい)


functions.php

<?php
 
function mb_wordwrap($string, $width=75, $break="\n", $cut = false) {
    if (!$cut) {
        $regexp = '#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){'.$width.',}\b#U';
    } else {
        $regexp = '#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){'.$width.'}#';
    }
    $string_length = mb_strlen($string,'UTF-8');
    $cut_length = ceil($string_length / $width);
    $i = 1;
    $return = '';
    while ($i < $cut_length) {
        preg_match($regexp, $string,$matches);
        $new_string = $matches[0];
        $return .= $new_string.$break;
        $string = substr($string, strlen($new_string));
        $i++;
    }
    return $return.$string;
}

実行

<?php

require_once __DIR__ .'/functions.php';

$contact = mb_wordwrap($_POST['contact'], 75, "\n", true);
 

https://www.php.net/manual/ja/function.wordwrap.php#89369

Follow me!