用org-mime在org-mode中发送html邮件
目录
Sending html emails from org-mode with org-mime
在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)
org-mime
你可以通过命令 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-mime-org-buffer-htmlize
From an org-headline in an org-file
你可以将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"))
完了后, 通过命令 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))
org-mime-subtree
下面是一些例子,可以看看这些元素是否能正常的转换为html.
标记
粗体
下划线
斜体
删除线
代码
下标: H_{2}O 上标: H^{+} 实体: To ∞ and beyond
等式
\(x^2\)
\[x^4\]
\(e^x\)
表格
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')
图1 A spiral
其他目录中的图片
图2 A gold particle
org-ref的引用
a | b | c |
See Table ref:table-1.
cite:Dominik201408
bibliography:../../../Dropbox/bibliography/references.bib
In a mail message
如果你想直接在邮件里用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))
mu4e-compose-org-mail
在发送时,我们需要使用 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)
org-babel-hash-at-point | org-babel-execute-safely-maybe | htmlize-and-send |
下面的方法则可以可非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)
org-babel-hash-at-point | org-babel-execute-safely-maybe | htmlize-and-send | org-htmlize-and-send |
Equations and file attachments do not seem to work out of the box
\(e^{i\pi} - 1 = 0\)
不做任何配置的情况下, org-mime似乎并不会将file链接的文件加入到电子邮件的附件中,也不会将内容中的等式转换成图片..
下面的 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)))
org-mime-compose
Summary
用这种方法来发送具有丰富格式的html邮件真是太棒了.