@@ 1,6 1,6 @@
;;; pkg-email.el --- Email client configuration -*- lexical-binding: t -*-
-;; Copyright (C) 2024 Cytrogen
+;; Copyright (C) 2026 Cytrogen
;;; Commentary:
@@ 32,10 32,11 @@
;;; mu4e Setup (延迟加载)
;;; ============================================================
-;; 添加 mu4e 路径
+;; 添加 mu4e 路径并加载 autoloads
(let ((mu4e-path "/usr/share/emacs/site-lisp/mu4e"))
(when (file-directory-p mu4e-path)
- (add-to-list 'load-path mu4e-path)))
+ (add-to-list 'load-path mu4e-path)
+ (load "mu4e-autoloads" t t)))
(with-eval-after-load 'mu4e
;; Context 生成函数
@@ 59,18 60,19 @@
(when msg
(string-prefix-p maildir-prefix
(mu4e-message-field msg :maildir))))
- :vars `((user-mail-address . ,email)
- (user-full-name . ,fullname)
- (mu4e-sent-folder . ,(concat maildir-prefix "/" sent))
- (mu4e-drafts-folder . ,(concat maildir-prefix "/" drafts))
- (mu4e-trash-folder . ,(concat maildir-prefix "/" trash))
- (mu4e-refile-folder . ,(concat maildir-prefix "/" archive))
- (mu4e-maildir-shortcuts
- . ((:maildir ,(concat maildir-prefix "/" inbox) :key ?i)
- (:maildir ,(concat maildir-prefix "/" sent) :key ?s)
- (:maildir ,(concat maildir-prefix "/" drafts) :key ?d)
- (:maildir ,(concat maildir-prefix "/" trash) :key ?t)
- (:maildir ,(concat maildir-prefix "/" archive) :key ?a)))))))
+ :vars (list (cons 'user-mail-address email)
+ (cons 'user-full-name fullname)
+ (cons 'mu4e-sent-folder (concat maildir-prefix "/" sent))
+ (cons 'mu4e-drafts-folder (concat maildir-prefix "/" drafts))
+ (cons 'mu4e-trash-folder (concat maildir-prefix "/" trash))
+ (cons 'mu4e-refile-folder (concat maildir-prefix "/" archive))
+ (cons 'mu4e-maildir-shortcuts
+ (list
+ (list :maildir (concat maildir-prefix "/" inbox) :key ?i :name (concat maildir-prefix "/" inbox))
+ (list :maildir (concat maildir-prefix "/" sent) :key ?s :name (concat maildir-prefix "/" sent))
+ (list :maildir (concat maildir-prefix "/" drafts) :key ?d :name (concat maildir-prefix "/" drafts))
+ (list :maildir (concat maildir-prefix "/" trash) :key ?t :name (concat maildir-prefix "/" trash))
+ (list :maildir (concat maildir-prefix "/" archive) :key ?a :name (concat maildir-prefix "/" archive))))))))
(defun my/email--setup-contexts ()
"Generate mu4e-contexts from `my/email-accounts'."
@@ 91,6 93,25 @@
(setq mu4e-view-show-addresses t)
(setq mu4e-use-fancy-chars t)
(setq mu4e-compose-dont-reply-to-self t)
+ (setq mu4e-modeline-support t)
+
+ ;; HTML 渲染配置
+ (setq mm-text-html-renderer 'shr)
+ (setq shr-use-colors t)
+ (setq shr-use-fonts nil)
+ (setq shr-max-image-proportion 0.6)
+ (setq shr-image-animate nil)
+ (setq shr-width nil)
+ (setq shr-discard-aria-hidden t)
+ (setq shr-cookie-policy nil)
+
+ ;; Gnus 图片配置
+ (setq gnus-inhibit-images nil)
+ (setq gnus-blocked-images ".") ; 阻止追踪图片
+
+ ;; 自动换行
+ (add-hook 'mu4e-view-mode-hook #'visual-line-mode)
+ (setq mm-fill-flowed t)
;; msmtp 发送配置
(setq sendmail-program "/usr/bin/msmtp")
@@ 99,8 120,62 @@
(setq message-sendmail-f-is-evil t)
(setq message-sendmail-extra-arguments '("--read-envelope-from"))
+ ;; 动态标记为垃圾邮件(支持所有账户)
+ (defun my/mu4e-mark-as-spam ()
+ "Mark message at point as spam (move to Spam folder of current account)."
+ (interactive)
+ (let* ((ctx (mu4e-context-current))
+ (ctx-name (when ctx (mu4e-context-name ctx)))
+ (spam-folder (cond
+ ((string= ctx-name "Gmail") "/Gmail/[Gmail]/Spam")
+ ((string= ctx-name "iCloud") "/iCloud/Junk")
+ ((string= ctx-name "Boo") "/Cytrogen/Junk Mail")
+ (t "/Gmail/[Gmail]/Spam")))) ; 默认
+ (mu4e-mark-set 'move spam-folder)))
+
+ (define-key mu4e-headers-mode-map (kbd "C-d") #'my/mu4e-mark-as-spam)
+ (define-key mu4e-view-mode-map (kbd "C-d") #'my/mu4e-mark-as-spam)
+
+ ;; 垃圾邮件过滤查询
+ (defvar my/spam-filter-query
+ (concat
+ "NOT flag:trashed " ; 排除已删除
+ "NOT maildir:/Gmail/\\[Gmail\\]/Spam " ; 排除垃圾文件夹
+ "NOT from:noreply " ; 排除无回复地址
+ "NOT from:no-reply "
+ "NOT subject:unsubscribe " ; 排除退订相关
+ "NOT subject:\"verify your\" " ; 排除验证邮件
+ "NOT subject:\"confirm your\" "
+ "NOT subject:\"your order\" ") ; 可根据需要扩展
+ "Query to filter out spam-like messages.")
+
+ ;; 添加书签:过滤后的 inbox 视图
+ (add-to-list 'mu4e-bookmarks
+ '(:name "Clean Inbox"
+ :query (lambda ()
+ (concat "maildir:/Gmail/Inbox "
+ my/spam-filter-query))
+ :key ?c))
+
+ (add-to-list 'mu4e-bookmarks
+ '(:name "All Inboxes (Clean)"
+ :query (lambda ()
+ (concat "(maildir:/Gmail/Inbox OR "
+ "maildir:/iCloud/Inbox OR "
+ "maildir:/Cytrogen/Inbox) "
+ my/spam-filter-query))
+ :key ?C))
+
;; 设置 contexts
- (my/email--setup-contexts))
+ (my/email--setup-contexts)
+
+ ;; 修复 context 切换时 maildir shortcuts 不更新的问题
+ (add-hook 'mu4e-context-changed-hook
+ (lambda ()
+ (setq mu4e--maildir-items-cached nil)))
+
+ ;; 链接点击支持
+ (define-key mu4e-view-mode-map (kbd "RET") #'mu4e-view-browse-url-from-binding))
;;; ============================================================
;;; Interactive Commands