Skip to content
0

使用 NeoMutt 在 macOS 终端中管理邮件

本指南将引导你完成在 macOS 上配置邮件环境的整个过程,最终实现完全在终端中接收、阅读和发送邮件。

配置环境如下:

  • 操作系统:macOS Sequoia Version 15.6.1 → macOS Tahoe 26.0.1
  • 终端命令行:iTerm2
  • 文本编辑器:Neovim
  • 邮件客户端:NeoMutt
  • 管理联系人:khard
  • 查看其他文件格式的小工具:w3m/zathura/imgcat

整个配置基于即时登录远程邮件服务器。当服务器邮件数量较多时,每次登录刷新邮件列表需要耗费一点时间,1000 封邮件大约是几秒或十几秒的样子。

目录结构

为提高全套配置文件的可移植性,尽量把全部的配置文件放置在同一个目录下,主要的功能也采用模块化的配置文件。

~/.config/neomutt/
├── neomuttrc                # Main config, sources everything else
├── settings                 # General settings (editor, options, etc.)
├── mappings                 # Keybindings and macros
├── mailcap                  # External program handlers (use env vars)
├── accounts/                # Account configs and signatures
└── themes/                  # Theme configs

其中,neomuttrc 是配置主要入口,文件内部引用另外的四个独立的配置文件:

  • settings
  • mappings
  • themes/dracula.muttrc
  • accounts/twine

配置了这四个文件之后,就可以在终端里顺畅地使用 NeoMutt 接收、查看、编辑、回复、转发邮件,邮件客户端的基本功能已经具备。

最后的一个配置文件 mailcap 是在实现了最初的文本邮件的基本功能之后,再增加几个额外的功能,例如,在 NeoMutt 中查看 HMTL 格式的邮件,查看 PDF 格式的附件,查看图片格式的附件,等等。这个配置文件是在 settings 内部被引用。

安装工具

在 macOS 系统上,我们使用 Homebrew 来安装所有必要的软件。打开你的终端,比如我使用的是 iTerm2,运行以下命令:

bash
brew install neomutt
brew install w3m zathura

配置文件

按照建议的目录结构创建相应的目录和文件。

neomuttrc

配置文件 neomuttrc 是主要入口:

muttrc
# vim: filetype=muttrc

# Source general settings, mappings, and theme
source ~/.config/neomutt/settings
source ~/.config/neomutt/mappings
source ~/.config/neomutt/themes/dracula.muttrc

# Accounts
source ~/.config/neomutt/accounts/twine
folder-hook $folder source ~/.config/neomutt/accounts/twine

主文件依次分别引入基本配置、快捷键、主题颜色、默认邮箱帐户。子目录 themes 下有多个主题可选,这里设置使用了 dracula 主题;子目录 accounts 下有包含默认帐户 twine 在内的其他多个邮箱帐户,切换各个帐户的快捷键 F2F3F4 则定义在 mappings 里面。

settings

muttrc
# vim: filetype=muttrc

# Used when creating an email
set tmpdir = /tmp/$USER/neomutt       # Where to keep temp files

# set editor to Neovim
set editor = "nvim"

set imap_check_subscribed

# Set preffered view modes
# view html automatically
auto_view text/html text/calendar application/ics
alternative_order text/html text/plain text/enriched text/*

# Main options
set envelope_from
set edit_headers                     # show headers when composing
set fast_reply                       # skip to compose when replying
set askcc                            # ask for CC:
set fcc_attach                       # save attachments with the body
set forward_format = "Fwd: %s"       # format of subject when forwarding
set forward_decode                   # decode when forwarding
set attribution = "On %d, %n wrote:" # format of quoting header
set reply_to                         # reply to Reply to: field
set reverse_name                     # reply as whomever it was to
set include                          # include message in replies
set forward_quote                    # include message in forwards

# When enabled, NeoMutt creates emails with `text/plain; format=flowed`
# instead of just `text/plain`.
# This format uses spaces at the end of lines to indicate
# intentional line breaks vs. soft wrapping.
set text_flowed = yes

set sig_dashes = no                  # no default `-- ` dashes before signature
set sig_on_top = yes                 # signature shall always stick to your email body

unset mime_forward                   # forward attachments as part of body
# unset help                           # No help bar at the top of Index
unset confirmappend       # don't ask, just do!
set quit                  # don't ask, just do!
unset mark_old            # read/new is good enough for me
set beep_new              # bell on new mails
set pipe_decode           # strip headers and eval mimes when piping
set thorough_search       # strip headers and eval mimes before searching
set timeout = 0

# Status bar, date format, finding stuff etc.
set status_chars = " *%A"
set status_format = "[ Folder: %f ] [%r%m messages%?n? (%n new)?%?d? (%d to delete)?%?t? (%t tagged)? ]%>─%?p?( %p postponed )?"
set date_format = "%d.%m.%Y %H:%M"
set sort = reverse-date
set uncollapse_jump
set sort_re
set reply_regexp = "^(([Rr][Ee]?(\[[0-9]+\])?: *)?(\[[^]]+\] *)?)*"
set quote_regexp = "^( {0,4}[>|:#%]| {0,4}[a-z0-9]+[>|]+)+"
set send_charset = "utf-8:iso-8859-1:us-ascii"
set charset = "utf-8"
set arrow_cursor = "no"

# Pager View Options
# set use_threads = yes           # show email in threads in the Index
set pager_index_lines = 10      # show 10 lines of Index when Pager is active
set pager_context = 3           # lines of context between pages
set pager_stop
set menu_scroll
set tilde
unset markers                   # don't show + for wrapped lines in the pager

set mailcap_path = ~/.config/neomutt/mailcap

set header_cache = ~/.cache/mutt
set message_cachedir = ~/.cache/mutt

set query_command = "khard email --parsable --search-in-source-files '%s'"

set sidebar_format = "%B %<N?(%N)>%* %S"

注意要点如下:

  • editor 设置为调用 Neovim 用以编辑邮件头部和主体内容
  • query_command 设置使用 Tab 键搜索和补全联系人的电邮地址:主要使用在当编辑邮件头部的表单区域,例如 To:/Cc:/Bcc: 等位置,需要添加电邮地址的时候,随便打几个你依稀记得的收件人姓名或者电邮地址的若干字母,然后按 Tab 键就可一键补全,非常快捷实用

mappings

muttrc
# vim: filetype=muttrc

# General rebindings
bind attach <return> view-mailcap
bind attach l view-mailcap
bind editor <space> noop
bind pager c imap-fetch-mail
bind index G last-entry
bind index g noop
bind index gg first-entry
bind pager,attach h exit
bind pager j next-line
bind pager k previous-line
bind pager l view-attachments
bind index D delete-message
bind index U undelete-message
bind index L limit
bind index h noop
bind index l display-message
bind browser h goto-parent
bind browser l select-entry
bind pager,browser gg top-page
bind pager,browser G bottom-page
bind index,pager,browser d half-down
bind index,pager,browser u half-up
bind index,pager R group-reply
bind index \031 previous-undeleted	# Mouse wheel
bind index \005 next-undeleted		# Mouse wheel
bind pager \031 previous-line		# Mouse wheel
bind pager \005 next-line		# Mouse wheel
bind editor <Tab> complete-query


# sidebar mappings
bind index,pager \Ck sidebar-prev
bind index,pager \Cj sidebar-next
bind index,pager \Cl sidebar-open
bind index,pager \Cp sidebar-prev-new
bind index,pager \Cn sidebar-next-new
bind index,pager B sidebar-toggle-visible

# global index and pager shortcuts
bind index,pager @ compose-to-sender
bind index,pager D purge-message
bind index <tab> sync-mailbox
bind index <space> collapse-thread

# Email completion bindings
bind editor <Tab> complete-query
bind editor ^T complete

# Press A to add contact to Khard address book
macro index,pager A \
    "<pipe-message>khard add-email<return>" \
    "add the sender email address to khard"

# Shortcuts to switch email account
macro index,pager <f2> '<sync-mailbox><enter-command>source ~/.config/neomutt/accounts/twine<enter><change-folder>!<enter>'
macro index,pager <f3> '<sync-mailbox><enter-command>source ~/.config/neomutt/accounts/soundfreaq<enter><change-folder>!<enter>'
macro index,pager <f4> '<sync-mailbox><enter-command>source ~/.config/neomutt/accounts/biaget<enter><change-folder>!<enter>'

注意要点如下:

  • Ctrl + o 在 macOS 下已另作他用,无法设定给 sidebar-open 使用,故更换为 Ctrl + l

配置签名

  1. 创建 ~/.config/neomutt/signature,并在文件内添加签名内容。

  2. 在 NeoMutt 配置文件内添加签名的引用位置:

    # .config/neomutt/neomuttrc
    set signature = "./sigature

管理联系人

  1. 安装 khard

    bash
    brew install khard
  2. 在 NeoMutt 配置文件内添加关于 khard 的配置:

    # =============================================================================
    # 通讯录 (Address Book)
    # =============================================================================
    # 设置 khard 为地址查询命令
    set query_command = "khard email --parsable --search-in-source-files '%s'"
    
    bind editor <Tab> complete-query
    
    # 在邮件列表或邮件内容界面按 "A" 键,将发件人添加到 khard
    macro index,pager A "<pipe-message>khard add-email<enter>" "Add sender to khard"

    这个配置成功之后,在撰写邮件、添加收件人时,只需先简单敲入几个字符,例如 mich,然后使用 Tab 可以自动补全收件人 Michael 的电邮地址 mchui@example.com(当仅有一个搜索匹配时),或弹出下拉列表供选择多个待选电邮(当存在多个搜索匹配时)。

FAQ

  1. How to re-edit a draft email in NeoMutt? By defalut, use R key to recall a postponed message. Since in my config, the R key has been remapped to group-reply, you can use command :recall-message directly to recall a postponed message. Not working!
  2. What is the difference between delete-message and purge-message? a. delete-message delete the current entry (into Trash) b. purge-message delete the current entry, bypassing the trash folder

参考

最近更新