Here at Honeywell, the email addresses of those who labor under
Microsoft Mail are not the normal "Firstname Lastname" format one
would expect, but rather "Lastname, Firstname."  After adding a whole
lot of AKA fields, I got bored with that and made the following hack
to bbdb-annotate-message-sender.  As you can see I just redefined this
function using eval-after-load, because I couldn't figure out how to
reconcile my stuff with the distributed code.

There are two primary reasons for my inability to reconcile the stuff,
which I had thought would be possible using advice:

1.  the piece of code that ought to be advised is bbdb-search-simple,
    which is defined using defsubst, instead of defun;

2.  despite many attempts, I just can't manage to grok the emacs lisp
    advice facility.

Hope some of you find this useful.

R


(eval-after-load "bbdb-rmail"
  (defun bbdb-annotate-message-sender (from &optional loudly create-p
                                            prompt-to-create-p)
    "Fills the record corresponding to the sender with as much info as possible.
A record may be created by this; a record or nil is returned.
If bbdb-readonly-p is true, then a record will never be created.
If CREATE-P is true, then a record may be created, otherwise it won't.
If PROMPT-TO-CREATE-P is true, then the user will be asked for confirmation
before the record is created, otherwise it is created without confirmation 
\(assuming that CREATE-P is true\).  "
    (let* ((data (mail-extract-address-components from))
           (name (car data))
           (net (car (cdr data))))
      (if (equal name net) (setq name nil))
      (bbdb-debug
       (if (equal name "") (error "mail-extr returned \"\" as name"))
       (if (equal net "") (error "mail-extr returned \"\" as net")))

      (if (and net bbdb-canonicalize-net-hook)
          (setq net (bbdb-canonicalize-address net)))

      (let ((change-p nil)
            ;;this is the stuff I changed, because the MS mail
            ;;systems that send stuff to me often have peoples'
            ;;names last-name-first.[goldman:1994.12.3.0:14.14.CST]
            (record (or (bbdb-search-simple name net)
                        (let ((name-break (string-match "," name)))
                          (when name-break
                            (let ((new-name (concat
                                             ;;stuff after last name
                                             (substring name
                                                        (1+ (match-end 0)))
                                             " "
                                             (substring name 0
                                                        name-break))))
                              (bbdb-search-simple new-name net))))))
            (created-p nil)
            (fname name)
            (lname nil)
            old-name
            bogon-mode)
        (and record (setq old-name (bbdb-record-name record)))

        ;; This is to prevent having losers like "John <blat@foop>" match
        ;; against existing records like "Someone Else <john>".
        ;;
        ;; The solution implemented here is to never create or show records
        ;; corresponding to a person who has a real-name which is the same
        ;; as the network-address of someone in the db already.  This is not
        ;; a good solution.
        (let (down-name old-net)
          (if (and record name
                   (not (equal (setq down-name (downcase name))
                               (and old-name (downcase old-name)))))
              (progn
                (setq old-net (bbdb-record-net record))
                (while old-net
                  (if (equal down-name (downcase (car old-net)))
                      (progn
                        (setq bogon-mode t
                              old-net nil)
                        (message
                         "Ignoring bogon %s's name \"%s\" to avoid name-clash with 
\"%s\""
                         net name old-name)
                        (sit-for 2))
                    (setq old-net (cdr old-net)))))))
    
        (if (or record
                bbdb-readonly-p
                (not create-p)
                (not (or name net))
                bogon-mode)
            ;; no further action required
            nil
          ;; otherwise, the db is writable, and we may create a record.
          (setq record (if (or (null prompt-to-create-p)
                               (bbdb-y-or-n-p (format "%s is not in the db; rectify? " 
name)))
                           (make-vector bbdb-record-length nil))
                created-p (not (null record)))
          (if record
              (bbdb-record-set-cache record (make-vector bbdb-cache-length nil)))
          (if created-p (bbdb-invoke-hook 'bbdb-create-hook record)))
        (if (or bogon-mode (null record))
            nil
          (bbdb-debug (if (bbdb-record-deleted-p record)
                          (error "nasty nasty deleted record nasty.")))
          (if (and name
                   (not (equal (and name (downcase name))
                               (and old-name (downcase old-name))))
                   (or (null bbdb-use-alternate-names)
                       (not (bbdb-check-alternate-name name record)))
                   (let ((fullname (bbdb-divide-name name))
                         tmp)
                     (setq fname (car fullname)
                           lname (nth 1 fullname))
                     (not (and (equal (downcase fname)
                                      (and (setq tmp (bbdb-record-firstname record))
                                           (downcase tmp)))
                               (equal (downcase lname)
                                      (and (setq tmp (bbdb-record-lastname record))
                                           (downcase tmp)))))))
              ;; have a message-name, not the same as old name.
              (cond (bbdb-readonly-p nil)
                    ;;(created-p nil)
                    ((and bbdb-quiet-about-name-mismatches old-name)
                     (message "name mismatch: \"%s\" changed to \"%s\""
                              (bbdb-record-name record) name)
                     (sit-for 1))
                    ((or created-p
                         (if (null old-name)
                             (bbdb-y-or-n-p (format "Assign name \"%s\" to address 
\"%s\"? "
                                                    name (car (bbdb-record-net 
record))))
                           (bbdb-y-or-n-p (format "Change name \"%s\" to \"%s\"? "
                                                  old-name name))))
                     (setq change-p 'sort)
                     (and old-name bbdb-use-alternate-names
                          (if (bbdb-y-or-n-p (format "Keep name \"%s\" as an AKA? " 
old-name))
                              (bbdb-record-set-aka record
                                                   (cons old-name (bbdb-record-aka 
record)))
                            (bbdb-remhash (downcase old-name))))
                     (bbdb-record-set-namecache record nil)
                     (bbdb-record-set-firstname record fname)
                     (bbdb-record-set-lastname record lname)
                     (bbdb-debug (or fname lname
                                     (error "bbdb: should have a name by now")))
                     (bbdb-puthash (downcase (bbdb-record-name record))
                                   record)
                     )
                    ((and old-name
                          bbdb-use-alternate-names
                          (bbdb-y-or-n-p
                           (format "Make \"%s\" an alternate for \"%s\"? "
                                   name old-name)))
                     (setq change-p 'sort)
                     (bbdb-record-set-aka
                      record
                      (cons name (bbdb-record-aka record)))
                     (bbdb-puthash (downcase name) record)
                     )))

          ;; It's kind of a kludge that the "redundancy" concept is built in.
          ;; Maybe I should just add a new hook here...  The problem is that the
          ;; canonicalize-net-hook is run before database lookup, and thus can't
          ;; refer to the database to determine whether a net is redundant.
          (if bbdb-canonicalize-redundant-nets-p
              (setq net (or (bbdb-net-redundant-p net (bbdb-record-net record))
                            net)))

          (if (and net (not bbdb-readonly-p))
              (if (null (bbdb-record-net record))
                  ;; names are always a sure match, so don't bother prompting here.
                  (progn (bbdb-record-set-net record (list net))
                         (bbdb-puthash (downcase net) record) ; important!
                         (or change-p (setq change-p t)))
                ;; new address; ask before adding.
                (if (let ((rest-net (bbdb-record-net record))
                          (new (downcase net))
                          (match nil))
                      (while (and rest-net (null match))
                        (setq match (string= new (downcase (car rest-net)))
                              rest-net (cdr rest-net)))
                      match)
                    nil
                  (if (cond
                       ((eq bbdb-always-add-addresses t)
                        t)
                       (bbdb-always-add-addresses ; non-t and non-nil = never
                        nil)
                       (t
                        (and
                         (not (equal net "???"))
                         (let ((the-first-bit
                                (format "add address \"%s\" to \"" net))
                               ;; this groveling is to prevent the "(y or n)" from
                               ;; falling off the right edge of the screen.
                               (the-next-bit (mapconcat 'identity
                                                        (bbdb-record-net record)
                                                        ", "))
                               (w (window-width (minibuffer-window))))
                           (if (> (+ (length the-first-bit)
                                     (length the-next-bit) 15) w)
                               (setq the-next-bit
                                     (concat
                                      (substring the-next-bit
                                                 0 (max 0 (- w (length the-first-bit) 
20)))
                                      "...")))
                           (bbdb-y-or-n-p (concat the-first-bit the-next-bit
                                                  "\"? "))))))
                      (let ((front-p (cond ((null bbdb-new-nets-always-primary)
                                            (bbdb-y-or-n-p
                                             (format
                                              "Make \"%s\" the primary address? "
                                              net)))
                                           ((eq bbdb-new-nets-always-primary t)
                                            t)
                                           (t nil))))
                        (bbdb-record-set-net record
                                             (if front-p
                                                 (cons net (bbdb-record-net record))
                                               (nconc (bbdb-record-net record) (list 
net))))
                        (bbdb-puthash (downcase net) record) ; important!
                        (or change-p (setq change-p t)))))))
          (bbdb-debug
           (if (and change-p bbdb-readonly-p)
               (error
                "doubleplus ungood: how did we change anything in readonly mode?")))
          (if (and loudly change-p)
              (if (eq change-p 'sort)
                  (message "noticed \"%s\"" (bbdb-record-name record))
                (if (bbdb-record-name record)
                    (message "noticed %s's address \"%s\"" (bbdb-record-name record) 
net)
                  (message "noticed naked address \"%s\"" net))))
          (if change-p
              (bbdb-change-record record (eq change-p 'sort)))
          (bbdb-invoke-hook 'bbdb-notice-hook record)
          record)))))

Reply via email to