JISの長文メールの文字化けの解消

CGIテクニック集トップへ





概要

JIS(ISO-2022-JP)にエンコードした日本語文字列をスクリプトからメールで送る場合に、一行が996バイト以上になると自動的に改行が入り2バイト文字が壊され文字化けすることがあります。Jcodeのjfoldを使ってその文字化けを解決する方法です。メッセージボード5で使用されています。 本来ならば一行が1000バイトにもなる文は元々スクリプトに引き渡さないのが望ましいです。

必用な処理

  1. PerlのPackage Jcodeを読み込む
  2. 文字列を行ごとに分ける
  3. Jcodeのメソッドjfoldで日本語文字列を考慮したバイト数で分割する。
  4. 新たに分割された文をまた改行で連結する

サンプルコード

 use Jcode;
 
 my $string = "これは既にJISでエンコードされた長文日本語文字列とします。
               既に改行も複数含まれ、一行の行数が72バイト以上と仮定します。";
 
 my $contents = join "\n", map {jcode($_)->jfold(72)} split /\n/, $string;

コードの解説

 use Jcode;

PerlのPackage Jcodeを読み込みます。

 my $string = "これは既にJISでエンコードされた長文日本語文字列とします。
               既に改行も複数含まれ、一行の行数が72文字以上と仮定します。";

$stringには任意のJISコードでエンコードされた日本語文字列が入っています。サンプルのため短い例文ですが、実際は複数行で一行の長さが72バイト以上とします。72バイトというのも一例に過ぎません。実際は900バイトくらいでも問題ありません。

 my $contents = join "\n", map {jcode($_)->jfold(72)} split /\n/, $string;

全ての処理を一行に書くとこのようになります。$contentsには全ての行が「\n」で改行された全文が入ります。$contentsをメールで送信することで72バイト毎に改行された文が送信され文字化けを防ぐことができます。 上記のコードを一行ずつ処理すると以下のようになります。

 my @alllines = split /\n/, $string;
 my @foledlines = map {jcode($_)->jfold(72)} @alllines;
 my $contents = join "\n", @foldedlines;

各行は以下のようになっています。

 my @alllines = split /\n/, $string;

まず$stringをすでに存在する改行で分割します。一行が72バイト以上の文字列を処理したいので各行ごとに処理します。既に一行が72バイト以下ならばなんの処理もされません。

 my @foledlines = map {jcode($_)->jfold(72)} @alllines;

各行をjcode($_)->jfold(72)で日本語文字列を考慮した上で72バイト毎に分割します。2バイト文字を維持したままなので実際に一行は72バイト前後になります。72バイト以上の行が分割されるので、最終的に@foldedlinesの要素の数は元の@alllinesのそれよりも多くなります。

 my $contents = join "\n", @foldedlines;

@foldedlinesの各要素を「\n」で連結し、元の$stringと同じ状態に戻します。$contentsの一行(改行間)は最長でも72バイト前後となっています。

関連するCGIテクニック

文字コード変換の仕方
文字コードの取得
メールのタイトル用にエンコードする方法
Shift_JISでの文字列サーチする方法
Perl 5.6.1でのUTF-8の処理の方法
テキストメールを送信する方法
HTMLメールを送信する方法
英文スパムなどのアスキーコードのみの文字列を排除する方法