Skip to content

Instantly share code, notes, and snippets.

@michaelmrose
Created October 10, 2018 17:42
Show Gist options
  • Save michaelmrose/8d078ea1019b4cad891e1607e11986bc to your computer and use it in GitHub Desktop.
Save michaelmrose/8d078ea1019b4cad891e1607e11986bc to your computer and use it in GitHub Desktop.

A systemd user service to watch via imapnotify

[Unit]
Description=watch email via imapnotify

[Service]
ExecStart=/home/michael/scripts/watchemail.fish

Restart=on-failure
RestartSec=5min

[Install]
WantedBy=default.target

A script called by said service

#!/usr/bin/env fish
offlineimap -o
and imapnotify -c /home/michael/.config/imap_inotify/gmail.js

Config for imapnotify

exports.host = "imap.gmail.com";
exports.port = 993;
exports.tls = true;
exports.tlsOptions = { "rejectUnauthorized": false };
exports.username = "myemail";
exports.password = "notapassword";
exports.onNotify = "offlineimap -o";
exports.onNotifyPost = {"mail": "/home/michael/scripts/onreceiptofemail.fish"}
exports.boxes = [ "INBOX" ];

Config for offlineimap

[general]
accounts = OldGmail

[Account OldGmail]
localrepository = OldLocalGmail
remoterepository = OldRepositoryGmail
autorefresh = 1
quick = 10

[Repository OldLocalGmail]
type = Maildir
localfolders = ~/mail/OldGmail

[Repository OldRepositoryGmail]
type = Gmail
maxconnections = 3
remoteuser = myemail
remotepass = notapassword
folderfilter = lambda foldername: foldername not in ['[Gmail]/All Mail', '[Gmail]/Important']
sslcacertfile = /etc/ssl/certs/ca-certificates.crt

A script run on receipt of new email by imapnotify

This updates mus index and my blocklet on my workspace bar with a count of unread email

#!/usr/bin/env fish
emacsclient -a '' -e '(mu4e-update-mail-and-index t)' &
sleep 5
pkill -RTMIN+11 i3blocks &

A shell function showing the recent current unread count

# Defined in /home/michael/.config/fish/functions/unread-mail-count.fish @ line 2
function unread-mail-count
	mu find date:7D..now and flag:unread and not flag:trashed and not maildir:\[Gmail\].Spam 2> /dev/null | wc -l
end

I3blocks segment

[mail]
label= 
command=ff unread-mail-count
interval=60
signal=11
color=#E2FF77

My email related elisp configuration

;;; michael.el mu4e setup
;;; Commentary:
;;; Code:
(add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e")
(require 'mu4e)
(require 'smtpmail)
;; evil-mu4e defines evil friendly keys for mu4e in motion map by default
;; revise that lets say instead that its a buggy piece of crap
; (require 'evil-mu4e)
;;alerts in modeline or via desktop if you prefer
(use-package mu4e-conversation)
(use-package mu4e-alert
  :config)
;;more info in main mu4e dashboard
(use-package mu4e-maildirs-extension
  :config (mu4e-maildirs-extension))

(setq mu4e-maildir "~/mail"
      user-mail-address "myemail"
      user-full-name  "Michael Rose"
      ;; don't update automatically we will do this
      ;; automatically when we receive mail via imapnotify
      mu4e-update-interval nil
      ;; looks nicer if your font supports it
      mu4e-use-fancy-chars t
      mu4e-view-show-images t
      mu4e-view-show-addresses t
      message-send-mail-function 'smtpmail-send-it
      smtpmail-stream-type 'starttls
      ;; mu4e-html2text-command 'mu4e-shr2text
      ;; looks better with a dark theme
      shr-color-visible-luminance-min 80 shr-color-visible-distance-min 5
      smtpmail-default-smtp-server "smtp.gmail.com"
      smtpmail-smtp-server "smtp.gmail.com"
      smtpmail-smtp-service 587
      message-kill-buffer-on-exit nil
      mu4e-org-contacts-file "/home/michael/org/contacts.org"
      mu4e-compose-in-new-frame 'nil
      )

;; trashed mark doesn't work with source code pro
(setcdr (plist-get (cdr (assq 'delete mu4e-marks)) :char) "") 

(setq mu4e-bookmarks `(("maildir:/OldGmail/INBOX or maildir:/Gmail/INBOX" "Inbox" ?i)
                       ("maildir:/archive" "Archive" ?a)
                       ("flag:flagged" "Flagged messages" ?f)
                       ("date:today..now" "Today's messages" ?t)
                       ("flag:unread and date:7d..now" "Recent" ?r)
                       ("date:7d..now" "Last 7 days" ?7) 
                       ("flag:unread" "Unread" ?u )))
;; My spelling is terrile a little joke
(add-hook 'mu4e-compose-mode-hook 'turn-on-flyspell)
(add-hook 'mu4e-compose-mode-hook 'turn-on-auto-fill)
;; TODO: add description
(add-hook 'mu4e-mark-execute-pre-hook
          (lambda (mark msg)
            (cond ((member mark '(refile trash)) (mu4e-action-retag-message msg "-\\Inbox"))
                  ((equal mark 'flag) (mu4e-action-retag-message msg "\\Starred"))
                  ((equal mark 'unflag) (mu4e-action-retag-message msg "-\\Starred"))))) ;; don't keep message buffers around
(add-function :after message-send-mail-function 'kill-buffer-and-window)

;; better rendering of html email purportedly
(require 'mu4e-contrib)
(setq mu4e-html2text-command 'mu4e-shr2text)
(add-hook 'mu4e-view-mode-hook
          (lambda()
            ;; try to emulate some of the eww key-bindings
            (local-set-key (kbd "<tab>") 'shr-next-link)
            (local-set-key (kbd "<backtab>") 'shr-previous-link)))
(defun michael-mu4e-select-all-messages ()
  (interactive)
  (beginning-of-buffer)
  (call-interactively 'set-mark-command)
  (end-of-buffer)
  (previous-line)
  )

(defun my-mu4e-mark-execute-all-no-confirm ()
  "Execute all marks without confirmation."
  (interactive)
  (mu4e-mark-execute-all 'no-confirm)
  (shell-command "signal-i3blocks 11")
  ) 

;;mu4e-alert


(setq mu4e-alert-interesting-mail-query
      (concat
       "flag:unread"
       " AND NOT flag:trashed"
       " AND NOT maildir:"
       "\"/[Gmail].All Mail\""))
(mu4e-alert-set-default-style 'libnotify)
(add-hook 'after-init-hook #'mu4e-alert-enable-mode-line-display)

(defun my-mu4e-destroy-everything ()
  (interactive)
  (michael-mu4e-select-all-messages)
  (mu4e-headers-mark-for-delete)
  (mu4e-mark-execute-all)
  (shell-command "signal-i3blocks 11")
  )


;; bindings for mu4e
(defun michael-mu4e-bindings ()
  (interactive)
  (define-key mu4e-headers-mode-map (kbd "j") 'next-line)
  (define-key mu4e-headers-mode-map (kbd "k") 'previous-line)
  (define-key mu4e-headers-mode-map (kbd "g") 'beginning-of-buffer)
  (define-key mu4e-headers-mode-map (kbd "G") 'end-of-buffer)
  (define-key mu4e-headers-mode-map (kbd "J") 'mu4e~headers-jump-to-maildir)
  (define-key mu4e-headers-mode-map (kbd "V") 'set-mark-command)
  (define-key mu4e-headers-mode-map (kbd "x") 'my-mu4e-mark-execute-all-no-confirm)
  (define-key mu4e-headers-mode-map (kbd "X") 'my-mu4e-destroy-everything)
  (define-key mu4e-headers-mode-map (kbd "e") 'michael-mu4e-select-all-messages)
  (define-key mu4e-headers-mode-map (kbd "f") 'avy-goto-word-or-subword-1)
  (define-key mu4e-headers-mode-map (kbd "/") 'evil-search-forward)
  (define-key mu4e-headers-mode-map (kbd "n") 'evil-search-next)
  (define-key mu4e-headers-mode-map (kbd "z") 'mu4e-headers-rerun-search)
  (define-key mu4e-headers-mode-map (kbd "l") 'michael-mu4e-find-similar)


  (define-key mu4e-main-mode-map (kbd "j") 'next-line)
  (define-key mu4e-main-mode-map (kbd "k") 'previous-line)
  (define-key mu4e-main-mode-map (kbd "J") 'mu4e~headers-jump-to-maildir)
  (define-key mu4e-main-mode-map (kbd "f") 'avy-goto-word-or-subword-1)
  (define-key mu4e-main-mode-map (kbd "/") 'evil-search-forward)
  (define-key mu4e-main-mode-map (kbd "n") 'evil-search-next)

  (define-key mu4e-view-mode-map (kbd "j") 'next-line)
  (define-key mu4e-view-mode-map (kbd "k") 'previous-line)
  (define-key mu4e-view-mode-map (kbd "J") 'mu4e~headers-jump-to-maildir)
  (define-key mu4e-view-mode-map (kbd "f") 'avy-goto-word-or-subword-1)
  (define-key mu4e-view-mode-map (kbd "/") 'evil-search-forward)
  (define-key mu4e-view-mode-map (kbd "n") 'evil-search-next)
  (define-key mu4e-view-mode-map (kbd "l") 'michael-mu4e-find-similar)
  )

(defun michael-mu4e-find-similar ()
  "Search maildir for messages from either the same sender or with a subject containing the same words from any sender."
  (interactive)
  (mu4e-headers-search (concat "from:"(car(car(mu4e-message-field (mu4e-message-at-point) :from)))
                               " or subject:"
                               (mu4e-message-field (mu4e-message-at-point) :subject)
                               ))
  )

(add-hook 'mu4e-main-mode-hook 'michael-mu4e-bindings)
(add-hook 'mu4e-headers-mode-hook 'michael-mu4e-bindings)
(add-hook 'mu4e-view-mode-hook 'michael-mu4e-bindings)
(evil-set-initial-state 'mu4e-main-mode 'emacs)
(evil-set-initial-state 'mu4e-headers-mode 'emacs)
(evil-set-initial-state 'mu4e-compose-mode 'emacs)
(evil-set-initial-state 'mu4e-view-mode 'emacs)

(require 'mu4e-actions)
(add-to-list 'mu4e-headers-actions
  '("org-contact-add" . mu4e-action-add-org-contact) t)
(add-to-list 'mu4e-view-actions
             '("org-contact-add" . mu4e-action-add-org-contact) t)
;;xwidgets swiped for somewhere
(defun my-mu4e-action-view-with-xwidget (msg)
  "View the body of the message inside xwidget-webkit."
  (kill-matching-buffers-without-prompt "^\*xwidget")
  (unless (fboundp 'xwidget-webkit-browse-url)
    (mu4e-error "No xwidget support available"))
  (let* ((html (mu4e-message-field msg :body-html))
         (txt (mu4e-message-field msg :body-txt))
         (tmpfile (format "%s%x.html" temporary-file-directory (random t))))
    (unless (or html txt)
      (mu4e-error "No body part for this message"))
    (with-temp-buffer
      ;; simplistic -- but note that it's only an example...
      (insert (or html (concat "<pre>" txt "</pre>")))
      (write-file tmpfile)
      (xwidget-webkit-browse-url (concat "file://" tmpfile) t))))

(add-to-list 'mu4e-view-actions
             '("xViewXWidget" . my-mu4e-action-view-with-xwidget) t)

;;pixel scrolling
(pixel-scroll-mode t)
(setq pixel-resolution-fine-flag t)
(setq mouse-wheel-scroll-amount '(1))
(setq fast-but-imprecise-scrolling t)
(setq jit-lock-defer-time 0)
(setq mouse-wheel-progressive-speed nil)

(provide 'myemail)
;;; myemail.el ends here
@isimluk
Copy link

isimluk commented Dec 29, 2018

Inspiring! Thank You!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment