在org-mode的邮件列表中进行哦一些关于如何用orgmode发送html格式邮件的讨论. 之前用mu4e来实现的方式已经过时了. 你可以用org-mime这个库来代替以前的实现方法. 我试用了一下这个库,发现还存在以下一些缺陷:
- 我发现org中的等式并不会渲染成html中的图片,而且org中所链接的文件也不会自动成为邮件的附件. 对此我做了一些修改.
- 我发现使用org-mime命令从org buffer中生成email时,若能把光标保留在
To:
的位置就好了. - 我使用mu4e来发送邮件, 因此我创建了一个函数来用
org-mu4e-compose-org-mode
编辑message, 然后为C-c C-c
添加了一个hook来方便我发送邮件(函数定义参见这里).
这篇博文主要记录了我折腾出来发送html邮件的那些步骤. 经过实验, 上面列出的有些缺陷已经在最新的org-mime中得到了修复.
第一步,你需要require org-mime
这个库.
(require 'org-mime)
你可以通过命令 elisp:org-mime-org-buffer-htmlize 来将整个org buffer作为html邮件来发送. 不过这个命令并不能支持所有的内部链接(at least in gmail).
这个命令默认会把你的光标移动到buffer的末尾位置,这样很不方便. 我们可以稍微修改一下这个函数来让光标定位到 To:
的位置.
(defun org-mime-org-buffer-htmlize ()
"Create an email buffer containing the current org-mode file
exported to html and encoded in both html and in org formats as
mime alternatives."
(interactive)
(org-mime-send-buffer 'html)
(message-goto-to))
你可以将org buffer中的某个heading内容转换为html邮件发送. 这种情况下, 你需要为heading指定 MAIL_FMT
属性为html, 像这样:
:PROPERTIES: :MAIL_FMT: html :END:
除此之外,你还可以设置下面这些属性.
(subject (or (funcall mp "MAIL_SUBJECT") (nth 4 (org-heading-components))))
(to (funcall mp "MAIL_TO"))
(cc (funcall mp "MAIL_CC"))
(bcc (funcall mp "MAIL_BCC"))
完了后, 通过命令 elisp:org-mime-subtree 来将该heading作为邮件发送出去.
同样的,我也修改了一下这个函数,来让光标停留在 To:
位置.
(defun org-mime-subtree ()
"Create an email buffer containing the current org-mode subtree
exported to a org format or to the format specified by the
MAIL_FMT property of the subtree."
(interactive)
(org-mime-send-subtree
(or (org-entry-get nil "MAIL_FMT" org-mime-use-property-inheritance) 'org))
(message-goto-to))
下面是一些例子,可以看看这些元素是否能正常的转换为html.
粗体
下划线
斜体
删除线
代码
下标: H_{2}O 上标: H^{+} 实体: To ∞ and beyond
\(x^2\)
\[x^4\]
x | y |
1 | 2 |
嵌套列表.
- one
- Subentry under one.
- two
定义列表:
- def1
- first definition
检查列表:
- [ ] A checkbox
带数字编号的列表:
- number 1
- number 2
import numpy as np
import matplotlib.pyplot as plt
t = np.linspace(0, 10)
x = np.cos(t) * np.exp(-t)
y = np.sin(t) * np.exp(-t)
plt.plot(x, y)
plt.savefig('spiral.png')
a | b | c |
See Table ref:table-1.
cite:Dominik201408
bibliography:../../../Dropbox/bibliography/references.bib
如果你想直接在邮件里用org的形式编写内容. 你可以用下面的方式适用于mu4e用户. 下面的这个命令会以org-mode打开一个写消息的窗口,而且在邮件header与邮件body之间切换的同时也会切换到不同的mode下. 如果你经常这样做,那么你可以为message-mode加一个hook. 我自己不怎么发送html邮件因此我没有这样做.
(defun mu4e-compose-org-mail ()
(interactive)
(mu4e-compose-new)
(org-mu4e-compose-org-mode))
在发送时,我们需要使用 org-mime
来将org内容转换成html, 因此我们为 C-c C-c
添加一个hook函数来发送邮件.
这个hook函数有一些棘手, 我们需要保持 C-c C-c
在org-mode中的行为不变, 例如,在code block中按下 C-c C-c
要能执行该代码块, 但是当 C-c C-c
不触发其他动作时则发送邮件. 为了做到这一点,你需要将该hook函数放在hook的最末尾才行.
当然,你也可以为该功能分配其他的快捷键,或者直接用 M-x
运行该命令也行.
需要注意的是,这个 C-c C-c
hook函数只有在光标处于email的boy时才生效. 当在email的header处按下 C-c C-c
则会将邮件内容以纯文本的方式发送出去.
(defun htmlize-and-send ()
"When in an org-mu4e-compose-org-mode message, htmlize and send it."
(interactive)
(when (member 'org~mu4e-mime-switch-headers-or-body post-command-hook)
(org-mime-htmlize)
(message-send-and-exit)))
(add-hook 'org-ctrl-c-ctrl-c-hook 'htmlize-and-send t)
下面的方法则可以可非mu4e用户做到在直接在邮件里编写org格式的内容,但是它无法做到mode的自动切换. 因此你会失去邮件的补全功能,以及那些与邮件header相关的功能,除非你重新切换回message-mode.
(defun compose-html-org ()
(interactive)
(compose-mail)
(message-goto-body)
(setq *compose-html-org* t)
(org-mode))
(defun org-htmlize-and-send ()
"When in an org-mu4e-compose-org-mode message, htmlize and send it."
(interactive)
(when *compose-html-org*
(setq *compose-html-org* nil)
(message-mode)
(org-mime-htmlize)
(message-send-and-exit)))
(add-hook 'org-ctrl-c-ctrl-c-hook 'org-htmlize-and-send t)
\(e^{iπ} - 1 = 0\)
不做任何配置的情况下, org-mime似乎并不会将file链接的文件加入到电子邮件的附件中,也不会将内容中的等式转换成图片..
file:html-email.org
下面的 org-mime-compose
能帮你实现这一点.
(defun org-mime-compose (body fmt file &optional to subject headers)
(require 'message)
(let ((bhook
(lambda (body fmt)
(let ((hook (intern (concat "org-mime-pre-"
(symbol-name fmt)
"-hook"))))
(if (> (eval `(length ,hook)) 0)
(with-temp-buffer
(insert body)
(goto-char (point-min))
(eval `(run-hooks ',hook))
(buffer-string))
body))))
(fmt (if (symbolp fmt) fmt (intern fmt)))
(files (org-element-map (org-element-parse-buffer) 'link
(lambda (link)
(when (string= (org-element-property :type link) "file")
(file-truename (org-element-property :path link)))))))
(compose-mail to subject headers nil)
(message-goto-body)
(cond
((eq fmt 'org)
(require 'ox-org)
(insert (org-export-string-as
(org-babel-trim (funcall bhook body 'org)) 'org t)))
((eq fmt 'ascii)
(require 'ox-ascii)
(insert (org-export-string-as
(concat "#+Title:\n" (funcall bhook body 'ascii)) 'ascii t)))
((or (eq fmt 'html) (eq fmt 'html-ascii))
(require 'ox-ascii)
(require 'ox-org)
(let* ((org-link-file-path-type 'absolute)
;; we probably don't want to export a huge style file
(org-export-htmlize-output-type 'inline-css)
(org-html-with-latex 'dvipng)
(html-and-images
(org-mime-replace-images
(org-export-string-as (funcall bhook body 'html) 'html t)))
(images (cdr html-and-images))
(html (org-mime-apply-html-hook (car html-and-images))))
(insert (org-mime-multipart
(org-export-string-as
(org-babel-trim
(funcall bhook body (if (eq fmt 'html) 'org 'ascii)))
(if (eq fmt 'html) 'org 'ascii) t)
html)
(mapconcat 'identity images "\n")))))
(mapc #'mml-attach-file files)))
用这种方法来发送具有丰富格式的html邮件真是太棒了.