2019-05-01

Emacs + Gnusでメールを読み書きする設定(Gmail、IMAP、POP複数アカウント)

普段Wanderlustを使っているのですが久しぶりにGnusに再挑戦、メールの読み書きが出来るようにしてみました。

環境

GNU Emacs 26.1.92 (build 1, x86_64-w64-mingw32)
 of 2019-03-08
Gnus v5.13

Gnus関連ファイルをひとつのディレクトリにまとめる

デフォルトだと ~/ の下にいろんなファイルを勝手に作るのでそれを ~/gnus/ に変更しました。 既に使っているWanderlustと併用したいので ~/Mail/ は特に困ります。

Gnus用設定ファイルも ~/gnus/.gnus.el に移したいのですが、これは .emacs や init.el の方に書かないとダメですね。その他の設定は .gnus.el に書くことにします。

  1. .emacs や init.el に (setq gnus-home-directory "~/gnus") を書く
  2. 次のコードを ~/gnus/.gnus.el に書く
;; Move home directory to ~/gnus
;; Write (setq gnus-home-directory "~/gnus") on init.el
(setq message-directory "~/gnus/Mail"
      mail-source-directory "~/gnus/Mail"
      nnfolder-directory "~/gnus/Mail/archive"
      pop3-uidl-file "~/gnus/.pop3-uidl"
      nntp-authinfo-file "~/gnus/.authinfo"
      auth-sources '("~/gnus/.authinfo" "~/gnus/.authinfo.gpg" "~/gnus/.netrc"))

受信設定

設定したメールアカウントは次の4つです。

  • Gmail
  • IMAPで扱う独自のアカウント
  • POPで扱う独自のアカウント(二つ)
;;; ~/gnus/.gnus.el

(require 'nnir)

;; Make Gnus NOT ignore [Gmail] mailboxes
;; Gmailのメールボックス名を無視しないようにする。
;; デフォルトの正規表現だと[Gmail]という名前にマッチしてしまうので。
(setq gnus-ignored-newsgroups "^to\\.\\|^[0-9. ]+\\( \\|$\\)\\|^[\"]\"[#'()]")

;; Use gnus-secondary-select-methods only
;; gnus-select-method は使わず gnus-secondary-select-methods のみを使う。
;; リストだけ使う方が追加・廃止が楽なので。
(setq gnus-select-method '(nnnil))

;; Gmail (IMAP)
(add-to-list
 'gnus-secondary-select-methods
 '(nnimap "gmail"
          (nnimap-address "imap.gmail.com")
          (nnimap-server-port 993)
          (nnimap-stream ssl)
          ;; Search
          (nnir-search-engine imap)))

;; My Email 1 (IMAP)
(add-to-list
 'gnus-secondary-select-methods
 '(nnimap "myaccount1"
          (nnimap-address "myimapserver1.example.jp")
          (nnimap-server-port 993)
          (nnimap-stream ssl)
          ;; Search
          (nnir-search-engine imap)))

;; WanderlustのMH形式フォルダを読み込む。が、起動時に毎回時間がかかるのでコメントアウト。
;; ;; My Old Email Archive (Wanderlust's MH Folders)
;; (add-to-list
;;  'gnus-secondary-select-methods
;;  '(nnmh ""
;;         (nnmh-directory "~/Mail")
;;         (nnmh-get-new-mail nil)))

;; 手元にダウンロードしてくるタイプのPOP、IMAPアカウント。
;; My Email 2,3 (POP)
(add-to-list
 'gnus-secondary-select-methods
 '(nnml ""))

(setq mail-sources
      '((pop :server "mypopserver2.example.jp"
             :port 995
             :user "mypopuser2"
;;             :password "???" ;;=> .authinfo に machine mypopserver2.example.jp login mypopuser2 port 995 password ??? と書いた方が良い。ミニバッファにパスワードを入力しても、POPの場合はなぜか自動で保存してくれないので手動で書き込んだ方が良い。
             :authentication apop
             :stream ssl
             :leave t ;; or N days
             )
        (pop :server "mypopserver3.example.jp"
             :port 995
             :user "mypopuser3"
;;             :password "???"
             :authentication apop
             :stream ssl
             :leave t
             )))

;; ソースによってグループを分ける。
(setq nnmail-split-methods
      '(("myaccount2" "^X-Gnus-Mail-Source: pop:mypopuser2@mypopserver2\\.example\\.jp$")
        ("myaccount3" "^X-Gnus-Mail-Source: pop:mypopuser3@mypopserver3\\.example\\.jp$")
        ("unknown-source" "")))

Gnusでは情報源は gnus-select-methodgnus-secondary-select-methods に設定します。 なぜか同じような機能のものが二つあるのですが、おそらく最初は gnus-select-method だけがあって、後から複数の情報源を設定出来る gnus-secondary-select-methods を追加したのではないでしょうか? 今回はリストで複数設定出来る gnus-secondary-select-methods のみを使います。 gnus-select-method には nnnil を設定して無効化しました。ネットニュースを読むならニュースサーバをここに設定しても良いと思います。

nnimap で指定したIMAPサーバ上のメッセージは、手元にファイルをダウンロードすることなく読むことが出来ます。

nnmlmail-sources で指定したPOPサーバ上のメッセージは、 ~/gnus/Mail/ (デフォルトだと~/Mail/)にダウンロードしてから読むことになります。

mail-sources に複数のアカウントを指定した場合、全アカウントのメールが全て一箇所にまとめられてしまうようでした。なので nnmail-split-methods で振り分けの設定をしています。幸い X-Gnus-Mail-Source というヘッダーがついていたのでそれで振り分けられました。何かもう少しうまい仕組みがあれば良いのですが……。グループパラメータの mail-source が使えるかなとも思ったのですがそちらは試していません。

POPでメールをサーバに残すには :leave t を指定します。これが無いと受信したメールはサーバから削除してしまうので注意してください。整数で日数を指定することも出来るようです。

POPのパスワードは .authinfo(や.authinfo.gpg)にあらかじめ書いておくことをおすすめします。どこにも書かなければアクセス時にミニバッファで聞かれますが、自動的に .authinfo に保存してくれませんでした。 nnimap の場合は保存してくれたのですが。

IMAP(nnimap)のパスワードも .authinfo に保存します。あらかじめ書かなくてもミニバッファで聞かれたときに入力すれば自動的に保存されました(むしろ下手に書いて形式に間違いがあってハマりました)。

Gmailで二段階認証している場合等はアプリパスワードを発行する必要があると思います。

送信設定

複数のアカウントがあるので送信設定も適切に切り替える必要があります。

何を切り替えるべきか:

  • (Fromの)名前
  • (Fromの)メールアドレス
  • 文末の署名
  • 送信したメールをどこに保存するか(Bcc, Gcc)
  • SMTPサーバとの接続情報

切り替える条件案:

  • Fromヘッダー
  • メール作成時のグループ

探してみるとFromによってSMTPを切り替える設定(Multiple SMTPAccounts – Emacs Wiki)を見つけたのですが、色々試してみて最終的に gnus-posting-styles でメール作成時のグループにより適切なヘッダーを設定する方法で落ち着きました。

;;; ~/gnus/.gnus.el

;; デフォルト送信設定
(setq smtpmail-stream-type 'starttls) ;;基本的に全てstarttlsで送る。
(setq smtpmail-smtp-server "mysmtpserver2.example.jp"
      smtpmail-smtp-service 587
      smtpmail-smtp-user "mysmtpuser2") ;;デフォルトのSMTPサーバ
(setq user-full-name "My FullName"
      user-mail-address "myaccount2@example.jp") ;;デフォルトの名前とメールアドレス

;; メール作成時に作用する設定
(setq gnus-posting-styles
      '(
        ;; IMAP
        ("^nnimap\\+gmail:"
         (name "My FullNameG")
         (address "myaccountg@gmail.com")
         (signature "My FullNameG\nmyaccountg@gmail.com")
         (gcc "nnimap+gmail:Sent")
         ("X-Message-SMTP-Method" "smtp smtp.gmail.com 587 myaccountg@gmail.com"))

        ("^nnimap\\+myaccount1:"
         (name "My FullName1")
         (address "myaccount1@example.jp")
         (gcc "nnimap+myaccount1:INBOX")
         ("X-Message-SMTP-Method" "smtp mysmtpserver1.example.jp 587 mysmtpuser1"))

        ;; POP
        ("^nnml:myaccount2\\(\\..*\\)?$"
         (name "My FullName2")
         (address "myaccount2@example.jp")
         ("Bcc" "myaccount2@example.jp")
         ("X-Message-SMTP-Method" "smtp mysmtpserver2.example.jp 587 mysmtpuser2"))

        ("^nnml:myaccount3\\(\\..*\\)?$"
         (name "My FullName3")
         (address "myaccount3@example.jp")
         ("Bcc" "myaccount3@example.jp")
         (signature "** My FullName3 **")
         ("X-Message-SMTP-Method" "smtp mysmtpserver3.example.jp 587 mysmtpuser3"))
        ))

gnus-posting-styles変数を使用すると様々な条件でメールヘッダーや署名等を切り替えることが出来ます。この変数はメール作成を開始する時点で作用するので、本文を書くときに効果を目で確認出来ます。

上の設定ではメール作成時のグループ名を元に、名前、メールアドレス、署名、送信済みメールの送り先、使用するSMTPサーバを切り替えています。

送信したメールの保存先は、私の場合次のようにしました。

  • POPアカウントならBccで自分自身にコピーを送る
  • IMAPアカウントならGccを送信済みフォルダーに設定する

POPでBccしているのは他のPCからでも見られるようにするためですが、それが不要ならばGccをnnml:myaccount2とかにしてローカルに保存するだけでも良さそうです。

X-Message-SMTP-Method というヘッダーを使用すると送信時に使用するSMTPサーバ(ポート、ユーザ名)を指定出来ます。このヘッダーは送信時に削除されて相手には届きませんでした(試した限り)。 この方法だとSSL/TLS暗号化の方式を個別に指定出来ないような気がしますが、私の場合は全てSTARTTLSで問題ありませんでした。デフォルトの設定では、使えるならSTARTTLS、使えなければ暗号なしになるみたいです。

見た目の設定

;;; ~/gnus/.gnus.el

;; Tree view for groups.
;; デフォルトをトピックモードとする。
;; https://www.gnu.org/software/emacs/manual/html_node/gnus/Group-Topics.html
(add-hook 'gnus-group-mode-hook 'gnus-topic-mode)

;; Referencesヘッダーを元にスレッドを構築する。同じSubjectというだけでスレッドになると困るので。
;; gather threads by References headers (default is by subject)
(setq gnus-summary-thread-gathering-function 'gnus-gather-threads-by-references)

;; Summary Line Format
;; 短い年月日日時(190503T1234)、短いFrom、記事行数不要
(setq gnus-summary-line-format "%U%R%z %&user-date; %I%(%[%-15,15f%]%) %s\n"
      gnus-user-date-format-alist '((t . "%y%m%dT%H%M")))

GnusかWanderlustか

ここまでやってみましたが、結局私は当面Wanderlustを使うと思います。

手元の環境(Windows+自分でビルドしたEmacs)だと数回に一回は送受信時にエラーが発生します。これはGnusでもWanderlustでも起きるのですが未だに原因がつかめていません(SSLでも平文でも起こるのでgnutlsがらみでも無さそう?)。 今回Gnusを試してみたのはこれが解決するかもしれないと思ったのが一番の理由なのですが残念ながら変わりませんでした。

メールソフトとしての使い勝手はWanderlustの方が普通だと思います。カスタマイズを進めていけばGnusでもそれほど悪くないのかもしれませんけれど、デフォルトの状態があまりにも。

Wanderlustはバグが多くそれが一向に解決される気配が無いのも今回Gnusを試した理由の一つなのですが、まぁ、Wanderlustでも一応最低限は使えていますので。

添付ファイルまわりとか日本語まわりとかはまだ試していないので分かりません。Wanderlustだとおかしな挙動をすることが良くあるので、それがGnusで問題なければ良いのですが。