email-eww

Emacs library to send region or eww buffer by email
git clone https://logand.com/git/email-eww.git/
Log | Files | Refs

email-eww.el (16849B)


      1 ;;; -*- lexical-binding: t -*-
      2 ;;;
      3 ;;; email-eww.el
      4 ;;;
      5 ;;; Emacs library to send region or eww buffer by email.
      6 ;;;
      7 ;;; Author: Tomas Hlavaty <tom at logand dot com>
      8 ;;;
      9 ;;; License: GPL v3 or later
     10 ;;;
     11 ;;; Inspired by
     12 ;;; http://kitchingroup.cheme.cmu.edu/blog/2014/06/08/Better-integration-of-org-mode-and-email/
     13 
     14 (require 'eww)
     15 
     16 (defcustom email-eww-from
     17   ""
     18   "Sender email address."
     19   :group 'email-eww
     20   :type 'string)
     21 
     22 (defcustom email-eww-to
     23   ""
     24   "Recipient email address."
     25   :group 'email-eww
     26   :type 'string)
     27 
     28 (defun email-string (string &optional url title in-reply-to)
     29   (compose-mail email-eww-to
     30                 (or title
     31                     (with-temp-buffer
     32                       (insert string)
     33                       (goto-char (point-min))
     34                       (end-of-line)
     35                       (buffer-substring (point-min) (point))))
     36                 `(("From" . ,email-eww-from)
     37                   ("In-Reply-To" . ,in-reply-to)))
     38   (message-goto-body)
     39   (when url
     40     (insert url)
     41     (insert "\n\n"))
     42   (insert string)
     43   (message-goto-to))
     44 
     45 (defun email-region (start end)
     46   "Send region as the body of an email."
     47   (interactive "r")
     48   (let ((string (buffer-substring start end)))
     49     (email-string string
     50                   (or (plist-get eww-data :url)
     51                       (buffer-name (current-buffer)))
     52                   (plist-get eww-data :title))))
     53 
     54 (defun clean-up-ycombinator ()
     55   (forward-line)
     56   (kill-line 2)
     57   (cond
     58    ((search-forward "Ask HN" nil t)
     59     )
     60    ((search-forward "comment" nil t)
     61     (beginning-of-line))
     62    )
     63   (let ((start (point)))
     64     (cond
     65      ((search-forward "add comment" nil t)
     66       (beginning-of-line)
     67       (forward-line)
     68       (delete-region start (point)))
     69      ))
     70   (goto-char (point-max))
     71   (search-backward "reply")
     72   (forward-line)
     73   (delete-region (point) (point-max))
     74   (message-goto-body)
     75   (unless (bolp)
     76     (forward-line 1))
     77   (delete-whitespace-rectangle (point) (point-max) nil)
     78   (message-goto-body)
     79   (flush-lines "^reply$" (point) (point-max)))
     80 
     81 (defun clean-up-reddit ()
     82   (forward-line 2)
     83   (let ((start (point)))
     84     (cond
     85      ((search-forward "Posted by" nil t)
     86       (beginning-of-line)
     87       (forward-line)
     88       (delete-region start (point)))
     89      ((search-forward-regexp "^submitted" nil t)
     90       (beginning-of-line)
     91       (forward-line -1)
     92       (backward-paragraph)
     93       (delete-region start (point)))
     94      ))
     95   (goto-char (point-max))
     96   (or (search-backward "Community Details" nil t)
     97       (search-backward "* reply"))
     98   (beginning-of-line)
     99   (delete-region (point) (point-max))
    100   (message-goto-body)
    101   (flush-lines "^share$" (point) (point-max))
    102   (flush-lines "^save$" (point) (point-max))
    103   (flush-lines "^hide$" (point) (point-max))
    104   (flush-lines "^report$" (point) (point-max))
    105   (flush-lines "^search$" (point) (point-max))
    106   (flush-lines "^Reply$" (point) (point-max))
    107   (flush-lines "^reportSave$" (point) (point-max))
    108   (flush-lines "^Sort by$" (point) (point-max))
    109   (flush-lines "^best$" (point) (point-max))
    110   (flush-lines "^besttopnewcontroversialoldq&a$" (point) (point-max))
    111   (flush-lines "^* permalink$" (point) (point-max))
    112   (flush-lines "^* embed$" (point) (point-max))
    113   (flush-lines "^* save$" (point) (point-max))
    114   (flush-lines "^* parent$" (point) (point-max))
    115   (flush-lines "^* report$" (point) (point-max))
    116   (flush-lines "^* give gold$" (point) (point-max))
    117   (flush-lines "^* share$" (point) (point-max))
    118   (flush-lines "^Post a comment!$" (point) (point-max))
    119   (flush-lines "^Create an account$" (point) (point-max))
    120   (flush-lines "^* reply$" (point) (point-max))
    121   (flush-lines "^*$" (point) (point-max))
    122   ;;(delete-blank-lines)
    123   (while (search-forward-regexp "\\(^\\s-*$\\)\n" nil t)
    124     (replace-match "\n")
    125     (unless (= (point) (point-max))
    126       (forward-char 1))))
    127 
    128 (defun clean-up-faz () ;; TODO Artikel auf einer Seite lesen @@@ cuts out end
    129   (forward-line 2)
    130   (let ((start (point)))
    131     (goto-char (point-max))
    132     (or
    133      (search-backward "Zugang zu allen FAZ" nil t)
    134      (search-backward "Quelle:" nil t)
    135      (search-backward "Mehr zum Thema" nil t)
    136      (search-backward "* Submit Submit")
    137      )
    138     (forward-line -1)
    139     (delete-region (point) (point-max))
    140     (goto-char (point-max))
    141     (search-backward "Abo")
    142     (beginning-of-line)
    143     (forward-line 2)
    144     (delete-region start (point)))
    145   (message-goto-body))
    146 
    147 (defun clean-up-mmnews ()
    148   (forward-line 2)
    149   (let ((start (point)))
    150     (forward-line)
    151     (search-forward-regexp "^[*]$" nil t)
    152     (forward-line 4)
    153     (delete-region start (point))
    154     ;;
    155     (goto-char (point-max))
    156     (or (search-backward "Wissen macht reich:" nil t)
    157         (search-backward "Neue Videos:" nil t))
    158     (beginning-of-line)
    159     (forward-line -1)
    160     (delete-region (point) (point-max)))
    161   (message-goto-body))
    162 
    163 (defun clean-up-voanews ()
    164   (forward-line 2)
    165   (let ((start (point)))
    166     (search-forward "Print this page")
    167     (beginning-of-line)
    168     (forward-line 3)
    169     (delete-region start (point))
    170     (search-forward "Related Stories")
    171     (forward-line -3)
    172     (delete-region (point) (point-max)))
    173   (message-goto-body))
    174 
    175 (defun clean-up-guardian ()
    176   (forward-line 2)
    177   (let ((start (point)))
    178     (goto-char (point-max))
    179     (search-backward-regexp "^Topics")
    180     (delete-region (point) (point-max))
    181     (goto-char start)
    182     (or (search-forward "Last modified" nil t)
    183         (search-forward "First published" nil t)
    184         (search-forward-regexp "^Published")
    185         )
    186     (or (search-backward "Submit" nil t)
    187         (search-backward-regexp "^* ")
    188         )
    189     (beginning-of-line)
    190     (forward-line 1)
    191     (delete-region start (point)))
    192   (message-goto-body))
    193 
    194 (defun clean-up-wikipedia ()
    195   (or (search-forward "Retrieved from" nil t)
    196       (search-forward "Abgerufen von" nil t))
    197   (beginning-of-line)
    198   (delete-region (point) (point-max))
    199   (message-goto-body))
    200 
    201 (defun clean-up-stackoverflow ()
    202   (forward-line 2)
    203   (let ((start (point)))
    204     (search-forward "Ask Question" nil t)
    205     (beginning-of-line)
    206     (search-backward "Learn more" nil t)
    207     (beginning-of-line)
    208     (forward-line 3)
    209     (delete-region (point) start))
    210   (goto-char (point-max))
    211   (search-backward "Add a comment" nil t)
    212   (beginning-of-line)
    213   (delete-region (point) (point-max))
    214   (message-goto-body))
    215 
    216 (defun clean-up-schneier ()
    217   (forward-line 2)
    218   (let ((start (point)))
    219     (search-forward "HomeBlog" nil t)
    220     (beginning-of-line)
    221     (forward-line 2)
    222     (delete-region (point) start))
    223   (goto-char (point-max))
    224   (search-backward "Atom Feed" nil t)
    225   (beginning-of-line)
    226   (delete-region (point) (point-max))
    227   (message-goto-body))
    228 
    229 (defun clean-up-counterpunch ()
    230   (forward-line 2)
    231   (let ((start (point)))
    232     (search-forward "Submit" nil t)
    233     (beginning-of-line)
    234     (forward-line 1)
    235     (delete-region (point) start))
    236   (goto-char (point-max))
    237   (search-backward "New from" nil t)
    238   (beginning-of-line)
    239   (delete-region (point) (point-max))
    240   (message-goto-body))
    241 
    242 (defun clean-up-wallstreetonparade ()
    243   (forward-line 1)
    244   (let ((start (point)))
    245     (search-forward "Search for:" nil t)
    246     (beginning-of-line)
    247     (forward-line 1)
    248     (forward-paragraph 1)
    249     (delete-region (point) start))
    250   (goto-char (point-max))
    251   (search-backward "Bookmark the permalink." nil t)
    252   (beginning-of-line)
    253   (delete-region (point) (point-max))
    254   (message-goto-body))
    255 
    256 (defun clean-up-cnn ()
    257   (forward-line 1)
    258   (let ((start (point)))
    259     (search-forward "Follow CNN" nil t)
    260     (beginning-of-line)
    261     (forward-paragraph 2)
    262     (delete-region (point) start))
    263   (goto-char (point-max))
    264   (search-backward "Submit" nil t)
    265   (beginning-of-line)
    266   (delete-region (point) (point-max))
    267   (message-goto-body))
    268 
    269 (defun clean-up-commondreams ()
    270   (forward-line 1)
    271   (let ((start (point)))
    272     (or (search-forward "(Photo" nil t)
    273         (search-forward "A project of Common Dreams" nil t))
    274     (beginning-of-line)
    275     (forward-paragraph 2)
    276     (delete-region (point) start))
    277   (goto-char (point-max))
    278   (or (search-backward "From Your Site Articles" nil t)
    279       (search-backward "SUBSCRIBE TO OUR FREE NEWSLETTER" nil t))
    280   (beginning-of-line)
    281   (delete-region (point) (point-max))
    282   (message-goto-body))
    283 
    284 (defun clean-up-wsws ()
    285   (forward-line 1)
    286   (let ((start (point)))
    287     (search-forward "* Donate" nil t)
    288     (beginning-of-line)
    289     (forward-paragraph)
    290     (delete-region (point) start))
    291   (goto-char (point-max))
    292   (or
    293    (search-backward "The World Socialist Web Site is the voice" nil t)
    294    (search-backward "Sign up for " nil t)
    295    (search-backward "Read more" nil t)
    296    (search-backward "Join the fight for socialism" nil t)
    297    (search-backward "Only by building an independent movement" nil t)
    298    )
    299   (beginning-of-line)
    300   (delete-region (point) (point-max))
    301   (message-goto-body))
    302 
    303 (defun clean-up-zsposepneho ()
    304   (forward-line 1)
    305   (let ((start (point)))
    306     (search-forward "Publikováno" nil t)
    307     (beginning-of-line)
    308     (backward-paragraph 2)
    309     (delete-region (point) start))
    310   (goto-char (point-max))
    311   (search-backward "Rychle k cíli" nil t)
    312   (beginning-of-line)
    313   (forward-line -1)
    314   (delete-region (point) (point-max))
    315   (message-goto-body))
    316 
    317 (defun clean-up-euractiv () ;; TODO Better
    318   (forward-line 1)
    319   (let ((start (point)))
    320     (cond
    321      ((search-forward "Lights off" nil t)
    322       (forward-line)
    323       (delete-region (point) start))
    324      ((search-forward "--------------" nil t)
    325       (forward-line)
    326       (delete-region (point) start))
    327      ((search-forward "Most recent" nil t)
    328       (delete-region (point) start))
    329      ((search-forward "Est. " nil t)
    330       (beginning-of-line)
    331       (backward-paragraph 3)
    332       (delete-region (point) start))
    333      ((search-forward "Content-Type:" nil t)
    334       (backward-paragraph 3)
    335       (delete-region (point) start)))
    336     ;; tail
    337     (goto-char (point-max))
    338     (or
    339      (search-backward "Last updated" nil t)
    340      (search-backward "Euractiv is part of the Trust Project" nil t)
    341      (search-backward "Topics" nil t)
    342      (search-backward "Read more with Euractiv" nil t)
    343      )
    344     (when (< start (point))
    345       (beginning-of-line)
    346       (forward-line -1)
    347       (backward-paragraph 1)
    348       (delete-region (point) (point-max)))
    349     ;; whitespace
    350     (goto-char start)
    351     (while (re-search-forward "^[ \t]+" nil t)
    352       (replace-match "")))
    353   (message-goto-body))
    354 
    355 (defun clean-up-infomigrants ()
    356   (forward-line 1)
    357   (let ((start (point)))
    358     (search-forward "Published on : " nil t)
    359     (beginning-of-line)
    360     (backward-paragraph 2)
    361     (delete-region (point) start)
    362     ;; tail
    363     (goto-char (point-max))
    364     (search-backward "More articles" nil t)
    365     (beginning-of-line)
    366     (forward-line -1)
    367     (delete-region (point) (point-max))
    368     ;; other
    369     (goto-char start)
    370     (while (re-search-forward "^*\n" nil t)
    371       (replace-match ""))
    372     (goto-char start)
    373     (while (re-search-forward "^Also read: " nil t)
    374       (beginning-of-line)
    375       (forward-line -1)
    376       (kill-paragraph 1))
    377     )
    378   (message-goto-body))
    379 
    380 (defun clean-up-fefe () ;; TODO append external links
    381   (forward-line 1)
    382   (let ((start (point)))
    383     (search-forward "Fragen? Antworten! Siehe auch: Alternativlos" nil t)
    384     (beginning-of-line)
    385     (forward-paragraph)
    386     (delete-region (point) start)
    387     ;; tail
    388     (goto-char (point-max))
    389     (search-backward "ganzer Monat" nil t)
    390     (beginning-of-line)
    391     (forward-line -1)
    392     (delete-region (point) (point-max))
    393     )
    394   (message-goto-body))
    395 
    396 (defun clean-up-nixos-discourse ()
    397   (forward-line 1)
    398   (let ((start (point)))
    399     (forward-paragraph)
    400     (delete-region (point) start)
    401     ;; tail
    402     (goto-char (point-max))
    403     (backward-paragraph 2)
    404     (delete-region (point) (point-max))
    405     )
    406   (message-goto-body))
    407 
    408 ;; TODO techdirt until ^Hide this
    409 
    410 (defun clean-up-aljazeera () ;; TODO better
    411   (forward-line 1)
    412   (let ((start (point)))
    413     (search-forward "Submit" nil t)
    414     (search-forward "Submit" nil t)
    415     (search-forward "Submit" nil t)
    416     (forward-paragraph)
    417     (delete-region (point) start)
    418     ;; tail
    419     (goto-char (point-max))
    420     (or (search-backward "Advertisement" nil t)
    421         (search-backward "Source:" nil t)
    422         (search-backward "Click here to share on social media" nil t)
    423         (search-backward "Recommended Stories" nil t))
    424     (beginning-of-line)
    425     (forward-line -1)
    426     (delete-region (point) (point-max))
    427     )
    428   (message-goto-body))
    429 
    430 (defun clean-up-neovlivni ()
    431   (forward-line 1)
    432   (let ((start (point)))
    433     (forward-paragraph 3)
    434     (delete-region (point) start)
    435     ;; tail
    436     (goto-char (point-max))
    437     (when (search-backward "Sdílet článek" nil t)
    438       (beginning-of-line)
    439       (delete-region (point) (point-max))))
    440   (message-goto-body))
    441 
    442 (defun clean-up-sputnik ()
    443   (forward-line 1)
    444   (let ((start (point)))
    445     (search-forward "Subscribe" nil t)
    446     (beginning-of-line)
    447     (forward-paragraph 2)
    448     (delete-region (point) start)
    449     ;; tail
    450     (goto-char (point-max))
    451     (search-backward "Sputnik International" nil t)
    452     (backward-paragraph 2)
    453     (delete-region (point) (point-max))
    454     )
    455   (message-goto-body))
    456 
    457 (defun email-eww ()
    458   (interactive)
    459   (let ((content (buffer-substring-no-properties (point-min) (point-max)))
    460         (title (or (plist-get eww-data :title)
    461                    (buffer-name (current-buffer))))
    462         (url (plist-get eww-data :url)))
    463     (compose-mail email-eww-to title `(("From" . ,email-eww-from)))
    464     (message-goto-body)
    465     (when url
    466       (insert url)
    467       (insert "\n\n"))
    468     (insert content)
    469     (message-goto-body)
    470     (delete-trailing-whitespace)
    471     (message-goto-body)
    472     (cond
    473      ((string-match "news.ycombinator.com" url)
    474       (clean-up-ycombinator))
    475      ((string-match "reddit.com" url)
    476       (clean-up-reddit))
    477      ((string-match "faz.net" url)
    478       (clean-up-faz))
    479      ((string-match "mmnews.de" url)
    480       (clean-up-mmnews))
    481      ((string-match "voanews.com" url)
    482       (clean-up-voanews))
    483      ((string-match "guardian.com" url)
    484       (clean-up-guardian))
    485      ((string-match "wikipedia.org" url)
    486       (clean-up-wikipedia))
    487      ((or (string-match "stackoverflow.com" url)
    488           (string-match "stackexchange.com" url))
    489       (clean-up-stackoverflow))
    490      ((string-match "schneier.com" url)
    491       (clean-up-schneier))
    492      ((string-match "counterpunch.org" url)
    493       (clean-up-counterpunch))
    494      ((string-match "wallstreetonparade.com" url)
    495       (clean-up-wallstreetonparade))
    496      ((string-match "cnn.com" url)
    497       (clean-up-cnn))
    498      ((string-match "commondreams.org" url)
    499       (clean-up-commondreams))
    500      ((string-match "wsws.org" url)
    501       (clean-up-wsws))
    502      ((string-match "zsposepneho.cz" url)
    503       (clean-up-zsposepneho))
    504      ((string-match "euractiv.com" url)
    505       (clean-up-euractiv))
    506      ((string-match "infomigrants.net" url)
    507       (clean-up-infomigrants))
    508      ((string-match "blog.fefe.de" url)
    509       (clean-up-fefe))
    510      ((string-match "discourse.nixos.org" url)
    511       (clean-up-nixos-discourse))
    512      ((string-match "aljazeera.com" url)
    513       (clean-up-aljazeera))
    514      ((string-match "neovlivni.cz" url)
    515       (clean-up-neovlivni))
    516      ((string-match "sputnikglobe.com" url)
    517       (clean-up-sputnik))
    518      )
    519     (goto-char (point-max))
    520     (delete-blank-lines)
    521     (message-goto-to)
    522     (current-buffer)))
    523 
    524 ;; (defun email-w3m (url)
    525 ;;   (when url
    526 ;;     (let ((b (get-buffer-create url)))
    527 ;;       (shell-command (concat "w3m -dump " (shell-quote-argument url)) b b)
    528 ;;       (with-current-buffer b
    529 ;;         (email-region (point-min) (point-max))
    530 ;;         (message-goto-body)
    531 ;;         (insert url)
    532 ;;         (insert "\n\n")
    533 ;;         (cond
    534 ;;          ((or
    535 ;;            (string-match "serverfault.com" url)
    536 ;;            (string-match "stackexchange.com" url)
    537 ;;            (string-match "stackoverflow.com" url)
    538 ;;            (string-match "superuser.com" url)
    539 ;;            )
    540 ;;           (search-forward "Ask Question" nil t)
    541 ;;           (beginning-of-line)
    542 ;;           (backward-paragraph 1)
    543 ;;           (beginning-of-line)
    544 ;;           (forward-line 3)
    545 ;;           (delete-region (point) start)
    546 ;;           (clean-up-stackoverflow)))
    547 ;;         (message-goto-to)))))
    548 ;;(email-w3m "https://superuser.com/questions/199286/organize-email-by-date-using-procmail")
    549 ;;(email-w3m "https://unix.stackexchange.com/questions/3092/organize-email-by-date-using-procmail-or-maildrop")
    550 ;;(email-w3m "https://stackoverflow.com/questions/5882840/procmail-move-to-folder-and-mark-as-read")
    551 ;;(email-w3m "https://serverfault.com/questions/403873/how-to-create-default-subfolders-using-procmail-with-maildir-and-postfix-that")
    552 ;;subject \n\n Ask Question\n ... Your Answer\n
    553 
    554 ;; TODO websend url|eww url + clean up + eww vs w3m|lynx|...
    555 ;; TODO pull feeds and websend direct to maildir (sorted by YYYY-MM?)
    556 ;; TODO url substitutions e.g. -> onion or old.reddit
    557 
    558 (provide 'email-eww)