Using mu4e-headers-actions to view in browser

445 views
Skip to first unread message

Larrabee Strow

unread,
Mar 25, 2014, 3:26:52 PM3/25/14
to mu-di...@googlegroups.com
First, so nice to be doing email in emacs again.  Many thanks.

It often takes my system (Mac OS X) a long time to render html emails into text.  I would like to ask mu4e to view those messages in the browser while only header view is open so I don't have to wait for rendering it to an emacs buffer.  I did the following in my emacs init.el

 (add-to-list 'mu4e-headers-actions
   '("View in browser" . mu4e-action-view-in-browser) t)

When in header mode, I hit "a", I see [V]iew in browser

But when I hit V I always get the message:

[mu4e] No body part for this message

(It will render into emacs, or go to the browser once I am in message view).

What am I doing wrong?

Thanks, Larrabee



Dirk-Jan C. Binnema

unread,
Mar 26, 2014, 7:52:34 AM3/26/14
to mu-di...@googlegroups.com
For speed-reasons, there's no body information associated with the
messages when you see them in the headers-view. Not much we can do about
that.

However, the root problem seems to be that the rendering of html
messages is slow; it might be useful to try some different value for
`mu4e-html2text', and see if that helps (see its docstring for details).

Cheers,
Dirk.


--
Dirk-Jan C. Binnema Helsinki, Finland
e:dj...@djcbsoftware.nl w:www.djcbsoftware.nl
pgp: D09C E664 897D 7D39 5047 A178 E96A C7A1 017D DA3C

Olli P

unread,
Dec 27, 2015, 2:40:39 AM12/27/15
to mu-discuss
I am looking to add this features as well, as there are some messages where I know beforehand that they will look much nicer when viewed from the browser. I can already do this by opening the message first and then calling the action for viewing it in the browser, but I'd like to avoid the extra step of having to open the message first and just directly open up the message in the browser.

I was digging through the source code of mu4e to figure out how to retrieve the body of the message using the :docid or :path fields that are available to me from the headers view, but in the end I gave up after unsuccessfully trying to shadow  the mu4e-view-func with a function of my own in the scope of a let. There seems to be a very tight coupling between the message view buffer and commands that get sent to the mu process. Is there some way around this, or perhaps I should just make my action use the message view buffer and automate the opening in the browser part while there?

- Olli

Florian Adamsky

unread,
Dec 27, 2015, 3:28:45 AM12/27/15
to mu-di...@googlegroups.com

On Sunday, Dez 27 2015, Olli P wrote:

> I am looking to add this features as well, as there are some messages where
> I know beforehand that they will look much nicer when viewed from the
> browser. I can already do this by opening the message first and then
> calling the action for viewing it in the browser, but I'd like to avoid the
> extra step of having to open the message first and just directly open up
> the message in the browser.

I have the following code snippet in my emacs config. I stole this
snippet from [1], however, it seems that this website is down at the
moment.

#+BEGIN_SRC emacs-lisp
(defun mu4e-msgv-action-view-in-browser (msg)
"View the body of the message in a web browser."
(interactive)
(let ((html (mu4e-msg-field (mu4e-message-at-point t) :body-html))
(tmpfile (format "%s/%d.html" temporary-file-directory (random))))
(unless html (error "No html part for this message"))
(with-temp-file tmpfile
(insert
"<html>"
"<head><meta http-equiv=\"content-type\""
"content=\"text/html;charset=UTF-8\">"
html))
(browse-url (concat "file://" tmpfile))))

(add-to-list 'mu4e-view-actions
'("View in browser" . mu4e-msgv-action-view-in-browser) t)
#+END_SRC

[...]

Regards

[1] http://www.brool.com/index.php/using-mu4e
--
Florian Adamsky
http://florian.adamsky.it/

Dirk-Jan C. Binnema

unread,
Dec 27, 2015, 4:09:47 AM12/27/15
to mu-di...@googlegroups.com

On Sunday Dec 27 2015, Olli P. wrote:

> I am looking to add this features as well, as there are some messages where
> I know beforehand that they will look much nicer when viewed from the
> browser. I can already do this by opening the message first and then
> calling the action for viewing it in the browser, but I'd like to avoid the
> extra step of having to open the message first and just directly open up
> the message in the browser.
>
> I was digging through the source code of mu4e to figure out how to retrieve
> the body of the message using the :docid or :path fields that are available
> to me from the headers view, but in the end I gave up after unsuccessfully
> trying to shadow the mu4e-view-func with a function of my own in the scope
> of a let. There seems to be a very tight coupling between the message view
> buffer and commands that get sent to the mu process. Is there some way
> around this, or perhaps I should just make my action use the message view
> buffer and automate the opening in the browser part while there?

Let-binding is a bit hard for some of the mu4e-functions, since the
messages come in asynchronously, ie., after we've left the let-bound
area.

You could use the message-view, I suppose, but you do not have the
message body there; you do have the :path (to the raw message), but it
would take a bit of processing to have that show nicely in a
browser. There's some code in toys/mug which can do the latter, but
would require some changes for this particular use-case.

However, the real question is perhaps why we can't have all messages
look nice inside emacs - that should be the goal, I think. It's gotten a
lot better when using 'shr' (see manual) for rendering, but there are
still some error-cases (like airline-emails).

An interesting solution would be to create a email view widget (like the
one in 'mug'), and integrate that in emacs, using the upcoming
xwidget/ffi functionality.

Kind regards,

Olli P

unread,
Dec 27, 2015, 1:22:57 PM12/27/15
to mu-discuss, fa...@haktar.org
That's actually exactly the snippet that I am using myself to view messages from the message-view. I am actually trying to accomplish doing the same but form the headers view, without having to first open up the message to its own view.

- Olli

Olli P

unread,
Dec 27, 2015, 2:23:07 PM12/27/15
to mu-discuss
Thank you for your suggestions. Using 'shr' is definitely an improvement although still far from perfect. I thought I might try just calling `mu view` with the path of the message form the header-view, but that didn't turn out to work for html based messages.

My current solution looks like this:

(defun mu4e/headv-action-view-in-browser2 ()
  (interactive)
  (save-window-excursion
    (mu4e-headers-view-message)
    (let* ((msg (mu4e-message-at-point))
           (html (mu4e-msg-field (mu4e-message-at-point t) :body-html))
           (txt (mu4e-message-field msg :body-txt)))
      (unless (or html txt)
        (mu4e-error "No html part for this message"))
      (mu4e/display-stuff-in-browser
       (or html (concat "<pre>" txt "</pre>"))))))

It works, but it leaves me with the message-view buffer instead of the headers-view. I have yet to figure out how to reliably close the message-view buffer and return to the headers view. Any ideas on that front?

- Olli

Olli P

unread,
Dec 27, 2015, 2:36:55 PM12/27/15
to mu-discuss
Adding a `(sleep-for 0.1)` at the end solved it for me. Still open for less hacky solutions :). Here's everything I have now in case anyone else might find it useful:

(defun mu4e/display-stuff-in-browser (stuff)
  "Displays STUFF as HTML in an external browser."
  (let ((tmp-file (format "%s/%d.html" temporary-file-directory (random t))))
    (with-temp-file tmp-file

      (insert
       "<html>"
       "<head><meta http-equiv=\"content-type\""
       "content=\"text/html;charset=UTF-8\">"
       stuff))
    (browse-url (concat "file://" tmp-file))))

(defun mu4e/msgv-action-view-in-browser (msg)
  "View the body of the message in an external web browser."
  (interactive)
  (let ((html (mu4e-msg-field (mu4e-message-at-point t) :body-html))

        (txt (mu4e-message-field msg :body-txt)))
    (unless (or html txt)
      (mu4e-error "No html part for this message"))
    (mu4e/display-stuff-in-browser
     (or html (concat "<pre>" txt "</pre>")))))

(defun mu4e/headerv-action-view-in-browser (msg)

  (interactive)
  (save-window-excursion
    (mu4e-headers-view-message)
    (let* ((msg (mu4e-message-at-point))
           (html (mu4e-msg-field (mu4e-message-at-point t) :body-html))
           (txt (mu4e-message-field msg :body-txt)))
      (unless (or html txt)
        (mu4e-error "No html part for this message"))
      (mu4e/display-stuff-in-browser
       (or html (concat "<pre>" txt "</pre>"))))
    (sleep-for 0.1)))

(add-to-list 'mu4e-view-actions
             '("browser view" . mu4e/msgv-action-view-in-browser) t)
(add-to-list 'mu4e-headers-actions
             '("browser view" . mu4e/headerv-action-view-in-browser) t)
Reply all
Reply to author
Forward
0 new messages