This is the documentation for Personality Crisis, an add-on for the mail reader VM which allows you to do all sorts of things automatically when you compose new mail messages or replies.

Copyright © 1999  Rob Hodges, 2006 Robert Widhopf-Fenk

Personality Crisis for VM
*************************

This is the documentation for Personality Crisis 0.9.1

It was written by Rob Hodges <s323140@student.uq.edu.au>.

It is currently maintained by Robert Widhopf-Fenk <hack@robf.de>

Please read the docs before sending email about problems you are having. Most problems are due to incorrect regexps.  That said, if something in the docs is unclear, I'd like to know so that I can improve them.  And if you find a bug, I'd definitely like to know.  I hope you enjoy this package.

The incompete list of Roberts which have been involved in vm-prisis:

  * Rob Hodges

  * Robert Widhopf-Fenk

  * Robert P. Goldman

  * Robert Marshall

Getting Started
***************

Installation
============

 1. Load VM if you haven't previously done so in your current Emacs session.

 2. Byte-compile vm-pcrisis.el, using M-x byte-compile-file.  You may get some byte-compiler warnings; ignore them.  (For the curious: Personality Crisis uses some functions that have different names in FSF Emacs and XEmacs, automatically detecting which one you are running.  The byte-compiler isn't smart enough to know this, so it warns of the functions it doesn't know about, even though they'll never be run.)

 3. Place the resulting .elc file somewhere in your Emacs load-path.  It would probably be a good idea to leave the .el file there with it too, but you don't have to.

 4. Add the following line to your ~/.vm file:

          (require 'vm-pcrisis)

 5. Read the rest of this manual and set up the variables it describes.

Quick start
===========

You do not want to read a manual but solve your personal crisis now?

Then add the following to your ~/.vm file:

     (require 'vm-pcrisis)
     (vmpc-my-identities "me@company1.nil" "me@home.nil" "me@alterego.nil")

Where you add you own email addresses to the call of vmpc-my-identities.  This will prompt you for the profile to use when first writing an message to a unknown email address.

Description
===========

Personality Crisis can look at the headers of a message you are replying to or forwarding, or a message you are composing, and you can set it up to do just about anything based on those.  To get some ideas about how this might be useful, see Common Uses.  You can also use it to explicitly choose a "personality" when composing new messages.

Specific Abilities
==================

Based on the headers of a message you are replying to, you can get vm-pcrisis to do any number of these things:

  * Change or insert any headers you like in your reply.

  * Change or insert a signature in your reply.

  * Insert some text in the body of your reply.

  * Change any header in your reply to the value of any of the headers in the message you are replying to.

  * Call some functions before VM creates the reply.

  * Call some functions in the reply buffer.

  * Prompt you for a personality profile to use, and optionally, remember to use that profile when sending messages to the same address in the future.

Similar functionality is available when forwarding messages.

Based on the headers of a message you are composing, it can do these things:

  * Change or insert any headers you like.

  * Change or insert a signature.

  * Insert some text in the message body.

  * Call some functions in the message buffer.

  * Prompt you for a personality profile to use, and optionally, remember to use that profile when sending messages to the same address in the future.

If you wish, you can also have vm-pcrisis prompt you for a personality when composing a new mail, which is useful if you need to set up VM variables with new mails, or if you prefer to more deliberatly choose who you are for each message.

If you write your own functions to do things that vm-pcrisis can't do by itself, ready-made functions are provided to allow you easy access to the contents of headers in both the message you are replying to, and the message you are writing.

Common Uses
===========

These are some of the common uses for Personality Crisis.

  * People with multiple e-mail addresses can automatically set up headers such as From: and Reply-To:, so that eg. their work email keeps going to their work account, and their private email to their private account.

  * People who like to have different nicknames and signatures for different lists can do so.  (Well, uh, that's why I called it Personality Crisis...)  As of version 0.7, you can select your personality for new mail messages as well as replies.

  * When people send you html-formatted email, you can have your reply automatically include a form letter explaining why they shouldn't, and how to turn it off.  (Such a letter is not included with this package; you'll have to write it yourself.)

  * People who email in multiple languages can set up the encoding for the reply, along with the keymap, ispell dictionary, attribution line for citations, etc, in the reply buffer.

  * When you get email from a mailing list that has the Reply-To: header set for the whole list, automatically change the To: field in your reply to point to the original sender instead.  (You can do the reverse as well... if you can take the flamage.)  VM allows you to do this, but only if the correct reply address is in the "From" field.

  * Automatically change the signature and various headers, etc, in a new mail message after typing in the To: address.

  * Automatically remember which personality to use when sending to a particular address.

  * If you put your imagination to work while reading through this manual, you'll probably think of other ways that vm-pcrisis can help you.  Have fun!

Overview
========

When setting up variables for Personality Crisis, you begin by thinking about what you want it to do when a certain condition occurs, either when you are replying to or forwarding a message, or in the midst of writing a message.

You define the condition in vmpc-conditions, and the action you want vm-pcrisis to take in vmpc-actions, giving a name to each. You then associate the condition with the action in vmpc-reply-alist if it's one that relies on the headers of a message you are replying to, vmpc-forward-alist if it's a message you are forwarding, or vmpc-automorph-alist if it's based on the headers of your own message.  As of v0.84, you may also use vmpc-newmail-alist to associate conditions with actions for new messages, and since v0.85, vmpc-resend-alist for resending (bouncing) messages.

If you want to use the vmpc-automorph function, which takes actions based on the headers of a message you are composing, you should read Calling Automorph to decide where you want to hook it in.

The remainder of this manual will provide more information about how to do all of these things.

Calling Automorph
=================

The vmpc-automorph function automatically sets various things in a mail message based on what's already present in its headers. Obviously, you'll need to have entered those headers before it is called.

You'll have to set up what this function does --- for which, see vmpc-conditions, vmpc-actions and vmpc-automorph-alist --- but you'll also have to consider when you want it called.

Most people would prefer never to have to call it explicitly; it's generally nicer to just have it called automatically when you do one of the other things that you have to do in the course of composing a message.  Here are a couple of ideas:

  * Hitching a ride on the mail-text function: automorph with C-c C-t.
     A very good idea if you are in the habit of using this to move from your headers to the body of your message.

  * Let vm-pcrisis help you: tab between headers.
     See below for more about this.

  * Pre-empting vm-mail-send-and-exit: automorph with C-c C-c.
     A rather foolish idea, in my opinion.  You'll never get to see the results of what automorph does.  If there should happen to be a bug in Personality Crisis that fails to take into account, say, multi-line headers, you might end up sending a mail to your boss with an inappropriate signature that, say, mentions his wife in an unflattering way, and find yourself all-too-suddenly unemployed.  How likely is this?  Well, in a previous version, such a bug existed.  I fixed it, but there could be more like it; I wouldn't risk it.

  * Calling it explicitly with some key combo.
     Boring but easy.

The last of these is the easiest --- just bind it to a key in mail mode.  For example, to bind it to the F7 key, you might put this in your ~/.vm file:

     (define-key vm-mail-mode-map [f7] 'vmpc-automorph)

Attaching to other functions is also fairly straightforward.  Just use a wrapper function.  For example:

     (defun mail-text-and-automorph ()
        (interactive)
        (mail-text)
        (vmpc-automorph))

Then bind this function to C-c C-t (or whatever keystroke you like to use).

But what's this thing about tabbing between headers?  Well, if you just want to hit TAB to go from the To: field to the Subject: field, and TAB again to then go to the start of the message body, calling vmpc-automorph along the way, you can add this in your ~/.vm file:

     (define-key vm-mail-mode-map [tab] 'vmpc-tab-header-or-tab-stop)

If you also want shift-tab to take you back to the previous header, you should check what keysym is produced by shift-tab on your system, by doing Ctrl-h k Shift-TAB -- for me, it produces iso-left-tab.  So I add this to my ~/.vm:

     (define-key vm-mail-mode-map [iso-left-tab] 'vmpc-backward-tab-header-or-tab-stop)

You can use any one or more of these ideas, calling the automorph function as often as you like.  Because its actions depend on the headers, and those actions can include the changing of headers, calling it twice may not have the same effect as calling it once.  It may pay to bear this in mind when you set up the profiles!

vmpc-conditions
***************

The vmpc-conditions variable
============================

The vmpc-conditions variable is a list of conditions, each of which can cause Personality Crisis to take a different action.  You give each condition a unique, descriptive name.  The format of the list is something like this:

     '(   ("a descriptive name"
                  (lisp-statement-1) )
          ("another descriptive name"
                  (lisp-statement-2) )   )

The lisp-statement can be any statement in lisp that will evaluate to nil if the condition is to be considered false, or non-nil if true. (Don't be afraid, non-lispers, examples are coming...)  Personality Crisis provides some functions which can be used there, in combination with and, or, and vmpc-xor to produce a fine-grained control over when your actions will trigger.

If you are using vm-avirtual.el you can also use vmpc-check-virtual-selector to check a virtual folder selector.

  * vmpc-header-match is of course the main one.  When making replies or forwards, this matches against the contents of a header in the message you are replying/forwarding; when using the vmpc-automorph function, it matches against a header in the message you are composing.

  * vmpc-body-match is just like vmpc-header-match but allows you to match against the text in the body of the message.

  * vmpc-other-cond returns true when a specified condition earlier in the list has been found true.  It's essentially a shortcut for building more complex conditions from basic ones.

  * vmpc-none-true-yet returns true if none of the conditions that come before it in vmpc-conditions have returned true.  You can optionally specify exceptions, so that it can act as a "none-true-yet-except..." condition.  This is a very useful shortcut to place last in the list, in order to trigger an action prompting you for a profile to use.

You can also use y-or-n-p if you always want to have a choice in what to do when a certain condition occurs.

We will cover all of these in the examples that follow.

vmpc-conditions examples
========================

Suppose you wanted to set up a condition that triggered when you replied to messages that came from a particular mailing list.  Looking at the headers of these messages, (exposing all of them with t in VM), you see that they always have a header like this:

Resent-Sender: foo-list-maintainer@bar.baz.com

Then, in your ~/.vm file, you would have something like this:

     (setq vmpc-conditions '(
             ("foo-list messages"
             (vmpc-header-match "Resent-Sender"
                      "foo-list-maintainer@bar.baz.com"))
     ))

This gives you a condition called "foo-list messages" which returns true when the contents of the "Resent-Sender" header include a match for the regular expression "foo-list-maintainer@bar.baz.com".

-----------------------------------------------------------------

Regexp Aside #1:
----------------

Usually this will be perfectly adequate.  Of course, since the second string is a regexp, this will also match "foo-list-maintainer@barybaz.com", but the odds that you'll come across that are pretty low.  However, if the header contents had included another regexp special character, it might not match at all.  The easiest way to deal with both these problems is to wrap the string up in a call to regexp-quote.  Like this:

     (setq vmpc-conditions '(
             ("foo-list messages"
             (vmpc-header-match "Resent-Sender"
                     (regexp-quote "foo-list-maintainer@bar.baz.com")))
     ))

Regexp Aside #2:
----------------

The regexp-opt function provides a convenient way of producing a regexp to match against any number of strings.  Suppose the "Resent-Sender" field could contain either "foo-list-maintainer@bar.baz.com" or "foo-list-bot@bar.baz.com".  Then you could use regexp-opt like this:

     (setq vmpc-conditions '(
             ("foo-list messages"
             (vmpc-header-match "Resent-Sender"
                     (regexp-opt '("foo-list-maintainer@bar.baz.com"
                                     "foo-list-bot@bar.baz.com"))))
     ))

Regexp Aside #3:
----------------

If you write your own regular expressions instead of using regexp-quote and regexp-opt, you should keep in mind that they must be in lisp syntax.  In short, this means that you should use two backslashes wherever you would usually use one, and if you use a double-quote (") it should be escaped with a backslash to avoid prematurely ending the string.  You can learn more about regexps from your Emacs documentation.

Regexp Aside #4:
----------------

The behaviour of vmpc-header-match is to return true if a match for the regular expression occurs anywhere in the contents of the header.  If you want your regexp to only match the entire header contents, it should begin with a caret (^) and end with a dollar sign ($).

-----------------------------------------------------------------

Alright, enough about regexps!  Let's get on with the example.

Suppose the next thing you want to do is set up a condition that triggers when somebody sends you one of those blasted HTML emails. (When we look at vmpc-actions you'll see how you can automatically include a form letter asking them not to do this in your reply.)  Your setup might now expand to this:

     (setq vmpc-conditions '(
             ("foo-list messages"
             (vmpc-header-match "Resent-Sender"
                     (regexp-quote "foo-list-maintainer@bar.baz.com")))
             ("html messages"
             (vmpc-header-match "Content-type"
     			    "multipart/alternative\\|html"))
     ))

Let's further suppose that foo-list is set up so that replies go to the entire list, and that you haven't over-ridden this with vm-reply-ignored-reply-tos because it's usually what you want. But when somebody sends an html message to the list, you now have a setup which results in your anti-html form letter being included in a message to the whole list.  You'd rather it went to them personally. Okay, let's set up some more refined conditions:

     (setq vmpc-conditions '(
             ("foo-list messages"
               (vmpc-header-match "Resent-Sender"
                     (regexp-quote "foo-list-maintainer@bar.baz.com")))
             ("html messages"
               (vmpc-header-match "Content-type"
     			    "multipart/alternative\\|html"))
             ("plaintext messages from foo-list"
               (and (vmpc-other-cond "foo-list messages")
                    (not (vmpc-other-cond "html messages"))))
             ("html messages from foo-list"
               (and (vmpc-other-cond "foo-list-messages")
                    (vmpc-other-cond "html messages")))
             ("html messages not from foo-list"
               (and (vmpc-other-cond "html messages")
                    (not (vmpc-other-cond "foo-list messages"))))
     ))

All of a sudden you have five conditions, but you'll only associate the last three of them with actions.  The first two are just building blocks for the others.  So now you can associate different actions with each condition:  For html messages from foo-list, you can change the To: address in your reply to point to the original sender, as well as including your anti-html form letter; for html messages not from foo-list, just include the form letter; and for plaintext messages from foo-list, set up your desired personality for a normal reply to the list.

What if you want a condition that always returns true, so you can associate it with an action that you want performed every time?  It would look like this:

             ("condition that's always true"
               't)

-----------------------------------------------------------------

Aside:
------

If you want one that always triggers for replies, but not when using vmpc-automorph, it would look like this:

             ("condition that's always true for replies"
               (eq vmpc-current-state 'reply))

Similarly, for one that always triggers with automorph, but not for replies, you'd have:

             ("condition that's always true for automorph"
               (eq vmpc-current-state 'automorph))

-----------------------------------------------------------------

If you add that condition, and more to deal with other mailing lists and situations, you might want to be prompted about what action to take when none of the conditions match (except, of course, the one that's always true).  This simplest way to produce such a condition (which you can then associate with a prompting action) is to use vmpc-none-true-yet.  So you'd end up with something like:

     (setq vmpc-conditions '(
             ("condition that's always true"
               't)
             ("foo-list messages"
               (vmpc-header-match "Resent-Sender"
                     (regexp-quote "foo-list-maintainer@bar.baz.com")))
             ("html messages"
               (vmpc-header-match "Content-type"
     			    "multipart/alternative\\|html"))
             ("plaintext messages from foo-list"
               (and (vmpc-other-cond "foo-list messages")
                    (not (vmpc-other-cond "html messages"))))
             ("html messages from foo-list"
               (and (vmpc-other-cond "foo-list-messages")
                    (vmpc-other-cond "html messages")))
             ("html messages not from foo-list"
               (and (vmpc-other-cond "html messages")
                    (not (vmpc-other-cond "foo-list messages"))))

             ;; any number of other conditions could go here

             ("unknown sender"
               (vmpc-none-true-yet "condition that's always true"))
     ))

It's also possible to match against the text in the body of a message you are replying to, forwarding or composing.  If you wanted to check whether the phrase "make money fast" appeared in a message, you'd have a condition like this:

     ("message from an idiot"
             (vmpc-body-match "make[\n ]+money[\n ]+fast"))

Note how the regexp is constructed in order to take account of the fact that the phrase may be split over more than one line.

Both vmpc-header-match and vmpc-body-match are affected by your default value of case-fold-search.  If you wanted to force a case-sensitive search in the previous example, you'd re-write it like this:

     ("message from an idiot using all-caps"
             (let ((case-fold-search nil))
               (vmpc-body-match "MAKE[\n ]+MONEY[\n ]+FAST")))

Similarly, if you wanted to force it to be case-insensitive, you'd do this:

     ("message from an idiot using any case"
             (let ((case-fold-search t))
               (vmpc-body-match "make[\n ]+money[\n ]+fast")))

You can use vmpc-header-match to test if a regexp appears in any header field matching another regexp.  For example, to find out if the regexp "fire\\|water" appears in any header, you would use something like

     (vmpc-header-match "[^ \t\n:]+:" "fire\\|water" ", ")

Essentially what this does is to take the contents of every header in the message, put them all together in a gigantic string -- separated from each other by a comma and a space -- and run

     (string-match "fire\\|water" gigantic-string-of-all-headers)

In the event that you want to look for a regexp that includes ", " you can use a different string as the separator to ensure that a match doesn't span the contents of different headers.

The above header field regexp checks every single header -- even the X-VM-v5-Data header.  You could use a more restrictive regular expression for the header name if you prefer.  For example, to check only the From: and Apparently-To: headers, you could use

     (vmpc-header-match "From:\\|Apparently-To:" "fire\\|water" ", ")

What if you have an action that you only want to perform if the message is from foo-list and doesn't have "bar" in the subject, or the message is not from foo-list and does have "bar" in the subject, or if the message has "quux" in the subject, regardless of whether it's from foo-list or not?  And what if, even then, you only want the action performed if you answer yes to a prompt?  Here's what the condition would look like:

     ("a complex condition"
       (and
         (or  (vmpc-xor (vmpc-other-cond "foo-list-messages")
                        (vmpc-header-match "bar"))
              (vmpc-header-match "quux"))
         (y-or-n-p "Perform action for complex condition? ")))

It will only prompt you if the or part is true, because that's how the and form works in elisp --- it stops evaluating its arguments after the first false one it finds.

Okay, I believe I've gone into much more depth here than the average user will ever need; the point is that with a little lisp knowledge you can have as fine a control over the automated actions of vm-pcrisis as you need.  Even without real lisp knowledge, I hope that you can figure out enough from these examples to achieve such control.

vmpc-actions
************

The vmpc-actions variable
=========================

The vmpc-actions variable is a list of actions, which can equally be referred to as "profiles".  You will set up some of them for replies, some for vmpc-automorph (if you use it), and some for when you are prompted for a profile (if you have an action that uses vmpc-prompt-for-profile).  Many will be equally applicable in all three cases, which is why they are all kept in the same place.

Each action is given a unique, descriptive name, and consists of one or more function calls, so that the format of the list looks something like this:

     '(  ("foo"
             (function-1 arg1 arg2)
             (function-2)
             (function-3 arg1))
         ("bar"
             (function-4))  )

This will start making sense with the real examples in the next section. But first, we'll look at what functions are available here:

  * (vmpc-signature "signature-file") will replace the signature in your message with the contents of the specified file, if it exists; otherwise the string itself will be used as the signature.

  * (vmpc-pre-signature "pre-signature-file") works in the same way, but specifies a "pre-signature" --- text that is inserted in your message above the signature.

  * (vmpc-substitute-header "Header-Field" "new header contents") will replace the contents of the specified header-field in your message with the new contents, creating the header field if necessary.

  * (vmpc-substitute-replied-header "Dest-Header" "Src-Header") takes the contents of the Src-Header field in the message you are replying to, and inserts them as the contents of the Dest-Header field in your reply, creating the Dest-Header field if necessary.  (If it's contained in an action which is called when you are not replying to a message, it does nothing.  The same is true of all of these functions: when they are called in an inappropriate context, they only do as much as they can.)

  * (vmpc-pre-function (foo-function args)) evaluates the lisp expression

          (foo-function args)

     before VM creates a mail composition buffer.  (This is useful for setting VM variables which need to be set at this stage, such as the message encoding.)  It therefore does nothing in automorph mode.

  * (vmpc-composition-buffer (foo-function args)) does the same, but in the composition buffer.

  * (vmpc-prompt-for-profile arg) prompts the user for a profile (action) to run.  (The user would be well advised not to choose one which itself contains this function!)  If ARG is present, it should be set to 'prompt or 'always.  The presence of ARG indicates that you want it to check who your message is destined for, and remember to apply the profile you choose now to messages sent to that person in the future, instead of prompting you for a profile the next time.  If set to 'prompt, it will ask whether it should remember; if set to 'always, it will always remember.  If ARG is not present, it does not remember.

Do not include your own functions in actions directly; call them with vmpc-pre-function or vmpc-composition-buffer instead -- otherwise they will be called twice, both before and after the composition buffer is created.

vmpc-actions examples
=====================

In your ~/.vm you'll have something like this:

     (setq vmpc-actions '(
             ;; actions go here
     ))

Okay, here come some example actions which you can adapt and place, one after the other, in the place of the comment above.

Say you wanted two personality profiles from which you could choose when prompted, and to automatically apply when certain conditions were met with replies or in automorph mode.  One thing to bear in mind is that when you are prompted, there will be auto-completion available --- you'll only need to type enough to uniquely identify a profile (you won't even need to hit TAB).  Also, the first profile in vmpc-actions will be the default at the prompt, so you can just hit RET to use it. Therefore, the first profile you place in vmpc-actions should be the one you expect to use most often, and you should choose names for profiles which uniquely distinguish themselves at the first or second character.

Okay, here are a couple of profiles which show how to insert signatures and change the contents of a header field.

     ("foo on the hill"
       (vmpc-substitute-header "From"
             "\"The Foo On The Hill\" <foo@hill.com>")
       (vmpc-signature "~/.foo-sig"))
     ("david"
       (vmpc-substitute-header "From"
             "\"David Foo\" <foo@hill.com>")
       (vmpc-signature ""))

When an empty string is given as the signature, as in the second profile, vm-pcrisis will actually remove any signature that has been placed there by other actions.

Also note that by including a From: header, we override the values of user-full-name and user-mail-address.

We could equally well have chosen to override those values directly using composition-buffer-functions, like this:

     ("foo on the hill"
       (vmpc-composition-buffer
          (setq user-full-name "The Foo On The Hill")
          (setq user-mail-address "foo@hill.com"))
       (vmpc-signature "~/.foo-sig"))
     ("david"
       (vmpc-composition-buffer
           (setq user-full-name "David Foo"))
           (setq user-mail-address "foo@hill.com"))
       (vmpc-signature ""))

If we had two different mailboxes and wanted to direct replies back into the right one, we would want to also set mail-default-reply-to, or use vmpc-substitute-header to insert a Reply-To: header.

-----------------------------------------------------------------

Aside:
------

Why did we use vmpc-composition-buffer rather than vmpc-pre-function to set those variables?  Well, their values are only examined when you actually send your message, so you could equally well set them with either, but the vmpc-automorph function does not run pre-functions, so if we want these profiles to work properly for automorph, we need to use composition-buffer-functions.

In other cases, such as setting VM's charset variables, you have no option but to use pre-functions, because they have to be set to appropriate values before the composition buffer is created.  If anyone finds a workaround for this, please let me know so I can include it here.

-----------------------------------------------------------------

Pre-signatures can be specified in the same way as signatures:

     ("insert anti-html form letter"
       (vmpc-pre-signature "~/stuff/formletters/why_html_is_bad.txt"))

Alright, suppose that messages from foo-list have their Reply-To: header set to point back to the list, with the address of the real sender in the From: field.  We could override it with vm-reply-ignored-reply-tos, but usually we prefer this behaviour. Only under certain conditions do we want to set our To: field to the contents of the From: field in the replied message.  The action to do this would look like this:

     ("set To to From"
       (vmpc-substitute-replied-header "To" "From"))

Let's say we also want an action that can prompt us for a profile, so we can associate it with an "unknown sender" condition.  Here we go:

     ("prompt for a profile"
       (vmpc-prompt-for-profile))

If we want vm-pcrisis to figure out who our message is destined for and to remember to use the profile we choose the next time we send to that address instead of prompting, we would do it like this:

     ("prompt for a profile, and remember it automatically"
       (vmpc-prompt-for-profile 'always))

The associations between addresses and profiles will be stored in the file named by vmpc-auto-profiles-file --- by default, this is "~/.vmpc-auto-profiles".  If your OS has a shonky filesystem that can not deal with filenames like that, you might have to change this value.

Keep in mind that the associations stored in this file are only used by vmpc-prompt-for-profile.  They do not have the effect of adding new associations between addresses and profiles in the general operation of vm-pcrisis; they are simply used by vmpc-prompt-for-profile instead of prompting you in the future.

IMPORTANT: When vm-pcrisis decides who your message is destined for, it does so on the basis of the Reply-To: or From: field of the message being replied (or in the case of automorph, the To: field of your message).  This takes account of vm-reply-ignored-reply-tos, but DOES NOT take account of any other actions which might change the To: address in your message.  There is, therefore, a possibility that when using this feature in both automorph and reply mode, an association made in one mode may not be properly suited to the other.  The best way to avoid this problem is to set up your conditions so that the above action is not run in conjunction with other actions that change the To: field. This is not really limiting, because the situations in which you are changing the To: field will generally be ones in which you know which profile you want to use anyway.

You can also set it up so that after prompting you for a profile, it will tell you which address it has decided your message is going to, and prompt you whether to save an association between that profile and that address.  Like this:

     ("prompt for a profile, and remember it if I say so"
       (vmpc-prompt-for-profile 'prompt))

Associating Conditions with Actions
***********************************

vmpc-action-alist
=================

The vmpc-action-alist variable controls which actions are performed if various conditions are met when creating a reply.  Its format is something like this:

     '(  ("condition 1" "action 1" "action 2")
         ("condition 2" "action 3")
         ...                         )

If you do not want to set all the other alists then sent this one as it will be used as a fall back.

vmpc-reply-alist
================

The vmpc-reply-alist variable controls which actions are performed if various conditions are met when creating a reply.  Its format is something like this:

     '(  ("condition 1" "action 1" "action 2")
         ("condition 2" "action 3")
         ...                         )

If we follow on from our examples in the previous sections, we might have this in our ~/.vm file:

     (setq vmpc-reply-alist '(
       ("condition that's always true" "david")
       ("plaintext messages from foo-list" "foo on the hill")
       ("html messages from foo-list" "set To to From"
                                      "insert anti-html form letter")
       ("html messages not from foo-list" "insert anti-html form letter")
       ("unknown sender" "prompt for a profile, and remember it if I say so")
     ))

vmpc-automorph-alist
====================

The vmpc-automorph-alist variable has the same syntax as vmpc-reply-alist and follows the same principles.  (See vmpc-reply-alist.)  The only difference is that it controls which actions are associated with which conditions when the vmpc-automorph function is called.

vmpc-forward-alist
==================

The vmpc-forward-alist variable has the same syntax as vmpc-reply-alist and follows the same principles.  (See vmpc-reply-alist.)  The only difference is that it controls which actions are associated with which conditions when forwarding messages.

vmpc-resend-alist
=================

The vmpc-resend-alist variable has the same syntax as vmpc-reply-alist and follows the same principles.  (See vmpc-reply-alist.)  The only difference is that it controls which actions are associated with which conditions when resending messages with vm-resend-message.

vmpc-newmail-alist
==================

The vmpc-newmail-alist variable has the same syntax as vmpc-reply-alist and follows the same principles.  (See vmpc-reply-alist.)  The only difference is that it controls which actions are associated with which conditions when creating new messages with vm-mail.

One strategy for this is to have conditions based on the folder from which you are sending mail.  You might like to set things this up for some folders, and have vm-pcrisis prompt you for an action in the other folders.  Here's how you might do that...

In vmpc-conditions, you'd have a couple of conditions like this:

     ("mail to foo-list"
      (string-match "^foo" (buffer-name (current-buffer))))
     ("no cond"
      (vmpc-none-true-yet))

Then in vmpc-actions, you'd set up an action for your mail to foo-list, and another one to prompt you for a profile:

     ("foo profile"
      (vmpc-substitute-header "From"
     			 "\"The Foo King\" <david@bar.com>")
      (vmpc-signature "~/.foo-sig"))
     ("prompt"
      (vmpc-prompt-for-profile))

Finally, you'd set up vmpc-newmail-alist like this:

     (setq vmpc-newmail-alist
           '(
             ("mail to foo-list" "foo profile")
             ("no cond" "prompt")
             ))

Miscellaneous Variables
***********************

vmpc-auto-profiles-file
=======================

The variable vmpc-auto-profiles-file contains the name of the file used for saving profiles when vmpc-prompt-for-profile is used with an 'always or 'prompt argument (see The vmpc-actions variable and vmpc-actions examples).

By default it is set to "~/.vmpc-auto-profiles".

vmpc-auto-profiles-expunge-days
===============================

In order to keep vmpc-auto-profiles-file from becoming massive, Personality Crisis will check the age of profile associations in that file each time it adds a new one.  Associations that have not been used in the last number of days given by vmpc-auto-profiles-expunge-days will be removed.  This variable is set to 100 by default.

vmpc-sig-face
=============

This is the face used to highlight the signature.  You can use set-face-foreground, set-face-background and set-face-font to change the colours and font.

vmpc-pre-sig-face
=================

This is the face used to highlight the pre-signature.  You can use set-face-foreground, set-face-background and set-face-font to change the colours and font.

vmpc-intangible-sig
===================

If vmpc-intangible-sig is non-nil, movement and mouse commands will cause your cursor to slide to one side or the other of the signature, preventing you from actually writing text inside the area that Personality Crisis calls the signature.

This is somewhat useful because if automorph replaces the signature, you probably won't want any text you added to be replaced along with it.  To activate this feature, just add the following to your ~/.vm file:

     (setq vmpc-intangible-sig t)

vmpc-intangible-pre-sig
=======================

The vmpc-intangible-pre-sig variable works just like vmpc-intangible-sig, but affects the pre-signature.  See vmpc-intangible-sig.

vmpc-expect-default-signature
=============================

Traditionally, signatures are added to new mail messages using a signature-insertion function bound to mail-mode-hook or similar, so that every message you wrote started off containing a signature.  If you use the vm-pcrisis signature functions in addition to such a setup, you should add the following to your ~/.vm file:

(setq vmpc-expect-default-signature t)

This will allow Personality Crisis to properly take account of your setup, provided that your signature-insertion function uses the standard \n-- \n signature delimiter.

Debugging
*********

With a complex setup it can be come hard to understand why vm-pcrisis is doing a specific thing.  In order to understand what is going on you should check the value of the following variables:

  * vmpc-true-conditions is the list of true conditions.

  * vmpc-actions-to-run is the list of actions to run, i.e. those actions mapped by a vmpc-*-alist.

  * vmpc-saved-headers-alist the value of headers saved for substitution.

If you want to check new contions you can run vmpc-build-true-conditions-list interactively.

If you want to check which true conditions are mapped to actions you can run vmpc-build-actions-to-run-list interactively.  True conditions which are not mapped to an action are silently ignored.

If you want to run new actions you can run vmpc-read-actions and vmpc-run-actions interactively.

New In This Version
*******************

Version 0.11:

  * Profiles can now be stored in the BBDB instead of the file vmpc-auto-profiles-file.  To enable this and migrate your old profiles you should call vmpc-migrate-profiles-to-BBDB once. A backup of your BBDB will be created first as ~/.bbdb-vmpc-profile-migration-backup and your old profiles-file will be moved to ~/.vmpc-auto-profiles-migrated-to-BBDB.

  * Added vmpc-add-header which allows to create a header multiple times.  This is useful when having more than one FCC header.

  * vmpc-prompt-for-profile finds now all profiles, i.e. before it stopped at the first match, now it will check all email addresses.

Version 0.10:

  * Added support for a list of actions in vmpc-prompt-for-profile. Before it was only possible to specify a single action.

Version 0.9:

  * The new maintainer is: Robert Widhopf-Fenk <hack@robf.de>

  * All variables of pcrisis can be customized now.

  * Added new function vmpc-toggle-no-automorph to disable automorph for the current buffer.

  * vmpc-prompt-for-profile checks all relevant headers now and will only prompt for a profile if no matches were found.  It also can be called interactively to correct a existing profile association.

  * Renamed vmpc-composition-buffer-function to vmpc-composition-buffer.

  * vmpc-pre-function and vmpc-composition-buffer handle forms now, not only a single function which must be quoted.

  * Renamed vmpc-replies-alist to vmpc-reply-alist and vmpc-forwards-alist to vmpc-forward-alist for consistency.

  * New function vmpc-true-conditions to test conditions without actually running some actions.

  * New function vmpc-read-actions to set actions by hand.

  * vmpc-build-actions-to-run-list and vmpc-run-actions are interactive now.

  * vmpc-prompt-for-profile will search all headers for a recipient with an associated profile before prompting for one.

  * When calling vmpc-prompt-for-profile interactively form a composition buffer one will get prompted again for a profile.  This allows to easily fix a bad association.

  * The state variables become buffer-local now, which should prevent some bugs, i.e. for saved headers.

  * Rewrite of unlispish code.

  * M-x checkdoc RET

  * Several bug fixes and enhancements from Robert P. Goldman.

  * Fixes and updates of the info file.

Version 0.85:

  * This version adds vmpc-resend-alist, which should be especially useful for mailing list maintainers who receive bounced non-member posts, and anyone else who frequently uses vm-resend-message.

Version 0.84:

  * There is now a vmpc-newmail-alist in recognition of the fact that you can actually test for useful criteria (such as what folder you are in when you invoke vm-mail) when creating a brand new message.

  * Due to the above, the vmpc-newmail-prompt-for-profile variable is now obsoleted.  Its effect can be duplicated easily enough; see vmpc-newmail-alist for details.

Older versions:

  * Pre-signatures and signatures are now dealt with in a more sensible manner.  You might not notice the difference, except that you can now have them highlighted in vmpc-pre-sig-face and vmpc-sig-face, and you can set up either so that your cursor skips across them with vmpc-intangible-pre-sig and vmpc-intangible-sig.  However, if you use another signature package to insert a signature in every mail buffer, you should look at setting vmpc-expect-default-signature.

  * You can now use vm-pcrisis in conjunction with the forwarding functions of VM.  Just set up vmpc-forwards-alist, which has an identical format to vmpc-replies-alist.

  * There is now a vmpc-body-match function which matches text in the body of a message you are composing, replying to or forwarding.  See vmpc-conditions examples for more about that.

  * You can now use vmpc-header-match to test if a regexp appears in any header field matching another regexp.  For example, to find out if the regexp "fire\\|water" appears in any header, you would use something like

          (vmpc-header-match "[^ \t\n:]+:" "fire\\|water" ", ")

     For further details, again see vmpc-conditions examples.

  * vmpc-auto-profiles-expunge-days can now be set to nil if you want to never expunge old profile associations.  Associations are now "touched" each time they are used, so that as long as they are used more often than vmpc-auto-profiles-expunge-days they will never be expunged.