userapps:emacs:mu4e
差分
このページの2つのバージョン間の差分を表示します。
| 両方とも前のリビジョン前のリビジョン | |||
| userapps:emacs:mu4e [2024/08/27 02:16] – [mu4e] seirios | userapps:emacs:mu4e [2026/01/06 04:05] (現在) – [mu4e] seirios | ||
|---|---|---|---|
| 行 317: | 行 317: | ||
| * 送信サーバーは、メールのFromフィールドを見て自動で決定するようにした | * 送信サーバーは、メールのFromフィールドを見て自動で決定するようにした | ||
| - | まぁ、色々なところから色々設定持ってきたり、Perplexityのお世話になったりしてます。 | + | まぁ、色々なところから色々設定持ってきたり、PerplexityやMS copilotのお世話になったりしてます。 |
| 難しいcodeは書いてないから、コメント見ながら読めばわかると思いたい。 | 難しいcodeは書いてないから、コメント見ながら読めばわかると思いたい。 | ||
| というかわかるということにします。 | というかわかるということにします。 | ||
| - | |||
| - | あと、これだけでかいと leaf に書き換えるのは面倒くさい... | ||
| <code - mu4e-init.el> | <code - mu4e-init.el> | ||
| - | ;;;; .emacs.d/ | + | ;;; -*- lexical-binding: |
| - | ;;;; mu4e configuration | + | ;;; ~/.config/emacs/ |
| - | ;;;; | + | ;;; |
| - | ;;;; last updated: | + | ;;; last updated: |
| - | ;;;; Author: HEO SeonMeyong < | + | ;;; Author: HEO SeonMeyong < |
| + | ;;; | ||
| - | ;;; Require packages upfront | + | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| - | (add-to-list ' | + | ;;; Tips |
| - | (require ' | + | ;;; * Create new refile folder |
| - | ;; (require 'mu4e-speedbar) ; Speedbar | + | ;;; $ mkdir -p ~/Maildir/[Mailbox]/some/where/{new, |
| - | (require ' | + | ;;; $ chmod -R 700 ~/Maildir/[Mailbox]/some/ |
| + | ;;; $ mbsync | ||
| + | ;;; $ mu index | ||
| + | ;;; * 要するに、正しいpermissionで正しくFolder(Directory)を作成してmbsyncで同期してindexを張ればOK | ||
| + | ;;; * 逆に削除はDirectoryごと全部削除すればよさそう | ||
| - | ;;; Debugging | + | ;;; Informations(Links) |
| - | ;; (setq mu4e-mu-debug t) ; for mu debbuging | + | ;;; * https:// |
| - | ;; (setq mu4e-debug t) ; for mu4e debugging | + | |
| - | ;;; for mu4e general settings | + | ;;; 定義・機能一覧: |
| - | ;; external Binaries. | + | ;;; - my/which: Homebrew と環境 PATH の両方で実行ファイルを探索するヘルパー |
| - | (setq mu4e-get-mail-command (concat (executable-find "mbsync") " | + | ;;; - my-mu4e-update-mail-and-index-async: |
| - | (setq mu4e-mu-binary (executable-find " | + | ;;; |
| - | (setq sendmail-program (executable-find " | + | ;;; - my/ |
| + | ;;; - キーバインド: | ||
| + | ;;; - ポリシー: | ||
| + | ;;; | ||
| + | ;;; よく調整するパラメータ | ||
| + | ;;; * 定期更新間隔分: | ||
| + | ;;; * mbsync/mu/msmtp のパス探索候補: | ||
| + | ;;; * mu4e-context-policy / mu4e-compose-context-policy: | ||
| + | ;;; ' | ||
| + | ;;; * mu4e-headers-results-limit: | ||
| + | ;;; * display-buffer-alist: | ||
| + | ;;; ---------------------------------------------------------------------- | ||
| - | ;; Directories. | + | ;;; 小さなユーティリティ(実行ファイル探索と簡易コンテキスト生成) |
| - | (setq mu4e-maildir "~/Maildir" | + | (defun my/which (&rest candidates) |
| - | (setq mu4e-attachment-dir " | + | " |
| + | 候補は、絶対パス文字列とコマンド名の混在でよい。 | ||
| + | - 絶対パスが渡された場合: | ||
| + | - コマンド名が渡された場合: | ||
| - | ;; Manipulate mails | + | 例: |
| - | (setq mu4e-change-filenames-when-moving t) ; rename files when moving - needed for mbsync | + | (my/which \"/ |
| - | (setq mu4e-update-interval | + | (seq-some (lambda (c) |
| + | (cond | ||
| + | | ||
| + | (t (executable-find c)))) | ||
| + | candidates)) | ||
| - | ;; overall behavivior | + | (defun my/mk-context (name maildir-prefix email & |
| - | (setq mu4e-confirm-quit nil) ; don't have to confirm when quitting | + | " |
| - | (setq mu4e-modeline-show-global t) ; mu4e shares information on the modeline | + | NAME は識別名、MAILDIR-PREFIX は \"/XXXX\" |
| - | (add-hook ' | + | SIGNATURE を与えると `message-signature` を設定する。 |
| - | (lambda (query) | + | |
| - | (setq-local global-mode-string | + | |
| - | ' | + | |
| - | (concat | + | |
| - | (mu4e-context-label) | + | |
| - | " " | + | |
| - | | + | |
| - | (mu4e~quote-for-modeline mu4e~headers-last-query) | + | |
| - | 'face ' | + | |
| - | ' | + | |
| - | (setq mu4e-modeline-max-width 100) ; Change mu4e modeline to 100 chars | + | |
| - | (setq mode-name "mu4e-headers" | + | |
| - | (add-hook ' | + | |
| - | | + | |
| - | (setq mode-name | + | |
| - | (setq mu4e-split-view "vertical") ; Split-View. Using with display-buffer-alist | + | |
| - | (add-to-list ' | + | |
| - | `(, | + | |
| - | | + | |
| - | (side . right) | + | |
| - | | + | |
| - | (setq mu4e-hide-index-messages t) ; hide annoying "mu4e Retrieving mail..." | + | |
| - | (setq mu4e-context-policy ' | + | |
| - | ;; headers-view | + | 例: |
| - | (setq mu4e-headers-include-related nil) ; by default do not show related emails | + | (my/mk-context \" |
| - | (setq mu4e-headers-results-limit 5000) ; Limit of message view search results. default is 500 | + | (make-mu4e-context |
| - | (setq mu4e-headers-show-threads t) ; by default do not show threads | + | :name name |
| - | (setq mu4e-headers-date-format "%Y-%m-%dT%H: | + | : |
| - | (setq mu4e-headers-fields ; | + | :leave-func (lambda () (mu4e-message (format "Leave %s context" |
| - | ' | + | : |
| - | | + | (when msg |
| - | | + | |
| - | (:to | + | (mu4e-message-field |
| - | | + | |
| + | `((user-mail-address | ||
| + | (user-full-name | ||
| + | (mu4e-drafts-folder | ||
| + | | ||
| + | (mu4e-trash-folder | ||
| + | (when signature | ||
| + | `((message-signature . , | ||
| - | ;; Body-view | ||
| - | ;; prefer text messages. | ||
| - | (with-eval-after-load " | ||
| - | (add-to-list ' | ||
| - | (add-to-list ' | ||
| - | (setq mu4e-view-date-format " | ||
| - | (setq mu4e-view-fields ' | ||
| - | : | ||
| - | : | ||
| - | : | ||
| - | : | ||
| - | : | ||
| - | : | ||
| - | : | ||
| - | : | ||
| - | : | ||
| - | : | ||
| - | : | ||
| - | : | ||
| - | : | ||
| - | : | ||
| - | )) | ||
| - | ;; Draft and Compose | + | ;;;; mu4e のロードパスを動的に追加(Intel / Apple Silicon 両対応) |
| - | (setq mu4e-compose-context-policy | + | (dolist (cand '("/ |
| - | (setq mu4e-compose-signature-auto-include nil) ; Signature auto include | + | "/ |
| - | (defvaralias 'mu4e-compose-signature ' | + | (when (file-directory-p cand) |
| - | (setq message-citation-line-format "%N @ %Y-%m-%d %H:%M:%S : | + | (add-to-list 'load-path cand))) |
| - | (setq message-citation-line-function | + | |
| - | ; M-x find-function RET message-citation-line-format for docs | + | |
| - | ;; Sending mails | + | ;;;; 起動時の自動更新を制御するトグル |
| - | (setq mail-user-agent 'mu4e-user-agent) ; Use mu4e for e-mail in emacs | + | ;; Toggle for legacy |
| - | (setq send-mail-function ' | + | ;; - When t: mu4e の定期更新 |
| - | | + | ;; |
| - | (setq message-kill-buffer-on-exit t) ; don't keep message compose buffers around after sending: | + | (defvar my/mu4e-auto-update |
| - | (setq message-sendmail-envelope-from ' | + | " |
| - | ;; Additional supports | + | (leaf mu4e |
| - | (setq mu4e-eldoc-support | + | :load-path "/ |
| - | (add-hook 'mu4e-compose-mode-hook 'company-mode) ; mu4e address completion | + | : |
| - | (add-hook ' | + | :preface |
| + | | ||
| + | ;; これにより本文表示は極力 text/plain を優先する。 | ||
| + | | ||
| + | (add-to-list 'mm-discouraged-alternatives " | ||
| + | (add-to-list 'mm-discouraged-alternatives | ||
| - | ;;; Personal environment/Variables | + | :custom |
| - | ;;; Contexts | + | |
| - | (setq mu4e-contexts | + | ;; インデックス更新は常にバックグラウンドで(UIフリーズを避ける) |
| - | | + | ((mu4e-index-update-in-background . t) ; Run mu index update asynchronously to avoid UI blocking |
| - | ;; sample@example.com | + | |
| - | | + | |
| - | :name "sample_example" | + | |
| - | :match-func (lambda (msg) | + | ;; mbsync でメール移動時、ファイル名を変更(重複衝突などを回避) |
| - | (when msg | + | (mu4e-change-filenames-when-moving . t) |
| - | (string-prefix-p "/sample_example" (mu4e-message-field msg :maildir)))) | + | ;; 終了確認やモードライン表示 |
| - | :vars '((user-mail-address | + | (mu4e-confirm-quit . nil) |
| - | (user-full-name . " | + | |
| - | (mu4e-drafts-folder | + | |
| - | (mu4e-sent-folder | + | ;; 表示:本文ビューを右側へ固定(display-buffer-alist 併用) |
| - | (mu4e-trash-folder | + | (mu4e-split-view . "vertical") |
| - | )) | + | ;; ミニバッファに出る「Retrieving…」などの雑音を極力隠す |
| - | ;; sample@icloud.com | + | (mu4e-hide-index-messages |
| - | | + | |
| - | :name " | + | |
| - | : | + | ;; ヘッダ表示系(関連メッセージ非表示、結果上限、スレッド表示等) |
| - | (when msg | + | (mu4e-headers-include-related . nil) |
| - | (string-prefix-p "/ | + | (mu4e-headers-results-limit . 5000) |
| - | | + | |
| - | (user-full-name . " | + | |
| - | (mu4e-drafts-folder | + | (mu4e-headers-fields |
| - | (mu4e-sent-folder | + | . '((:date . 20) (:flags . 6) (:from . 16) (:to . 16) (:subject . nil))) |
| - | (mu4e-trash-folder | + | ;; 本文ビューのフィールド |
| - | )) | + | (mu4e-view-date-format |
| - | | + | |
| - | | + | . ' |
| - | :name "sample_gmail" | + | :tags : |
| - | | + | :path :user-agent)) |
| - | | + | ;; Compose 時のコンテキスト選択ポリシー(マッチしなければ確認) |
| - | | + | (mu4e-compose-context-policy |
| - | (when msg | + | ;; 署名の自動挿入は無効(コンテキストで signature を持つもののみ) |
| - | (string-prefix-p | + | (mu4e-compose-signature-auto-include |
| - | | + | ;; 送信系(mu4e を使い、sendmail 経由で送る) |
| - | (user-full-name | + | (mail-user-agent . 'mu4e-user-agent) |
| - | (mu4e-drafts-folder | + | |
| - | (mu4e-sent-folder | + | |
| - | (mu4e-trash-folder | + | (message-kill-buffer-on-exit . t) |
| - | )) | + | |
| - | | + | |
| + | | ||
| + | . '((:name "Unread messages" | ||
| + | (:name " | ||
| + | | ||
| + | (:name " | ||
| + | | ||
| + | (:name " | ||
| + | (:name " | ||
| + | (:name "seirios.RRnet" | ||
| + | | ||
| + | (:name "seirios.wm.gmail" :query " | ||
| + | (:name " | ||
| + | (:name " | ||
| + | : | ||
| + | : | ||
| + | (:name " | ||
| + | : | ||
| + | : | ||
| + | ;; Maildir ショートカット(ジャンプキー) | ||
| + | (mu4e-maildir-shortcuts | ||
| + | | ||
| + | (: | ||
| + | (: | ||
| + | | ||
| + | (:maildir "/ | ||
| + | | ||
| + | (:maildir "/ | ||
| - | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | + | |
| - | ;;; Bookmarks | + | (:maildir |
| - | (setq mu4e-bookmarks | + | (:maildir |
| - | (setq mu4e-bookmarks | + | (:maildir |
| - | '( | + | (:maildir |
| - | ( :name "Unread messages" | + | |
| - | :query " | + | |
| - | :favorite t | + | |
| - | | + | |
| - | ( :name | + | |
| - | | + | |
| - | :favorite t | + | |
| - | | + | |
| - | ( :name "Inbox - sample.icloud" | + | |
| - | :query " | + | |
| - | :favorite t | + | |
| - | :key ?2) | + | |
| - | ( :name "Inbox - sample.yahoo" | + | |
| - | :query " | + | |
| - | :favorite t | + | |
| - | | + | |
| - | ( :name "Inbox - sample.gmail" | + | |
| - | :query " | + | |
| - | :favorite t | + | |
| - | :key ?4) | + | |
| - | ( :name "SPAM/UCE" | + | |
| - | :query " | + | |
| - | :favorite t | + | |
| - | | + | |
| - | ( :name "Trash" | + | |
| - | :query " | + | |
| - | :favorite t | + | |
| - | :key ?t) | + | |
| - | ( :name "Today' | + | |
| - | :query " | + | |
| - | :favorite t | + | |
| - | | + | |
| - | )) | + | |
| - | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | + | |
| - | ;;; Maildir Shortcuts | + | (:maildir "/seirios_seirios/Individual/ |
| - | (setq mu4e-maildir-shortcuts ;; | + | (:maildir "/seirios_seirios/ |
| - | '( | + | (:maildir "/ |
| - | (:maildir "/sample_icloud/Finamce" | + | (:maildir "/seirios_seirios/ |
| - | (:maildir "/sample_icloud/ | + | (:maildir "/seirios_seirios/Activity/ |
| - | (:maildir "/sample_gmail/MyDiv" | + | (:maildir "/seirios_seirios/Activity/ |
| - | (:maildir "/sample_gmail/Logs" | + | (:maildir "/seirios_seirios/Activity/ |
| - | (:maildir "/sample_yahoo/Agent" | + | ;; 以下は「一覧に見せるため」の要素。: |
| - | (:maildir "/sample_example/Family" | + | (:maildir "/ |
| - | )) | + | (:maildir "/ |
| + | (:maildir "/ | ||
| + | (:maildir "/ | ||
| + | (:maildir "/ | ||
| + | (:maildir "/ | ||
| + | (:maildir "/ | ||
| + | (:maildir "/ | ||
| + | (:maildir "/ | ||
| + | (:maildir "/ | ||
| + | (:maildir "/ | ||
| + | (:maildir "/ | ||
| + | (:maildir "/ | ||
| + | (:maildir "/ | ||
| + | (:maildir "/ | ||
| + | (:maildir "/ | ||
| + | (:maildir "/ | ||
| + | (:maildir "/ | ||
| - | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | + | :config |
| - | ;;; Refile rules | + | ;; ---- 実行ファイルの場所を自動検出(Homebrew/ |
| - | (makunbound 'my-mu4e-refile-rules) | + | ;; mu/msmtp の実行パスは GUI 起動時(PATHが引き継がれないケース)でも見つかるよう、 |
| - | (defvar my-mu4e-refile-rules | + | ;; 絶対パス候補 → PATH の順に探索します。 |
| - | | + | (setq mu4e-mu-binary |
| - | | + | (setq sendmail-program (my/which "/usr/local/bin/msmtp" |
| - | ("/sample_icloud/ | + | |
| - | | + | |
| - | ("/ | + | |
| - | ("/ | + | |
| - | | + | |
| - | ("/ | + | |
| - | ("/sample_icloud/ | + | |
| - | ;; === MyDiv | + | |
| - | ("/sample_gmail/MyDiv" | + | |
| - | ;; === Log | + | |
| - | ("/sample_gmail/Logs" " | + | |
| - | ("/sample_gmail/Logs" | + | |
| - | ("/sample_gmail/Logs" "from" | + | |
| - | ("/sample_gmail/ | + | |
| - | ("/sample_gmail/Logs" | + | |
| - | ;; === Agent | + | |
| - | ("/sample_yahoo/Agent" " | + | |
| - | ;; === Family | + | |
| - | ("/sample_example/Family" | + | |
| - | ("/sample_example/Family" "from" | + | |
| - | ) | + | |
| - | "List of (refile-folder field regex) triples for refiling. | + | |
| - | Field can be ' | + | |
| - | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | + | |
| - | ;;; Personal functions | + | (with-eval-after-load ' |
| - | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | + | |
| - | ;;; Select SMTP account from from header at composed email | + | (let ((mbsync (my/which "/ |
| - | (defun my-mu4e-set-msmtp-account () ; chose from account before sending | + | (setq mu4e-get-mail-command (and mbsync (concat mbsync " -a" |
| - | (if (message-mail-p) | + | |
| + | | ||
| + | (if my/ | ||
| + | (progn | ||
| + | | ||
| + | (setq mu4e-update-interval (* 10 60)) | ||
| + | | ||
| + | ) | ||
| + | | ||
| + | (setq mu4e-update-interval nil) | ||
| + | (remove-hook ' | ||
| + | | ||
| + | ) | ||
| + | |||
| + | | ||
| + | (add-to-list ' | ||
| + | | ||
| + | | ||
| + | (side . right) (window-width . 0.5))) | ||
| + | |||
| + | | ||
| + | (setq mode-name " | ||
| + | (add-hook ' | ||
| + | |||
| + | | ||
| + | | ||
| + | (setq mu4e-contexts | ||
| + | (list | ||
| + | | ||
| + | (concat " | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | (defvar my-mu4e-refile-rules | ||
| + | ' | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | ("/ | ||
| + | (defun my-mu4e-refile-message (msg) | ||
| + | " | ||
| + | - 'any は to/ | ||
| + | - 'rcpt は to/cc/bcc の受信側集合で判定" | ||
| + | (cl-loop for (folder field regex) in my-mu4e-refile-rules | ||
| + | for addresses = (pcase field | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | when (seq-some (lambda (addr) | ||
| + | (and addr (string-match-p regex | ||
| + | (downcase (if (listp addr) | ||
| + | (or (plist-get addr :email) "" | ||
| + | addr))))) | ||
| + | addresses) | ||
| + | | ||
| + | | ||
| + | |||
| + | | ||
| + | (setq mu4e-refile-folder | ||
| + | (lambda (msg) | ||
| + | (or (my-mu4e-refile-message msg) | ||
| + | (mu4e-message-field msg : | ||
| + | |||
| + | | ||
| + | | ||
| + | (let ((target (funcall mu4e-refile-folder msg))) | ||
| + | (when (and target | ||
| + | (not (string= target (mu4e-message-field msg : | ||
| + | (mu4e-mark-set ' | ||
| + | (defun my-mu4e-auto-refile () | ||
| + | " | ||
| + | (interactive) | ||
| + | (let* ((current (mu4e-message-field (mu4e-message-at-point) : | ||
| + | | ||
| + | (mu4e-headers-search query) | ||
| + | (add-hook ' | ||
| + | (defun my-mu4e-auto-refile-hook () | ||
| + | (remove-hook ' | ||
| + | (goto-char (point-min)) | ||
| + | (while (not (eobp)) | ||
| + | (let ((msg (mu4e-message-at-point))) | ||
| + | (my-mu4e-auto-refile-process msg)) | ||
| + | (forward-line)) | ||
| + | | ||
| + | (mu4e-headers-next nil)) | ||
| + | (keymap-set mu4e-headers-mode-map " | ||
| + | |||
| + | ;; ---- 送信補助(msmtp選択/ | ||
| + | ;; Fromヘッダと msmtp アカウントの対応表(追加・変更はここへ) | ||
| + | (defvar my/ | ||
| + | ' | ||
| + | (" | ||
| + | (" | ||
| + | (" | ||
| + | (" | ||
| + | (" | ||
| + | (" | ||
| + | (" | ||
| + | (" | ||
| + | (" | ||
| + | (defun my-mu4e-set-msmtp-account () | ||
| + | " | ||
| + | - ヘッダから送信者アドレスを取り出し、`my/ | ||
| + | - 一致がない場合は何もしない(ユーザ手動選択に委ねる)" | ||
| + | | ||
| + | (save-excursion | ||
| + | (let* ((from (save-restriction | ||
| + | | ||
| + | (or (message-fetch-field " | ||
| + | (acct (seq-some (lambda (pair) | ||
| + | (and (string-match (regexp-quote (car pair)) from) | ||
| + | (cdr pair))) | ||
| + | | ||
| + | (when acct | ||
| + | (message "Using msmtp account: %s" acct) | ||
| + | (setq message-sendmail-extra-arguments (list " | ||
| + | (add-hook ' | ||
| + | |||
| + | (defun my-add-cc-and-bcc () | ||
| + | " | ||
| + | - Cc 行が存在しない場合は新規に付与 | ||
| + | - 既に自アドレスが含まれていれば何もしない" | ||
| (save-excursion | (save-excursion | ||
| - | (let* | + | (goto-char (point-min)) |
| - | ((from (save-restriction | + | (if (re-search-forward " |
| - | | + | (unless (re-search-forward (concat (regexp-quote user-mail-address)) |
| - | | + | |
| - | | + | (end-of-line) |
| - | (cond | + | (insert |
| - | ((string-match "sample@example.com" | + | user-mail-address |
| - | ((string-match " | + | (concat |
| - | ((string-match " | + | (message-add-header |
| - | ((string-match "sample@gmail.com" | + | |
| - | ))) | + | (add-hook 'mu4e-compose-mode-hook #'my-add-cc-and-bcc) |
| - | (setq message-sendmail-extra-arguments | + | |
| - | ))) | + | |
| - | (add-hook 'message-send-mail-hook 'my-mu4e-set-msmtp-account) | + | |
| - | ;;; Add Cc and Bcc field when compose Email. | + | |
| - | (add-hook ' | + | "件名が空なら送信前に確認ダイアログを出す。 |
| - | | + | 誤送信防止のための軽量ガード。" |
| - | "My Function to automatically add Cc & Bcc: headers. | + | (let ((sub (message-field-value "Subject"))) |
| - | This is in the mu4e compose mode." | + | (or (and sub (not (string-match "\\`[ \t]*\\' |
| - | (save-excursion | + | (yes-or-no-p "Really send without Subject? |
| - | | + | (keyboard-quit)))) |
| - | (save-excursion (message-add-header | + | (add-hook ' |
| - | ;;; Require confirmation before sending mail without subject. | + | |
| - | (defun | + | (defun |
| - | "Require confirmation before sending without subject." | + | "ヘッダバッファ末尾のメッセージID(: |
| - | (let ((sub (message-field-value " | + | (when (mu4e-current-buffer-type-p ' |
| - | (or (and sub (not (string-match "\\`[ \t]*\\'" | + | (save-excursion |
| - | (yes-or-no-p " | + | |
| - | (keyboard-quit)))) | + | (forward-line -1) |
| + | (plist-get (mu4e-message-at-point) :message-id)))) | ||
| - | (add-hook 'message-send-hook #'confirm-empty-subject) | + | |
| + | " | ||
| + | この呼び出し中のみ `mu4e-search-full` を t にして上限を外す。" | ||
| + | (interactive) | ||
| + | (when (mu4e-current-buffer-type-p | ||
| + | (let* ((mu4e-search-full t) ;; ★ この関数の間だけ全件モード | ||
| + | | ||
| + | (mu4e-search-sort-direction ' | ||
| + | ;; 念のため「ほぼ無限」上限もローカルに設定(古いmu4eへの互換) | ||
| + | | ||
| + | | ||
| + | (when-let ((query (mu4e-last-query))) | ||
| + | (message " | ||
| + | ;; append=t で結果を追記。last-msg をアンカーに、それより古い側を取得。 | ||
| + | (mu4e-search query nil nil t last-msg) | ||
| + | ;; 視認性のため末尾へ移動 | ||
| + | (goto-char (point-max)) | ||
| + | (forward-line -1) | ||
| + | ;; スレッド折りたたみを使っている場合は全畳みで見通しを確保 | ||
| + | (when (bound-and-true-p mu4e-thread-folding-mode) | ||
| + | (mu4e-headers-fold-all)) | ||
| + | (message " | ||
| - | ;;; Header viewでmail Search時にMaxmumを拡張して全部を検索する | + | |
| - | (defvar my-mu4e-page 1 " | + | (keymap-set mu4e-headers-mode-map "N" |
| - | (defun my-mu4e-reset-page (&rest _r) | + | |
| - | | + | |
| - | (setq my-mu4e-page 1)) | + | |
| - | ;; Need to reset the "standard searches" | + | |
| - | (add-hook 'mu4e-search-bookmark-hook #'my-mu4e-reset-page) | + | ;; Parameters: |
| - | (advice-add 'mu4e-search-maildir :before #'my-mu4e-reset-page) | + | ;; - mbsync path resolution: my/which tries / |
| + | ;; - Timer interval: call (my/ | ||
| + | ;; - Log buffer: | ||
| + | ;; Behavior: | ||
| + | ;; | ||
| + | ;; | ||
| + | ;; | ||
| + | (setq mu4e-index-update-in-background t) | ||
| - | (defun my-mu4e-next-messages-for-query () | + | |
| - | "Fetch the next number of messages for current | + | "Run mbsync asynchronously and, upon success, trigger |
| - | Move to last message in current view so that newly fetched | + | ENV/PATH NOTES: |
| - | messages are visible." | + | - GUI起動のEmacsでは Homebrew の PATH が見えないことがある。必要なら exec-path-from-shell を併用。 |
| - | (interactive) | + | LOGGING: |
| - | (when (and (mu4e-current-buffer-type-p ' | + | - mbsync の標準出力/ |
| - | (not mu4e-search-full)) | + | ERROR HANDLING: |
| - | (when-let ((query (mu4e-last-query))) | + | |
| - | (cl-incf my-mu4e-page) | + | |
| - | (let ((mu4e-search-results-limit | + | (let* ((mbsync (my/which "/ |
| - | | + | (args ' |
| - | (last-msg (save-excursion | + | (unless mbsync |
| - | (goto-char | + | (user-error " |
| - | (forward-line -1) | + | (let ((buf (get-buffer-create " *mu4e-mbsync*" |
| - | (plist-get | + | (with-current-buffer buf (erase-buffer)) |
| - | | + | (message "[mu4e] start mbsync |
| - | :message-id)))) | + | (let ((proc (apply #' |
| - | (mu4e-search query nil nil t last-msg))))) | + | (set-process-query-on-exit-flag proc nil) |
| + | (set-process-sentinel | ||
| + | proc | ||
| + | (lambda | ||
| + | (when (eq (process-status p) 'exit) | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | (progn | ||
| + | (message | ||
| + | code (buffer-name (process-buffer p))) | ||
| + | | ||
| - | (keymap-set mu4e-headers-mode-map "N" #' | + | ;; Uキーを非同期版に差し替え(メイン/ |
| + | | ||
| + | #' | ||
| + | (define-key | ||
| + | | ||
| - | ;;; Refile | + | |
| - | (makunbound 'my-mu4e-refile-message) | + | (let ((mbsync |
| - | (defun my-mu4e-refile-message | + | (setq mu4e-get-mail-command |
| - | " | + | |
| - | | + | |
| - | for addresses = (cond | + | |
| - | ((string= field "any") | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | ((string= field "rcpt") (append (mu4e-message-field msg :to) | + | |
| - | | + | |
| - | | + | |
| - | ((string= field "subj") (list (mu4e-message-field msg :subject))) | + | |
| - | | + | |
| - | ((string= field " | + | |
| - | (t (mu4e-message-field msg (intern | + | |
| - | when (seq-some (lambda (addr) | + | |
| - | (when addr | + | |
| - | (string-match-p regex | + | |
| - | (downcase | + | |
| - | (if (listp addr) | + | |
| - | (or (plist-get addr :email) "") | + | |
| - | addr))))) | + | |
| - | addresses) | + | |
| - | | + | |
| - | | + | |
| - | ;; mu4e-refile-message関数を利用してrefileする | + | |
| - | (setq mu4e-refile-folder "" | + | (defvar |
| - | (setq mu4e-refile-folder | + | " |
| - | | + | |
| - | (or (my-mu4e-refile-message msg) | + | |
| - | | + | |
| - | (makunbound ' | + | |
| - | (defun my-mu4e-auto-refile-process | + | "MINUTES 分間隔で非同期取得+インデックス更新を開始する。 |
| - | "Process a single message for auto-refiling." | + | |
| - | (let ((target-folder (funcall mu4e-refile-folder msg))) | + | |
| - | (when (and target-folder | + | |
| - | (not (string= target-folder (mu4e-message-field msg : | + | |
| - | (mu4e-mark-set ' | + | |
| - | (makunbound 'my-mu4e-auto-refile) | + | Parameters: |
| - | (defun | + | MINUTES |
| - | " | + | Behavior: |
| - | | + | |
| - | | + | |
| - | | + | - 非同期関数 |
| - | "AND (flag:new OR flag: | + | Tuning: |
| - | "AND NOT flag: | + | - 初回遅延 10 秒は必要に応じて変更可能(run-at-time の第一引数)。" |
| - | (mu4e-headers-search query) | + | |
| - | (add-hook 'mu4e-headers-found-hook | + | (cancel-timer my/ |
| + | (setq my/mu4e-background-timer | ||
| + | (run-at-time 30 (* minutes 60) #' | ||
| + | (message " | ||
| - | (makunbound ' | + | |
| - | (defun my-mu4e-auto-refile-hook () | + | "バックグラウンド更新タイマーを停止する。 |
| - | "Hook to process messages after headers search." | + | 従量制ネットワークや一時的に負荷を避けたい場合に使用。" |
| - | (remove-hook ' | + | (interactive) |
| - | (goto-char (point-min)) | + | (when my/mu4e-background-timer |
| - | (while (not (eobp)) | + | (cancel-timer my/mu4e-background-timer) |
| - | (let ((msg (mu4e-message-at-point))) | + | (setq my/mu4e-background-timer nil) |
| - | (my-mu4e-auto-refile-process msg)) | + | (message " |
| - | (forward-line)) | + | |
| - | (mu4e-headers-next nil)) ; Move to the next unread message after marking | + | |
| - | (makunbound ' | + | ;; 既定では 10 分間隔で開始(好みに合わせて値を変更) |
| - | (defun my-mu4e-headers-auto-refile () | + | (my/mu4e-start-background-update 30))) |
| - | "Run auto-refile marking in headers view." | + | |
| - | (interactive) | + | |
| - | (my-mu4e-auto-refile)) | + | |
| - | (keymap-set mu4e-headers-mode-map "e" #'my-mu4e-headers-auto-refile) ; Refile | + | ;;; 追加: スレッド折りたたみ(見通しを良くするUI拡張) |
| + | (leaf mu4e-thread-folding | ||
| + | :vc (:url " | ||
| + | :require t | ||
| + | :config | ||
| + | (define-key | ||
| + | (define-key | ||
| + | (define-key mu4e-headers-mode-map (kbd "< | ||
| + | (define-key mu4e-headers-mode-map (kbd "< | ||
| + | (define-key mu4e-headers-mode-map (kbd "< | ||
| + | (define-key mu4e-headers-mode-map (kbd "< | ||
| + | (add-hook ' | ||
| - | ;; Local Variables: | + | ;;; 必要なら明示ロード(smtpmail は組み込みだが、leaf で明示しておくと見通しが良い) |
| - | ;; coding: utf-8 | + | (leaf smtpmail |
| - | ;; comment-column: | + | |
| - | ;; version-control: t | + | |
| - | ;; kept-old-versions: | + | |
| - | ;; kept-new-versions: | + | |
| - | ;; End: | + | |
| </ | </ | ||
userapps/emacs/mu4e.txt · 最終更新: by seirios
