15

使用 Emacs 阅读邮件与 RSS

 3 years ago
source link: https://liujiacai.net/blog/2021/03/05/emacs-love-mail-feed/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
使用 Emacs 阅读邮件与 RSS Emacs as Email client

对于程序员来说,除了编写代码外,阅读邮件与技术文章是耗时比较久的事情,更重要的一点是,这两个的信息输入量都比较大,会涉及到做笔记、TODO 等,一般来说这些事情都是分散在不同应用解决的,但对 Emacs 用户来说,自然希望能在 Emacs 里做所有事

这篇文章就给读者分享下 Emacs 作为邮件、RSS 客户端的使用方式与心得。在介绍具体配置前,先展示下使用效果(主题使用 gruvbox),以便读者欣赏。

mu4e 主界面

mu4e 邮件列表,默认以话题归类

mu4e 浏览邮件

mu4e 回复邮件

elfeed-dashborad 主界面

elfeed 文章列表

elfeed 浏览文章

阅读邮件我使用的软件主要有

  • offlineimap 使用 imap 协议,以 Maildir 格式来同步邮件;类似的软件有 Mbsync

  • mu4e mu 的 Emacs 插件,mu 可以对 Maildir 格式的邮件建索引,便于搜索;类似的软件有 Gnus

offlineimap 使用 Python 编写,在 macOS 直接使用 brew 即可安装。下面是我目前的配置文件(配置文件推荐放在 ~/.config/offlineimap/config ,尽量避免直接在家目录创建 ~/.offlineimaprc

[general]
# 默认开启的账户,可以是多个
accounts = ljc, outlook
# 定义额外的 python 脚本,里面有获取密码的函数
pythonfile = ~/.config/offlineimap/pass.py

# 开始配置第一个账户
[Account ljc]
# 一个账户主要包含 local 与 remote 这两个配置项
localrepository = LocalLJC
remoterepository = RemoteLJC
# 可选配置项,邮件同步时间:这里只同步 365 天之内的
# 需要注意,一些邮件提供商也存在同步限制,比如 QQ 邮箱默认只同步 30 天内的数据,可以在设置中修改
maxage = 365

[Repository LocalLJC]
type = Maildir
localfolders = ~/.mail/ljc
# 需要与 RemoteLJC 里面的 nametrans 配置起来使用,解释见正文
nametrans = lambda folder: re.sub('^=', '&UXZO1mWHTvZZOQ-/', folder)

[Repository RemoteLJC]
nametrans = lambda folder: re.sub('^&UXZO1mWHTvZZOQ-\/', '=', folder)
# 配置 ssl 证书,macOS 下安装 openssl 即可
sslcacertfile = /usr/local/etc/[email protected]/cert.pem
# 过滤掉一些目录,不进行同步
folderfilter = lambda f: 'kK5O9l9SaGM' not in f and '&UXZO1mWHTvZZOQ-' != f
# 下面是 IMAP 的配置,我这里是使用的腾讯企业邮箱
type = IMAP
remotehost = imap.exmail.qq.com
remoteport = 993
remoteuser = [email protected]
# 调用 pass.py 中的函数获取密码
remotepasseval = get_password_emacs("imap.exmail.qq.com", "[email protected]", "993")
# 也可通过下面配置直接设置密码
# remotepass = YOUR_MAIL_PASSWORD
[Account outlook]
... 大致同上,这里不在赘述

上面的配置比较直观,也有相应注释,这里重点介绍如何设置 remotepassevalnametrans

GPG Auth Source 配置密码

Emacs 中使用 Auth Source 来管理密码,它相当于一个接口层,可以对接多个存储后端,netrc 是最常见的后端,除此之外,还支持 JSON、Secret Service API、pass。很多命令,比如 wgetcurlgit 等都支持从 netrc 读取密码,因为这里只介绍其用法:

machine mymachine login myloginname password mypassword port myport

上面描述了 netrc 文件的通用格式,下面是我邮箱的相关配置:

# cat ~/.authinfo
machine imap.exmail.qq.com login [email protected] password 123456 port 993
machine smtp.exmail.qq.com login [email protected] password 123456 port 465

993 是 imap 端口,接受邮件用;465 是 smtp 端口,发送邮件用。为了安全,还可以对 netrc 使用 GPG 加密,Emacs 会自动解密读取。

(setq auth-sources '("~/.authinfo.gpg" "~/.authinfo" "~/.netrc"))

Emacs 默认从上面几个地方找文件,读者可按需修改。

我上面对配置中使用了 get_password_emacs 这个函数来获取密码,其实现如下:

def get_password_emacs(machine, login, port):
    s = "machine %s login %s password ([^ ]*) port %s\n" % (
        machine, login, port)
    p = re.compile(s)
    authinfo = os.popen("gpg -q --no-tty -d ~/.config/authinfo.gpg").read()
    return p.search(authinfo).group(1)

nametrans 文件名转换

配置好密码后,就可以进行邮件同步了。但是在同步前,可以通过 offlineimap --info 命令查看邮件服务器中的内容,确认下需要同步哪些目录

$ offlineimap --info
OfflineIMAP 7.3.3
  Licensed under the GNU GPL v2 or any later version (with an OpenSSL exception)
imaplib2 v2.101 (bundled), Python v2.7.17, OpenSSL 1.1.1i  8 Dec 2020
  imaplib2: 2.101 (bundled)
Remote repository 'RemoteLJC': type 'IMAP'
Host: imap.exmail.qq.com Port: None SSL: True
Establishing connection to imap.exmail.qq.com:993 (RemoteLJC)
Server supports ID extension.
Server welcome string: * OK [CAPABILITY IMAP4 IMAP4rev1 ID AUTH=PLAIN AUTH=LOGIN NAMESPACE] QQMail IMAP4Server ready
Server capabilities: ('IMAP4', 'IMAP4REV1', 'XLIST', 'MOVE', 'IDLE', 'XAPPLEPUSHSERVICE', 'NAMESPACE', 'CHILDREN', 'ID', 'UIDPLUS')

folderfilter= lambda f: 'kK5O9l9SaGM' not in f and '&UXZO1mWHTvZZOQ-' != f

nametrans= lambda folder: re.sub('^&UXZO1mWHTvZZOQ-\/', '=', folder)

Folderlist:
 &UXZO1mWHTvZZOQ- (disabled)
 &UXZO1mWHTvZZOQ-/clojure -> =clojure
 &UXZO1mWHTvZZOQ-/GitHub -> =GitHub
 &UXZO1mWHTvZZOQ-/golang -> =golang
 Deleted Messages
 Drafts
 INBOX
 Junk
 Sent Messages

在 Folderlist 下面就是邮件服务器中的目录, &UXZO1mWHTvZZOQ- 开头的目录为自定义目录,为了保证同步下来的目录中没有这一串字母,我使用 nametrans 配置把它转化为了 = 符号。

由于 IMAP 的同步是双向的,本地的状态也需要返回给远端,因此在 LocalLJC 中又使用 nametrans= 转成了那串字母,这样两边就能正确同步邮件状态了,下面是本地的状态:

Local repository 'LocalLJC': type 'Maildir'
nametrans= lambda folder: re.sub('^=', '&UXZO1mWHTvZZOQ-/', folder)

Folderlist:
 INBOX
 Drafts
 Junk
 =GitHub -> &UXZO1mWHTvZZOQ-/GitHub
 Deleted Messages
 =golang -> &UXZO1mWHTvZZOQ-/golang
 =clojure -> &UXZO1mWHTvZZOQ-/clojure
 Sent Messages

最后,直接运行 offlineimap 就可以同步邮件了。

邮件同步到本地后,在使用前需要使用 mu 建索引,参考命令:

export XAPIAN_CJK_NGRAM=true
# 只需要执行一次 init,可以指定多个邮件地址
mu init --my-address [email protected] --my-address [email protected] -m ~/.mail
# index 在每次收取邮件后都需要执行,mu4e 可以配置自动执行
mu index

XAPIAN_CJK_NGRAM 环境变量主要是开启对 CJK 的分词,方便用中文搜索邮件。不过 mu 使用的 Xapian 对中文支持比较弱,只能搜索两个字的词,比如搜「雷峰塔」就不行,可参考这里的解决方案。

mu4e 在 mu 的安装目录内,不需要再额外安装。除 mu4e 外,推荐安装下面这几个 Emacs 插件

  • maildirs,它可以把每个目录邮件数展示出来。mu4e 相关配置可以在

  • org-mime,它可以把 org-mode 格式转为 HTML 的邮件

  • visual-fill-column,相当于 fill-column 与 visual-line-mode 的结合版,主要方便在大屏显示器上阅读,效果是把长行拆分是多行。

这几个插件的配置可以在这里找到,这里主要介绍核心配置,细节不再赘述:

  • mu4e-contexts 配置多账户

  • mu4e-update-interval 配置自动同步邮件与建索引间隔

  • mu4e-get-mail-command 配置同步邮件的命令

  • mu4e-view-actions 增加 mu4e-action-view-in-browser ,这样在阅读邮件时,按 a b 在浏览器打开邮件,这对那些只有 HTML 格式的邮件来说比较重要

  • message-citation-line-format 定义符合 Gmail 的引用格式,Gmail 会用 ... 将引用隐藏起来

  • mu4e-maildirs-extension-custom-list 配置目录展示顺序

  • org-mime 主要有两种使用方式

    1. 在一个 org 文件中调用 org-mime-org-buffer-htmlize (推荐绑定到 C-c C-c ),这会自动把当前 org 文件转为 html 并打开编辑邮件的 buffer

    2. 在编辑邮件的 buffer 中,调用 org-mime-edit-mail-in-org-mode (推荐绑定到 C-c ' )打开 org-mode 编辑区,编辑好后调用 org-mime-htmlize (推荐放到 message-send-hook 里面)将 org 格式转为 html 邮件

配置好后,直接运行 M-x mu4e 就能打开主视图 mu4e-main-view ,通过快捷键来在不同视图下切换(图片来源):

mu4e 主要视图交互流程

下面是我在不同视图下,常用的一些快捷键:

  • j 跳转目录

  • b 跳转书签

  • U 收取邮件与重建索引

  • g 访问当前邮件中的 URL

  • a Action 选项

  • h html/text 格式切换

  • . 查看邮件源文件

  • A 附件选项

  • C 写新邮件

  • R 回复邮件

compose
  • C-c C-c 发送

  • C-c C-k 废弃

  • C-c C-d 存草稿

  • C-c C-a 添加附件

Flags 含义

u unread S Seen D Draft A has-attachment F Flagged N New P Passed/Forwarded R Replied T Trashed x encrypted s signed

查询语法

查询语句 含义 date:today..now 今天的邮件 from:jim and not flag:attach 来自 jim 且没有附件的邮件 "maildir:/Sent Items" and rupert 发送目录内,包含 rupert 的邮件 subject:wombat and date:20170601..20170630 指定时间内,主题中包含 wombat 的邮件

说明:mu 使用 https://emacs-china.org/t/topic/305/77?u=jiacai2050


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK