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)