[!NOTE]
- 这是一个指南而非教程, 重点带你理清它们之间的配置关系
围绕整个流程,简单画个了图,很好地概括了我的邮件管理流程。
Others
||\
|| Send
Receive ||
\||
------------------ Email Sever -----------------
||\ /|\
|| |
Sync Send
|| |
\|| |
mbsync -----> notmuch --tags--> neomutt -----> msmtp
IMAP client SMTP client
- isync (mbsync): 作为 IMAP 客户端, 支持双向同步
- notmuch: 负责为邮件打标签
- neomutt: 作为邮件客户端 (TUI)
- msmtp: 作为 SMTP 客户端
- alot: notmuch 的一个前端, 可以很方便看 taglist (TUI)
- oama: OAuth 凭证管理器, 用于获取 OAUTH2 Token 和 授权访问邮件地址
Step 0: 获取 OAUTH2 令牌 (Token)
Gmail 和 Outlook 都要求使用 OAUTH2 认证。
这一步是所有步骤中最麻烦的一步,相信大部分人在这一步可能就止步于此了。
获取 OAUTH2 令牌前,你需要先获取 client_id 和 client_secret
- 对于 Gmail, 你需要在 Google 的云平台注册一个 OAuth 应用程序,这样你才能获取 OAuth
client_id和client_secret密钥。 - 对于 Outlook, 你有两种方式。
- 和 Gmail 一样, 只不过是在 Microsoft 的云平台 (Azure) 进行类似操作。(Azure 帐户必须至少是应用程序开发人员)
- 使用设备代码流(device code flow)授权方法,
client_secret可能不是必要的, 因此你可以使用开源邮件客户端例如Thunderbird或者Evolution的client_id。
具体操作步骤可参考:
这里我以 Outlook 邮箱,并采用第二种方式举例
这里是一些开源的邮件客户端 client_id。
| Application | client_id | Sources |
|---|---|---|
| Mozilla/Thunderbird | 9e5f94bc-e8a4-4e73-b8be-63364c29d753 | 1 |
| GNOME/Evolution | 20460e5d-ce91-49af-a3a5-70b6be7486d1 | 1 |
首先安装 oama, 在 ~/.config/oama/config.yaml 添加下面的配置,然后执行 oama authorize microsoft <you@outlook.com> --device, 在浏览器页面完成认证。
## Possible options for keeping refresh and access tokens:
## GPG - in a gpg encrypted file $XDG_STATE_HOME/oama/<email-address>.oauth
## (XDG_STATE_HOME defaults to ~/.local/state)
## GPG - in a gpg encrypted file ~/.local/state/oama/<email-address>.oauth
## KEYRING - in the keyring of a password manager with Secret Service API
##
## Choose exactly one.
encryption:
tag: KEYRING
# encryption:
# tag: GPG
# contents: your-KEY-ID
services:
microsoft:
client_id: 20460e5d-ce91-49af-a3a5-70b6be7486d1 # Evolution
Step 1: 从邮件服务器拉取邮件
我们使用 isync 来从远程服务器双向同步邮件 (注意, 它的命令行名称是 mbsync)
这里需要配置三个部分
- IMAP Accounts
- IMAP Stores
- Channels and Groups
IMAPAccount <随便起一个名字>
Host outlook.office365.com
Port 993
User <你的Outlook邮箱地址>
AuthMechs XOAUTH2
PassCmd "oama access <你的Outlook邮箱地址>"
TLSType IMAPS
SystemCertificates yes
Timeout 10
- IMAPStore: 远程 IMAP Store
- MaildirStore: 本地 Maildir Store
- Path: 设定 Maildir 的根目录, 之后拉取的邮箱都存储在这里。(注意: 最后这个
/不能忽略) - Inbox: INBOX 邮箱的路径
IMAPStore outlook-remote
Account <指定你刚刚定义的 IMAPAccount>
# Where are we going to keep the mail associated with this account
MaildirStore outlook-local
SubFolders Verbatim
Path ~/.local/share/maildir/outlook/
Inbox ~/.local/share/maildir/outlook/INBOX
之后利用 Channel 建立远程邮箱与本地邮箱的映射关系
你可以建立多个 Channel 和 Group 并自由组合它们
之后你可以选定其中一个 Channel 或 Group 来同步邮件, 例如 mbsync outlook-inbox 仅同步 INBOX 邮箱, mbsync outlook 同步多个邮箱。
Channel outlook-inbox
Far :outlook-remote:INBOX
Near :outlook-local:INBOX
Channel outlook-sent
Far :outlook-remote:"Sent"
Near :outlook-local:"Sent"
Channel outlook-drafts
Far :outlook-remote:"Drafts"
Near :outlook-local:"Drafts"
Channel outlook-trash
Far :outlook-remote:"Deleted"
Near :outlook-local:"Trash"
Channel outlook-archive
Far :outlook-remote:"Archive"
Near :outlook-local:"Archive"
Channel outlook-notes
Far :outlook-remote:"Notes"
Near :outlook-local:"Notes"
Channel outlook-spam
Far :outlook-remote:"Junk"
Near :outlook-local:"Spam"
Group outlook
Channel outlook-inbox
Channel outlook-sent
Channel outlook-drafts
Channel outlook-trash
Channel outlook-notes
Channel outlook-archive
Channel outlook-spam
对应的映射关系如下,
| IMAP mailboxes | Local mailboxes |
|---|---|
INBOX |
~/.local/share/maildir/outlook/INBOX |
Sent |
~/.local/share/maildir/outlook/Sent |
Drafts |
~/.local/share/maildir/outlook/Drafts |
Deleted |
~/.local/share/maildir/outlook/Trash |
| ... | ... |
Step 2: 为本地邮箱邮件打标签
这一步是为所有邮箱中的邮件进行打标签,之后在 neomuut 时我们可以通过标签筛选过滤以创建虚拟邮箱。
- database.mail_root: 指向我们本地邮箱的根路径
- database.path: 指定 xapian 路径, 这是 notmuch 标签数据库的位置
- database.hook_dir: 指定 hook 路径, 默认是 database.path/notmuch/hooks, 我建议放在配置文件附近方便修改
- new.tags: 当执行
notmuch new后, 会为所有邮件打上的标签 - search.exclude_tags: 当执行
notmuch search时, 排除带有特定标签的邮箱。
[!NOTE]
注意:
- 这里不能使用
~, 只能写成/home/<User>形式
[database]
mail_root=/home/<User>/.local/share/maildir/outlook
path=/home/<User>/.local/share/notmuch/outlook
hook_dir=/home/<User>/.config/notmuch/outlook/hooks
[user]
name=<用户名>
primary_email=<你的 Outlook 邮箱地址>
[new]
tags=inbox
ignore=/.*[.](json|lock|bak)$/
[search]
# https://notmuchmail.org/excluding/
exclude_tags=deleted;spam;
[maildir]
synchronize_flags=true
接下来在 hook_dir 目录下创建一个 post-new 钩子 (不要忘记给它可执行权限)
你可以在这里完成自动化打标签的操作, 这样每次 notmuch new 时自动完成打标签。
它支持以 from:xxx, to:xxx, folder:xxx, cc:xxx 等前缀作为过滤条件
[!NOTE]
注意:
- 使用 notmuch 相关命令时, 它会假设指向的是
default目录下的配置, 所以你会看到我这里使用了一个NOTMUCH包装函数, 使用--config选项指定特定配置文件new.tags = inbox会为所有邮件打上inbox标签, 可以通过-inbox移除它, 避免污染标签folder:xxx是以mail_root为相对路径- 可以使用
--batch批量添加
#!/usr/bin/env bash
NOTMUCH() {
notmuch --config="$HOME/.config/notmuch/outlook/config" "$@"
}
## Apply tags
NOTMUCH tag --batch <"$HOME/email/taglist/tags.outlook"
NOTMUCH tag -inbox +sent -- folder:"Sent"
NOTMUCH tag -inbox +drafts -- folder:"Drafts"
NOTMUCH tag -inbox +deleted -- folder:"Trash"
NOTMUCH tag -inbox +junk -- folder:"Spam"
这里的 tags.outlook 是我自己维护的一个标签过滤列表
例如, 这里的第一条为来自 noreply@github.com 或者 no-reply@github.com 的邮件打上 noreply, github 标签
+noreply +github -- from:noreply@github.com or from:no-reply@github.com
+noreply +codeberg -- from:noreply@codeberg.org
+noreply +google -- from:noreply@google.com or from:no-reply@accounts.google.com
+noreply +firefox -- from:accounts@firefox.com
+noreply +steam -- from:noreply@steampowered.com
+noreply +forum +kde -- from:noreply@discuss.kde.org
+noreply +forum +emacscn -- from:noreply@emacs-china.org
+noreply +forum +archcn -- from:noreply@archlinuxcn.org
+noreply +forum +debiancn -- from:debiancn@outlook.com
+noreply +forum +susecn -- from:noreply@suse.org.cn
+noreply +forum -- from:forum@cachyos.org
你可以使用 alot 查看标签列表,例如下图这样
Step 3: 使用 neomutt 显示邮箱邮件
neomutt 是 mutt 的一个分支,相较于 mutt 加了许多补丁,并且和上述提到的工具集成良好。
neomutt 涉及的内容比较多,由于篇幅原因,这里我重点说明与账号邮箱相关的配置, 它与前两步的配置相关。
# 这里的邮箱类型请选择 Maildir
set mbox_type = "Maildir"
set realname = "<用户名, 发邮件时会显示>"
set from = "<你的 Outlook 邮箱地址>"
与 mbsync 配置相关的部分
## folder 指向你邮箱的根目录
set folder = "~/.local/share/maildir/outlook"
## 这些变量请与你邮箱名保持一致, `+` 表示如果不存在会自动创建, 路径相对于你的${folder}
set spoolfile = "+INBOX"
set record = "+Sent"
set postponed = "+Drafts"
set trash = "+Trash"
与 notmuch 配置相关的部分
## 与 notmuch 配置相关, 与你的 notmuch 配置保持一致
set nm_default_url = "notmuch://$HOME/.local/share/notmuch/outlook" # 与 database.path 保持一致
set nm_config_profile = "outlook" # notmuch 配置的目录名, 默认是 `default`
# 这个不必一致,它相当是为每个 notmuch://?query=tag:xx 后面默认加了一个 and not tag:deleted and not tag:junk
set nm_exclude_tags = "deleted, junk"
## 创建的虚拟邮箱
## 这里就用到了 notmuch 过滤, 这里仅是我的一个参考, 具体看你自己的过滤规则和喜好任意排布
named-mailboxes " INBOX" "notmuch://?query=tag:inbox"
named-mailboxes " Unread" "notmuch://?query=tag:unread"
named-mailboxes "> Sent" "notmuch://?query=tag:sent"
named-mailboxes "> Drafts" "notmuch://?query=tag:drafts"
named-mailboxes " Forums" "notmuch://?query=tag:forum"
named-mailboxes " KDE" "notmuch://?query=tag:forum and tag:kde"
named-mailboxes " Arch (CN)" "notmuch://?query=tag:forum and tag:archcn"
named-mailboxes " Debian (CN)" "notmuch://?query=tag:forum and tag:debiancn"
named-mailboxes " OpenSuse (CN)" "notmuch://?query=tag:forum and tag:susecn"
named-mailboxes " Emacs (CN)" "notmuch://?query=tag:forum and tag:emacscn"
named-mailboxes " Github" "notmuch://?query=tag:github"
named-mailboxes " > noreply" "notmuch://?query=tag:noreply and tag:github"
named-mailboxes " Codeberg" "notmuch://?query=tag:codeberg"
named-mailboxes " > noreply" "notmuch://?query=tag:noreply and tag:codeberg"
named-mailboxes " Google" "notmuch://?query=tag:google"
named-mailboxes " > noreply" "notmuch://?query=tag:noreply and tag:google"
named-mailboxes " Firefox" "notmuch://?query=tag:firefox"
named-mailboxes " > noreply" "notmuch://?query=tag:noreply and tag:firefox"
named-mailboxes " Steam" "notmuch://?query=tag:steam"
named-mailboxes " > noreply" "notmuch://?query=tag:noreply and tag:steam"
named-mailboxes " Spam" "notmuch://?query=tag:junk"
named-mailboxes " Trash" "=Trash"
可以看到我的侧边栏和上面这个布局一致,可以通过快捷键进入不同的邮箱。
与 msmtp 配置相关的部分 (这一步暂时先跳过)
# 当你发送邮件时,它会调用执行的命令 (这里使用 msmtp)
# 这里 -a 是为了指向使用哪个账号发信, 之后会提到 msmtp 配置, 这里暂时不要管它
set sendmail = "/usr/bin/msmtp -a <你设置的 msmtp 账号>"
Step 4: msmtp 负责发送邮件
msmtp 作为 SMTP 客户端。
除了主机地址与端口不同,这里的许多配置与 isync 配置类似。
# Set default values for all following accounts.
defaults
auth on
tls on
#tls_trust_file system
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile ~/.cache/msmtp/msmtp.log
## Microsoft Outlook
account <msmtp 账号名>
from <你的 Outlook 邮箱地址>
user <你的 Outlook 邮箱地址>
host smtp-mail.outlook.com
#host smtp.office365.com
port 587
tls_starttls on
#auth oauthbearer
auth xoauth2
passwordeval oama access <你的 Outlook 邮箱地址>
技巧
最后,我为每个账号写了一个脚本, 用于自动同步邮件并打标签
#!/usr/bin/env bash
MAILDIR="$HOME/.local/share/maildir/outlook"
NOTMUCH_CONF="$HOME/.config/notmuch/outlook/config"
ISYNC_CONF="$HOME/.config/mbsync/config.outlook"
is_open_tui=0
is_only_push=0
NOTMUCH() {
notmuch --config="$NOTMUCH_CONF" "$@"
}
MBSYNC() {
mbsync --config "$ISYNC_CONF" "$@"
}
mkdir -p "$MAILDIR"
while [ -n "$1" ]; do
case "$1" in
-n | --now)
MBSYNC outlook
;;
--push)
# only push
MBSYNC --push outlook
is_only_push=1
;;
--pull)
# only pull
MBSYNC --pull outlook
;;
--tui)
is_open_tui=1
;;
esac
shift
done
if [ $is_only_push -ne 1 ]; then
NOTMUCH new
fi
if [ $is_open_tui -eq 1 ]; then
alot -n "$NOTMUCH_CONF"
fi
可以将它绑定到 neomutt 上的一个快捷键, 这样就可以在 neomutt 界面进行同步邮件了。
macro index S \
"<shell-escape>~/.local/bin/email/sync-outlook -n<Enter>" \
"Sync Outlook inbox in background"
结语
关于配置 neomutt/mutt 的帖子很少或是已经过时, 我花了大概一周时间才慢慢搞懂里面的许多内容, 更不提里面还有很多坑。
由于篇幅原因,我只挑了其中最重要的部分进行解释, 还有很多技巧和配置 (例如多账号、mailcap等)没有在这里展示。
完整的配置可以在我的 Codeberg 仓库找到。记得查看 devel 分支, main 分支可能不是最新。

