+(defun notmuch-address-harvest-msg (msg)
+ (let* ((headers (plist-get msg :headers))
+ (to (ignore-errors (mail-extract-address-components (plist-get headers :To) t)))
+ (cc (ignore-errors (mail-extract-address-components (plist-get headers :Cc) t)))
+ (bcc (ignore-errors (mail-extract-address-components (plist-get headers :Bcc) t))))
+ (mapc (lambda (parts)
+ (let* ((name (car parts))
+ (email (cadr parts))
+ (entry (if name (format "%s <%s>" name email) email)))
+ (puthash entry t notmuch-address-completions)))
+ (append to cc bcc))
+ nil))
+
+(defun notmuch-address-harvest-handle-result (obj)
+ (notmuch-query-map-threads 'notmuch-address-harvest-msg (list obj)))
+
+(defun notmuch-address-harvest-filter (proc string)
+ (when (buffer-live-p (process-buffer proc))
+ (with-current-buffer (process-buffer proc)
+ (save-excursion
+ (goto-char (point-max))
+ (insert string))
+ (notmuch-sexp-parse-partial-list
+ 'notmuch-address-harvest-handle-result (process-buffer proc)))))
+
+(defvar notmuch-address-harvest-proc nil) ; the process of a harvest underway
+
+(defun notmuch-address-harvest (&optional filter-query synchronous callback)
+ "Collect addresses completion candidates. It queries the
+notmuch database for all messages sent by the user optionally
+matching FILTER-QUERY (if not nil). It collects the destination
+addresses from those messages and stores them in
+`notmuch-address-completions'. Address harvesting may take some
+time so the address collection runs asynchronously unless
+SYNCHRONOUS is t. In case of asynchronous execution, CALLBACK is
+called when harvesting finishes."
+ (let* ((from-me-query (mapconcat (lambda (x) (concat "from:" x)) (notmuch-user-emails) " or "))
+ (query (if filter-query
+ (format "(%s) and (%s)" from-me-query filter-query)
+ from-me-query))
+ (args `("show" "--format=sexp" "--format-version=2"
+ "--body=false" "--entire-thread=false" ,query)))
+ (if synchronous
+ (notmuch-query-map-threads 'notmuch-address-harvest-msg
+ (apply 'notmuch-call-notmuch-sexp args))
+ ;; Asynchronous
+ (when notmuch-address-harvest-proc
+ (kill-buffer (process-buffer notmuch-address-harvest-proc))) ; this also kills the process
+ (setq notmuch-address-harvest-proc
+ (apply 'notmuch-start-notmuch
+ "notmuch-address-harvest" ; process name
+ " *notmuch-address-harvest*" ; process buffer
+ callback ; process sentinel
+ args))
+ (set-process-filter notmuch-address-harvest-proc 'notmuch-address-harvest-filter)
+ (set-process-query-on-exit-flag notmuch-address-harvest-proc nil)))
+ ;; return value
+ nil)
+