2012年12月20日木曜日

FreeBSD, Perl の Net::SMTP::TLS ではまる

 Net::SMTP::TLS は2006年1月以来更新が止まっていて,2016年時点ではすでに非推奨になっている。 そこで,2016年11月に FreeBSD で,Perl で gmail からメールを送る:Net::SMTP::TLS をやめて,Net::SMTP,IO::Socket::SSL,Authen::SASL を使うことにした というのを書いたので,そちらも参照してみて欲しい。
1年ほど後に FreeBSD で Net::SMTP::TLS を使うには (2013/11 現在) というのを書いた。 そちらも参考にしてみて欲しい。
2009年3月に FreeBSD 上で FreeBSD,Perl スクリプトで,GmailのSMTPからメールを送るを書いた。その時は Net::SMTP::TLS のバージョンは 0.12 だった。

 その後も順調に Net::SMTP::TLS を使ってメールの配信をしていたのだが,FreeBSD 上で portupgrade をしたら,急にメールが送信できなくなってしまった。その時に出てきたメッセージが以下のようなもの。
  at /usr/local/lib/perl5/site_perl/5.16.2/Net/SMTP/TLS.pm line 181.
invalid SSL_version specified at /usr/local/lib/perl5/site_perl/5.16.2/IO/Socket/SSL.pm line 380.
[1] 40204 exit 2 ./Mail_gmail_smtp_587_namelist.pl test subject message "2011/01/01,07:00:00"
 実は,上記の出力はエラーを再現するためにさっき取ったものであり,Perl のバージョンが新しくなっている。このメッセージを見ると,Net::SMTP::TLS 自体がエラーを吐いてるのではなくて,Net::SMTP::TLS が呼び出している IO::Socket::SSL が文句を言ってる。どうも SSL_version がおかしいらしい。そんなこと言われてもなぁ…,と思ってしまった。この時の IO::Socket::SSL のバージョンは 1.76 だった。アップデートする直前の IO::Socket::SSL のバージョンは 1.59 だった。つまり,IO::Socket::SSL のバージョンが 1.59 から 1.76 に上がったらエラーが出るようになった(間に他のバージョンもあったはずだが,アップデートのタイミングでそうなった)。

 上記のエラーに対応するために最初にとった作戦は,IO::Socket::SSL のバージョンを下げることだった。FreeBSDports から portsdowngrade というのをインストールしてみた。これは ports に数多くあるアプリケーションの古いバージョンのリストを表示し,その中から選んでアプリケーションのバージョンを下げれる,というもの。IO::Socket::SSL の場合は,どうもバージョン 1.59 辺りが良さげだった。そこで IO::Socket::SSL のバージョン 1.59 をインストールしてみた。するとうまく SMTP でメールを送ることができた。しかし,ports をアップデートするたびにうまく行かなくなってしまった。そこで,/usr/ports/security/p5-IO-Socket-SSL/ をディレクトリごと保存しておいて,ports のアップデートをする度にコピーしてみたが,アップデートをする度にコピーしないといけないのはちょっとイマイチの作戦。特定の ports のみをアップデートさせないようにすることもできるが,本質的な解決策ではないので,しばし放置することにした。

 しばらく(数ヶ月)Net::SMTP::TLS がアップデートされるのを待っていたが,いつまで経ってもアップデートされなかった。そこでネットでごそごそ調べてみた。ところが同じ症状で困っている,という人は日本語でブログ等を書く人にはいなかった…。仕方ないので,CPAN でドキュメントを調べてみよう,と思った。すると,Net::SMTP::TLS の最新バージョンは 0.12 であり,私がインストールしているものがまさにこのバージョンは 0.12 だった。日付は 2006年1月16日 付だった。それって全然更新されてへんやん!!(この投稿は2012/12に書いた) 一方 IO::Socket::SSL は 最新バージョンが 1.81 であり,日付は 2012年12月6日 付となっている。私が最初にメールが送信できなくなった時のバージョン(ver 1.76)は 2012年6月17日 付だった。メールがうまく送信できた時のバージョン(ver 1.59)は 2012年3月8日 付だった。それぞれの間にはいっぱいバージョンがあり,かなり頻繁に更新がなされている。

 更新日付の情報を見る限りでは,どうも Net::SMTP::TLS は更新がストップしていて,新しいバージョンの IO::Socket::SSL に対応できていないみたい。困った。他のモジュールで良いのがないのかと探してみたが,テストしたりするのにある程度時間がかかりそうで,悩ましかった。そこでいろいろ見ていると CPAN の中に Net-SMTP-TLS-ButMaintained というのを見つけた。なんか変な名前だが,どうも更新が止まってしまっている Net::SMTP::TLS の後継みたいな感じがした。最新バージョンは 0.21 であり,更新日は 2012年12月4日 となっていた。そこで,Perl module の実体ファイルである ButMaintained.pm をゲットして,TLS.pm (ver 0.12) と比較してみた。改行の位置や,スペースの入れ方が違っていたりしたが,最終的にはほぼ同じものであり,IO::Socket::SSL の変更に対処した変更の部分だけが違っている感じだった。そこで,ButMaintained.pm の名前を TLS.pm と変更して,/usr/local/lib/perl5/site_perl/5.16.2/Net/SMTP/ の下にある TLS.pm と置き換えてみた。すると,うまくメールが送信できた。

 今回の問題点の解決をしたと思われる部分は以下のところ。行番号は Net::SMTP::TLS のバージョン 0.12 での行番号を表している。
181 行:以下の4行
        if(not IO::Socket::SSL::socket_to_SSL($me->{sock},
                SSL_version     =>      "SSLv3 TLSv1")){
                        croak "Couldn't start TLS: ".IO::Socket::SSL::errstr."\n";
        }
  を以下の4行に置き換え
        if (not IO::Socket::SSL::socket_to_SSL($me->{sock}, 
            { SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE })) {
            croak "Couldn't start TLS: ".IO::Socket::SSL::errstr."\n";
        }

 ちなみに解決直前に出てたエラーメッセージは文言が増えて以下のようなものだった。 Net-SMTP-TLS-ButMaintained での変更点も以下の文言にあるように SSL_verify_mode というパラメーターに SSL_VERIFY_NONE を代入する,というものだった。まさにこの作業をしたみたい。
*******************************************************************
 Using the default of SSL_verify_mode of SSL_VERIFY_NONE for client
 is depreciated! Please set SSL_verify_mode to SSL_VERIFY_PEER
 together with SSL_ca_file|SSL_ca_path for verification.
 If you really don't want to verify the certificate and keep the
 connection open to Man-In-The-Middle attacks please set
 SSL_verify_mode explicitly to SSL_VERIFY_NONE in your application.
*******************************************************************
  at /usr/local/lib/perl5/site_perl/5.16.2/Net/SMTP/TLS.pm line 181.
invalid SSL_version specified at /usr/local/lib/perl5/site_perl/5.16.2/IO/Socket/SSL.pm line 380.
[1] 40204 exit 2 ./Mail_gmail_smtp_587_namelist.pl test subject message "2011/01/01,07:00:00"

 今回の件は,元の作者が更新を止めてしまったけど,まだ使えるので他の人が更新作業をしている,ということみたい。ほとんど同じ内容なので,同じ名前で新しいバージョンとして登録してくれる方が使い勝手はいいのだが,著作権の問題とかあるのかもしれない。まぁ,こんな例もあるのか,という経験でした。

0 件のコメント: