Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

10.4: Complex Booleans for Smart Folders in Mail 2.0 Apps
Tiger only hintBy understanding a few simple aspects of the structure of Mail.app's SmartMailboxes.plist file, complex Boolean queries joining strings of AND, OR, and NOT operations are possible. This allows for more advanced, complex manipulations than the previous Use boolean expressions in Mail 2.0 hint. In this hint, I will walk through the basic terms you'll see in the plist file, and follow it with an example for a folder that required the use of a more complex boolean expression than Mail would allow within its interface.

You can find the SmartMailboxes.plist file in /Users -> your_user -> Library -> Mail -> SmartMailboxes.plist. First, I recommend creating a backup of this file before you go on an editing spree. Also, I'm not going to cover every element or attribute in Apple's doctype... I don't even know what they all do. I'm just going to go over what I think is absolutely necessary to get this working.

[robg adds: What follows in the remainder of this hint is a detailed look at Mail's Smart Mailbox folders, and how to modify them to do some fairly advanced searches. I haven't tested this hint yet, but the structure described below makes logical sense and should work as described. You should be comfortable editing files in a pure text editor before you try this -- and as noted above, please make a backup first!]


INTRODUCTION: The basic parameters of the plist file.

In the SmartMailboxes.plist file, you'll see a bunch of XML element tags, including:

<dict>
<key>
<array>
<integer>
<string>
Every command or expression that you write for a smart mailbox is found within a block -- which means that it is found between an opening tag and a closing tag. Also, the XML is organized so that whenever you want to refer to a characteristic, you refer to it by enclosing it within tags, and immediately follow it with an integer or string value that represents what you're looking for. For example, if I want to search the senders of messages, I would want to look in the "From" element of the header of my email messages, so I would write:

<key>Header</key>
<string>From</string>
This alone is not too helpful, since I haven't specified what I'm searching for. I specify the search expression in another key-string pair within the same block:

<key>Expression</key>
<string>google@yahoo.edu</string>
Now I'm searching for all messages sent by google@yahoo.edu. Following the Key-String/Integer pattern, each dict block that specifies a rule also has something that looks like this at the top:

<key>CriterionUniqueId</key>
<string>260AC489-51C6-41BD-9255-89CDBBE3C834</string>
Fortunately, the CriterionUniqueId value is *not required* (which is very, very good since we are going to be writing our own blocks).
BOOLEANS

There are at least three supported booleans in Mail.app: AND, OR, and NOT. The Mail interface allows simple editing and stringing together of these operations, which means it's sufficient for many tasks. One might want messages from Nancy or Steve (Nancy OR Steve), or messages from yesterday and today (Yesterday AND Today). The problem arises when you want messages from today from only Nancy or Steve, and messages from yesterday from everyone but Bob. ((Today AND (Nancy OR Steve)) OR (Yesterday AND (NOT Bob))) You can't do this with the Mail interface, but you can do it without much struggle by editing the plist file and taking advantage of the block. First things first, though: AND, OR, and NOT.

AND looks like:

<key>MailboxAllCriteriaMustBeSatisfied</key>
<string>YES</string>
OR looks like:

<key>MailboxAllCriteriaMustBeSatisfied</key>
<string>NO</string>
NOT looks like:

<key>Qualifier</key>
<string>IsNotEqualTo</string>
(and NOT's opposite looks like):

<key>Qualifier</key>
<string>IsEqualTo</string>
Pretty straightforward, right? NOT is a little trickier than AND and OR, because it is not always used, so I'll first deal with AND and OR.
PUTTING IT TO USE

You'll see MailboxCriteria after the main expression for AND or OR, followed by an array of dict blocks specifying rules. So if I wanted all rules followed (joined by AND), I would write:

<key>MailboxAllCriteriaMustBeSatisfied</key>
<string>YES</string>
<key>MailboxCriteria</key>
<array>
  <dict>Rule 1...
 </dict>
 
      <dict>Rule 2...
 </dict>
</array>
Within the array for MailboxCriteria, you can have more arrays with Criteria. Note that only the topmost says "MailboxCriteria" and all the rest simply say "Criteria". So, to extend the example above, we might add rules 3 and 4, but want 1 AND 2 AND (3 OR 4) to be allowed.

<key>MailboxAllCriteriaMustBeSatisfied</key>
<string>YES</string>
<key>MailboxCriteria</key>
<array>
 <dict>Rule 1...
 </dict>
 
      <dict>Rule 2...
 </dict>
 
      <dict>
          <key>MailboxAllCriteriaMustBeSatisfied</key>
              <string>NO</string>
               <key>Criteria</key>
               <array>
                 <dict>Rule 3...
                 </dict>
                 
                      <dict>Rule 4...
                 </dict>
         </array>
        </dict>
</array>
Okay, so now let's write some pseudo-code to get ((Today AND (Nancy OR Steve)) OR (Yesterday AND (NOT Bob))). We can figure out what's at the highest level by looking for the lowest score (like golf): a lower number of parantheses means a higher level join. In this case, it's the "OR" before "Yesterday." So a rewrite of this set of rules might be:

{OR: joining Today and Yesterday}
<array>
  {AND joining Today and (Nancy OR Steve)}
              {OR joining Nancy and Steve}
  
      {AND joining Yesterday and NOT Bob}
</array>
So the top level looks like this, which presents the OR joining Today and Yesterday:

<key>MailboxAllCriteriaMustBeSatisfied</key>
<string>NO</string>

<key>MailboxCriteria</key>
<array>
</array>
Now adding the AND joining Today and Nancy/Steve, and the AND joining Yesterday and NOT Bob

<key>MailboxAllCriteriaMustBeSatisfied</key>
<string>NO</string>

<key>MailboxCriteria</key>
<array>
        
      <dict>
          <key>MailboxAllCriteriaMustBeSatisfied</key>
              <string>YES</string>
              
              <key>Criteria</key>
               <array>
         </array>
        </dict>
 
      <dict>
          <key>MailboxAllCriteriaMustBeSatisfied</key>
              <string>YES</string>
              
              <key>Criteria</key>
               <array>
         </array>
        </dict>
 
</array>
Now adding the Rules for Today, Yesterday, and NOT-Bob (but not yet Nancy/Steve)

<key>MailboxAllCriteriaMustBeSatisfied</key>
<string>NO</string>

<key>MailboxCriteria</key>
<array>
        
      <dict>
          <key>MailboxAllCriteriaMustBeSatisfied</key>
              <string>YES</string>
              
              <key>Criteria</key>
               <array>
                 <dict>
                          {Rule for Today}
                      </dict>
                 
                      ...
                   
              </array>
        </dict>
 
      <dict>
          <key>MailboxAllCriteriaMustBeSatisfied</key>
              <string>YES</string>
              
              <key>Criteria</key>
               <array>
                 <dict>
                          {Rule for Yesterday}
                  </dict>
                 
                      <dict>
                          {Rule for NOT Bob}
                    </dict>
         </array>
        </dict>
 
</array>
And finally, adding yet another dict array for (Nancy OR Steve), we get the complete outline of the rule

<key>MailboxAllCriteriaMustBeSatisfied</key>
<string>NO</string>

<key>MailboxCriteria</key>
<array>
        
      <dict>
          <key>MailboxAllCriteriaMustBeSatisfied</key>
              <string>YES</string>
              
              <key>Criteria</key>
               <array>
                 <dict>
                          {Rule for Today}
                      </dict>
                 
                      <dict>
                          <key>MailboxAllCriteriaMustBeSatisfied</key>
                              <string>NO</string>
                               
                              <key>Criteria</key>
                               <array>
                                 <dict>
                                          {Rule for Nancy}
                                      </dict>
                                 
                                      <dict>
                                          {Rule for Steve}
                                      </dict>
                         </array>
                        </dict>
                 
              </array>
        </dict>
 
      <dict>
          <key>MailboxAllCriteriaMustBeSatisfied</key>
              <string>YES</string>
              
              <key>Criteria</key>
               <array>
                 <dict>
                          {Rule for Yesterday}
                  </dict>
                 
                      <dict>
                          {Rule for NOT Bob}
                    </dict>
         </array>
        </dict>
 
</array>

WRITING THE RULES

Well, I'd like to go through writing all the rules, and working on the intricacies of NOT, but there is a much easier way:

Go into Mail and write mailbox rules. Find those rules in the plist, and put them into the placeholders you've made for the rules. Oh, and ditch the CriterionUniqueID. I don't know if it'll mess Mail up or not if it's not unique, but it doesn't seem to matter if it's not present.
IMPORTANT NOTES

Mail will erase any edits to SmartMailboxes.plist that deviate from the simple boolean rules if you try to edit any Smart Mailbox using Mail (even if you don't change anything). So keep a backup of your handmade rules!
    •    
  • Currently 3.40 / 5
  • 1
  • 2
  • 3
  • 4
  • 5
  (5 votes cast)
 
[23,851 views]  

10.4: Complex Booleans for Smart Folders in Mail 2.0 | 6 comments | Create New Account
Click here to return to the '10.4: Complex Booleans for Smart Folders in Mail 2.0' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
10.4: Complex Booleans for Smart Folders in Mail 2.0
Authored by: lolopb on Jun 30, '05 12:07:23PM
You can create an uuid (for the CriterionUniqueID) with the command line tool uuidgen, just type
uuidgen
in a terminal window and copy-paste the result. For more informations,
man uuidgen
-- Laurent

[ Reply to This | # ]
10.4: Complex Booleans for Smart Folders in Mail 2.0
Authored by: designbot on Jun 30, '05 01:40:32PM
Now this is a hint.

[ Reply to This | # ]
Seriously...
Authored by: lullabud on Jun 30, '05 02:55:39PM

But can I get a hint on how to use this hint??



[ Reply to This | # ]
Seriously...
Authored by: pediddle on Jul 01, '05 03:07:03PM

Just cut-n-paste the last block of code.



[ Reply to This | # ]
Seriously...
Authored by: sjk on Jul 01, '05 03:49:22PM
copy-n-paste. :-)

[ Reply to This | # ]
10.4: Complex Booleans for Smart Folders in Mail 2.0
Authored by: mayo2ca on Jul 04, '05 03:38:54AM

Actually, it will only replace your modified smart mailbox if you modify the mailbox itself. You can happily create and delete any other smart mailboxes without any worries. You can even hit edit on the smart mailbox, so long you click "cancel"... At least from my experience of having used this for some time now.



[ Reply to This | # ]