1 ;;; -*- Mode:Emacs-Lisp -*-
3 ;;; This file is part of the Insidious Big Brother Database (aka BBDB),
4 ;;; copyright (c) 1991, 1992, 1993 Jamie Zawinski <jwz@netscape.com>.
5 ;;; Various additional functionality for the BBDB. See bbdb.texinfo.
7 ;;; The Insidious Big Brother Database is free software; you can redistribute
8 ;;; it and/or modify it under the terms of the GNU General Public License as
9 ;;; published by the Free Software Foundation; either version 2 or (at your
10 ;;; option) any later version.
12 ;;; BBDB is distributed in the hope that it will be useful, but WITHOUT ANY
13 ;;; WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 ;;; FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 ;;; You should have received a copy of the GNU General Public License
18 ;;; along with GNU Emacs; see the file COPYING. If not, write to
19 ;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21 ;;; This file lets you do stuff like
23 ;;; o automatically update a "timestamp" field each time a record is
25 ;;; o automatically add some string to the notes field(s) based on the
26 ;;; contents of header fields of the current message
27 ;;; o only automatically create entries when certain header fields
29 ;;; o don't automatically create entries when certain header fields
32 ;;; Read the docstrings; read the texinfo file.
35 ;; $Id: bbdb-hooks.el,v 1.7 2007-02-23 20:24:07 fenk Exp $
53 (autoload 'mh-show "mh-e")
59 (defvar mh-show-buffer)
62 (defvar bbdb-time-internal-format "%Y-%m-%d"
63 "The internal date format.")
66 (defun bbdb-timestamp-hook (record)
67 "For use as a `bbdb-change-hook'; maintains a notes-field called `timestamp'
68 for the given record which contains the time when it was last modified. If
69 there is such a field there already, it is changed, otherwise it is added."
70 (bbdb-record-putprop record 'timestamp (format-time-string
71 bbdb-time-internal-format
75 (defun bbdb-creation-date-hook (record)
76 "For use as a `bbdb-create-hook'; adds a notes-field called `creation-date'
77 which is the current time string."
78 ;; hey buddy, we've known about your antics since the eighties...
79 (bbdb-record-putprop record 'creation-date (format-time-string
80 bbdb-time-internal-format
84 ;;; Determining whether to create a record based on the content of the
88 (defvar vm-mail-buffer)
89 (defvar vm-message-pointer)
90 (autoload 'vm-start-of "vm")
91 (autoload 'bbdb/vm-pop-up-bbdb-buffer "bbdb-vm"))
94 (defun bbdb-header-start ()
95 "Returns a marker at the beginning of the header block of the current
96 message. This will not necessarily be in the current buffer."
97 (cond ((memq major-mode
98 '(gnus-group-mode gnus-summary-mode gnus-article-mode))
99 (set-buffer (or gnus-original-article-buffer
100 gnus-article-buffer))
102 ((memq major-mode '(vm-presentation-mode vm-mode vm-summary-mode))
103 (if vm-mail-buffer (set-buffer vm-mail-buffer))
104 (vm-start-of (car vm-message-pointer)))
105 ((memq major-mode '(rmail-mode rmail-summary-mode))
106 (if (and (boundp 'rmail-buffer) rmail-buffer)
107 (set-buffer rmail-buffer))
109 ;; MH-E clause added by knabe.
110 ((eq major-mode 'mh-folder-mode)
112 (set-buffer mh-show-buffer)
114 (t (point-min-marker))
119 (defun bbdb-extract-field-value (field-name)
120 "Given the name of a field (like \"Subject\") this returns the value of
121 that field in the current message, or nil. This works whether you're in
122 Gnus, Rmail, or VM. This works on multi-line fields, but if more than
123 one field of the same name is present, only the last is returned. It is
124 expected that the current buffer has a message in it, and (point) is at the
125 beginning of the message headers."
126 ;; we can't special-case VM here to use its cache, because the cache has
127 ;; divided real-names from addresses; the actual From: and Subject: fields
128 ;; exist only in the message.
131 '(gnus-summary-mode gnus-article-mode gnus-tree-mode))
133 (set-buffer (get-buffer gnus-original-article-buffer))
134 (goto-char (point-min))))
135 (setq field-name (concat (regexp-quote field-name) "[ \t]*:[ \t]*"))
136 (let ((case-fold-search t)
139 (looking-at "\n") ; we're at BOL
141 (if (looking-at field-name)
143 (goto-char (match-end 0))
144 (setq done (buffer-substring (point)
145 (progn (end-of-line) (point))))
146 (while (looking-at "\n[ \t]")
147 (setq done (concat done " "
148 (buffer-substring (match-end 0)
149 (progn (end-of-line 2) (point))))))))
152 (mail-decode-encoded-word-string done)))))
154 (defcustom bbdb-ignore-most-messages-alist '()
155 "*An alist describing which messages to automatically create BBDB
156 records for. This only works if bbdb/news-auto-create-p or
157 bbdb/mail-auto-create-p (or both) is 'bbdb-ignore-most-messages-hook.
158 The format of this alist is
159 (( HEADER-NAME . REGEXP ) ... )
161 ((\"From\" . \"@.*\\.maximegalon\\.edu\")
162 (\"Subject\" . \"time travel\"))
163 will cause BBDB entries to be made only for messages sent by people at
164 Maximegalon U., or (that's *or*) people posting about time travel.
166 See also bbdb-ignore-some-messages-alist, which has the opposite effect."
167 :group 'bbdb-noticing-records
169 (string :tag "Header name")
170 (regexp :tag "Regex to match on header value"))))
173 (defcustom bbdb-ignore-some-messages-alist '()
174 "*An alist describing which messages *not* to automatically create
175 BBDB records for. This only works if bbdb/news-auto-create-p or
176 bbdb/mail-auto-create-p (or both) is 'bbdb-ignore-some-messages-hook.
177 The format of this alist is
178 (( HEADER-NAME . REGEXP ) ... )
180 ((\"From\" . \"mailer-daemon\")
181 (\"To\" . \"mailing-list-1\\\\|mailing-list-2\")
182 (\"CC\" . \"mailing-list-1\\\\|mailing-list-2\"))
183 will cause BBDB entries to not be made for messages from any mailer daemon,
184 or messages sent to or CCed to either of two mailing lists.
186 See also bbdb-ignore-most-messages-alist, which has the opposite effect."
187 :group 'bbdb-noticing-records
189 (string :tag "Header name")
190 (regexp :tag "Regex to match on header value"))))
194 (defun bbdb-ignore-most-messages-hook (&optional invert-sense)
195 "For use as the value of bbdb/news-auto-create-p or bbdb/mail-auto-create-p.
196 This will automatically create BBDB entries for messages which match
197 the bbdb-ignore-most-messages-alist (which see) and *no* others."
198 ;; don't need to optimize this to check the cache, because if
199 ;; bbdb/*-update-record uses the cache, this won't be called.
200 (let ((rest (if invert-sense
201 bbdb-ignore-some-messages-alist
202 bbdb-ignore-most-messages-alist))
206 (marker (bbdb-header-start))
207 field regexp fieldval)
208 (set-buffer (marker-buffer marker))
211 (while (and rest (not done))
213 (setq field (car (car rest))
214 regexp (cdr (car rest))
215 fieldval (bbdb-extract-field-value field))
216 (if (and fieldval (string-match regexp fieldval))
218 (setq rest (cdr rest))))
224 ;;; Provided by Bill Carpenter.
225 (defvar bbdb-ignore-selected-messages-confirmation nil
226 "*If bbdb-ignore-selected-messages-hook is used as an auto-create-hook, this
227 variable governs whether you are prompted for creation of BBDB entries.")
230 (defun bbdb-ignore-selected-messages-hook ()
231 "For use as a bbdb/news-auto-create-hook or bbdb/mail-auto-create-hook.
232 This will automatically create BBDB entries for messages based on a
233 combination of bbdb-ignore-some-messages-alist and
234 bbdb-ignore-most-messages-alist. It first looks at the SOME list. If
235 that doesn't disqualify a message, then it looks at the MOST list. If
236 that qualifies the message, the record is auto-created, but a
237 confirmation is conditionally sought, based on the value of
238 `bbdb-ignore-selected-messages-confirmation'."
239 (if (bbdb-ignore-some-messages-hook)
241 (if (bbdb-ignore-most-messages-hook)
243 (if bbdb-ignore-selected-messages-confirmation
244 (let ((case-fold-search t)
245 (marker (bbdb-header-start))
248 (set-buffer (marker-buffer marker))
252 (setq from (bbdb-extract-field-value "FROM"))))
253 (setq record-exists (bbdb-annotate-message-sender from))
255 (y-or-n-p (concat "Create BBDB record from " from "? "))))
256 ;; no confirmation desired so let it be
262 (defun bbdb-ignore-some-messages-hook ()
263 "For use as a `bbdb/news-auto-create-hook' or `bbdb/mail-auto-create-hook'.
264 This will automatically create BBDB entries for messages which do *not*
265 match the `bbdb-ignore-some-messages-alist' (which see)."
266 (bbdb-ignore-most-messages-hook t))
269 ;;; Automatically add to the notes field based on the current message.
271 (defcustom bbdb-auto-notes-alist nil
272 "*An alist which lets you have certain pieces of text automatically added
273 to the BBDB record representing the sender of the current message based on
274 the subject or other header fields. This only works if `bbdb-notice-hook'
275 contains `bbdb-auto-notes-hook'. The format of this alist is
277 ((HEADER-NAME [ADDRESS-CLASS-LIST]
278 (REGEXP . STRING) ... )
281 ((\"To\" (\"-vm@\" . \"VM mailing list\"))
282 (\"Subject\" (\"sprocket\" . \"mail about sprockets\")
283 (\"you bonehead\" . \"called me a bonehead\")))
285 will cause the text \"VM mailing list\" to be added to the notes field of
286 the record corresponding to anyone you get mail from via one of the VM
287 mailing lists. If, that is, `bbdb/mail-auto-create-p' is set such that the
288 record would have been created, or the record already existed.
290 A ADDRESS-CLASS-LIST is optional and by default actions will be performed only
291 for records of authors of a message. However, by giving an list of classes
292 specified in `bbdb-get-addresses-headers'. Actions will then only be
293 performed if the currently processed email is of a class listed in
294 ADDRESS-CLASS-LIST. ADDRESS-CLASS-LIST might also be an alist with elements
295 of the form (CLASS . HEADER) which allows actions only when the current
296 address matches one of the elemets.
298 The format of elements of this list may also be
299 (REGEXP FIELD-NAME STRING)
301 (REGEXP FIELD-NAME STRING REPLACE-P)
305 meaning add the given string to the named field. The field-name may not
306 be name, address, phone, or net (builtin fields) but must be either ``notes,''
307 ``company,'' or the name of a user-defined note-field.
308 (\"pattern\" . \"string to add\")
310 (\"pattern\" notes \"string to add\")
312 STRING can contain \\& or \\N escapes like in function
313 `replace-match'. For example, to automatically add the contents of the
314 \"organization\" field of a message to the \"company\" field of a BBDB
315 record, you can use this:
317 (\"Organization\" (\".*\" company \"\\\\&\"))
319 \(Note you need two \\ to get a single \\ into a lisp string literal.\)
321 If STRING is an integer N, the N'th matching subexpression is used, so
322 the above example could be written more efficiently as
324 (\"Organization\" (\".*\" company 0))
326 If STRING is neither a string or an integer, it should be a function, which
327 will be called with the contents of the field. The result of that function
328 call is used as the field value (the returned value must be a string.)
330 If REPLACE-P is t, the string replaces the old contents instead of
331 being appended to it.
333 If multiple clauses match the message, all of the corresponding strings
336 This works for news as well. You might want to arrange for this to have
337 a different value when in mail as when in news.
339 See also variables `bbdb-auto-notes-ignore' and `bbdb-auto-notes-ignore-all'."
340 :group 'bbdb-noticing-records
342 (bbdb-alist-with-header
343 (string :tag "Header name")
345 (cons :tag "Address Class"
348 (const recipients))))
349 (cons :tag "Value Pair"
350 (regexp :tag "Regexp to match on header value")
351 (string :tag "String for notes if regexp matches"))
352 (list :tag "Replacement list"
353 (regexp :tag "Regexp to match on header value")
354 (choice :tag "Record field"
355 (const notes :tag "Notes")
356 (const company :tag "Company")
357 (symbol :tag "Other"))
358 (choice :tag "Regexp match"
359 (string :tag "Replacement string")
360 (integer :tag "Subexpression match")
361 (function :tag "Callback Function"))
362 (choice :tag "Replace previous contents"
363 (const :tag "No" nil)
364 (const :tag "Yes" t))))))))
366 (defcustom bbdb-auto-notes-ignore nil
367 "Alist of headers and regexps to ignore in `bbdb-auto-notes-hook'.
368 Each element looks like
374 (\"Organization\" . \"^Gatewayed from\\\\\|^Source only\")
376 would exclude the phony `Organization:' headers in GNU mailing-lists
377 gatewayed to gnu.* newsgroups. Note that this exclusion applies only
378 to a single field, not to the entire message. For that, use the variable
379 `bbdb-auto-notes-ignore-all'."
380 :group 'bbdb-noticing-records
382 (string :tag "Header name")
383 (regexp :tag "Regexp to match on header value"))))
385 (defcustom bbdb-auto-notes-ignore-all nil
386 "Alist of headers and regexps which cause the entire message to be ignored
387 in `bbdb-auto-notes-hook'. Each element looks like
393 (\"From\" . \"BLAT\\\\.COM\")
395 would exclude any notes recording for message coming from BLAT.COM.
396 Note that this is different from `bbdb-auto-notes-ignore', which applies
397 only to a particular header field, rather than the entire message."
398 :group 'bbdb-noticing-records
400 (string :tag "Header name")
401 (regexp :tag "Regexp to match on header value"))))
405 (defun bbdb-auto-notes-hook (record)
406 "For use as a `bbdb-notice-hook'. This might automatically add some text
407 to the notes field of the BBDB record corresponding to the current record
408 based on the header of the current message. See the documentation for
409 the variables `bbdb-auto-notes-alist' and `bbdb-auto-notes-ignore'."
410 ;; This could stand to be faster...
411 ;; could optimize this to check the cache, and noop if this record is
412 ;; cached for any other message, but that's probably not the right thing.
413 (unless bbdb-readonly-p
414 (let ((rest bbdb-auto-notes-alist)
415 (ignore-all bbdb-auto-notes-ignore-all)
418 (marker (bbdb-header-start))
420 field pairs fieldval ; do all bindings here for speed
421 regexp string notes-field-name notes
423 (set-buffer (marker-buffer marker))
427 (if (and (setq fieldval (bbdb-extract-field-value "From"))
428 (string-match (bbdb-user-mail-names) fieldval))
429 ;; Don't do anything if this message is from us. Note that we have
430 ;; to look at the message instead of the record, because the record
431 ;; will be of the recipient of the message if it is from us.
433 ;; check the ignore-all pattern
434 (while (and ignore-all (not ignore))
436 (setq field (car (car ignore-all))
437 regexp (cdr (car ignore-all))
438 fieldval (bbdb-extract-field-value field))
440 (string-match regexp fieldval))
442 (setq ignore-all (cdr ignore-all))))
444 (unless ignore ; ignore-all matched
445 (while rest ; while there are still clauses in the auto-notes alist
447 (setq field (car (car rest)) ; name of header, e.g., "Subject"
448 pairs (cdr (car rest)) ; (REGEXP . STRING) or
449 ; (REGEXP FIELD-NAME STRING) or
450 ; (REGEXP FIELD-NAME STRING REPLACE-P)
451 fieldval (bbdb-extract-field-value field)) ; e.g., Subject line
453 ;; we perform the auto notes stuff only for authors of a message
454 ;; or if explicitly requested
455 (if (or (symbolp (caar pairs)) (listp (caar pairs)))
456 (if (or (memq bbdb-update-address-class (car pairs))
457 (and (assoc bbdb-update-address-class (car pairs))
458 (string= bbdb-update-address-header
459 (cdr (assoc bbdb-update-address-class
461 (setq pairs (cdr pairs))
463 (if (not (and (eq 'authors bbdb-update-address-class)
464 (string-match "From" bbdb-update-address-header)))
467 ;; now handle the remaining pairs
469 (setq regexp (car (car pairs))
470 string (cdr (car pairs)))
471 (if (consp string) ; not just the (REGEXP . STRING) format
472 (setq notes-field-name (car string)
473 replace-p (nth 2 string) ; perhaps nil
474 string (nth 1 string))
475 ;; else it's simple (REGEXP . STRING)
476 (setq notes-field-name 'notes
478 (setq notes (bbdb-record-getprop record notes-field-name))
480 (and (string-match regexp fieldval)
481 ;; make sure it is not to be ignored
482 (let ((re (cdr (assoc field
483 bbdb-auto-notes-ignore))))
485 (not (string-match re fieldval))
487 ;; An integer as STRING is an index into match-data:
488 ;; A function as STRING calls the function on fieldval:
491 (cond ((integerp string) ; backward compat
493 (match-beginning string)
496 (bbdb-auto-expand-newtext fieldval string))
499 (let ((s (funcall string fieldval)))
502 (error "%s returned %s: not a string"
505 ;; need expanded version of STRING here:
507 string ; A function as STRING may return nil
509 ;; check that STRING is not already
510 ;; present in the NOTES field
512 (regexp-quote string)
515 ;; replace old contents of field with STRING
517 (when (not bbdb-silent-running)
518 (if (eq notes-field-name 'notes)
519 (message "Replacing with note \"%s\"" string)
520 (message "Replacing field \"%s\" with \"%s\""
521 notes-field-name string)))
522 (bbdb-record-putprop record notes-field-name string)
523 (bbdb-maybe-update-display record))
524 ;; add STRING to old contents, don't replace
525 (when (not bbdb-silent-running)
526 (if (eq notes-field-name 'notes)
527 (message "Adding note \"%s\"" string)
528 (message "Adding \"%s\" to field \"%s\""
529 string notes-field-name)))
530 (bbdb-annotate-notes record string notes-field-name))))
531 (setq pairs (cdr pairs))))
532 (setq rest (cdr rest))))))
535 (defun bbdb-auto-expand-newtext (string newtext)
536 ;; Expand \& and \1..\9 (referring to STRING) in NEWTEXT.
537 ;; Note that in Emacs 18 match data are clipped to current buffer
538 ;; size...so the buffer had better not be smaller than STRING (arrrrggggh!!)
540 (len (length newtext))
541 (expanded-newtext ""))
543 (setq expanded-newtext
544 (concat expanded-newtext
545 (let ((c (aref newtext pos)))
547 (cond ((= ?\& (setq c (aref newtext
548 (setq pos (1+ pos)))))
554 ;; return empty string if N'th
555 ;; sub-regexp did not match:
557 (if (match-beginning n)
562 (t (char-to-string c)))
563 (char-to-string c)))))
568 ;;; I use this as the value of bbdb-canonicalize-net-hook; it is provided
569 ;;; as an example for you to customize.
571 (defcustom bbdb-canonical-hosts
572 (mapconcat 'regexp-quote
573 '("cs.cmu.edu" "ri.cmu.edu" "edrc.cmu.edu" "andrew.cmu.edu"
574 "mcom.com" "netscape.com" "cenatls.cena.dgac.fr"
575 "cenaath.cena.dgac.fr" "irit.fr" "enseeiht.fr" "inria.fr"
576 "cs.uiuc.edu" "xemacs.org")
578 "Certain sites have a single mail-host; for example, all mail originating
579 at hosts whose names end in \".cs.cmu.edu\" can (and probably should) be
580 addressed to \"user@cs.cmu.edu\" instead. This variable lists other hosts
581 which behave the same way."
583 :type '(regexp :tag "Regexp matching sites"))
585 (defmacro bbdb-match-substring (string match)
586 (list 'substring string
587 (list 'match-beginning match) (list 'match-end match)))
590 (defun sample-bbdb-canonicalize-net-hook (addr)
593 ;; rewrite mail-drop hosts.
596 (concat "\\`\\([^@%!]+@\\).*\\.\\(" bbdb-canonical-hosts "\\)\\'")
598 (concat (bbdb-match-substring addr 1) (bbdb-match-substring addr 2)))
600 ;; Here at Lucid, our workstation names sometimes get into our email
601 ;; addresses in the form "jwz%thalidomide@lucid.com" (instead of simply
602 ;; "jwz@lucid.com"). This removes the workstation name.
604 ((string-match "\\`\\([^@%!]+\\)%[^@%!.]+@\\(lucid\\.com\\)\\'" addr)
605 (concat (bbdb-match-substring addr 1) "@" (bbdb-match-substring addr 2)))
607 ;; Another way that our local mailer is misconfigured: sometimes addresses
608 ;; which should look like "user@some.outside.host" end up looking like
609 ;; "user%some.outside.host" or even "user%some.outside.host@lucid.com"
610 ;; instead. This rule rewrites it into the original form.
612 ((string-match "\\`\\([^@%]+\\)%\\([^@%!]+\\)\\(@lucid\\.com\\)?\\'" addr)
613 (concat (bbdb-match-substring addr 1) "@" (bbdb-match-substring addr 2)))
615 ;; Sometimes I see addresses like "foobar.com!user@foobar.com".
616 ;; That's totally redundant, so this rewrites it as "user@foobar.com".
618 ((string-match "\\`\\([^@%!]+\\)!\\([^@%!]+[@%]\\1\\)\\'" addr)
619 (bbdb-match-substring addr 2))
621 ;; Sometimes I see addresses like "foobar.com!user". Turn it around.
623 ((string-match "\\`\\([^@%!.]+\\.[^@%!]+\\)!\\([^@%]+\\)\\'" addr)
624 (concat (bbdb-match-substring addr 2) "@" (bbdb-match-substring addr 1)))
626 ;; The mailer at hplb.hpl.hp.com tends to puke all over addresses which
627 ;; pass through mailing lists which are maintained there: it turns normal
628 ;; addresses like "user@foo.com" into "user%foo.com@hplb.hpl.hp.com".
629 ;; This reverses it. (I actually could have combined this rule with
630 ;; the similar lucid.com rule above, but then the regexp would have been
631 ;; more than 80 characters long...)
633 ((string-match "\\`\\([^@!]+\\)%\\([^@%!]+\\)@hplb\\.hpl\\.hp\\.com\\'"
635 (concat (bbdb-match-substring addr 1) "@" (bbdb-match-substring addr 2)))
637 ;; Another local mail-configuration botch: sometimes mail shows up
638 ;; with addresses like "user@workstation", where "workstation" is a
639 ;; local machine name. That should really be "user" or "user@netscape.com".
640 ;; (I'm told this one is due to a bug in SunOS 4.1.1 sendmail.)
642 ((string-match "\\`\\([^@%!]+\\)[@%][^@%!.]+\\'" addr)
643 (bbdb-match-substring addr 1))
645 ;; Sometimes I see addrs like "foo%somewhere%uunet.uu.net@somewhere.else".
646 ;; This is silly, because I know that I can send mail to uunet directly.
648 ((string-match ".%uunet\\.uu\\.net@[^@%!]+\\'" addr)
649 (concat (substring addr 0 (+ (match-beginning 0) 1)) "@UUNET.UU.NET"))
651 ;; Otherwise, leave it as it is. Returning a string EQ to the one passed
652 ;; in tells BBDB that we're done.
657 ;;; Here's another approach; sometimes one gets mail from foo@bar.baz.com,
658 ;;; and then later gets mail from foo@baz.com. At this point, one would
659 ;;; like to delete the bar.baz.com address, since the baz.com address is
660 ;;; obviously superior. See also var `bbdb-canonicalize-redundant-nets-p'.
662 ;;; Turn this on with
663 ;;; (add-hook 'bbdb-change-hook 'bbdb-delete-redundant-nets)
665 (defun bbdb-delete-redundant-nets (record)
666 "Deletes redundant network addresses.
667 For use as a value of `bbdb-change-hook'. See `bbdb-net-redundant-p'."
668 (let* ((nets (bbdb-record-net record))
672 (setq net (car rest))
673 (if (bbdb-net-redundant-p net nets)
674 (setq redundant (cons net redundant))
675 (setq new (cons net new)))
676 (setq rest (cdr rest)))
678 (message "Deleting redundant nets %s..."
679 (mapconcat 'identity (nreverse redundant) ", "))
680 (setq new (nreverse new))
681 (bbdb-record-set-net record new)
687 (defun bbdb-force-record-create ()
688 "Force automatic creation of a BBDB records for the current message.
689 You might add this to the reply hook of your MUA in order to automatically
690 get records added for those people you reply to."
692 (let ((bbdb/mail-auto-create-p t)
693 (bbdb/news-auto-create-p t)
694 (bbdb-message-caching-enabled nil)
695 (bbdb/gnus-update-records-mode 'annotating)
696 (bbdb/rmail-update-records-mode 'annotating)
697 (bbdb/mhe-update-records-mode 'annotating)
698 (bbdb/vm-update-records-mode 'annotating))
700 (cond ((member major-mode '(vm-mode vm-virtual-mode vm-summary-mode
701 vm-presentation-mode))
702 (bbdb/vm-pop-up-bbdb-buffer))
703 ((member major-mode '(gnus-summary-mode gnus-article-mode
705 (bbdb/gnus-pop-up-bbdb-buffer))
706 ((member major-mode '(rmail-mode rmail-summary-mode))
707 (bbdb/rmail-pop-up-bbdb-buffer))
708 ((member major-mode '(mhe-mode mhe-summary-mode mh-folder-mode))
709 (bbdb/mh-pop-up-bbdb-buffer))
712 (provide 'bbdb-hooks)