MIME::EcoEncode.pm - MIMEエンコード用Perlモジュール (エコ改良版)

概要

本ライブラリはメールヘッダのMIMEエンコード用Perlモジュールです。 Jcode.pm (バージョン 2.7) の mime_encode メソッド及び Perl 5.8.8 以降の Encode::MIME::Header モジュールに含まれる MIME-Header-ISO_2022_JP にて採用されている アルゴリズムを全面改良し、 長い文字列でも高速にMIMEエンコードを行えるように実装しました。

特徴

※1 詳細は“ベンチマーク結果”の節をご覧ください。
※2 GB2312は中国、EUC-KRは韓国、Big5は台湾・香港で使用されている文字コードです。
※3 “使用上の注意”の節をご覧ください。
※4 同梱の MIME::EcoEncode::Param モジュールの機能です。

新着情報

2013-11-14
バージョン 0.95 を公開しました。
(エンコード速度を向上しました。
MIME::EcoEncode::Param と MIME::EcoEncode::Fold モジュールを追加しました。
ISO-2022-JP の Qエンコード をできるようにしました。
Shift_JIS の エンコード をできるようにしました。
末尾の改行文字の取り扱いを修正しました。)
2013-09-27
バージョン 0.93 を公開しました。
(エンコード速度を少しだけ向上しました。)
[更新履歴]

ダウンロード

MIME-EcoEncode-0.95.tar.gz (16,824バイト)
MD5 = 4cb6d18f2877fd01f3a450dd22e840e8
SHA1 = 248372a71e5a7b839ccbf9408f3eb63588a945b6

CPAN からもダウンロードできます。

ライセンス

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

使用方法

use MIME::EcoEncode;
$encoded = mime_eco($str, 'UTF-8');        # utf8 文字列をエンコード
$encoded = mime_eco($str, 'UTF-8?B');      #   〃 (Bエンコード)
$encoded = mime_eco($str, 'UTF-8?Q');      #   〃 (Qエンコード)
$encoded = mime_eco($str, 'UTF-8*XX');     # XX は RFC 2231 の言語タグ
$encoded = mime_eco($str, 'UTF-8*XX?B');   #   〃 (Bエンコード)
$encoded = mime_eco($str, 'UTF-8*XX?Q');   #   〃 (Qエンコード)
$encoded = mime_eco($str, 'GB2312');       # euc-cn 文字列をエンコード
$encoded = mime_eco($str, 'EUC-KR');       # euc-kr 文字列をエンコード
$encoded = mime_eco($str, 'Big5');         # big5 文字列をエンコード
$encoded = mime_eco($str, 'Shift_JIS');    # cp932 文字列をエンコード
$encoded = mime_eco($str, 'ISO-2022-JP');  # 7bit-jis 文字列をエンコード
$encoded = mime_eco($str, $sbcs);          # $sbcs :
                                           #   シングルバイト文字セット
                                           #     (例: 'ISO-8859-1')

$decoded = mime_deco($encoded);            # エンコード文字列をデコード
                                           #   (単一文字セットの場合)

($decoded, $charset, $language)            # 配列を返す
         = mime_deco($encoded);            #   (単一文字セットの場合)

use Encode;
$decoded = mime_deco($encoded, \&cb);      # cb はコールバック・サブルーチン
                                           #   (複数文字セットの場合)

# コールバック・サブルーチンの例
sub cb {
  my ($encoded_word, $charset, $language, $decoded_word) = @_;
  encode_utf8(decode($charset, $decoded_word));
}

オプション

$encoded = mime_eco($str, $charset, $lf, $bpl, $mode, $lss);
             # $charset : 'UTF-8' / 'UTF-8?Q' / 'UTF-8*XX' /
             #            'GB2312' / 'EUC-KR' / 'Big5' /
             #            'Shift_JIS' / 'ISO-2022-JP' / ...
             #            (デフォルト: 'UTF-8')
             #            注: 全てのデフォルトはBエンコード
             #                その他は全てシングルバイト文字列
             #                としてエンコード
             # $lf      : 行の折り返し (デフォルト: "\n")
             # $bpl     : 折り返すバイト数 (デフォルト: 76)
             # $mode    : 0 : 非構造化ヘッダ (例: Subject)
             #            1 : 構造化ヘッダ (例: To, Cc, From)
             #            2 : 自動 (Subject か Comments は 0、その他は 1)
             #            (デフォルト: 2)
             # $lss     : 保証空白長 (デフォルト: 25)

使用例

ここでは、ソースの文字コードが UTF-8 で保存されているものとします。

utf8 文字列をエンコードする場合

use MIME::EcoEncode;
my $str = 'Subject: Re: あ A い I う U え E お O';
print mime_eco($str, 'UTF-8') . "\n";

出力結果は以下のようになります。

Subject: Re: =?UTF-8?B?44GC?= A =?UTF-8?B?44GE?= I =?UTF-8?B?44GG?= U
 =?UTF-8?B?44GI?= E =?UTF-8?B?44GK?= O

7bit-jis 文字列をエンコードする場合

use Encode;
use MIME::EcoEncode;
my $str = 'Subject: Re: あ A い I う U え E お O';
print mime_eco(encode('7bit-jis', decode_utf8($str)), 'ISO-2022-JP') . "\n";

出力結果は以下のようになります。

Subject: Re: =?ISO-2022-JP?B?GyRCJCIbKEI=?= A =?ISO-2022-JP?B?GyRCJCQbKEI=?=
 I =?ISO-2022-JP?B?GyRCJCYbKEI=?= U =?ISO-2022-JP?B?GyRCJCgbKEI=?= E
 =?ISO-2022-JP?B?GyRCJCobKEI=?= O

構造化ヘッダをエンコードする場合

デフォルトでは Subject と Comments ヘッダ以外を 自動的に構造化ヘッダと判定するので、 特に何も指定する必要はありません。 以下は、ISO-2022-JP 文字列の From ヘッダをエンコードする場合の例です。 (連続する空白文字にも対応していることを示すため、 わざと2つ連続した空白文字による区切りを入れています。)

use Encode;
use MIME::EcoEncode;
my $str = 'From: OKAZAKI Sakurako  <sakura@example.jp>  (岡崎 桜子)';
print mime_eco(encode('iso-2022-jp', decode_utf8($str)),
               'ISO-2022-JP') . "\n";

出力結果は以下のようになります。

From: OKAZAKI Sakurako  <sakura@example.jp>  (=?ISO-2022-JP?B?GyRCMiwbKEI=?=
 =?ISO-2022-JP?B?GyRCOmobKEIgGyRCOnk7UhsoQg==?=)

使用上の注意

構造化ヘッダでコメントを使用する場合は以下の注意点があります。 (特定のケースで RFC 違反になるのを防止するため、あえてこのような仕様にしています。)

'(' の直前、')' または '),' の直後に空白かタブ文字が入っていないと、 コメントの開始と終了を認識しません。 また、コメントの中にあるコメントは深さ3までしか認識しません。

保証空白長($lss)オプションについて

保証空白長とは、 '(コメント1)____(コメント2)' のようにコメントの後ろにコメントが続く場合において、 '(コメント1)' と '(コメント2)' の間に長い空白文字列が続くと RFC 違反になるのを防止するため、 何文字までの空白をエンコードせず、 そのまま出力するかを数値で調整できるようにした独自の機能です。 (ここでの '____' は連続する空白文字を指すものとします。)

保証空白長のデフォルトは 25 となっており、 空白文字列長がこの値を超えると、 エンコードの挙動が変化します。

'(コメント1)____(コメント2)' のような場合で、 '(コメント1)' と '(コメント2)' の間の空白が 25 文字を超えた場合は、 'コメント1)____(コメント2' を1つのコメントにまとめてエンコードします。

また、先頭が '____あ' のように空白文字列で始まったり、 末尾が 'あ____' のように空白文字列で終了する場合において、 空白文字列長が 25 を超える場合は、 空白を25文字を残し、その他はエンコードします。

その他には、'a____あ' のように ASCII の直後に空白文字列、non-ASCII と続き、 空白文字列内で折り返しが必要になった場合において、 エンコードの挙動が変化します。 空白文字列長が 25 を超える場合は、 'a___' と '_あ' のように non-ASCII の直前の空白1文字以外は、 全て ASCII に結合して折り返します。

ベンチマーク結果

ISO-2022-JP 文字列のMIMEエンコードにかかる時間を計測したところ、 以下のような結果になりました。

件名の長さ Jcode
(v2.7)
MIME::EcoEncode
(v0.95)
速度向上率
全角1文字 3603.60/s 12165.45/s 約3倍
全角25文字 615.38/s 3305.79/s 約5倍
全角50文字 146.09/s 1785.71/s 約12倍
全角100文字 31.98/s 813.01/s 約25倍

※ 測定環境: CPU: Intel(R) Pentium(R) 4 CPU 2.40GHz、 メモリ: 1GB、OS: CentOS 6.4

[ベンチマーク用ソースコード]

参考にしたページ

Copyright(C) 2011-2014 MURATA Yasuhisa. All rights reserved.
Last modified: 2014-01-08