emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/bbdb a8d03908b0: Establish record-addresses association


From: Roland Winkler
Subject: [elpa] externals/bbdb a8d03908b0: Establish record-addresses associations before annotating records.
Date: Sun, 20 Feb 2022 23:11:09 -0500 (EST)

branch: externals/bbdb
commit a8d03908b09344ef74ff225d4b82a6a75ba7db3a
Author: Roland Winkler <winkler@gnu.org>
Commit: Roland Winkler <winkler@gnu.org>

    Establish record-addresses associations before annotating records.
---
 README           |  20 +-
 lisp/bbdb-mua.el | 561 ++++++++++++++++++++++++++++---------------------------
 lisp/bbdb.el     | 105 ++++++++---
 3 files changed, 369 insertions(+), 317 deletions(-)

diff --git a/README b/README
index e8300343ee..233ed4f3bf 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-Copyright (C) 2010-2017 Free Software Foundation, Inc.
+Copyright (C) 2010-2022 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 BBDB is the Insidious Big Brother Database for GNU Emacs.
@@ -147,7 +147,7 @@ Interactive commands
 --------------------
 
 Call bbdb-initialize (usually in your init file) to initialize
-the MUA interfaces based on interactive commands
+the MUA interfaces based on interactive commands.
 
 MUA commands include
 
@@ -158,7 +158,7 @@ MUA commands include
 These MUA commands operate either on existing records only.  Or they
 can also create new records.
 
-All these commands are controlled by bbdb-mua-update-interactive-p.
+All these commands are controlled by bbdb-mua-interactive-action.
 This is a cons pair (WITHOUT-PREFIX . WITH-PREFIX).
 The car is used if the command is called without a prefix.
 The cdr is used if the command is called with a prefix (and if the prefix
@@ -196,14 +196,14 @@ bbdb-mua-auto-update automatically updates the BBDB 
records for the
 sender and/or recipients of a message.  If bbdb-mua-pop-up is non-nil,
 the matching records are also displayed in a continuously updated BBDB window,
 
-The behavior of bbdb-mua-auto-update is controlled by bbdb-mua-auto-update-p.
-This may take the same values as bbdb-mua-update-interactive-p (except read).
+The behavior of bbdb-mua-auto-update is controlled by bbdb-mua-auto-action.
+This may take the same values as bbdb-mua-interactive-action (except read).
 Binding this to a function is often most helpful for noninteractive use.
-For example, you may want to bind bbdb-mua-auto-update-p to the function
+For example, you may want to bind bbdb-mua-auto-action to the function
 bbdb-select-message,  see bbdb-accept-message-alist and
 bbdb-ignore-message-alist.  If a message is accepted by bbdb-select-message,
 the actual action performed by BBDB (i.e., the return value of
-bbdb-select-message) is given by bbdb-update-records-p.
+bbdb-select-message) is given by bbdb-mua-action.
 
 ==================================================================
 
@@ -211,9 +211,7 @@ Notes for BBDB lisp hackers:
 ----------------------------
 
 If you write your own functions and commands to modify BBDB records,
-do not call the low-level functions bbdb-record-set-* such as
-bbdb-record-set-aka, bbdb-record-set-mail etc.  The recommended
-sequence of calls is
+do not modify the records directly.  The recommended sequence of calls is
 
 - one or multiple calls of bbdb-record-set-field for the respective
   fields to be changed.  This not only sets the fields, but it also
@@ -228,7 +226,7 @@ sequence of calls is
 
 ==================================================================
 
-Copyright (C) 2010-2017 Free Software Foundation, Inc.
+Copyright (C) 2010-2022 Free Software Foundation, Inc.
 
 This file is part of the Insidious Big Brother Database (aka BBDB),
 
diff --git a/lisp/bbdb-mua.el b/lisp/bbdb-mua.el
index 296dc7770a..2117e98bff 100644
--- a/lisp/bbdb-mua.el
+++ b/lisp/bbdb-mua.el
@@ -133,8 +133,8 @@ MIME encoded headers are decoded.  Return nil if HEADER 
does not exist."
 
 ;;;###autoload
 (defun bbdb-accept-message (&optional invert)
-  "For use with variable `bbdb-mua-update-interactive-p' and friends.
-Return the value of variable `bbdb-update-records-p' for messages matching
+  "For use with variable `bbdb-mua-interactive-action' and friends.
+Return the value of variable `bbdb-mua-action' for messages matching
 `bbdb-accept-message-alist'.  If INVERT is non-nil, accept messages
 not matching `bbdb-ignore-message-alist'."
   (let ((rest (if invert bbdb-ignore-message-alist
@@ -147,20 +147,20 @@ not matching `bbdb-ignore-message-alist'."
           (if (bbdb-message-header-re header (cdr elt))
               (setq done t)))))
     (if invert (setq done (not done)))
-    (if done bbdb-update-records-p)))
+    (if done bbdb-mua-action)))
 
 ;;;###autoload
 (defun bbdb-ignore-message (&optional invert)
-  "For use with variable `bbdb-mua-update-interactive-p' and friends.
-Return the value of variable `bbdb-update-records-p' for messages not matching
+  "For use with variable `bbdb-mua-interactive-action' and friends.
+Return the value of variable `bbdb-mua-action' for messages not matching
 `bbdb-ignore-message-alist'.  If INVERT is non-nil, accept messages
 matching `bbdb-accept-message-alist'."
   (bbdb-accept-message (not invert)))
 
 ;;;###autoload
 (defun bbdb-select-message ()
-  "For use with variable `bbdb-mua-update-interactive-p' and friends.
-Return the value of variable `bbdb-update-records-p' for messages both matching
+  "For use with variable `bbdb-mua-interactive-action' and friends.
+Return the value of variable `bbdb-mua-action' for messages both matching
 `bbdb-accept-message-alist' and not matching `bbdb-ignore-message-alist'."
   (and (bbdb-accept-message)
        (bbdb-ignore-message)))
@@ -211,11 +211,11 @@ is ignored. If IGNORE-ADDRESS is nil, use value of 
`bbdb-user-mail-address-re'."
                (bbdb-get-address-components nil ignore-address))))))
 
 ;;;###autoload
-(defun bbdb-update-records (address-list &optional update-p sort)
+(defun bbdb-update-records (address-list &optional action sort)
   "Return the list of BBDB records matching ADDRESS-LIST.
 ADDRESS-LIST is a list of mail addresses.  (It can be extracted from
 a mail message using `bbdb-get-address-components'.)
-UPDATE-P may take the following values:
+ACTION may take the following values:
  search       Search for existing records matching ADDRESS.
  update       Search for existing records matching ADDRESS;
                 update name and mail field if necessary.
@@ -228,187 +228,179 @@ UPDATE-P may take the following values:
                 It should return one of the above values.
 
 If SORT is non-nil, sort records according to `bbdb-record-lessp'.
-Ottherwise, the records are ordered according to ADDRESS-LIST.
+Otherwise, the records are ordered according to ADDRESS-LIST.
 
 Usually this function is called by the wrapper `bbdb-mua-update-records'."
-  ;; UPDATE-P allows filtering of complete messages.
+  ;; ACTION allows filtering of complete messages.
   ;; Filtering of individual addresses within an accepted message
   ;; is done by `bbdb-get-address-components' using 
`bbdb-user-mail-address-re'.
-  ;; We resolve UPDATE-P repeatedly.  This is needed, for example,
-  ;; with the chain `bbdb-mua-auto-update-p' -> `bbdb-select-message'
-  ;; -> `bbdb-update-records-p'.
-  (while (and (functionp update-p)
+  ;; We resolve ACTION repeatedly.  This is needed, for example,
+  ;; with the chain `bbdb-mua-auto-action' -> `bbdb-select-message'
+  ;; -> `bbdb-mua-action'.
+  (while (and (functionp action)
               ;; Bad! `search' is a function in `cl.el'.
-              (not (eq update-p 'search)))
-    (setq update-p (funcall update-p)))
-  (cond ((eq t update-p)
-         (setq update-p 'create))
-        ((not (memq update-p '(search update query create nil)))
-         (error "Illegal value of arg update-p: %s" update-p)))
-
-  (let (;; `bbdb-update-records-p' and `bbdb-offer-to-create' are used here
-        ;; as internal variables for communication with `bbdb-query-create'.
-        ;; This does not affect the value of the global user variable
-        ;; `bbdb-update-records-p'.
-        (bbdb-offer-to-create 'start)
-        (bbdb-update-records-p update-p)
-        address records)
-
-    (when update-p
-      (while (setq address (pop address-list))
-        (let* ((bbdb-update-records-address address)
-               hits
-               (task
-                (catch 'done
-                  (setq hits
-                        ;; We put the call of `bbdb-notice-mail-hook'
-                        ;; into `bbdb-annotate-message' so that this hook
-                        ;; runs only if the user agreed to change a record.
-                        (cond ((or bbdb-read-only
-                                   (eq bbdb-update-records-p 'search))
-                               ;; Search for records having this mail address
-                               ;; but do not modify an existing record.
-                               ;; This does not run `bbdb-notice-mail-hook'.
-                               (bbdb-message-search (car address)
-                                                    (cadr address)))
-                              ((eq bbdb-update-records-p 'update)
-                               (bbdb-annotate-message address 'update))
-                              ((eq bbdb-update-records-p 'query)
-                               (bbdb-annotate-message
-                                address 'bbdb-query-create))
-                              ((eq bbdb-update-records-p 'create)
-                               (bbdb-annotate-message address 'create))))
-                  nil)))
+              (not (eq action 'search)))
+    (setq action (funcall action)))
+  (cond ((eq t action)
+         (setq action 'create))
+        ((not (memq action '(search update query create nil)))
+         (error "Illegal value of arg action: %s" action)))
+
+  (let (records-alist records elt)
+    ;; association list: records -> addresses
+    (dolist (address (nreverse address-list))
+      (let* ((mail (nth 1 address)) ; possibly nil
+             (name (unless (equal mail (car address))
+                     (car address)))
+             (records (bbdb-message-search name mail)))
+        (if records
+            (dolist (record records) ; order of RECORDS insignificant!
+              ;; Accumulate list of addresses for each RECORD.
+              (if (setq elt (assq record records-alist))
+                  (setcar (cdr elt) (cons address (cadr elt)))
+                (push (list record (list address)) records-alist)))
+          ;; We do not yet have a record for the address
+          (when (or name mail) ; ignore empty addresses
+            ;; If there is no NAME, try to use MAIL as NAME
+            ;; (but only if we do not yet have a record for MAIL).
+            (if (and mail bbdb-message-mail-as-name
+                     (or (null name)
+                         (string= "" name)))
+                ;; Clean MAIL as if it was a NAME.
+                (setcar address (funcall bbdb-message-clean-name-function 
mail)))
+            (push (list nil (list address)) records-alist)))))
+
+    (if bbdb-record-address-alist-function
+        (setq records-alist (funcall bbdb-record-address-alist-function
+                                     records-alist)))
+
+    (let (task)
+      (while (setq elt (pop records-alist))
+        (let* ((record (nth 0 elt))
+               (address (nth 0 (nth 1 elt)))
+               (mail (or (nth 0 address) (nth 1 address))))
+          (when (and (not record) mail (eq action 'query) (not bbdb-read-only))
+            (setq task (bbdb-query-create mail))
+            (if (memq task '(search create update))
+                (setq action task)))
           (cond ((eq task 'quit)
-                 (setq address-list nil))
-                ((not (eq task 'next))
-                 (dolist (hit (delq nil (nreverse hits)))
-                   (bbdb-pushnew hit records))))
-          (if (and records (not bbdb-message-all-addresses))
-              (setq address-list nil))))
-      (setq records
-            (if sort (sort records 'bbdb-record-lessp)
-              ;; Make RECORDS a list ordered like ADDRESS-LIST.
-              (nreverse records))))
-
-    ;; `bbdb-message-search' might yield multiple records
-    (if (and records (not bbdb-message-all-addresses))
-        (setq records (list (car records))))
+                 (setq records-alist nil))
+                ((eq task 'next)) ; do nothing
+                ((not (or record mail))) ; do nothing
+                ((or bbdb-read-only (eq action 'search))
+                 (if record (push record records)))
+                (t
+                 (if (or (eq action 'create)
+                         (eq task 'create-current) ; and (eq action 'query)
+                         (and record (eq action 'update)))
+                     ;; If we have more than one record, all but the first
+                     ;; one are new.  So no need to worry about duplicates.
+                     (setq records
+                           (nconc (bbdb-annotate-message record
+                                                         (nth 1 elt) action)
+                                  records))))))
+        (if (and records (not bbdb-message-all-addresses))
+            (setq records-alist nil))))
+
+    (setq records
+          ;; Sorting RECORDS is useful when RECORDS are displayed.
+          (if sort (sort records 'bbdb-record-lessp)
+            ;; Make RECORDS a list ordered like ADDRESS-LIST.
+            ;; Useful if RECORDS are processed further.
+            (nreverse records)))
 
     (unless bbdb-read-only
-      (bbdb-editable)
       (dolist (record records)
         (run-hook-with-args 'bbdb-notice-record-hook record)))
 
     records))
 
-(defun bbdb-query-create ()
-  "Interactive query used by `bbdb-update-records'.
-Return t if the record should be created or `nil' otherwise.
-Honor previous answers such as `!'."
-  (let ((task bbdb-offer-to-create))
-    ;; If we have remembered what the user typed previously,
-    ;; `bbdb-offer-to-create' holds a character, i.e., a number.
-    ;; -- Right now, we only remember "!".
-    (when (not (integerp task))
-      (let ((prompt (format "%s is not in BBDB; add? (y,!,n,s,q,?) "
-                            (or (nth 0 bbdb-update-records-address)
-                                (nth 1 bbdb-update-records-address))))
-            event)
-        (while (not event)
-          (setq event (read-key-sequence prompt))
-          (setq event (if (stringp event) (aref event 0))))
-        (setq task event)
-        (message ""))) ; clear the message buffer
-
-    (cond ((eq task ?y)
-           t)
-          ((eq task ?!)
-           (setq bbdb-offer-to-create task)
-           t)
-          ((or (eq task ?n)
-               (eq task ?\s))
-           (throw 'done 'next))
-          ((or (eq task ?q)
-               (eq task ?\a)) ; ?\a = C-g
-           (throw 'done 'quit))
-          ((eq task ?s)
-           (setq bbdb-update-records-p 'search)
-           (throw 'done 'next))
-          (t ; any other key sequence
-           (save-window-excursion
-             (let* ((buffer (get-buffer-create " *BBDB Help*"))
-                    (window (or (get-buffer-window buffer)
-                                (split-window (get-lru-window)))))
-               (with-current-buffer buffer
-                 (special-mode)
-                 (let (buffer-read-only)
-                   (erase-buffer)
-                   (insert
-                    "Your answer controls how BBDB updates/searches for 
records.
-
-Type ?  for this help.
-Type y  to add the current record.
-Type !  to add all remaining records.
-Type n  to skip the current record. (You might also type space)
-Type s  to switch from annotate to search mode.
-Type q  to quit updating records.  No more search or annotation is done.")
-                   (set-buffer-modified-p nil)
-                   (goto-char (point-min)))
-                 (set-window-buffer window buffer)
-                 (fit-window-to-buffer window)))
-             ;; Try again!
-             (bbdb-query-create))))))
-
-
-
-(defun bbdb-annotate-message (address &optional update-p)
-  "Fill the records for message ADDRESS with as much info as possible.
-If a record for ADDRESS does not yet exist, UPDATE-P controls whether
-a new record is created for ADDRESS.  UPDATE-P may take the values:
- update or nil  Update existing records, never create a new record.
- query          Query interactively whether to create a new record.
- create or t    Create a new record.
- a function     This functions will be called with no arguments.
-                  It should return one of the above values.
-Return the records matching ADDRESS or nil."
-  (let* ((mail (nth 1 address)) ; possibly nil
-         (name (unless (equal mail (car address))
-                 (car address)))
-         (records (bbdb-message-search name mail))
-         created-p new-records)
-    (if (and (not records) (functionp update-p))
-        (setq update-p (funcall update-p)))
-    (cond ((eq t update-p) (setq update-p 'create))
-          ((not update-p) (setq update-p 'update)))
-
-    ;; Create a new record if nothing else fits.
-    ;; In this way, we can fill the slots of the new record with
-    ;; the same code that updates the slots of existing records.
-    (unless (or records
-                (eq update-p 'update)
-                (not (or name mail)))
-      ;; If there is no name, try to use the mail address as name
-      (if (and bbdb-message-mail-as-name mail
-               (or (null name)
-                   (string= "" name)))
-          (setq name (funcall bbdb-message-clean-name-function mail)))
-      (if (or (eq update-p 'create)
-              (and (eq update-p 'query)
-                   (y-or-n-p (format "%s is not in the BBDB.  Add? "
-                                     (or name mail)))))
-          (setq records (list (bbdb-empty-record))
-                created-p t)))
-
-    (dolist (record records)
-      (let* ((old-name (bbdb-record-name record))
+(defun bbdb-query-create (mail)
+  "Query action for MAIL address not yet known to BBDB.
+Used by `bbdb-update-records'.  Return values include:
+ create-current [y] Create a new record for MAIL.
+ create         [!] Switch to create mode for remaining addresses.
+ search         [s] Switch to search mode for remaining addresses.
+ update         [u] Switch to update mode for remaining addresses.
+ next           [n] Continue with next mail address, skip MAIL.
+ quit           [q] Quit, ignore all remaining MAIL addresses."
+  (let ((prompt (format "%s is not in BBDB; add? (y,!,s,u,n,q,?) " mail))
+        task action)
+    (save-window-excursion
+      (while (not action)
+        (setq task nil)
+        (while (not task)
+          (setq task (read-key-sequence prompt))
+          (setq task (if (stringp task) (aref task 0))))
+        (message "") ; clear the message buffer
+
+        (setq action
+              (cond ((eq task ?y)
+                     'create-current)
+                    ((eq task ?!)
+                     'create)
+                    ((eq task ?s)
+                     'search)
+                    ((eq task ?u)
+                     'update)
+                    ((or (eq task ?n)
+                         (eq task ?\s))
+                     'next)
+                    ((or (eq task ?q)
+                         (eq task ?\a)) ; ?\a = C-g
+                     'quit)
+                    (t ; any other key sequence
+                     (let* ((buffer (get-buffer-create " *BBDB Help*"))
+                            (window (or (get-buffer-window buffer)
+                                        (split-window (get-lru-window)))))
+                       (with-current-buffer buffer
+                         (special-mode)
+                         (let (buffer-read-only)
+                           (erase-buffer)
+                           (insert
+                            "Your answer controls how BBDB updates/searches 
for records.
+
+y  Create a new record for the current address.
+!  Switch to create mode.
+s  Switch to search mode.
+u  Switch to update mode.
+n  Continue with next address, skip the current address.
+q  Quit updating records.
+?  This help.")
+                           (set-buffer-modified-p nil)
+                           (goto-char (point-min)))
+                         (set-window-buffer window buffer)
+                         (fit-window-to-buffer window)))
+                     nil))))) ;; Try again!
+    action))
+
+(defun bbdb-annotate-message (record address-list action)
+  "Anotate RECORD using ADDRESS-LIST.
+ADDRESS-LIST has elements (NAME MAIL HEADER HEADER-CLASS MUA)
+as returned by `bbdb-get-address-components'.
+ACTION controls whether new records beyond RECORD may be created.
+ACTION may take the values:
+ update or nil  Update RECORD, but do not create new records.
+ query          Query interactively whether to create new records.
+ create or t    Permit creating new records.
+Return the records matching ADDRESS."
+  (let ((new (not record))
+        (record (or record (bbdb-empty-record)))
+        records)
+
+    (dolist (address address-list)
+      (let* ((record record) ; possibly changed below
+             (mail (nth 1 address)) ; possibly nil
+             (name (unless (equal mail (nth 0 address))
+                     (nth 0 address)))
              (fullname (bbdb-divide-name (or name "")))
              (fname (car fullname))
              (lname (cdr fullname))
-             (mail mail) ;; possibly changed below
-             (created-p created-p)
-             (update-p update-p)
-             change-p add-mails add-name ignore-redundant)
+             (old-name (bbdb-record-name record)) ; possibly ""
+             (old-name-nonempty (not (string= "" old-name)))
+             change add-mails add-name ignore-redundant)
+        ;; Is there anything meaningful we could do with the other elements
+        ;; in ADDRESS?
 
         ;; Analyze the name part of the record.
         (cond ((or (not name)
@@ -418,7 +410,7 @@ Return the records matching ADDRESS or nil."
                         (equal lname (bbdb-record-lastname record))) ; nil
                    (member-ignore-case name (bbdb-record-aka record)))) ; do 
nothing
 
-              (created-p ; new record
+              (new ; new record
                (bbdb-record-set-field record 'name (cons fname lname)))
 
               ((not (setq add-name (bbdb-add-job bbdb-add-name record name)))) 
; do nothing
@@ -430,31 +422,30 @@ Return the records matching ADDRESS or nil."
                  (sit-for add-name)))
 
               ((bbdb-eval-spec add-name
-                               (if old-name
+                               (if old-name-nonempty
                                    (format "Change name \"%s\" to \"%s\"? "
                                            old-name name)
                                  (format "Assign name \"%s\" to address 
\"%s\"? "
                                          name (car (bbdb-record-mail 
record)))))
                ;; Keep old-name as AKA?
-               (when (and old-name
-                          (not (member-ignore-case old-name (bbdb-record-aka 
record))))
-                 (if (bbdb-eval-spec (bbdb-add-job bbdb-add-aka record 
old-name)
-                                     (format "Keep name \"%s\" as an AKA? " 
old-name))
-                     (bbdb-record-set-field
-                      record 'aka (cons old-name (bbdb-record-aka record)))
-                   (bbdb-remhash old-name record)))
+               (if (and old-name-nonempty
+                        (not (member-ignore-case old-name (bbdb-record-aka 
record)))
+                        (bbdb-eval-spec (bbdb-add-job bbdb-add-aka record 
old-name)
+                                        (format "Keep name \"%s\" as an AKA? " 
old-name)))
+                   (bbdb-record-set-field
+                    record 'aka (cons old-name (bbdb-record-aka record))))
                (bbdb-record-set-field record 'name (cons fname lname))
-               (setq change-p 'name))
+               (setq change 'name))
 
               ;; make new name an AKA?
-              ((and old-name
+              ((and old-name-nonempty
                     (not (member-ignore-case name (bbdb-record-aka record)))
                     (bbdb-eval-spec (bbdb-add-job bbdb-add-aka record name)
                                     (format "Make \"%s\" an alternate for 
\"%s\"? "
                                             name old-name)))
                (bbdb-record-set-field
                 record 'aka (cons name (bbdb-record-aka record)))
-               (setq change-p 'name)))
+               (setq change 'name)))
 
         ;; Is MAIL redundant compared with the mail addresses
         ;; that are already known for RECORD?
@@ -478,11 +469,11 @@ Return the records matching ADDRESS or nil."
                              (y-or-n-p (format "Ignore redundant mail %s?" 
mail)))
                          (setq mail redundant))))))
 
-        ;; Analyze the mail part of the new records
+        ;; Analyze the mail part of the new record
         (cond ((or (not mail) (equal mail "???")
                    (member-ignore-case mail (bbdb-record-mail-canon record)))) 
; do nothing
 
-              (created-p ; new record
+              (new ; new record
                (bbdb-record-set-field record 'mail (list mail)))
 
               ((not (setq add-mails (bbdb-add-job bbdb-add-mails record 
mail)))) ; do nothing
@@ -497,17 +488,19 @@ Return the records matching ADDRESS or nil."
                    bbdb-silent
                    (y-or-n-p (format "Add address \"%s\" to %s? " mail
                                      (bbdb-record-name record)))
-                   (and (or (and (functionp update-p)
-                                 (progn (setq update-p (funcall update-p)) 
nil))
-                            (memq update-p '(t create))
-                            (and (eq update-p 'query)
+                   ;; The user decided interactively not to add MAIL
+                   ;; to the existing record for NAME.  Then, if ACTION
+                   ;; is create or the user confirms after query,
+                   ;; we make a new record for NAME and MAIL.
+                   (and (or (memq action '(t create))
+                            (and (eq action 'query)
                                  (y-or-n-p
                                   (format "Create a new record for %s? "
                                           (bbdb-record-name record)))))
                         (progn
                           (setq record (bbdb-empty-record))
                           (bbdb-record-set-name record fname lname)
-                          (setq created-p t))))
+                          (setq new t))))
 
                (let ((mails (bbdb-record-mail record)))
                  (if ignore-redundant
@@ -543,19 +536,20 @@ Return the records matching ADDRESS or nil."
                                            (format "Make \"%s\" the primary 
address? " mail)))
                       (cons mail mails)
                     (nconc mails (list mail))))
-                 (unless change-p (setq change-p t)))))
+                 (unless change (setq change t)))))
 
-        (cond (created-p
+        (cond (new
                (unless bbdb-silent
                  (if (bbdb-record-name record)
                      (message "created %s's record with address \"%s\""
                               (bbdb-record-name record) mail)
                    (message "created record with naked address \"%s\"" mail)))
+               (setq new nil)
                (bbdb-change-record record))
 
-              (change-p
+              (change
                (unless bbdb-silent
-                 (cond ((eq change-p 'name)
+                 (cond ((eq change 'name)
                         (message "noticed \"%s\"" (bbdb-record-name record)))
                        ((bbdb-record-name record)
                         (message "noticed %s's address \"%s\""
@@ -564,16 +558,23 @@ Return the records matching ADDRESS or nil."
                         (message "noticed naked address \"%s\"" mail))))
                (bbdb-change-record record)))
 
-        (run-hook-with-args 'bbdb-notice-mail-hook record)
-        (push record new-records)))
+        ;; `bbdb-notice-mail-hook' runs only if the user agreed to change
+        ;; a record.  It runs for every ADDRESS.  Use ‘bbdb-notice-record-hook’
+        ;; if you want to notice each record only once per message.
+        ;; We make ADDRESS available to `bbdb-notice-mail-hook'
+        ;; via `bbdb-update-records-address'.
+        (let ((bbdb-update-records-address address))
+          (run-hook-with-args 'bbdb-notice-mail-hook record))
+        (push record records)))
 
-    (nreverse new-records)))
+    ;; Return records
+    records))
 
-(defun bbdb-mua-update-records (&optional header-class update-p sort)
+(defun bbdb-mua-update-records (&optional header-class action sort)
   "Wrapper for `bbdb-update-records'.
 HEADER-CLASS is defined in `bbdb-message-headers'.  If it is nil,
 use all classes in `bbdb-message-headers'.
-UPDATE-P is defined in `bbdb-update-records'.
+ACTION is defined in `bbdb-update-records'.
 If SORT is non-nil, sort records according to `bbdb-record-lessp'."
   (let ((mua (bbdb-mua)))
     (save-current-buffer
@@ -584,37 +585,37 @@ If SORT is non-nil, sort records according to 
`bbdb-record-lessp'."
         (vm-error-if-folder-empty)
         (let ((enable-local-variables t))  ; ...or vm bind this to nil.
           (bbdb-update-records (bbdb-get-address-components header-class)
-                               update-p sort)))
+                               action sort)))
        ;; Gnus
        ((eq mua 'gnus)
         (set-buffer gnus-article-buffer)
         (bbdb-update-records (bbdb-get-address-components header-class)
-                             update-p sort))
+                             action sort))
        ;; MH-E
        ((eq mua 'mh)
         (if mh-show-buffer (set-buffer mh-show-buffer))
         (bbdb-update-records (bbdb-get-address-components header-class)
-                             update-p sort))
+                             action sort))
        ;; Rmail
        ((eq mua 'rmail)
         (set-buffer rmail-buffer)
         (bbdb-update-records (bbdb-get-address-components header-class)
-                             update-p sort))
+                             action sort))
        ;; mu4e
        ((eq mua 'mu4e)
         (set-buffer (if (boundp 'mu4e~view-buffer-name)
                         mu4e~view-buffer-name ; old version of mu4e
                       gnus-article-buffer))
         (bbdb-update-records (bbdb-get-address-components header-class)
-                             update-p sort))
+                             action sort))
        ;; Wanderlust
        ((eq mua 'wl)
         (bbdb-update-records (bbdb-get-address-components header-class)
-                             update-p sort))
+                             action sort))
       ;; Message and Mail
        ((memq mua '(message mail))
         (bbdb-update-records (bbdb-get-address-components header-class)
-                             update-p sort))))))
+                             action sort))))))
 
 (defmacro bbdb-mua-wrapper (&rest body)
   "Perform BODY in a MUA buffer."
@@ -634,23 +635,26 @@ If SORT is non-nil, sort records according to 
`bbdb-record-lessp'."
             ;; rmail, mail, message, mu4e and wl do not require any wrapper
             ,@body))))
 
-(defun bbdb-mua-update-interactive-p ()
-  "Interactive spec for arg UPDATE-P of `bbdb-mua-display-records' and friends.
+(define-obsolete-function-alias 'bbdb-mua-update-interactive-p
+  #'bbdb-mua-interactive-action "3.0")
+(defun bbdb-mua-interactive-action ()
+  "Interactive spec for arg ACTION of `bbdb-mua-display-records' and friends.
 If these commands are called without a prefix, the value of their arg
-UPDATE-P is the car of the variable `bbdb-mua-update-interactive-p'.
-Called with a prefix, the value of UPDATE-P is the cdr of this variable."
-  (let ((update-p (if current-prefix-arg
-                      (cdr bbdb-mua-update-interactive-p)
-                    (car bbdb-mua-update-interactive-p))))
-    (if (eq update-p 'read)
+ACTION is the car of the variable `bbdb-mua-interactive-action'.
+Called with a prefix, the value of ACTION is the cdr of this variable."
+  (let ((action (if current-prefix-arg
+                    (cdr bbdb-mua-interactive-action)
+                  (car bbdb-mua-interactive-action))))
+    (if (eq action 'read)
         (let ((str (completing-read "Action: " '((query) (search) (create))
                                     nil t)))
           (unless (string= "" str) (intern str))) ; nil otherwise
-      update-p)))
+      action)))
 
 (defun bbdb-mua-window-p ()
   "Return lambda function matching the MUA window.
-This return value can be used as arg HORIZ-P of `bbdb-display-records'."
+This return value can be used as arg HORIZ-P of
+`bbdb-pop-up-window' and `bbdb-display-records'."
   (let ((mm-alist bbdb-mua-mode-alist)
         elt fun)
     (while (setq elt (cdr (pop mm-alist)))
@@ -662,24 +666,24 @@ This return value can be used as arg HORIZ-P of 
`bbdb-display-records'."
     fun))
 
 ;;;###autoload
-(defun bbdb-mua-display-records (&optional header-class update-p all)
+(defun bbdb-mua-display-records (&optional header-class action all)
   "Display the BBDB record(s) for the addresses in this message.
 This looks into the headers of a message according to HEADER-CLASS.
 Then for the mail addresses found the corresponding BBDB records are displayed.
-UPDATE-P determines whether only existing BBDB records are displayed
+ACTION determines whether only existing BBDB records are displayed
 or whether also new records are created for these mail addresses.
 
 HEADER-CLASS is defined in `bbdb-message-headers'.  If it is nil,
 use all classes in `bbdb-message-headers'.
-UPDATE-P may take the same values as `bbdb-update-records-p'.
-For interactive calls, see function `bbdb-mua-update-interactive-p'.
+ACTION may take the same values as `bbdb-mua-action'.
+For interactive calls, see function `bbdb-mua-interactive-action'.
 If ALL is non-nil, bind `bbdb-message-all-addresses' to ALL."
-  (interactive (list nil (bbdb-mua-update-interactive-p)))
+  (interactive (list nil (bbdb-mua-interactive-action)))
   (let ((bbdb-pop-up-window-size bbdb-mua-pop-up-window-size)
         (bbdb-message-all-addresses (or all bbdb-message-all-addresses))
         records)
     (bbdb-mua-wrapper
-     (setq records (bbdb-mua-update-records header-class update-p t)))
+     (setq records (bbdb-mua-update-records header-class action t)))
     (if records (bbdb-display-records records nil nil nil (bbdb-mua-window-p)))
     records))
 
@@ -688,36 +692,36 @@ If ALL is non-nil, bind `bbdb-message-all-addresses' to 
ALL."
 ;; modify or adapt these simple commands to your liking.
 
 ;;;###autoload
-(defun bbdb-mua-display-sender (&optional update-p)
+(defun bbdb-mua-display-sender (&optional action)
   "Display the BBDB record(s) for the sender of this message.
-UPDATE-P may take the same values as `bbdb-update-records-p'.
-For interactive calls, see function `bbdb-mua-update-interactive-p'."
-  (interactive (list (bbdb-mua-update-interactive-p)))
-  (bbdb-mua-display-records 'sender update-p))
+ACTION may take the same values as `bbdb-mua-action'.
+For interactive calls, see function `bbdb-mua-interactive-action'."
+  (interactive (list (bbdb-mua-interactive-action)))
+  (bbdb-mua-display-records 'sender action))
 
 ;;;###autoload
-(defun bbdb-mua-display-recipients (&optional update-p)
+(defun bbdb-mua-display-recipients (&optional action)
   "Display the BBDB record(s) for the recipients of this message.
-UPDATE-P may take the same values as `bbdb-update-records-p'.
-For interactive calls, see function `bbdb-mua-update-interactive-p'."
-  (interactive (list (bbdb-mua-update-interactive-p)))
-  (bbdb-mua-display-records 'recipients update-p))
+ACTION may take the same values as `bbdb-mua-action'.
+For interactive calls, see function `bbdb-mua-interactive-action'."
+  (interactive (list (bbdb-mua-interactive-action)))
+  (bbdb-mua-display-records 'recipients action))
 
 ;;;###autoload
-(defun bbdb-mua-display-all-records (&optional update-p)
+(defun bbdb-mua-display-all-records (&optional action)
   "Display the BBDB record(s) for all addresses in this message.
-UPDATE-P may take the same values as `bbdb-update-records-p'.
-For interactive calls, see function `bbdb-mua-update-interactive-p'."
-  (interactive (list (bbdb-mua-update-interactive-p)))
-  (bbdb-mua-display-records nil update-p t))
+ACTION may take the same values as `bbdb-mua-action'.
+For interactive calls, see function `bbdb-mua-interactive-action'."
+  (interactive (list (bbdb-mua-interactive-action)))
+  (bbdb-mua-display-records nil action t))
 
 ;;;###autoload
-(defun bbdb-mua-display-all-recipients (&optional update-p)
+(defun bbdb-mua-display-all-recipients (&optional action)
   "Display BBDB records for all recipients of this message.
-UPDATE-P may take the same values as `bbdb-update-records-p'.
-For interactive calls, see function `bbdb-mua-update-interactive-p'."
-  (interactive (list (bbdb-mua-update-interactive-p)))
-  (bbdb-mua-display-records 'recipients update-p t))
+ACTION may take the same values as `bbdb-mua-action'.
+For interactive calls, see function `bbdb-mua-interactive-action'."
+  (interactive (list (bbdb-mua-interactive-action)))
+  (bbdb-mua-display-records 'recipients action t))
 
 ;; The commands `bbdb-annotate-record' and `bbdb-mua-edit-field'
 ;; have kind of similar goals, yet they use rather different strategies.
@@ -743,18 +747,18 @@ If ANNOTATION is an empty string and REPLACE is non-nil, 
delete FIELD."
   (bbdb-record-set-field record field annotation (not replace))
   (bbdb-change-record record))
 
-;; FIXME: For interactive calls of the following commands, the arg UPDATE-P
+;; FIXME: For interactive calls of the following commands, the arg ACTION
 ;; should have the same meaning as for `bbdb-mua-display-records',
-;; that is, it should use `bbdb-mua-update-interactive-p'.
+;; that is, it should use `bbdb-mua-interactive-action'.
 ;; But here the prefix arg is already used in a different way.
 ;; We could possibly solve this problem if all `bbdb-mua-*' commands
 ;; used another prefix arg that is consistently used only for
-;; `bbdb-mua-update-interactive-p'.
+;; `bbdb-mua-interactive-action'.
 ;; Yet this prefix arg must be defined within the key space of the MUA(s).
 ;; This results in lots of conflicts...
 ;;
 ;; Current workaround:
-;; These commands use merely the car of `bbdb-mua-update-interactive-p'.
+;; These commands use merely the car of `bbdb-mua-interactive-action'.
 ;; If one day someone proposes a smart solution to this problem (suggestions
 ;; welcome!), this solution will hopefully include the current workaround
 ;; as a subset of all its features.
@@ -771,35 +775,36 @@ If ANNOTATION is an empty string and REPLACE is non-nil, 
delete FIELD."
                  bbdb-annotate-field)))
     (list (read-string (format "Annotate `%s': " field))
           field current-prefix-arg
-          (car bbdb-mua-update-interactive-p))))
+          (car bbdb-mua-interactive-action))))
 
 ;;;###autoload
-(defun bbdb-mua-annotate-sender (annotation &optional field replace update-p)
+(defun bbdb-mua-annotate-sender (annotation &optional field replace action)
   "Add ANNOTATION to field FIELD of the BBDB record(s) of message sender(s).
 FIELD defaults to `bbdb-annotate-field'.
 If REPLACE is non-nil, ANNOTATION replaces the content of FIELD.
-UPDATE-P may take the same values as `bbdb-update-records-p'.
-For interactive calls, use car of `bbdb-mua-update-interactive-p'."
+ACTION may take the same values as `bbdb-mua-action'.
+For interactive calls, use car of `bbdb-mua-interactive-action'."
   (interactive (bbdb-mua-annotate-field-interactive))
   (bbdb-mua-wrapper
-   (dolist (record (bbdb-mua-update-records 'sender update-p))
+   (dolist (record (bbdb-mua-update-records 'sender action))
      (bbdb-annotate-record record annotation field replace))))
 
 ;;;###autoload
 (defun bbdb-mua-annotate-recipients (annotation &optional field replace
-                                                update-p)
+                                                action)
   "Add ANNOTATION to field FIELD of the BBDB records of message recipients.
 FIELD defaults to `bbdb-annotate-field'.
 If REPLACE is non-nil, ANNOTATION replaces the content of FIELD.
-UPDATE-P may take the same values as `bbdb-update-records-p'.
-For interactive calls, use car of `bbdb-mua-update-interactive-p'."
+ACTION may take the same values as `bbdb-mua-action'.
+For interactive calls, use car of `bbdb-mua-interactive-action'."
   (interactive (bbdb-mua-annotate-field-interactive))
   (bbdb-mua-wrapper
-   (dolist (record (bbdb-mua-update-records 'recipients update-p))
+   (dolist (record (bbdb-mua-update-records 'recipients action))
      (bbdb-annotate-record record annotation field replace))))
 
 (defun bbdb-mua-edit-field-interactive ()
-  "Interactive specification for command `bbdb-mua-edit-field' and friends."
+  "Interactive specification for command `bbdb-mua-edit-field' and friends.
+This uses `bbdb-mua-interactive-action'."
   (bbdb-editable)
   (list (if (eq 'all-fields bbdb-mua-edit-field)
             (intern (completing-read
@@ -808,14 +813,14 @@ For interactive calls, use car of 
`bbdb-mua-update-interactive-p'."
                              (append '(name affix organization aka mail)
                                      bbdb-xfield-label-list))))
           bbdb-mua-edit-field)
-        (bbdb-mua-update-interactive-p)))
+        (bbdb-mua-interactive-action)))
 
 ;;;###autoload
-(defun bbdb-mua-edit-field (&optional field update-p header-class)
+(defun bbdb-mua-edit-field (&optional field action header-class)
   "Edit FIELD of the BBDB record(s) of message sender(s) or recipients.
 FIELD defaults to value of variable `bbdb-mua-edit-field'.
-UPDATE-P may take the same values as `bbdb-update-records-p'.
-For interactive calls, see function `bbdb-mua-update-interactive-p'.
+ACTION may take the same values as `bbdb-mua-action'.
+For interactive calls, see function `bbdb-mua-interactive-action'.
 HEADER-CLASS is defined in `bbdb-message-headers'.  If it is nil,
 use all classes in `bbdb-message-headers'."
   (interactive (bbdb-mua-edit-field-interactive))
@@ -824,7 +829,7 @@ use all classes in `bbdb-message-headers'."
         ((not field)
          (setq field bbdb-mua-edit-field)))
   (bbdb-mua-wrapper
-   (let ((records (bbdb-mua-update-records header-class update-p))
+   (let ((records (bbdb-mua-update-records header-class action))
          (bbdb-pop-up-window-size bbdb-mua-pop-up-window-size))
      (when records
        (bbdb-display-records records nil nil nil (bbdb-mua-window-p))
@@ -832,38 +837,38 @@ use all classes in `bbdb-message-headers'."
          (bbdb-edit-field record field))))))
 
 ;;;###autoload
-(defun bbdb-mua-edit-field-sender (&optional field update-p)
+(defun bbdb-mua-edit-field-sender (&optional field action)
   "Edit FIELD of record corresponding to sender of this message.
 FIELD defaults to value of variable `bbdb-mua-edit-field'.
-UPDATE-P may take the same values as `bbdb-update-records-p'.
-For interactive calls, see function `bbdb-mua-update-interactive-p'."
+ACTION may take the same values as `bbdb-mua-action'.
+For interactive calls, see function `bbdb-mua-interactive-action'."
   (interactive (bbdb-mua-edit-field-interactive))
-  (bbdb-mua-edit-field field update-p 'sender))
+  (bbdb-mua-edit-field field action 'sender))
 
 ;;;###autoload
-(defun bbdb-mua-edit-field-recipients (&optional field update-p)
+(defun bbdb-mua-edit-field-recipients (&optional field action)
   "Edit FIELD of record corresponding to recipient of this message.
 FIELD defaults to value of variable `bbdb-mua-edit-field'.
-UPDATE-P may take the same values as `bbdb-update-records-p'.
-For interactive calls, see function `bbdb-mua-update-interactive-p'."
+ACTION may take the same values as `bbdb-mua-action'.
+For interactive calls, see function `bbdb-mua-interactive-action'."
   (interactive (bbdb-mua-edit-field-interactive))
-  (bbdb-mua-edit-field field update-p 'recipients))
+  (bbdb-mua-edit-field field action 'recipients))
 
 ;; Functions for noninteractive use in MUA hooks
 
 ;;;###autoload
-(defun bbdb-mua-auto-update (&optional header-class update-p)
+(defun bbdb-mua-auto-update (&optional header-class action)
   "Update BBDB automatically based on incoming and outgoing messages.
 This looks into the headers of a message according to HEADER-CLASS.
 Then for the mail addresses found the corresponding BBDB records are updated.
-UPDATE-P determines whether only existing BBDB records are taken
+ACTION determines whether only existing BBDB records are taken
 or whether also new records are created for these mail addresses.
 Return matching records.
 
 HEADER-CLASS is defined in `bbdb-message-headers'.  If it is nil,
 use all classes in `bbdb-message-headers'.
-UPDATE-P may take the same values as `bbdb-mua-auto-update-p'.
-If UPDATE-P is nil, use `bbdb-mua-auto-update-p' (which see).
+ACTION may take the same values as `bbdb-mua-auto-action'.
+If ACTION is nil, use `bbdb-mua-auto-action' (which see).
 
 If `bbdb-mua-pop-up' is non-nil, BBDB pops up the *BBDB* buffer
 along with the MUA window(s), displaying the matching records
@@ -876,8 +881,8 @@ into the respective MUA hooks.
 See `bbdb-mua-display-records' and friends for interactive commands."
   (let* ((bbdb-silent-internal t)
          (records (bbdb-mua-update-records header-class
-                                           (or update-p
-                                               bbdb-mua-auto-update-p)))
+                                           (or action
+                                               bbdb-mua-auto-action)))
          (bbdb-pop-up-window-size bbdb-mua-pop-up-window-size))
     (if bbdb-mua-pop-up
         (if records
diff --git a/lisp/bbdb.el b/lisp/bbdb.el
index e472dcc76c..964d637137 100644
--- a/lisp/bbdb.el
+++ b/lisp/bbdb.el
@@ -797,7 +797,9 @@ Any other symbol is interpreted as the label of an xfield."
   :group 'bbdb-mua
   :type '(symbol :tag "Field to edit"))
 
-(defcustom bbdb-mua-update-interactive-p '(search . query)
+(define-obsolete-variable-alias 'bbdb-mua-update-interactive-p
+  'bbdb-mua-interactive-action "3.0")
+(defcustom bbdb-mua-interactive-action '(search . query)
   "How BBDB's interactive MUA commands update BBDB records.
 This is a cons pair (WITHOUT-PREFIX . WITH-PREFIX).
 The car is used if the command is called without a prefix.
@@ -833,7 +835,9 @@ WITHOUT-PREFIX and WITH-PREFIX may take the values
                        (function :tag "User-defined function")
                        (const :tag "read arg interactively" read))))
 
-(defcustom bbdb-mua-auto-update-p 'bbdb-select-message
+(define-obsolete-variable-alias 'bbdb-mua-auto-update-p
+  'bbdb-mua-auto-action "3.0")
+(defcustom bbdb-mua-auto-action 'bbdb-select-message
   "How `bbdb-mua-auto-update' updates BBDB records automatically.
 
 Allowed values are (here ADDRESS is an email address found in a message):
@@ -861,10 +865,12 @@ for the respective MUAs in your init file."
                  (const :tag "annotate all messages" create)
                  (function :tag "User-defined function")))
 
-(defcustom bbdb-update-records-p 'search
+(define-obsolete-variable-alias 'bbdb-update-records-p
+  'bbdb-mua-action "3.0")
+(defcustom bbdb-mua-action 'search
   "Return value for `bbdb-select-message' and friends.
 These functions can select messages for further processing by BBDB,
-The amount of subsequent processing is determined by `bbdb-update-records-p'.
+The amount of subsequent processing is determined by `bbdb-mua-action'.
 
 Allowed values are (here ADDRESS is an email address selected
 by `bbdb-select-message'):
@@ -889,7 +895,7 @@ by `bbdb-select-message'):
                  (function :tag "User-defined function")))
 
 (defcustom bbdb-message-headers
-  '((sender     "From" "Resent-From" "Reply-To" "Sender")
+  '((sender     "Resent-From" "Reply-To" "From" "Sender")
     (recipients "Resent-To" "Resent-CC" "To" "CC" "BCC"))
   "Alist of headers to search for sender and recipients mail addresses.
 Each element is of the form
@@ -897,7 +903,9 @@ Each element is of the form
   (CLASS HEADER ...)
 
 The symbol CLASS defines a class of headers.
-The strings HEADER belong to CLASS."
+The strings HEADER belong to CLASS.
+The most important HEADERs should appear first.
+If `bbdb-message-all-addresses' is nil, use only the first matching header."
   :group 'bbdb-mua
   :type 'list)
 
@@ -954,7 +962,8 @@ See also `bbdb-accept-message-alist', which has the 
opposite effect."
 
 (defcustom bbdb-user-mail-address-re
   (and (stringp user-mail-address)
-       (string-match "\\`\\([^@]*\\)\\(@\\|\\'\\)" user-mail-address)
+       (let ((case-fold-search t))
+         (string-match "\\`\\([^@]*\\)\\(@\\|\\'\\)" user-mail-address))
        (concat "\\<" (regexp-quote (match-string 1 user-mail-address)) "\\>"))
   "A regular expression matching your mail addresses.
 Several BBDB commands extract either the sender or the recipients' email
@@ -974,7 +983,7 @@ Allowed values are:
  t           Automatically change the name to the new value.
  query       Query whether to use the new name.
  nil         Ignore the new name.
- a number    Number of seconds BBDB displays the name mismatch.
+ a number    Number of seconds BBDB displays the name mismatch
                (without further action).
  a function  This is called with two args, the record and the new name.
                It should return one of the above values.
@@ -1052,7 +1061,9 @@ See also `bbdb-add-mails'."
                  (function :tag "Function for analyzing primary handling")
                  (regexp :tag "If the new mail address matches this regexp put 
it at the end.")))
 
-(defcustom bbdb-canonicalize-mail-function #'bbdb-string-trim
+(define-obsolete-variable-alias 'bbdb-canonicalize-mail-function
+  'bbdb-message-clean-mail-function "3.3")
+(defcustom bbdb-message-clean-mail-function #'bbdb-string-trim
   "If non-nil, it should be a function of one arg: a mail address string.
 When BBDB \"notices\" a message, the corresponding mail addresses are passed
 to this function first.  It acts as a kind of \"filter\" to transform
@@ -1064,6 +1075,16 @@ See also `bbdb-ignore-redundant-mails'."
   :group 'bbdb-mua
   :type 'function)
 
+(defcustom bbdb-message-ignore-mail-re nil
+  "If non-nil, mail addresses matching this regexp are ignored.
+This can be something like \"not?[-_]?reply@\".
+This variable applies to the case where the name associated with a mail address
+matches an existing record.  Unlike `bbdb-ignore-redundant-mails', it also
+applies to new records.  See also `bbdb-message-clean-mail-function'."
+  :group 'bbdb-mua
+  :type '(choice (const :tag "Do nothing" nil)
+                 (regexp :tag "If a mail address matches this regexp ignore 
it.")))
+
 (define-obsolete-variable-alias 'bbdb-canonicalize-redundant-mails
   'bbdb-ignore-redundant-mails "3.0")
 (defcustom bbdb-ignore-redundant-mails 'query
@@ -1083,7 +1104,8 @@ Allowed values are:
                It should return one of the above values.
  a regexp    If the new mail address matches this regexp never ignore
                this mail address.  Otherwise query to ignore it.
-See also `bbdb-add-mails' and `bbdb-canonicalize-mail-function'."
+See also `bbdb-add-mails', `bbdb-message-clean-mail-function',
+and 'bbdb-message-ignore-mail-re'."
   :group 'bbdb-mua
   :type '(choice (const :tag "Automatically ignore redundant mail addresses" t)
                  (const :tag "Query whether to ignore them" query)
@@ -1095,7 +1117,27 @@ See also `bbdb-add-mails' and 
`bbdb-canonicalize-mail-function'."
 (defcustom bbdb-message-clean-name-function #'bbdb-message-clean-name-default
   "Function to clean up the name in the header of a message.
 It takes one argument, the name as extracted by
-`mail-extract-address-components'."
+`mail-extract-address-components'.
+If this function returns nil, BBDB assumes that there is no name."
+  :group 'bbdb-mua
+  :type 'function)
+
+(defcustom bbdb-message-ignore-name-re nil
+  "If non-nil, names in a message matching this regexp are ignored."
+  :group 'bbdb-mua
+  :type '(choice (const :tag "Do nothing" nil)
+                 (regexp :tag "If a name matches this regexp ignore it.")))
+
+(defcustom bbdb-record-address-alist-function #'identity
+  "Function massaging the record-addresses associations for annotating records.
+The argument of this function is an alist with elements
+  (RECORD (ADDRESS1 ADDRESS2 ...))
+RECORD is the record that will be annotated.  Each element ADDRESS is a list
+  (NAME MAIL HEADER HEADER-CLASS MUA)
+as returned by `bbdb-get-address-components'.  RECORD may be nil
+when no existing record matches an address.  In such a case, there is
+only one element ADDRESS that BBDB uses to create a new record.
+The return value should be an alist with the same structure as the argument."
   :group 'bbdb-mua
   :type 'function)
 
@@ -1154,7 +1196,7 @@ Hook is run with one argument, the record."
 This automatically annotates the BBDB record of the sender or recipient
 of a message based on the value of a header such as the Subject header.
 This requires that `bbdb-notice-mail-hook' contains `bbdb-auto-notes'
-and that the record already exists or `bbdb-update-records-p' returns such that
+and that the record already exists or `bbdb-mua-action' returns such that
 the record will be created.  Messages matching 
`bbdb-auto-notes-ignore-messages'
 are ignored.
 
@@ -1709,11 +1751,8 @@ See also `bbdb-silent'.")
 (defvar bbdb-append-display nil
   "Controls the behavior of the command `bbdb-append-display'.")
 
-(defvar bbdb-offer-to-create nil
-  "For communication between `bbdb-update-records' and `bbdb-query-create'.")
-
 (defvar bbdb-update-records-address nil
-  "For communication between `bbdb-update-records' and `bbdb-query-create'.
+  "For `bbdb-notice-mail-hook'.
 It is a list with elements (NAME MAIL HEADER HEADER-CLASS MUA).")
 
 ;;; Buffer-local variables for the database.
@@ -2165,7 +2204,8 @@ Used with variable `bbdb-add-name' and friends."
   (cond ((functionp spec)
          (funcall spec record string))
         ((stringp spec)
-         (unless (string-match spec string) 'query)) ; be least aggressive
+         (unless (let ((case-fold-search t))
+                   (string-match spec string) 'query))) ; be least aggressive
         (spec)))
 
 (defsubst bbdb-eval-spec (spec prompt)
@@ -2179,16 +2219,25 @@ Used with return values of `bbdb-add-job'."
 
 (defun bbdb-clean-address-components (components)
   "Clean mail address COMPONENTS.
-COMPONENTS is a list (FULL-NAME CANONICAL-ADDRESS) as returned
+COMPONENTS is a list (NAME MAIL) as returned
 by `mail-extract-address-components'.
-Pass FULL-NAME through `bbdb-message-clean-name-function'
-and CANONICAL-ADDRESS through `bbdb-canonicalize-mail-function'."
-  (list (if (car components)
-            (funcall (or bbdb-message-clean-name-function #'identity)
-                     (car components)))
-        (if (cadr components)
-            (funcall (or bbdb-canonicalize-mail-function #'bbdb-string-trim)
-                     (cadr components)))))
+Pass NAME through `bbdb-message-clean-name-function'
+and MAIL through `bbdb-message-clean-mail-function'."
+  (let ((name (car components))
+        (mail (cadr components)))
+    (if (and name bbdb-message-clean-name-function)
+        (setq name (funcall bbdb-message-clean-name-function name)))
+    (if (and name bbdb-message-ignore-name-re
+             (let ((case-fold-search t))
+               (string-match bbdb-message-ignore-name-re name)))
+        (setq name nil))
+    (if (and mail bbdb-message-clean-mail-function)
+        (setq mail (funcall bbdb-message-clean-mail-function mail)))
+    (if (and mail bbdb-message-ignore-mail-re
+             (let ((case-fold-search t))
+               (string-match bbdb-message-ignore-mail-re mail)))
+        (setq mail nil))
+    (list name mail)))
 
 (defun bbdb-extract-address-components (address &optional all)
   "Given an RFC-822 address ADDRESS, extract full name and canonical address.
@@ -2211,7 +2260,7 @@ from the outside world.  Yet when analyzing the mail 
addresses stored
 in BBDB, this pollutes the mail-aka space.  So we define here
 an intentionally much simpler function for decomposing the names
 and canonical addresses in the mail field of BBDB records."
-  (let (name address)
+  (let ((case-fold-search t) name address)
     ;; First find the address - the thing with the @ in it.
     (cond (;; Check `<foo@bar>' first in order to handle the quite common
           ;; form `"abc@xyz" <foo@bar>' (i.e. `@' as part of a comment)
@@ -2248,7 +2297,7 @@ Used by  `bbdb-canonicalize-mail-1'.  See also 
`bbdb-ignore-redundant-mails'."
   :type '(regexp :tag "Regexp matching sites"))
 
 (defun bbdb-canonicalize-mail-1 (address)
-  "Example of `bbdb-canonicalize-mail-function'.
+  "Example of `bbdb-message-clean-mail-function'.
 However, this function is too specific to be useful for the general user.
 Take it as a source of inspiration for what can be done."
   (setq address (bbdb-string-trim address))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]