## 13 Virtual Folders ¶

A virtual folder is a mapping of messages from one or more real folders into a container that in most ways acts like a real folder but has no real existence outside of VM. You can have a virtual folder that contains a subset of messages in a real folder or several real folders. A virtual folder can also contain a subset of messages from another virtual folder.

There are two ways of working with virtual folders. When you are visiting a folder, you can use one or more selectors or search keys to interactively create a virtual folder. We call such folders search folders. You can browse through the messages in the search folder and carry out actions on them which will be reflected back to the original folder. When you are done, you can quit the search folder and return to the original folder.

A second way of using virtual folders is to define them through the variable `vm-virtual-folder-alist`. You can visit such virtual folders by typing `V V` (`vm-visit-virtual-folder`). Any actions carried out on the virtual folder messages will be reflected back to the underlying real folders. When you quit a virtual folder, all its underlying real folders will also be quit, unless they were previously visited in the Emacs session. We call such virtual folders defined virtual folders.

### 13.1 Search Folders ¶

The command `vm-create-search-folder` (bound to `V C`) lets you interactively create a virtual folder from the messages of the current folder, using exactly one selector to choose the messages. If you type `V C header `RET` greeting`, VM will create a folder containing only those messages that contain the string ‘`greeting`’ in one of its headers. See Virtual Selectors, for virtual selectors you can use for this purpose.

The command `vm-create-search-folder-of-threads` (bound to `V T`) lets you create a virtual folder in the same way, but consisting of entire message threads. If a message thread contains any message matching the given selector then it is included in the virtual folder. For instance, if you type `V T author `RET` Peter` then all threads containing a message authored by ‘`Peter`’ will be included in the virtual folder.

The command `vm-apply-virtual-folder` (bound to `V X`) tries the selectors of a defined virtual folder against the messages of the current folder and creates a virtual folder containing the matching messages.

The commands `vm-create-virtual-folder-same-subject` (bound to `V S` in version 7.19) and `vm-create-virtual-folder-same-author` (bound to `V A` in version 7.19) create virtual folders containing all the messages in the current folder with the same subject or author as the current message. There are also short-cut key bindings for a number of frequently used selectors:

`V a (`vm-create-author-virtual-folder`)`
`V r (`vm-create-author-or-recipient-virtual-folder`)`
`V s (`vm-create-subject-virtual-folder`)`
`V t (`vm-create-text-virtual-folder`)`
`V d (`vm-create-date-virtual-folder`)`
`V l (`vm-create-label-virtual-folder`)`
`V ! (`vm-create-flagged-virtual-folder`)`
`V n (`vm-create-new-virtual-folder`)`
`V u (`vm-create-unseen-virtual-folder`)`

When you quit a search folder, the currently selected message in the virtual folder becomes the current message in the underlying folder. So, you can use the search folder facility to search for particular messages. For example, if you knew that one of the messages with the subject ‘`greeting`’ had a hotel offer and you wanted to find it, you can first create a search folder of messages with subject ‘`greeting`’, browse through them to find the message that had the hotel offer, and then quit the virtual folder. VM will return you to the copy of the same message in the original folder.

Search folders also form an efficient way to search for some string in the text of messages. The key binding `V t` (`vm-create-text-virtual-folder`) can be used to find all messages with the string. This is more efficient than the `vm-isearch-forward` command (see Selecting Messages) because it only searches in the text part of message bodies, not inside MIME attachments.

### 13.2 Defined Virtual Folders ¶

A defined virtual folder is defined by its name, the folders that it contains and its selectors. The variable `vm-virtual-folder-alist` is a list of the definitions of all such virtual folders. You can visit a virtual folder listed in `vm-virtual-folder-alist` with the `vm-visit-virtual-folder` (`V V`) command.

Each virtual folder definition should have the following form:

    (VIRTUAL-FOLDER-NAME
      ( (FOLDER ...)
        (SELECTOR [ARG ...]) ... )
      ... )

VIRTUAL-FOLDER-NAME is the name of the virtual folder being defined. This is the name by which you and VM will refer to this folder.

FOLDER should be the specification of a real folder: a file path for a local folder or a maildrop specification for a POP/IMAP folder. There may be more than one FOLDER listed, the SELECTORs within that sublist will apply to them all. If FOLDER is a directory, VM will assume this to mean that all the folders in that directory should be searched.

The SELECTOR is a Lisp symbol that tells VM how to decide whether a message should be included in the virtual folder. (See below for a complete list of the possible selectors.) Some SELECTORs require an argument ARG; unless otherwise noted, ARG may be omitted. When several selectors are listed, messages matching any one of them are included.

The `text` selector provides a particularly effective way to search for strings in messages. It is better than the `vm-isearch-forward/backward` functions because it avoids searching inside encoded attachments, hence faster.

Here is an example that you may find useful as a template for creating virtual folder definitions.

    (setq vm-virtual-folder-alist
       '(
         ;; start virtual folder definition
         ("virtual-folder-name"
          (("/path/to/folder" "/path/to/folder2")
           (header "foo")
           (header "bar")
          )
          (("/path/to/folder3" "/path/to/folder4")
           (and (header "baz") (header "woof"))
          )
         )
         ;; end of virtual folder definition
       )
    )

When you visit a defined virtual folder, all the underlying folders that it depends on will be visited automatically. Likewise, when you quit the virtual folder, all the underlying folders that were purposely visited as part of the virtual folder will be closed automatically. But any other underlying folders that you might have previously visited for independent reasons will remain open.

#### 13.2.1 Virtual Selectors ¶

#### Generic selectors ¶

`any`

  matches any message.

`header`

  matches message if ARG matches any part of the header portion of the message; ARG should be a regular expression.

`text`

  matches message if ARG matches any part of the text portion of the message; ARG should be a regular expression.

`header-or-text`

  matches message if ARG matches any part of the headers or the text portion of the message; ARG should be a regular expression.

`header-field`

  matches messages if the header field named ARG1 has text matching ARG2.

#### Selectors based on message headers ¶

`author`

  matches message if ARG matches the author; ARG should be a regular expression.

`author-or-recipient`

  matches message if ARG matches the author of the message or any of its recipients; ARG should be a regular expression.

`recipient`

  matches message if ARG matches any part of the recipient list of the message. ARG should be a regular expression.

`outgoing`

  matches message if your are the author of it, i.e. if the author matches `vm-summary-uninteresting-senders`.

`in-bbdb`

  matches message if its addresses are in the BBDB. With an optional first argument you can specify the address class (`authors` or `recipients`) . With an optional second argument `t`, the selector checks only the first address specified in the message. Examples:

      (in-bbdb authors)

      (in-bbdb recipients t)

`subject`

  matches message if ARG matches any part of the message’s subject; ARG should be a regular expression.

`sent-after`

  matches message if it was sent after the date ARG. A fully specified date looks like this:

      ``31 Dec 1999 23:59:59 GMT''

  although the parts can appear in any order. You can leave out any part and it will default to the current date’s value for that part, with the exception of the ‘`hh:mm:ss`’ part which defaults to midnight.

`sent-before`

  matches message if it was sent before the date ARG. A fully specified date looks like this:

      ``31 Dec 1999 23:59:59 GMT''

  although the parts can appear in any order. You can leave out any part and it will default to the current date’s value for that part, with the exception of the hh:mm:ss part which defaults to midnight.

`older-than`

  matches message if it is more than ARG days old

`newer-than`

  matches message if it is at most ARG days old

`message-id`

  matches message if its Message ID is ARG

`uid`

  matches message if its IMAP UID is ARG (for IMAP folders)

`uidl`

  matches message if its POP UIDL is ARG (for POP folders)

`spam-score`

  matches message if its spam score is at least ARG. See `vm-spam-score-headers` for configuration.

#### Selectors based on message attributes ¶

`deleted`

  matches message if it is flagged for deletion.

`undeleted`

  matches message if it has not been deleted.

`edited`

  matches message if it has been edited.

`unedited`

  matches message if it has not been edited.

`filed`

  matches message if it has been saved with its headers.

`unfiled`

  matches message if it has not been saved with its headers.

`written`

  matches message if it has been saved without its headers.

`new`

  matches message if it is new.

`recent`

  matches message if it is new. Same as the `new` selector.

`read`

  matches message if it is neither new nor unread.

`unread`

  matches message if it is not new and hasn’t been read.

`unseen`

  matches message if it is not new and hasn’t been read. Same as the `unread` selector.

`flagged`

  matches message if it is flagged.

`unflagged`

  matches message if it is not flagged.

`replied`

  matches message if it has been replied to.

`answered`

  matches message if it has been replied to. Same as the `replied` selector.

`unreplied`

  matches message if it has not been replied to.

`unanswered`

  matches message if it has not been replied to. Same as the `unreplied` selector.

`forwarded`

  matches message if it has been forwarded using a variant of `vm-forward-message`, `vm-send-digest` or one of their variants.

`unforwarded`

  matches message if it has not been forwarded using `vm-forward-message`, `vm-send-digest` or one of their variants.

`redistributed`

  matches message if it has been redistributed using `vm-resend-message`.

`unredistributed`

  matches message if it has not been redistributed using `vm-resend-message`.

`marked`

  matches message if it is marked, as with `vm-mark-message`.

#### Selectors based on analysing the text ¶

`attachment` ¶

  matches if a message contains an attachment, i.e., its text matches `vm-vs-attachment-regexp`.

`less-chars-than`

  matches message if message has less than ARG characters. ARG should be a number.

`less-lines-than`

  matches message if message has less than ARG lines. ARG should be a number.

`more-chars-than`

  matches message if message has more than ARG characters. ARG should be a number.

`more-lines-than`

  matches message if message has more than ARG lines. ARG should be a number.

#### Complex selector operations ¶

`sexp`

  matches message if the argument “s-expression” yields `t`. For example, to find all the messages from ‘`Jenny`’ with attachments, you can type `V C sexp `RET` (and (author "Jenny") attachment) `RET``.

  (This selector is available for creating interactive virtual folders. The argument “s-expression” can involve selectors combined using the logical connectives listed below. There would be no need to use the `sexp` selector in defining predefined virtual folders because those definitions can directly use “s-expressions”.)

`eval`

  matches message if evaluating the Lisp expression ARG yields `t`. The Lisp expression can refer to the message by the name `vm-virtual-message`. This is more flexible than the `sexp` selector because it allows arbitrary Lisp expressions, not only the built-in selectors. However, you would need some knowledge of the Lisp functions that manipulate VM messages to use this selector.

`and`

  matches the message if all its argument selectors match the message. Example:

      (and (author "Derek McGinty") (new))

  matches all new messages from Derek McGinty. `and` takes any number of arguments.

`not`

  matches message only if its selector argument does NOT match the message. Example:

      (not (deleted))

  matches messages that are not deleted.

`or`

  matches the message if any of its argument selectors match the message. Example:

      (or (author "Dave Weckl") (subject "drum"))

  matches messages from Dave Weckl or messages with the string “drum” in their Subject header. `or` takes any number of arguments.

`thread`

  matches a message thread if any message in the thread matches the argument selector. Example:

      (thread (outgoing))

  matches all threads that have an outgoing message, i.e., a message authored by you.

`thread-all`

  matches a message thread if all messages in the thread match the argument selector. Example:

      (thread (less-chars-than 1000))

  matches threads if all their messages contain fewer than 1000 characters.

#### Selectors based on context ¶

`folder-name`

  matches message if it is from a folder matching `ARG`

`virtual-folder-member`

  matches message if the message is already a member of some virtual folder currently being visited.

`vm-mode`

  matches the message if the current-buffer is in vm-mode and one of its argument selectors matches the message.

`mail-mode`

  matches the message if the current-buffer is in mail-mode and one of its argument selectors matches the message.

### 13.3 Working with Virtual Folders ¶

Once you’ve visited a virtual folder most VM commands work as they do in a normal folder. There are exceptions. If you use `S` (`vm-save-folder`), the folder save command will be invoked on each real folder in turn. Similarly if you use `g` (`vm-get-new-mail`) in a virtual folder, mail is retrieved from the spool files associated with each of the real folders. If any of the retrieved messages are matched by the virtual folder’s selectors, they will be added to the virtual folder.

These commands will signal an error when invoked in a virtual folder:

        vm-save-buffer
        vm-write-file
        vm-change-folder-type
        vm-expunge-imap-messages
        vm-expunge-pop-messages

Normally messages in a virtual folder share attributes with the underlying real messages. For example, if you delete a message in a virtual folder, it is also flagged as deleted in the real folder. If you then run `vm-expunge-folder` in the virtual folder, the deleted message is expunged from the virtual folder as well as the real folder. Labels are shared between virtual and real messages. However virtual folders have their own set of message marks.

To make virtual folders not share message attributes with real folders by default, set the variable `vm-virtual-mirror` to nil. This should be done in your VM init file and you should use `setq-default`, as this variable is automatically local to all buffers.

    (setq-default vm-virtual-mirror nil)

If you want to change virtual mirror status of a particular virtual folder, use the command `vm-toggle-virtual-mirror` (bound to `V M`). If the virtual folder is currently sharing attributes with real folders, it will no longer be. If it is not sharing attributes with the underlying folders then it will be.

### 13.4 vm-avirtual Package ¶

The ‘`vm-avirtual`’ add-on package created by Robert Widhopf-Fenk provides various automatic operations based on virtual selectors. These facilities are only partially documented.

The command `M-x vm-virtual-omit-message` (bound to `V O` in version 8) will omit a message from a virtual folder, irrespective of whether it satisfies the definition of the virtual folder. The command `M-x vm-virtual-update-folders` (bound to `V U` in version 8) will force an update of all the visited virtual folders to reflect the changes in their underlying folders.

The command `M-x vm-virtual-check-selector-interactive` (bound to `V T` in version 8) allows you to test a selector, i.e., a virtual folder definition, interactively by applying it to the current message. With a prefix argument, it will print diagnostic information in a separate buffer. This feature is useful because virtual folder selectors can get quite complicated and it is important to make sure that they work correctly.

The vm-avirtual packages allows you to use virtual selectors to carry out automatic deletion of messages (e.g., for spam) and for automatic saving of messages to folders.

#### Automatic deletion ¶

Automatic deletion of messages based on the virtual folder facility can be achieved with the command `vm-virtual-auto-delete-message` (bound to `V D` in version 8). First, set the variable `vm-virtual-auto-delete-message-selector` to the name of a virtual folder whose members should be normally deleted. Then invoking the command on the current message (or a COUNT number of messages with a prefix argument) deletes all those messages among them that belong to the virtual folder `vm-virtual-auto-delete-message-selector`. There is no need to separately view the virtual folder before deleting such messages.

The function `vm-virtual-auto-delete-messages` can be added to the VM hook `vm-arrived-messages-hook`. This causes all the messages matching the `vm-virtual-auto-delete-message-selector` in the incoming mail to be automatically deleted before you view them.

#### Automatic saving ¶

The commands `M-x vm-virtual-save-message` and `M-x vm-virtual-auto-archive-messages` provide variants of `vm-save-message` and `vm-auto-archive-messages` based on the virtual folder facility. To use them, you must first set the variable `vm-virtual-auto-folder-alist` to an association-list of the form

    ((VIRTUAL-FOLDER-NAME . FOLDER)
     ... )

where VIRTUAL-FOLDER-NAME is a string and FOLDER is either a string or an expression that evaluates to a string. If the message being saved is a member of VIRTUAL-FOLDER-NAME, as per its definition in `vm-virtual-folder-alist`, then FOLDER is regarded as the place where it should be saved. The command `vm-virtual-save-message` suggests this folder as the default location for saving. The command `vm-virtual-auto-archive-messages` archives all matching messages in the corresponding FOLDERs, as suggested by `vm-virtual-auto-folder-alist`.