その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

macOSでgit-send-emailがsmtpauthオプションを上手く扱えないという問題

brewでインストールしたgitのgit-send-mailsmtpauth を指定してもそれが上手く適用されず、問答無用で DIGEST-MD5 が利用されるという問題に当たったので、その解決方法をメモとして記します。
さくらのメールボックスMD5-DIGEST をサポートしておらず、PLAIN もしくは CRAM-MD5 を使う必要があるのでこの挙動は困るんですよね……

TL;DR

  • brewで入れたgitのgit-send-mailが依存しているCPANモジュールのバージョンが古い
  • 新しいバージョンのCPANモジュールがインストールされているPerlランタイムの PERL5LIBGITPERLLIB 環境変数に渡すと動く
    • 例:
$ GITPERLLIB="/path/to/.plenv/versions/5.32.1/lib/perl5/5.32.1/:/usr/local/Cellar/git/2.30.0/share/perl5" git send-email --smtp-debug 1 --smtp-auth CRAM-MD5 0001-something.patch
  • もしくは依存している Net::SMTP のバージョンを上げる (例えば3.11) と動く

環境

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.7
BuildVersion:   19H15
$ git version
git version 2.30.0
$ perl --version
This is perl 5, version 32, subversion 1 (v5.32.1) built for darwin-2level

なぜperlが必要かというとgit-send-mailはperlで実装されているためです。
なお、gitはbrewでインストールされており、おそらくこれも原因の一つです。

症状

$ git send-email 0001-something.patch
...snip...
Died at /usr/local/Cellar/git/2.30.0/libexec/git-core/git-send-email line 1578.

死んでまんな。そしてこのエラーメッセージは見覚えが……perlですね。

debug modeをenableにして再度見てみましょう。

$ git send-email --smtp-debug 1 0001-something.patch
...snip...
Send this email? ([y]es|[n]o|[e]dit|[q]uit|[a]ll): y
Net::SMTP>>> Net::SMTP(2.31)
Net::SMTP>>>   Net::Cmd(2.29)
Net::SMTP>>>     Exporter(5.68)
Net::SMTP>>>   IO::Socket::INET(1.33)
Net::SMTP>>>     IO::Socket(1.36)
Net::SMTP>>>       IO::Handle(1.34)
...snip...
Net::SMTP::SSL=GLOB(0x7ff38a07c878)<<< 250-AUTH CRAM-MD5 DIGEST-MD5 LOGIN PLAIN
Net::SMTP::SSL=GLOB(0x7ff38a07c878)<<< 250-DELIVERBY
Net::SMTP::SSL=GLOB(0x7ff38a07c878)<<< 250 HELP
Net::SMTP::SSL=GLOB(0x7ff38a07c878)>>> AUTH DIGEST-MD5
...snip...
Net::SMTP::SSL=GLOB(0x7ff38a07c878)>>>
Net::SMTP::SSL=GLOB(0x7ff38a07c878)<<< 235 2.0.0 OK Authenticated
...snip...
Died at /usr/local/Cellar/git/2.30.0/libexec/git-core/git-send-email line 1578.

依存しているCPANモジュールが軒並み古く、なおかつ >>> AUTH DIGEST-MD5 によって DIGEST-MD5 が指定されており、そして死んでいることがわかりますね (表面上は OK Authenticated が返ってきている一方、これは上手く動かない様子。参照: https://adiary.adiary.jp/0407)。


ウェブで検索をかけてみると、過去に同じような原因で詰まっており解決されている方が。

http://www.katsuster.net/index.php?arg_act=cmd_show_diary&arg_date=20180906&arg_range=1&arg_direction=0

なるほど〜、smtpauthPLAIN とかにしてみると良いんですね。現在はさくらのメールボックスCRAM-MD5 もサポートしているので、これを指定してみましょう。

$ git send-email --smtp-debug 1 --smtp-auth CRAM-MD5 0001-something.patch
...snip...
Net::SMTP::SSL=GLOB(0x7ff38a07c878)<<< 250-AUTH CRAM-MD5 DIGEST-MD5 LOGIN PLAIN
Net::SMTP::SSL=GLOB(0x7ff38a07c878)<<< 250-DELIVERBY
Net::SMTP::SSL=GLOB(0x7ff38a07c878)<<< 250 HELP
Net::SMTP::SSL=GLOB(0x7ff38a07c878)>>> AUTH DIGEST-MD5
...snip...
Net::SMTP::SSL=GLOB(0x7ff38a07c878)>>>
Net::SMTP::SSL=GLOB(0x7ff38a07c878)<<< 235 2.0.0 OK Authenticated
...snip...
Died at /usr/local/Cellar/git/2.30.0/libexec/git-core/git-send-email line 1578.

うーん、オプションで明示しても DIGEST-MD5 がまだ使われていますね。困った。

解決

とりあえずコード読んで、ちまちまデバッグしてみたところコード的には問題なさそう。つまり依存しているモジュールあるいはそのロードっぽいな〜、ということで git-send-email のコードを読んでみる。

#!/usr/bin/perl

use lib (split(/:/, $ENV{GITPERLLIB} || '/usr/local/Cellar/git/2.30.0/share/perl5:/Applications/Xcode.app/Contents/Developer/Library/Perl/5.18/darwin-thread-multi-2level:/Library/Developer/CommandLineTools/Library/Perl/5.18/darwin-thread-multi-2level'));
#
# Copyright 2002,2005 Greg Kroah-Hartman <greg@kroah.com>

なるほど〜、 GITPERLLIB 環境変数が渡されていない時はなんか全体的に古いモジュールを見てそうですね。

というわけで GITPERLLIB に使っているperlPERL5LIB 相当を渡して実行してみましょう。

$ GITPERLLIB="/path/to/.plenv/versions/5.32.1/lib/perl5/5.32.1/:/usr/local/Cellar/git/2.30.0/share/perl5" git send-email --smtp-debug 1 --smtp-auth CRAM-MD5 0001-something.patch
...snip...
Net::SMTP>>> Net::SMTP(3.11)
Net::SMTP>>>   Net::Cmd(3.11)
Net::SMTP>>>     Exporter(5.74)
Net::SMTP>>>   IO::Socket::IP(0.39)
Net::SMTP>>>     IO::Socket(1.36)
Net::SMTP>>>       IO::Handle(1.34)
...snip...
Net::SMTP=GLOB(0x7fb7d9825d38)<<< 250-AUTH CRAM-MD5 DIGEST-MD5 LOGIN PLAIN
Net::SMTP=GLOB(0x7fb7d9825d38)<<< 250-STARTTLS
Net::SMTP=GLOB(0x7fb7d9825d38)<<< 250-DELIVERBY
Net::SMTP=GLOB(0x7fb7d9825d38)<<< 250 HELP
Net::SMTP=GLOB(0x7fb7d9825d38)>>> AUTH CRAM-MD5
...snip...
Result: 250
Net::SMTP=GLOB(0x7fb7d9825d38)>>> QUIT

モジュールのバージョンが新しめで、ちゃんと >>> AUTH CRAM-MD5 が指定され、そして成功していますね。やりました。
なお /usr/local/Cellar/git/2.30.0/share/perl5 も併せて指定している理由は、これが存在しないとgitが用意しているモジュールをロードできない為です。ここは適宜環境に合わせて変更する必要があるでしょう。

ちなみに、今回は新しめのバージョンのperlランタイムのライブラリパスを渡すことで解決しましたが、単純に Net::SMTP のバージョンを上げる (3.11とか)、でも解決できると思います。


というわけでようやく動きました……ところで git-send-email、実ははじめて使いました。以上です。