新しい MH-E を nmh とともに使う

大木さんが引き続き github で nmh の日本語パッチの公開・更新を続けてくださっていることをお知ら せくださいましたので、その利用を前提とした内容に修正します。

MH-E での電子メールを読み 書きに、かつては MH-JP を使っていたのですが、最近は表題が ISO-2022-JP でなく UTF-8 で encode されているメールを受け取ることが多く、summary バッファで読めない ことが多いので、大木さんが 公開されてる nmh 修正版に移行しました。大木さんありがとうございます。

注意

昔の mh-e(バージョン 5 の頃)の使用法には慣れているものとします。こ こでは、その説明はいちいちしません。

私はあまり高度な機能は使っていません。speedbar, PGP, anti-spam software の併用、thread 表示などに関する情報はほとんど扱っていませんので あしからず。

また、Emacs のバージョンは 28.1 以降とします。

LANG 環境変数などで指定している locale は、日本語 EUC には 限定しません。現状、LANGja_JP.UTF-8 にして使っ ていますが、問題は起きていません。昔の MH-E と違って、scan, inc, mhl に 対して modify-coding-system-alist で日本語コードを指定した りはしていません。

そして、大木さんの修正キット中の README 中にあるように、 ~/.mh_profile には


encode_atom_wise: enable
scan_text_plain: enable
force_8bit: enable
wcwidth_fix: enable
guess_8bit_charset: enable

という行が追加されているとします。

ベースとなる MH

MH-E 8 がサポートするのは

の3種ですが、ここでは nmh に大木さんの日本語対応パッチを適用したものを 前提とします。

新しい MH-E では変数名に多少の変更が行われているので、以前 ~/.emacs でカスタマイズを行っていた人は 文書 によく目を通しておきましょう。

メールを読む

Summary 表示

文字化け

メールを読むとき、まず、素の状態で困るのが、Summary バッファにおいて 「差出人名」と「表題」が日本語の場合、「=?ISO-2022-JP?B…」 といった表示になっていて全然読めないことでしょう。これは、以前 の mh-e を MH-JP で利用していた頃には起きなかったことです。

こうなる理由は、現在の MH-E では、scan 時に独自の format パターンを与えているためです。これを解決する簡単な方法としては、 ~/.emacs


(setq mh-scan-format-file nil
      mh-adaptive-cmd-note-flag nil)

と書き、独自 format を使用しないようにしておくとよ いでしょう。これで文字化けが起きるとしたら、Emacs の process-coding-system 周りの設定のどこかがおかしいのだと思 います。

なお、MH-E の独自 format は、新機能「メール番号の桁数への動的対応」の ために必要とされるもののようなのですが、上記の設定はそれを殺しています。 なので、「桁数固定じゃいやだ!」という人は、mh-scan.elmh-scan-format-nmh をもとにして、nmh の decode 関数を用いた format file を作り、そのファイル名を mh-scan-format-file に指 定するとよいでしょう(未確認)。

色づけがずれる

文字化け以外の問題点として、font lock を利用してカラー表示をしている 場合、差出人名が日本語のメールは、色づけの境界がずれてしまっていることに 気づくと思います(差出人名を修飾するはずの黒色が、一部表題にまではみ出す; ごめんなさい、スクリーンショットは用意してません)。

この問題を完全に解決するのは難しいのですが、部分的な解決については 項を改めて後述します

本文表示

さて、上の設定で Summary バッファでの表示については大体問題はなくなっ たはずで、本文の表示にも大体は不都合はないはずですが、以下のように少数な がらまだ調整が必要なケースも残っています。

文字化け

本文を読むとき、次の条件をみたすメールが文字化けしてしまいます(ヘッ ダ、ボディともに)。

これもやはり、従来の MH-E ではなかった現象で、MIME 周りの処理を MH-E が自前で行うようになったことによるとばっちりです。

このようなメールは、最近では受け取ることも少なくなっているので、特に 問題が起きない、という人も多いでしょう。しかし、MIME が普及するよりも前 に受け取ったり、送ったりしたメールが資産として手元にある人にとっては、こ れでは困ります。日本で使うメールソフトとしては、MIME 関連のヘッダが 何もついていないメールを読むときは、JIS コードで記述されているという前提 で動作してくれないとものの役には立たないのです。 (何かのスクリプトで、まとめて MIME-Version ヘッダと Content-Type ヘッダ を付加してしまえばよい、ですって?嫌ですよ、そんなもん)

これを解決するため、私は以下のようなパッチを当て た上で、~/.emacs


(defun decode-message-body-without-mimeheader (orig-fun)
  "MIME-Version ヘッダなしでも、メール本文を decode させる。"
  (let ((mail-parse-charset 'undecided))
    (funcall orig-fun)))
(advice-add 'mh-decode-message-body :around
	    #'decode-message-body-without-mimeheader)

としています(多少汎用性を持たせるため、 'iso-2022-jp を直接指定するのではなく、 'undecided(自動判別)を利用しています)。 [2016, 10/14] emacs 24 辺りから入った「新しい advice の枠組」に対応して 更新しました。[2022, 9/19] このや り方だと、Content-Transfer-Encoding: 8bit で本文に utf-8 な どの文字がそのまま入ったメールを表示するとき、自動判別に失敗して文字化け が起きることがあることがわかりました。そこで、パッチの方で「MIME 形式で ないときだけ自動判別する」というやり方に変えました。 [2023, 2/24] これだけではまだ文字化けが発生 する場合がありました。次の「PGP 署名付きメッセージの検証・表示」の節の終 わりをご覧ください。

なお、文字化けを避ける別解として mh-mhl-format-filet または mhl 用の適切な format file を指定する、という手も あるのですが、これだと添付ファイルを「ボタン」化して扱える、という MH-E の新機能(※ 注)の恩恵が受けられない、というデメリットがあります。もち ろん、「添付ファイルなんかどうでもいい」という人はその方法でも構いません。 これだと、「ヘッダの表示される順番を format file で指定できる」というメ リットもありますしね!(mhl を使わなければ、ヘッダの順番は元のメールのま まソートされない)

PGP 署名付きメッセージの検証・表示

PGP 署名されたメッセージ(multipart/signed ではなく、署名され たメッセージ全体が text/plain になってるタイプ)を受け取った場合も、日本 語部分が decode されず読めない、という問題が起こります。

[2022, 4/18]emacs 28.1 では、以下の弥縫策 では回避できなくなっていました。大木さんが mm-uu-pgp-signed-extract-1にちゃんと手を入れるパッチを試作 して私信でお送りくださり、私の所では何とか読めるようになっています。その うち、大木さんのサイトで公開されるのではないかと思います。 [2016, 10/14] この問題は根が深く、完全に解決するのは難しいことがわかっ たのですが、とりあえず私が今の所受け取っている範囲のメールでは、以下で公 開しているパッチに加えて、.emacs 等で次の行を加えることによっ て問題は糊塗できています。


(setq mm-uu-text-plain-type '("text/plain" (charset . undecided)))

なお、mm-uu-text-plain-type に対する変更は、本来は上記のよ うな ad hoc な対処ではなく、関数 mm-uu-pgp-signed-extract-1 に decode 処理を入れるのが筋なのでしょう (mm-uu-pgp-encrypted-extract-1 みたいに)。 [2023, 2/24] どうも、この行は PGP 署名と無関係な場面でも必要(ないし有用)である場合があるこ とがわかってきました。細かい条件はよくわからないのですが、 Content-Type: text/plain; charset="utf-8" かつ Content-Transfer-Encoding: 8bit のメールが、本文に UTF-8 のバイト列がそのまま書かれている部分が decode されず raw 8-bit character のまま表示されてしまう例が一部(全部ではな い)存在しています。これは(理由はよくわかりませんが)


(setq mm-uu-text-plain-type '("text/plain" (charset . undecided)))
を入れることによって正しく表示されるようになりました。 mh-mime-display 中で、mm-uu-dissect が返す値が関わっていて、nil を返す場合は問題ないの ですが、そうでない場合に上の処置が必要(有効)な場合があります。 (もしかしたら、文字コード指定は undecided ではな く utf-8 決め打ちでもいいのかもしれません) mm-uu-dissect はやってることがややこしくて、詳しい 原因はよくわかりません…。しかし、こんな具合に mm-uu-text-plain-type がらみの問題が色々起きる所を 見ると、どうも MH-E は gnus の関数を正しく利用していないんじゃ ないかという気がします。MH-E で MIME 処理の際に下請けとして呼ん でいる gnus の諸関数(mm-何ちゃらという名前のやつ)は、もしかし たら生コードで書かれた文字を decode に呼ぶことを想定 しているものなんじゃないでしょうか。で、gnus 内で使うときはそう いう呼び方をしているのに、MH-E で呼ぶときは decode の、無変換 byte 列が入った unibyte バッファで呼んでしまっている のではないか、という気がします (mm-uu-text-plain-type のデフォルト値は

("text/plain" (charset . gnus-decoded))
で、gnus-decoded という名前からしていかにも 「decode ずみ」という感じがする)。この想定が正しいなら、大木さ んのパッチがなさっているように、mm-uu.el に手を入れるのは正しく なくて、MH-E 側での gnus 関数の呼び出し方こそを修正しないといけ ない、ということになるわけですが…

S/MIME [2014, 1/28]

銀行などから、差出人が真正であることを証明するために S/MIME 署名つきの メールが届くことがあります。ある時期まではこれも RET で表示さ せて K v で検証できていたのですが、いつの間にか検証がことごと く失敗するようになってしまっていました。原因は、私の場合は、 mml-smime-use の定義が

(defcustom mml-smime-use (if (featurep 'epg) 'epg 'openssl)

...
のようになっていて、「epg が有効な場合は epg 経由で S/MIME を処理する」 というようになっていたためでした。epg は S/MIME の処理には gnupg の gpgsm を利用するのですが、私が使っている FreeBSD で普通にインストールされる gnupg だと gpgsm は省かれるため、epg が検証を行うことができずエラーになっていたよう です。結局、epg が想定している「gnupg がインストールされている環境 では必ず gpgsm が使える」という仮定が粗い、ということなのでしょう。

試しに gpgsm を追加インストールしてみたり、mml-smime-use の 値を openssl にしてみたりすると、再びちゃんと検証がうまく行 くようになりました。

結局、こういう場合は、~/.emacs(あるいは、 ~/.emacs.d/init.el など)に次のように書いておけばいいようで す。

(setq mml-smime-use (if (executable-find "gpgsm") 'epg 'openssl))

もっとちゃんとやるには mml-smime.eldefcustom そのものをいじるんでしょうが、そこまでやるとおお ごとなのでとりあえずはこれで。

メールを書く

さて、ここまでで「受け取ったメールの表示」についての問題はおおよそ解 決できます。しかし、これだけではまだ、「自分が書いて、出すメール」に重大 な問題が残っています。

anti MIME

以下抹消部は、現在は放棄しました。一部の環境(おそらく、macOS のデフォ ルトのメールクライアント)では、受け取ったメールを表示しようとするとき、 MIME 形式でない場合は ISO-2022-JP のエスケープシークエンスがあるだけでは それを解釈しようとせず、すべて表示が文字化けしてしまうようです。ある時期 から「読めない」という返答が多く返ってくるようになったため、ついに諦めて、 不本意ながら全てのメールを MIME 形式で送るようにしています。

私は個人的に MIME というものが嫌いなので、添付ファイルを送る必要があ る場合を除き(つまり、本文が全文単なる平文で済む場合)、日本語を含む場合 も送信メールが MIME 形式にならないようにしています。現行の MH-E をそのよ うに振る舞わせるのには少々苦労しましたが、


(setq sendmail-coding-system 'iso-2022-jp)
(defun disguise-all-ascii ()
  "`mh-ascii-buffer-p' を無効化する。"
  (eq mail-send-nonascii t))
(advice-add 'mh-ascii-buffer-p :before-until #'disguise-all-ascii)
(setq mail-send-nonascii t)

(add-hook 'mh-compose-letter-function
	  (lambda (to subject cc)
	    (set-buffer-file-coding-system sendmail-coding-system)))

とすることによって、一応狙いどおりのことはできてい ます(※ これは、「自分が送る日本語メールはちゃんと全部 MIME 形式 にしたい」という人はやってはいけない設定です。くれぐれ もご注意ください)。[2016, 10/14] emacs 24 辺りから入った「新しい advice の枠組」に対応して更新しました。

Emacs 22+ の更なる問題

Emacs 22 以降で使う場合、これまでに問題が2つ1つ見つかっています。

[2012, 12/7] 以前、ここで書いていた 「default-sendmail-coding-system の起動時の値」についての問題は、 半田さんのお話によればむしろ「そういうもの」と理解すべきものだったこ とのようなので、カットしました。本文書では、単に sendmail-coding-systemiso-2022-jp にセットす る、という話に留めています。

もうひとつの問題ですが、emacs 22 では、「ヘッダが MIME 符号化されたメー ルに対して返信を書く」とき、 送信時に2重に MIME 符号化されてしまい、結果受け取った相手がまともに読めない、という問題 が発生するようになりました。これを解消するには、更に


;; for emacs 22 and later
(setq rfc2047-encode-encoded-words nil)

という設定を追加する必要があります。こちらは、 ~/.emacs 内なら置く位置はどこでもよいです。

[2012, 10/1] なお、 後者の問題は MH-E 8.3 では修正されたという触れ込みなのですが、よく読 むと書いてある通り、対処されているのは Subject ヘッダのみです。日本で使 う場合は、From ヘッダなど、他のヘッダでも MIME 符号化が行われるヘッダが 多いので、上記の設定は引き続き必要となるでしょう。

段落処理

メールを書いているときの推敲中、段落移動や、段落の整形処理がうまく働か ないことがあります。具体的には、1段落だけ整形するつもり で M-q と打ったのに、次の段落までまとめて1段落と見なされて整 形処理に巻き込まれる、というような現象が発生したりします。これは、メール を書くモードでの標準の「段落認識設定」が日本語文章向けにチューンされてい ないからです。

以下のような処理を ~/.emacs に追加するとよいでしょう。


(add-hook 'mh-letter-mode-hook
	  (lambda ()
	    ;; 空白から始まる行も段落の始めにする。欧米人はそうはしない
	    ;; のかもしれないけど、日本じゃこうなってないと困るよ…。
	    (paragraph-indent-minor-mode 1)
	    (setq paragraph-start (concat " .\\|" paragraph-start))))

本当は、current-language-environment をチェックして、日本 語環境の時だけ上記処理を実行する…というように丁寧に書く必要があるんでしょ うけど、そこまでは踏み込まないでおきます。

※ なお、上述の「日本語文書に対する段落認識処理」の 問題は、MH-E とは無関係に、text mode 系統の major mode 全般に見られるよ うになっています(emacs 20 頃から。確か、mule 2 の頃はこんなではなかった はず…)。ですので、少なくとも純正 text mode に対しては、次のような行を 追加しておくことをお勧めします(これは、emacs 22 以降でもそうでなくても)。


(add-hook 'text-mode-hook (lambda ()
	(if (eq major-mode 'text-mode)
	    (paragraph-indent-minor-mode 1))))

また、段落開始を表す字下げを全角空白で行うタイプの人は、上記 mh-letter-mode-hook への hook を参考にして、 paragraph-start に全角空白を追加する処理を hook に加えるとよ いでしょう。

純正 text mode 以外でも、必要に応じて paragraph-indent-minor-mode を呼び出す hook を追加するとよい と思います。

その他

私家版パッチ

emacs 29.1 付属の MH-E に見つけたいくつかのバグに対するパッチを置 いておきます。上述した不具合を修正するための個人的な変更も含めてあります。 本家にパッチを提 出するには sourceforge のアカウントを取らねばならないらしいので、こ こにひっそりと置いておくだけにします。

------>mh-e-8.6git-patch-29.1.xz (5852bytes) emacs 29.1 用 [2022, 9/19]

これ↓はどうも勘違いだったようです。バージョン管理システムで変更を巻き 戻したりしているうちに、ファイルの更新日時が変わったせいで make 時の依存 性の判定が狂ってしまっていたのだと思います。 [2022, 4/14-15] このパッチを使う場合、emacs コンパイル時 に、configure, make 後に、make install せずにいったん lisp サブディレクトリに降り、make mh-autoloads を行ってください。これで mh-loaddefs.el が更新されるはずなので、それを確認したら元のディレクトリに戻って再度 make を実行した後 make install しましょう。この手 順を踏まずに単に make install すると、以下の修正項目のうち、 「search-pattern バッファでは C-c C-f C-t などのキーバインド が mh-letter.el をロードするまで使えない」というバグが残っ たままになります。

バグとパッチの内容を説明しておきます。

  1. [2021,4/13] いつからこうなっていたのか わからないのですが、メールを表示するとき、html メールを表示するなどして一度 truncale-lines が有効になってしまった後は、np で別のメールの表示に移っても、ずっとそれが解除され ないままで長い行が途中までしか見えなくなってしまっていました。これ は非常に不便だったので修正しました。表示を別のメールに切り替える度 に truncale-lines の buffer local 値を滅する処理を追加し てあります。
  2. [2020, 8/22, 8/30] emacs 27.1 になって、 show バッファで引用文の色付けが効かなくなった (mh-highlight-citation-style がデフォルトの gnus のとき)のを修正しました。8/22 版ではメール を表示するとき、途中からになってしまうことがありました。今度は直っ ていると思います。
  3. [2017, 4/16, 4/30] nmh と MH-JP の併用を試していたとき、 mh-pathmh-sys-path よりも優先させることに失敗 しているバグを見つけたので修正しました。
  4. [2016, 10/14] メールを転送するとき、inline 形式だけでなく添付ファ イルとして転送することもできるオプションを追加しました。customize option mh-mime-forward-disposition"attachment" にすると、転送対象が添付ファイルになりま す。
  5. [2018, 5/30] emacs 付属の elisp library では、run time に cl library を要するようになってはいけない、というのが現在の emacs の方針で す。以前は MH-E はその指針に反していたのですが、emacs 26.1 からはそ れに対する修正が入っています。が、惜しくも僅かだけ修正が不足してい るようなので、追加の修正を入れてあります。
  6. [2016, 10/14] 以前は別個にしていた texinfo ファイルに対する修正も一 本化しました。
  7. mh-acros.el に対するパッチは単なる typo の修正ですが、 そもそもこの行の内容は describe-function のとき一番上 に表示されるので、取っぱらってしまった方がいいような気もします。
  8. forw コマンドに対する -mime オプションは MH 6.8.4 に対しても存在するはずですので、mh-comp.el でベー ス MH によらず mh-compose-forward-as-mime-flag を見るよ うにしました。
  9. mh-e.el は一部アクセントつきアルファベット母音を UTF-8 で記述していますが、これが正しく解釈されない(日本語 EUC locale で はもちろん、C locale であっても)ので、Local Variables に coding 指定を明示しました。
  10. Summary バッファ中最後のメールを SPC で読んでいって、最 後まで到達して「End of message (Type SPC to read next(previous) undeleted message)」と表示された時点で、DEL で逆スクロー ルしたとします。ここで再度 SPC を叩いたときは再スクロー ルして欲しいのですが、そうはならずに next(previous) undeleted message を表示しようとしてしまうので、mh-folder.el で この愚直な動作を修正しました。
  11. search-pattern バッファでは C-c C-f C-t などのキーバイン ドが使えるはずなのですが、mh-letter.el をロードするまで はこれらが使えなかったバグを修正しました。
  12. search-pattern バッファで C-c C-f C-b などで Bcc: ヘッダ を指定すると read only エラーが出るのですが、Bcc: ヘッダが検索対象と なることはないはずなので、mh-search.el でそのキーバ インドを削除しました([2007, 6/20] うーんそうか、でも draft フォルダー に残る書きかけのメールでは Bcc: ヘッダが残っていることもありうるか。 でも、書きかけのメールがそんなに検索を必要とするほどたくさん残ってる、 という事態は想定する必要はないかな?)。
  13. F v で他のフォルダに移るとき、document には
    it will show all the messages in the buffer as long there are fewer than `mh-large-folder' messages. If there are more, then you are prompted for a range of messages to scan.
    と書いてあるのですが、環境によっては後半の動作をせず、たくさんのメー ルが入っているフォルダに移るときも全メッセージを scan してしまうことがありました(もちろん、prefix argument をつければ range を訊いてこさせることは可能でしたが)。これは、 mh-seq.el の正規表現の不備が原因だったので、修正しま した。
  14. In-Reply-To ヘッダが複数行に渡るとき、2行目以降が正しく着色 されないという点を修正しました。
  15. ツールバー上の、alias 未登録な相手を新たに登録するボタンが機能して いなかったのを修正。ただ、このせいで、フォルダを開いたときは常に mh-alias.el がロードされるようになってしまいました。
  16. メニューとツールバーについて、いくつかの項目について、フォルダモー ドでカーソルがメッセージ行の上にない場合は無効化されるようにしまし た。※ そういう場合も、prefix argument を付ければ range が指定でき るので、一律無効化するのは適切ではないかもしれません。
  17. Auto fill を自動では on にせず、状況に応じて後から手で on にするか どうかを選択する主義の人のため、letter mode で normal-auto-fill-function を設定しておきました。
  18. [2009, 2/1]「どうも送信時、 C-u を付けて C-c C-c とすると Message-ID が 付かないな…?」と思っていたらバグだったので、修正しました。
  19. これはバグとは言い切れませんが、上の方でも解説した通り、MIME 形式で はない日本語メールを読むときに、文字化けしてしまうのを解消する変更 を入れてあります。(その結果、RFC に厳密には沿わなくなったモノを処 理することになっているはずなので、ちょっとインチキな修正ではありま す。が、おそらくそこら辺の処理には干渉しないはずなので、読むだけな らたぶんこれでも大丈夫)

    mh-mime.el では、 mh-decode-message-header した後で mh-show-addr している部分があるなあ…。これだと、MIME decode の結果、quote・escape さ れていた特殊文字が生で出てきているかもしれないので、アドレス解析が正しく 行く保証がないので、厳密にはバグじゃないだろうか。

  20. その他明白な typo 修正。

※ 上で修正したバグ以外に、日本語 Subject を持つメー ルに対し、フォルダモードで / s は大抵効かない、という不具合が あります。MH-JP の pick コマンドは、引数に RFC 2047 decode の文字列を与えなければいけないことが原因ですが、この問題には 対処していません。

色づけ再び

上で書いた通り、font-lock を利用している場合、 差出人名が日本語で書いてある メールは、Summary バッファでは色づけの境界位置がおかしくなるという問 題があります。これは、

ということから発生しています。

上の問題を、正規表現を工夫するだけで解決することは私には無理だったの で、とりあえず以下のような強引な手段によって mh-scan-subject-regexp を使わないようにして色づけをさせていま す。


(eval-after-load "mh-folder"
 '(defun mh-folder-font-lock-subject (limit)
    "Return MH-E scan subject strings to font-lock between point and LIMIT."
    (when (save-excursion
	     (or (bolp) (forward-line 1))
	     (move-to-column (+ mh-cmd-note mh-scan-field-subject-start-offset))
	     (if (< (point) limit)
		 (looking-at
		  "\\(\\(?:[Rr][Ee]\\(\\[[0-9]+\\]\\)?:\\s-*\\)*\\)\\([^<\n]*\\)")))
      (goto-char (match-end 0))
      (if (< (match-beginning 1) (match-end 1))
	   (set-match-data (list (match-beginning 1) (match-end 3)
				 (match-beginning 1) (match-end 3) nil nil))
	 (set-match-data (list (match-beginning 3) (match-end 3)
			       nil nil (match-beginning 3) (match-end 3))))
      t)))

が、これで問題が解決したわけではありません。正規表現が hard code され ていることにはまだ目をつぶるとしても、

という大きな問題が残っていて、猛烈にヘボヘボです。 この2つは色づけとは無関係な問題であり、font-lock を利用しているかどうか にかかわらず発生します。

また、類似の問題として、

というものもあります。

これらの問題を解決するのは、私にはちょっと無理そうなので、どなたかぜ ひ頑張ってください。どうぞよろしく(他力本願)。

大木さんの nmh 日本語パッチ

[2022, 4/14] 以下の問題は、現在のパッチで はなくなっています。[2018, 4/12] 問題点として、 scan 時に Subject 中の「☆」などの一部記号類がクエスチョン マークになって表示されてしまう、という不具合がまだあることに気づきました。 これはおそらく、unicode の分類ではこういった記号類は日本語以外のカテゴリー に分類されており、そのため「日本語の locale では表示できない文字」と判断 されているのだと思います。大した実害はないので、私は余り気にせず放ってあ ります。


コンピュータ関連のページ目次へ
トップページへ
井汲 景太 <ikumikeita@jcom.home.ne.jp.NOSPAM.>(迷惑メールお断り)
最終更新日: 2023年08月18日