How do save email in Mu4e to pdf?

165 views
Skip to first unread message

Richard Herbert

unread,
Aug 16, 2021, 1:28:12 AM8/16/21
to mu-discuss
I have not been able to discover how to save email to pdf from mu4e in a manner that ensures I have a client-ready document when needed.

[a] action choices when viewing an email that could help are:

   [v]iew as pdf  =>  I receive this "wrong type argument: stringp, nil"
   [V]iewInBrowser => "/tmp/filename.html has been saved"
   [S]ave to pdf => "Symbol's function definition is void: mu4e-action-save-pdf"

I can open up an email from maildir cur folders with kmail after it is downloaded and print to pdf. However, once the email has been viewed ([S]een), the email is no longer in .eml format and cannot be opened by kmail.

I can, after an email has been seen, select [V]iewInBrowser to get a transient .html copy of the email and open it with firefox and print to pdf from firefox. BUT, the email does not list attachments that were included with the email. This is a problem.

The [S]ave to pdf choice does not work. 

I am new to mu4e. There is a solution to save an email to pdf with attachments printed separately. 

What is it??

Richard

Richard Herbert

unread,
Aug 28, 2021, 8:52:23 AM8/28/21
to mu-discuss
I discovered a simple code to add to save Mu4e emails to pdf as follows with wkhtmltopdf installed (I installed through Yast with Opensuse Tumbleweed OS).

     (defun mu4e-action-save-to-pdf (msg)
       (let* ((date (mu4e-message-field msg :date))
              (infile (mu4e~write-body-to-html msg))
             (outfile (format-time-string "%Y-%m-%d%H%M%S.pdf" date)))
        (with-temp-buffer
          (shell-command
           (format "wkhtmltopdf %s ~/Desktop/Email/%s" infile outfile) t))))
   (add-to-list 'mu4e-view-actions '("Save to PDF" . mu4e-action-save-to-pdf) t)

The drawback at this time is that headers do not include Cc: or Attachment: but other header information is there as well as the full message.

Does anyone know hoe to include Cc: and Attachment: into the header?

Richard Herbert

unread,
Aug 28, 2021, 11:09:29 AM8/28/21
to mu-discuss
I added the following into Mu4e-action.el under mu4e~write-body-to-html:

      (insert (concat "<strong>Cc</strong>: "
                      (mu4e~action-header-to-html msg :cc) "</br>"))
      (insert (concat "<strong>Attachments</strong>: "
                      (mu4e~action-header-to-html msg :attachment) "</p>"))

Cc. is working in save to pdf with a header and names. However, I have an attachment header without listing attachments.

Help?

Richard Herbert

unread,
Aug 29, 2021, 1:04:15 PM8/29/21
to mu-discuss
I have tried to invoke plist msg to get names for attachments to save to pdf:

      (insert (concat "<strong>Attachments</strong>: "
                      (mu4e-message field msg :attachment) "</p>"))

This does not work either. I am not looking to have urls asscoated with the save to pdf. have attachment names will suffice.

The relevant code from mu4e-actions.el is:

 (defun mu4e~write-body-to-html (msg)
  "Write MSG's body (either html or text) to a temporary file; return the filename."
  (let* ((html (mu4e-message-field msg :body-html))
         (txt (mu4e-message-field msg :body-txt))
         (tmpfile (mu4e-make-temp-file "html"))
         (attachments (cl-remove-if (lambda (part)
                                      (or (null (plist-get part :attachment))
                                          (null (plist-get part :cid))))
                                    (mu4e-message-field msg :parts))))
    (unless (or html txt)
      (mu4e-error "No body part for this message"))
    (with-temp-buffer
      (insert "<head><meta charset=\"UTF-8\"></head>\n")
      (insert (concat "<p><strong>From</strong>: "
                      (mu4e~action-header-to-html msg :from) "</br>"))
      (insert (concat "<strong>To</strong>: "
                      (mu4e~action-header-to-html msg :to) "</br>"))
      (insert (concat "<strong>Cc</strong>: "
                      (mu4e~action-header-to-html msg :cc) "</br>"))
      (insert (concat "<strong>Date</strong>: "
                      (format-time-string mu4e-view-date-format (mu4e-message-field msg :date)) "</br>"))
      (insert (concat "<strong>Subject</strong>: "
                      (mu4e-message-field msg :subject) "</p>"))
      (insert (concat "<strong>Attachments</strong>: "
                      (mu4e-message-field msg :attachment) "</p>"))
      (insert (or html (concat "<pre>" txt "</pre>")))
      (write-file tmpfile)
      ;; rewrite attachment urls
      (mapc (lambda (attachment)
              (goto-char (point-min))
              (while (re-search-forward (format "src=\"cid:%s\""
                                                (plist-get attachment :cid)) nil t)
                (if (plist-get attachment :temp)
                    (replace-match (format "src=\"%s\""
                                           (plist-get attachment :temp)))
                  (replace-match (format "src=\"%s%s\"" temporary-file-directory
                                         (plist-get attachment :name)))
                  (let ((tmp-attachment-name
                         (format "%s%s" temporary-file-directory
                                 (plist-get attachment :name))))
                    (mu4e~proc-extract 'save (mu4e-message-field msg :docid)
                                       (plist-get attachment :index)
                                       mu4e-decryption-policy tmp-attachment-name)
                    (mu4e-remove-file-later tmp-attachment-name)))))
            attachments)
      (save-buffer)
      tmpfile)))

Any suggestions on how to get attachment names to save with the pdf?
Reply all
Reply to author
Forward
0 new messages