使用Clojure读取QQ邮箱

本文介绍如何使用Clojure通过IMAP读取QQ邮箱里的邮件。

引入依赖包

deps.edn里加入以下两个包,

io.forward/clojure-mail {:mvn/version "1.0.8"}
com.rpl/specter {:mvn/version "1.1.3"}

specter依赖并非必须,在这里只是方便我们后面解析邮件。

登录QQ邮箱并生成授权码

登录QQ邮箱,进入《设置》-《账户》在《POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务》部分生成授权码。

使用Oauth2登录QQ邮箱

(require '[clojure.string :as s])
(require '[clojure-mail.core :as mail]) 
(require '[clojure-mail.parser :as p])   
(require '[clojure-mail.message :as msg])   


;; 将[email protected]替换为你的QQ邮箱地址
;; 将oauth-token替换为刚才生成的是授权码
(defn make-store []
  (mail/xoauth2-store "imap.qq.com" "[email protected]" "oauth-token"))

读取邮件

下面这个方法从指定邮件目录读取最近n封邮件,并返回邮件标题,纯文本正文以及邮件发送与接受方:

(defn read-n-messages [store folder n]
  (->> (mail/all-messages store folder)
       (take n)
       (mapv msg/read-message)
       (mapv #(let [txt (some->>
                         (spec/select [(walker :content-type) :body (walker string?)] %)
                         (map p/html->text)
                         (s/join "\n"))
                    subject (:subject %)]
                {:body txt
                 :subject subject
                 :from (:from %)
                 :to (:to %)}))))

例如,读取收件箱的前5封邮件:

(def store (make-store))
(read-n-messages store "inbox" 5)
;; 返回如下数据:
;; ({:body "TEXT/HTML; charset=UTF-8\n英伟达 CUDA 编程方法是目前广泛使用的并行化程序编程方法。在深度学习,计算机视觉,生物医疗,环境科学,气象预报,石油勘探等领域具有大量的使用场景。Numba 是一个支持 Python CUDA 的编译器,它为 Python 开发人员提供了一个简单的进入 GPU 加速计算的入口,用最简单的方式加速您的应用。 直播时间:7月7日(周二)晚 20:00-21:30 参与方式:在线直播 听众收益: 1、cuBLAS 在 CUDA Python 中的使用 2、多流在 CUDA Python 中的使用 3、利用 CUDA Python 处理视频 立即报名 讲师介绍 何琨 开发者社区高级讲师, NVIDIA 拥有 7 年 GPU 开发经验,5 年人工智能开发经验。在人工智能、计算机视觉、高性能计算领域曾经独立完成过多个项目,并且在机器人和无人机领域,有丰富的研发经验。曾针对图像识别,目标的检测与跟踪等方面完成多种解决方案,作为主要研发者参与GPU 版气象模式 GRAPES 立即报名 添加小助手Tango2018cc获取直播链接,加入直播群 . 扫码加入直播群 点击这里取消订阅",
;;  :subject "用了Python,老板再也不用担心我写不了CUDA了!",
;;  :from ({:address "[email protected]", :name "InfoQ"}),
;;  :to ({:address "[email protected]", :name "abc"})})

问题

  • 不清楚如何读取QQ邮箱的其他文件夹。尝试过startrash,返回邮件列表均为空。
  • 通过在deps.edn里配置Socks代理访问Gmail邮箱失败,暂不清楚原因:
     :jvm-opts ["-Dhttp.proxySet=true"
                "-Dhttp.proxyHost=127.0.0.1"
                "-Dhttp.proxyPort=12331"
                "-Dhttp.nonProxyHosts=\"localhost|127.0.0.1|10.*.*.*|*.foo.com|etc\""]
    
    

参考

Comment