index rss mastodon twitter github linkedin email
Álvaro Ramírez
sponsor

Álvaro Ramírez

15 September 2023 Send note to Kindle

While on Mastodon, I spotted @summeremacs looking into sending Emacs text selections to a Kindle via email. This sparked my interest as I previously looked into sending pdfs to my Kindle via mu4e.

Kindle offers a neat service where you can email a file to your @kindle.com address and it automatically shows up in your Kindle library.

I already do email from my beloved editor, and like most Emacs things, it's powered by elisp. In other words, it's basically up for grabs if you'd like to glue it to anything else, so I did…

I can now select a region and invoke M-x send-to-kindle-as-txt to send it over to my Kindle.

send-to-my-kindle.gif

Soon enough, the note shows up on my Kindle.

listed.png

Opening the note reveals the same content we had previously selected and sent from our malleable editor.

repeated.png

While it looks kinda magical, it's fairly simple under the hood. It takes the region content, writes it to a txt file, creates an email message buffer attaching the file, and finally sends via message-send-and-exit.

If M-x send-to-kindle-as-txt is invoked with a C-u prefix, you get to inspect the message buffer right before sending via C-c C-c.

email.png

Here's the full snippet.

(defcustom send-to-kindle-from-email
  nil
  "Your own email address to send from via mu4e."
  :type 'string
  :group 'send-to-kindle)

(defcustom send-to-kindle-to-email
  nil
  "Your Kindle email address to send pdf to."
  :type 'string
  :group 'send-to-kindle)

(defun send-to-kindle-as-txt (review)
  (interactive "P")
  (unless send-to-kindle-from-email
    (setq send-to-kindle-from-email
          (read-string "From email address: ")))
  (unless send-to-kindle-to-email
    (setq send-to-kindle-to-email
          (read-string "To email address: ")))
  (let* ((content (string-trim (if (region-active-p)
                                   (buffer-substring (region-beginning) (region-end))
                                 (buffer-string))))
         (note-name (let ((name (string-trim (read-string "Note name: "))))
                      (if (string-empty-p name)
                          (nth
                           0 (string-split
                              (substring content 0 (min 40 (length content))) "\n"))
                        name)))
         (path (concat (temporary-file-directory) note-name))
         (txt (concat path ".txt"))
         (buffer (get-buffer-create (generate-new-buffer-name "*Email txt*"))))
    (with-temp-buffer
      (insert content)
      (write-file txt))
    (with-current-buffer buffer
      (erase-buffer)
      ;; Disable hooks
      (let ((message-mode-hook nil))
        (message-mode))
      (insert
       (format
        "From: %s
To: %s
Subject: %s
--text follows this line--
<#multipart type=mixed>
<#part type=\"text/plain\" filename=\"%s\" disposition=attachment>
<#/part>
<#/multipart>"
        send-to-kindle-from-email
        send-to-kindle-to-email
        note-name txt))
      (unless review
        (message-send-and-exit)))
    (when review
      (switch-to-buffer buffer))))

By the way, and I only just learned this today… To take a screenshot on a Kindle Paperwhite, tap on these opposite corners.

tap-screenshot.png