Net::SMTPSを使い始めたところからの悪夢⇒DLLがロードされない問題の調査方法
苦しんだ3日間の奮闘メモ。
事の始まり
PerlのNet::SMTPSモジュールを使って、GmailのSMTPサーバー経由でメールを送ろうという試みを始めたところから悪夢は始まった。
プログラムのコアな部分は大まかに以下のような感じ。
sub send { my $self = shift; my ($args) = @_; my $from = $args->{from}; my $to = $args->{to}; my $header = $args->{header}; my $body = $args->{body}; my $config = MyConfig->new; $config->load(); my $smtp = $config->getSmtpAddress(); my $port = $config->getSmtpPort(); my $user = $config->getSmtpUser(); my $password = $config->getSmtpPassword(); my $mail = Net::SMTPS->new($smtp, Hello => $smtp, Port => $port, doSSL => 'starttls', Debug => 0 ); # $mail->starttls(); $mail->auth($user, $password); $mail->mail($from); $mail->to($to); $mail->data(); $mail->datasend(join("\r\n", $header, $body)); $mail->dataend(); $mail->quit(); }
とか。
こうすればいいのか、とか。
まぁいろいろとあったが、何とかCentOS 7のVM上でNet::SMTPSを使ってGmailのSMTPサーバー経由でメールを送れるようになった。
問題はここから。
悪夢の始まり
Windows環境に持ってきて、XAMPPに同梱されているPerl.exeで同じプログラムを実行すると、なぜか
Failed to open SMTPS connection: Bad file descriptor at・・
というエラーメッセージが出てメールが送れない。 printデバッグで、
require IO::Socket::SSL;
しているところで失敗しているっぽいことを突き止めたり、
SET PERL_DL_DEBUG=1 とすると、以下のようにデバッグログが出ることを知ったりする。
DynaLoader.pm loaded (. C:/xampp/perl/site/lib C:/xampp/perl/vendor/lib C:/xampp/perl/lib, C:\xampp\c\lib \xampp\c\x86_64-w64-mingw32\lib \xampp\c\lib\gcc\x86_64-w64-mingw32\8.3.0) DynaLoader::bootstrap for Net::SSLeay (auto/Net/SSLeay/SSLeay.xs.dll) DynaLoader::bootstrap for Digest::MD5 (auto/Digest/MD5/MD5.xs.dll) Failed to open SMTPS connection: Bad file descriptor at ・・・
そこで、DLLのロードをしているDynaLoader.pmにprintデバッグして、
MD5.xs.dll ではなく、やはり SSLeay.xs.dll のロードに失敗していることを確認。
SSLeayと言えば libeay32.dll と ssleay32.dll という頭もあったのだろう。
また、以下のサイトを見てしまったのも悪夢を助長させる要因となった。
(・・・2日後・・・)
ふと、「そもそも依存しているのはlibeay32.dll と ssleay32.dllじゃなかったりする?」と疑問を持ったところから急展開を見せる。
「DLL 依存性」などのキーワードで探すと、あるDLLが依存しているDLLの一覧を出力する方法を知る。
最初、コマンドプロンプトで
C:\Users\hhelibex>dumpbin /dependents C:\xampp\perl\vendor\lib\auto\Net\SSLeay\SSLeay.xs.dll 'dumpbin' は、内部コマンドまたは外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されていません。
と言われて、あれ?と思って後者のサイトを見つけ、Visual Studio 2019をインストール&Windows OSの再起動をした。
サイトの記述に従い、Visual Studio 2019を起動し、[ツール]-[コマンドライン]-[開発者用 PowerShell]でPowerShellを起動し、コマンドを叩く。
すると、
**********************************************************************
** Visual Studio 2019 Developer PowerShell v16.11.26
** Copyright (c) 2021 Microsoft Corporation
**********************************************************************
PS C:\Users\hhelibex\source\repos> dumpbin /dependents C:\xampp\perl\vendor\lib\auto\Net\SSLeay\SSLeay.xs.dll
Microsoft (R) COFF/PE Dumper Version 14.29.30148.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file C:\xampp\perl\vendor\lib\auto\Net\SSLeay\SSLeay.xs.dll
File Type: DLL
Image has the following dependencies:
msvcrt.dll
KERNEL32.dll
libcrypto-1_1-x64__.dll
libssl-1_1-x64__.dll
perl532.dll
Summary
1000 .CRT
2000 .bss
1000 .data
1000 .edata
8000 .idata
3000 .pdata
D000 .rdata
1000 .reloc
5E000 .text
1000 .tls
4000 .xdata
PS C:\Users\hhelibex\source\repos>
libcrypto-1_1-x64__.dll と libssl-1_1-x64__.dll !?初めて見たぞ。
とりあえずググる。そして、いろいろとダウンロードして名前を変更して(アンダースコア2つ「__」が入っていないので)、順番に試す。 ダメ。
途方に暮れながら、何気なくPC内を探す。 ・・ なんかある!?
C:\Users\hhelibex> dir C:\xampp\apache\bin
ドライブ C のボリューム ラベルがありません。
ボリューム シリアル番号は 4006-07DE です
C:\Users\hhelibex\xampp\apache\bin のディレクトリ
2023/05/23 20:33 <DIR> .
2023/05/23 20:33 <DIR> ..
2023/03/07 22:22 98,816 ab.exe
2023/03/07 22:22 110,592 abs.exe
2023/03/07 22:22 43,008 ApacheMonitor.exe
2023/03/07 22:22 19,456 apr_crypto_openssl-1.dll
2023/03/07 22:22 31,232 apr_dbd_odbc-1.dll
2023/03/07 22:22 14,848 apr_ldap-1.dll
2022/05/30 19:58 215,352 curl-ca-bundle.crt
2019/02/06 15:58 4,110,456 curl.exe
2023/03/07 22:25 9,192 dbmmanage.pl
2023/03/07 22:22 101,888 htcacheclean.exe
2023/03/07 22:22 124,416 htdbm.exe
2023/03/07 22:22 86,016 htdigest.exe
2023/03/07 22:22 118,784 htpasswd.exe
2023/03/07 22:24 30,720 httpd.exe
2023/03/07 22:22 65,536 httxt2dbm.exe
2023/05/23 20:33 <DIR> iconv
2023/03/15 03:30 30,422,016 icudt71.dll
2023/03/15 03:30 3,031,552 icuin71.dll
2023/03/15 03:30 60,928 icuio71.dll
2023/03/15 03:30 2,253,312 icuuc71.dll
2021/09/12 18:59 55,808 jansson.dll
2023/03/07 22:20 215,552 libapr-1.dll
2023/03/07 22:20 36,864 libapriconv-1.dll
2023/03/07 22:20 294,912 libaprutil-1.dll
2023/02/09 21:49 3,445,248 libcrypto-1_1-x64.dll ⇐☆☆☆
2019/02/06 15:58 1,020,536 libcurl.dll
2023/03/07 22:21 459,776 libhttpd.dll
2023/03/15 03:30 209,920 libsasl.dll
2023/03/15 03:30 380,928 libssh2.dll
2023/02/09 21:50 689,664 libssl-1_1-x64.dll ⇐☆☆☆
2022/11/02 01:03 1,373,696 libxml2.dll
2023/03/07 22:22 58,368 logresolve.exe
2019/04/05 23:28 184,320 lua52.dll
2023/03/07 22:16 156,160 nghttp2.dll
2023/02/09 21:51 550,912 openssl.exe
2021/08/23 23:32 400,896 pcre.dll
2023/01/12 18:44 564,224 pcre2-8.dll
2012/04/17 02:30 61,440 pv.exe
2023/03/07 22:22 78,848 rotatelogs.exe
2023/03/07 22:22 18,432 wintty.exe
2022/11/02 01:06 89,600 zlib1.dll
40 個のファイル 51,294,224 バイト
3 個のディレクトリ 415,936,548,864 バイトの空き領域
C:\Users\hhelibex>
ファイル名はちょっと違うけど、それっぽい! 早速PATHを通して実行してみる。。。やっぱりダメ。じゃあ、コピーして名前を変更して実行。 ・・・ 動いた!!!
じゃあ、PATHを通さずに、libcrypto-1_1-x64__.dll と libssl-1_1-x64__.dllだけコピーして・・ダメ。
まぁ、とりあえず動く方法が見つかって、ようやく一安心したところで、詳細を調べてみた。
先ほどのDLLの依存関係の続き。
PS C:\Users\hhelibex\source\repos> dumpbin /dependents C:\Users\hhelibex\SMTPServer\libcrypto-1_1-x64__.dll
Microsoft (R) COFF/PE Dumper Version 14.29.30148.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file C:\Users\hhelibex\SMTPServer\libcrypto-1_1-x64__.dll
File Type: DLL
Image has the following dependencies:
WS2_32.dll
ADVAPI32.dll
USER32.dll
bcrypt.dll
KERNEL32.dll
VCRUNTIME140.dll
api-ms-win-crt-stdio-l1-1-0.dll
api-ms-win-crt-convert-l1-1-0.dll
api-ms-win-crt-string-l1-1-0.dll
api-ms-win-crt-time-l1-1-0.dll
api-ms-win-crt-utility-l1-1-0.dll
api-ms-win-crt-runtime-l1-1-0.dll
api-ms-win-crt-filesystem-l1-1-0.dll
api-ms-win-crt-heap-l1-1-0.dll
api-ms-win-crt-environment-l1-1-0.dll
Summary
1000 .00cfg
8000 .data
3000 .idata
1C000 .pdata
CF000 .rdata
8000 .reloc
1000 .rsrc
252000 .text
PS C:\Users\hhelibex\source\repos> dumpbin /dependents C:\Users\hhelibex\SMTPServer\libssl-1_1-x64__.dll
Microsoft (R) COFF/PE Dumper Version 14.29.30148.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file C:\Users\hhelibex\SMTPServer\libssl-1_1-x64__.dll
File Type: DLL
Image has the following dependencies:
libcrypto-1_1-x64.dll ⇐☆☆☆
KERNEL32.dll
VCRUNTIME140.dll
api-ms-win-crt-time-l1-1-0.dll
api-ms-win-crt-string-l1-1-0.dll
api-ms-win-crt-utility-l1-1-0.dll
api-ms-win-crt-runtime-l1-1-0.dll
api-ms-win-crt-convert-l1-1-0.dll
api-ms-win-crt-stdio-l1-1-0.dll
Summary
1000 .00cfg
5000 .data
6000 .idata
6000 .pdata
23000 .rdata
2000 .reloc
1000 .rsrc
74000 .text
PS C:\Users\hhelibex\source\repos>
・・おまえか! libssl-1_1-x64__.dll が libcrypto-1_1-x64.dll に依存している。
だからlibcrypto-1_1-x64__.dll と libssl-1_1-x64__.dllだけあってもダメで、同じ内容でファイル名だけ違う libcrypto-1_1-x64.dll がいないとダメなのか。
案の定、ファイルを3つ用意したら、PATHを通す必要もなく動いた。 あとは、これをWindowsサービス登録する形になるから、その場合にどうなるかだが、それはこれから調査。
反省
「SSLeay」と言えば「libeay32.dllとssleay32.dll」という思い込みから悪夢が始まり、3日間くらい浪費したので、思い込みは良くない。 でも、もう少しエラーメッセージを改善してほしい。依存しているけど見つからないライブラリをエラーメッセージに載せてくれればここまで悩まずに済んだんだけどな。