2024年12月17日 星期二

把所有帳號的信件都接收到自己的伺服器上 (二): mbsync + neomutt + msmtp

為了維護資料自主權, 上一篇 我們測試 MS o365 的 xoauth2 登入。 我覺得那是最困難的部分。 接下來的部分有點囉嗦, 但並不困難, 如果遇到問題, 都很容易看著錯誤訊息, 搜尋或問 chatgpt 解決。 (困難的部分我已經幫你撞過牆壁,把心得寫進本文裡了。) 我們要用 mbsync 把所有的 emails 都抓到自己的伺服器裡, 採用 Maildir 格式儲存, 以利將來搜尋/用AI分析/存檔。 並且設好以後, 就可以用 ssh 登入自己的伺服器、 在文字模式底下採用 neomutt 跟 msmtp 閱讀與發送信件。

一、 安裝軟體

MUA、MTA、MDA、... Neomutt 是一個 MUA, 是使用者直接面對的軟體。 (因為提問, 我現在變成 neomutt 的中文譯者了...目前是倒數第二名的國家...) 發送信件的時候, 它還需要另外呼叫 msmtp 這個 MTA 來幫忙。 在 debian 系列系統裡, 直接安裝: apt install neomutt msmtp 關於 MUA、MTA、MDA、... 這些名詞, 請參考 關於 email security 的大小事 — 原理篇, 或者光看右圖就很清楚了。

發送信件時, msmtp 還需要借助 cyrus-sasl-xoauth2 才能登入伺服器, 所以必須先

  1. 安裝開發相關套件: apt install build-essential autoconf libtool libsasl2-dev
  2. 下載 cyrus-sasl-xoauth2
  3. 進入目錄後, 編譯並安裝:
    ./autogen.sh
    ./configure
    sudo make install
    
  4. 但是要拷貝到正確的位置, msmtp 才找得到它: sudo cp -a /usr/lib/sasl2/* /usr/lib/x86_64-linux-gnu/

再來請下載我的範例: mbsync 與 msmtp 的設定檔 + mutt/ 目錄底下的四個設定檔

二、 Neomutt 設定檔

Neomutt 跟 它的來源 mutt 使用相同的設定檔, 可以是單一檔案 ~/.muttrc 或是一個目錄 ~/.mutt/。 我採用目錄, 除了主設定檔 muttrc 之外, 每個 email 帳戶 (o365、 gmail、 posteo) 也有各自的設定檔。 "folder-hook" 指定: 每當切換至某個目錄時, 就讀取對應帳號的設定檔。

三句 "macro" 設定用 F3、F4、F5 三個功能鍵切換不同的帳號 (切換到不同的目錄下), 這是從 這裡 抄來的。 下面許多指令 由 ossilator 提供, 主要是設定方向鍵, 讓 neomutt 變得比較像 pine, 操作起來比較順。

三個帳號專屬設定檔差不多。 就以 gmail來說, 除了設定 gmail 帳號對應的主目錄 (set folder=...) 及指定收件匣 (set spoolfile=...)、 草稿 (set postponed=...)、 寄件備份 (set record=...) 等等特定目錄之外, 又用 mailboxes ` ls ~/Mail/gmail/ | sed 's/^/+/' | tr '\n' ' ' ` 這一句來指定 ~/Mail/gmail/ 目錄裡的所有子目錄都要列在資料夾清單當中。 倒引號的用法跟 bash 類似, 但是 必須把所有的換列改成空格。 切換帳號的時候 必須用 unmailboxes 指令 把先前的設定清空, 不然後續的設定會累加上去。 最後幾句跟寄信相關, 下面再談。

三、 怎麼讀utf7目錄名稱?

前一篇 前一篇所說, 我的設定是: 用 mbsync 從郵件伺服器 (outlook.office365.com 或 google 或 posteo) 把信件都抓回本地伺服器。 可是 mbsync 所建立的 maildir 格式採用 utf7 編碼命名目錄名稱, 看起來像亂碼。 我的處理方式是:

ls | sed "s#^#'$HOME/Maildir/o365/# ; s#\$#'#" > /tmp/a
ls | imap7to8.py > /tmp/b # imap7to8.py 請見前一篇
paste -d' ' /tmp/a /tmp/b | sed 's/^/ln -s /' > /tmp/go.sh

查看 /tmp/go.sh 的內容, 如果沒有問題, 就在 ~/Mail/ 裡面執行它。 也就是說, 建立 (utf8 編碼的) 符號連結 (symbolic links), 這樣從 ~/Mail/ 裡面就可以看到中文的目錄名稱。 這個點子連 chatgpt 都稱讚 "elegant" :-)

四、 mbsync

我的 .mbsyncrc 設定檔修改自 Neomutt + isync / mbsync for Office365 這篇。 前面一段是所有帳戶共通的設定; 後面三個帳戶的個別設定, 各自包含四小段: 帳號密碼、 遠端名稱、 近端目錄、 連接遠近兩端的 channel。

到這裡, 可以先測試收信讀信功能是否設定成功: mbsync o365 要求 mbsync 按照 Channel o365 那一段的設定跟伺服器同步信件; mbsync -a 則是把所有 channels 都同步過一遍。 如果 neomutt 可以成功讀信, 就用 (用戶個人的) crontab -e 設定定時同步信件, 例如每小時的 23 分: 23 * * * * mbsync -a

五、 寄信

在 neomutt 裡面按 m 就進入寫信模式; 寫完之後按 y, neomutt 就會呼叫 msmtp 寄信。 當然, 前提是要先設定好 ~/.msmtprc。 我的範例的第一個段落設定所有帳戶的共同設定值, 包含有助於除錯的 logfile, 以及郵件伺服器傳資料給本機時會用到的本機公鑰 tls_trust_file。

再來是三個帳號的個別設定。 Gmail 帳號比較單純。 重點是 user 跟 from 都要填你的 gmail 地址。 它的認證方式跟 o365 一樣, 所以用 passwordeval 指定以 mutt_oauth2.py 產生餵給 gmail 吃的憑證; 它的參數 ~/私密目錄/google-token.json 必須照著前一篇, 先用 mutt_oauth2.py ... --authorize ... 準備好。

再來是 o365 的設定。 Cyut 的同事們請注意: user 必須長得類似這樣: t199dddd@o365.cyut.edu.tw 而 from 必須長得類似這樣: ckhung@o365.cyut.edu.tw。 我沒試過其他組合。

最後是 posteo。 想到以後的 email 地址裡面都會出現 o365, 等於在幫微軟免費廣告, 我就全身不舒服。 於是請 chatgpt 推薦一個尊重用戶資料自主權的 mail 服務。 其實它的匯出功能也僅限行事曆與通訊錄, 並不包含 email 的匯出, 所以也有必要從一開始就把信件抓回自己的伺服器。 但我猜這多半是技術因素, 而不是像微軟的惡意, 畢竟 posteo 只是一家 評價很好 的小公司。 註冊的時候可以選擇 .net、 .com 還有很多國家的網域 (可惜沒有 .tw)。 設定檔裡面的 user 跟 from 要填你選的 email ; 但是 host 固定都填 posteo.de。 另外, 在 ~/.mutt/ 底下, 每個帳號的設定檔裡面, 要用 set sendmail = "msmtp -a 某帳號名稱" 告訴 msmtp 要以哪一個帳號的資訊來請求對方伺服器寄信。 set from ... 必須是用來登入的同一帳號的 email; 但是可以用 my_hdr Reply-to: ... 來請收件人回信時回到自己偏好收信的帳號。

六、 結語

還沒處理的問題:

  1. 強化資安。
  2. 捨棄以資料夾分類的方式, 改用 notmuch 或 mailutils 以標籤 (tag) 的方式整理信件。
  3. 改成 webmail?

好了, 我還是設定以朝陽原來的郵箱收信, 但把信都轉到 posteo , 改以它收發信件。 所以原先的信箱收信一樣沒問題; 但寄出去的信說不定會被收件軟體丟到垃圾信箱。 寧可如此, 我也不要像是戴著腳鐐一樣到處告訴人家我是 o365 的囚徒 (握拳)!

1 則留言:

  1. neomutt 不是可以設定 smtp_url 和 smtp_pass 嗎? 應該可以不用額外設定 msmtp

    https://neomutt.org/man/neomuttrc#:~:text=smtp_pass

    回覆刪除

因為垃圾留言太多,現在改為審核後才發佈,請耐心等候一兩天。