古いCGIに残る`open(FH, ‘| sendmail -t -oi’)`をテストしたい

投稿者: Anonymous

openがまだ2引数でベアワードを織り交ぜていた頃のメール送信プログラムがあります。
このメールのメッセージをテストするスクリプトを書こうとしています。

一部だけ抜粋するとこのような感じになります:

require 'jcode.pl';
require 'mimew.pl';

open(FH, '| sendmail -t -oi');
print FH &mimeencode("From: $from") . "n";
print FH &mimeencode("To: $to") . "n";
print FH qq{Content-Type: text/plain; charset="iso-2022-jp"n};
print FH &mimeencode("Subject: $subject") . "n";
print FH "n";
foreach $line (@lines) {
    print FH &jcode::jis($line, 'sjis') . "n";
}
close(FH);

とりあえずざっくりと、テストスクリプトが対象のコードを舐めた時に実際にメールを送ってしまわないように、openにsendmailらしきコマンドが渡されたら黙って1を返すよう以下のようなコードをテストに含めました。

しかし、そこから一歩進んでファイルハンドルに書き込まれた内容を評価する方法が分かりません。

BEGIN {
    use Symbol ();
    *CORE::GLOBAL::open = sub : prototype(*;[email protected]) {
        no strict 'refs';
        $_[0] = defined $_[0] ? $_[0] : Symbol::qualify($_[0], scalar caller);
        return CORE::open($_[0]) if @_ == 1;
        return 1 if $_[1] =~ /sendmail/;
        return CORE::open($_[0], $_[1]) if @_ == 2;
        return 1 if $_[2] =~ /sendmail/;
        return CORE::open($_[0], $_[1], $_[2]) if @_ == 3 && defined $_[2];
        return CORE::open($_[0], $_[1], undef) if @_ == 3;
        return CORE::open($_[0], $_[1], @_[2..$#_]);
    };
}

以下の条件を満たしつつファイルハンドルに書き出された文字列をテストスクリプトの中で変数に代入することは可能でしょうか? また、可能であればどのように実現できますか?

  • テスト実行時に実際にメールを送信させてしまわないこと。
  • スクリプトが他で使っているsendmailと関係のないopenを壊さないこと。
  • テスト対象のスクリプトをいじらない事。

解決

CORE を直接弄るよりは、テスト時のみ sendmail への PATH を書き換えてそちらが標準入力から得た内容でテストした方が健全な気がします。

回答者: Anonymous

Leave a Reply

Your email address will not be published.