Bug 310359 - "search all address fields capability (Bcc:s too!)" - First part, implement 'From, To or CC' for local search [r=Standard8 sr=bienvenu]
authorKent James <kent@caspia.com>
Thu, 05 Mar 2009 10:07:44 +0000
changeset 2134 6bdc9d138c65f13698f31530ae3c6055c1e513bd
parent 2133 651cd46ed305d5511b4ff9ee9a076f2335d6737c
child 2135 6fadebfb15d1a6c74b25d7cdb381f762f49e8cb6
push id1725
push userbugzilla@standard8.plus.com
push dateThu, 05 Mar 2009 10:08:15 +0000
treeherdercomm-central@6bdc9d138c65 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersStandard8, bienvenu
bugs310359
Bug 310359 - "search all address fields capability (Bcc:s too!)" - First part, implement 'From, To or CC' for local search [r=Standard8 sr=bienvenu]
mail/base/content/mailWidgets.xml
mail/locales/en-US/chrome/messenger/search-attributes.properties
mailnews/base/search/public/nsMsgSearchCore.idl
mailnews/base/search/src/nsMsgImapSearch.cpp
mailnews/base/search/src/nsMsgLocalSearch.cpp
mailnews/base/search/src/nsMsgSearchTerm.cpp
mailnews/base/test/unit/test_searchAddressInAb.js
mailnews/test/data/bugmail1
mailnews/test/data/bugmail8
suite/locales/en-US/chrome/mailnews/search-attributes.properties
suite/mailnews/mailWidgets.xml
--- a/mail/base/content/mailWidgets.xml
+++ b/mail/base/content/mailWidgets.xml
@@ -1111,20 +1111,21 @@
             // Keywords has the null field IsEmpty
             if (this.searchAttribute == Components.interfaces.nsMsgSearchAttrib.Keywords) {
               if (val == Components.interfaces.nsMsgSearchOp.IsEmpty)
                 this.setAttribute("selectedIndex", "-1");
               else
                 this.setAttribute("selectedIndex", "5");
             }
 
-              // if it's not sender, to, cc, or toorcc, we don't care
+              // if it's not sender, to, cc, alladdresses, or toorcc, we don't care
               if (this.searchAttribute != Components.interfaces.nsMsgSearchAttrib.Sender && 
                 this.searchAttribute != Components.interfaces.nsMsgSearchAttrib.To && 
                 this.searchAttribute != Components.interfaces.nsMsgSearchAttrib.ToOrCC && 
+                this.searchAttribute != Components.interfaces.nsMsgSearchAttrib.AllAddresses &&
                 this.searchAttribute != Components.interfaces.nsMsgSearchAttrib.CC ) {
               this.internalOperator = val;
               return val;
             }
 
             var children = document.getAnonymousNodes(this);
             if (val == Components.interfaces.nsMsgSearchOp.IsntInAB ||
                 val == Components.interfaces.nsMsgSearchOp.IsInAB) {
@@ -1230,16 +1231,17 @@
           }
           else if (attrib == nsMsgSearchAttrib.AgeInDays)
             children[0].value = val.age;
           else if (attrib == nsMsgSearchAttrib.Date)
             children[3].value = convertPRTimeToString(val.date);
           else if (attrib == nsMsgSearchAttrib.Sender || 
                    attrib == nsMsgSearchAttrib.To ||
                    attrib == nsMsgSearchAttrib.CC ||
+                   attrib == nsMsgSearchAttrib.AllAddresses ||
                    attrib == nsMsgSearchAttrib.ToOrCC)
           {
             if (this.internalOperator == Components.interfaces.nsMsgSearchOp.IsntInAB ||
                 this.internalOperator == Components.interfaces.nsMsgSearchOp.IsInAB) {
               var abs = children[4].getElementsByAttribute("value", val.str);
               if (abs.item(0))
                 children[4].selectedItem = abs[0];
             }
@@ -1301,16 +1303,17 @@
                searchValue.status = children[2].value;
             else if (searchAttribute == nsMsgSearchAttrib.AgeInDays)
                searchValue.age = children[0].value;
             else if (searchAttribute == nsMsgSearchAttrib.Date)
                searchValue.date = convertStringToPRTime(children[3].value);
             else if (searchAttribute == nsMsgSearchAttrib.Sender ||
                    searchAttribute == nsMsgSearchAttrib.To ||
                    searchAttribute == nsMsgSearchAttrib.CC ||
+                   searchAttribute == nsMsgSearchAttrib.AllAddresses ||
                    searchAttribute == nsMsgSearchAttrib.ToOrCC)
             {
               if (this.internalOperator == Components.interfaces.nsMsgSearchOp.IsntInAB ||
                   this.internalOperator == Components.interfaces.nsMsgSearchOp.IsInAB)
                 searchValue.str = children[4].selectedItem.value;
               else
                 searchValue.str = children[0].value;
             }
--- a/mail/locales/en-US/chrome/messenger/search-attributes.properties
+++ b/mail/locales/en-US/chrome/messenger/search-attributes.properties
@@ -42,16 +42,16 @@ 34=reserved for AB
 35=reserved for AB
 36=reserved for AB
 37=reserved for AB
 38=reserved for AB
 39=reserved for AB
 40=reserved for AB
 41=reserved for AB
 42=reserved for AB
-43=reserved for AB
+43=From, To or CC
 44=Junk Score Origin
 45=Junk Percent
 46=Attachment Status
 47=Junk Status 
 48=Label
 49=Customize…
 # don't use above 49
--- a/mailnews/base/search/public/nsMsgSearchCore.idl
+++ b/mailnews/base/search/public/nsMsgSearchCore.idl
@@ -61,17 +61,17 @@ interface nsMsgSearchScope {
   const nsMsgSearchScopeValue allSearchableGroups = 9;
   const nsMsgSearchScopeValue newsFilter = 10;
   const nsMsgSearchScopeValue LocalABAnd = 11;
   const nsMsgSearchScopeValue LDAPAnd = 12;
 };
 
 typedef long nsMsgSearchAttribValue;
 
-[scriptable, uuid(4ee04610-cd79-11dc-95ff-0800200c9a66)]
+[scriptable, uuid(9ED17774-4748-46a6-9A18-E651E3B791F2)]
 interface nsMsgSearchAttrib {
     const nsMsgSearchAttribValue Default = -1;
     const nsMsgSearchAttribValue Subject = 0;  /* mail and news */
     const nsMsgSearchAttribValue Sender = 1;
     const nsMsgSearchAttribValue Body = 2;
     const nsMsgSearchAttribValue Date = 3;
 
     const nsMsgSearchAttribValue Priority = 4;      /* mail only */
@@ -101,17 +101,18 @@ interface nsMsgSearchAttrib {
     const nsMsgSearchAttribValue Pager = 26;
     const nsMsgSearchAttribValue Mobile = 27;
     const nsMsgSearchAttribValue City = 28;
     const nsMsgSearchAttribValue Street = 29;
     const nsMsgSearchAttribValue Title = 30;
     const nsMsgSearchAttribValue Organization = 31;
     const nsMsgSearchAttribValue Department = 32;
 
-    // 33 - 43, reserved for ab / LDAP;
+    // 33 - 42, reserved for ab / LDAP;
+    const nsMsgSearchAttribValue AllAddresses = 43;
     const nsMsgSearchAttribValue JunkScoreOrigin = 44;
     const nsMsgSearchAttribValue JunkPercent = 45;
     const nsMsgSearchAttribValue HasAttachmentStatus = 46;
     const nsMsgSearchAttribValue JunkStatus = 47;
     const nsMsgSearchAttribValue Label = 48; /* mail only...can search by label */
     //49 is for showing customize... in ui headers start from 50 onwards up until 99.
     const nsMsgSearchAttribValue OtherHeader = 49;  /* for mail and news. MUST ALWAYS BE LAST attribute since we can have an arbitrary # of these... */
     const nsMsgSearchAttribValue kNumMsgSearchAttributes = 100;      /* must be last attribute */
--- a/mailnews/base/search/src/nsMsgImapSearch.cpp
+++ b/mailnews/base/search/src/nsMsgImapSearch.cpp
@@ -238,16 +238,29 @@ nsMsgSearchValidityManager::InitOfflineM
   m_offlineMailTable->SetEnabled   (nsMsgSearchAttrib::ToOrCC, nsMsgSearchOp::BeginsWith, 1);
   m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::ToOrCC, nsMsgSearchOp::EndsWith, 1);
   m_offlineMailTable->SetEnabled   (nsMsgSearchAttrib::ToOrCC, nsMsgSearchOp::EndsWith, 1);
   m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::ToOrCC, nsMsgSearchOp::IsInAB, 1);
   m_offlineMailTable->SetEnabled   (nsMsgSearchAttrib::ToOrCC, nsMsgSearchOp::IsInAB, 1);
   m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::ToOrCC, nsMsgSearchOp::IsntInAB, 1);
   m_offlineMailTable->SetEnabled   (nsMsgSearchAttrib::ToOrCC, nsMsgSearchOp::IsntInAB, 1);
 
+  m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::Contains, 1);
+  m_offlineMailTable->SetEnabled   (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::Contains, 1);
+  m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::DoesntContain, 1);
+  m_offlineMailTable->SetEnabled   (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::DoesntContain, 1);
+  m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::BeginsWith, 1);
+  m_offlineMailTable->SetEnabled   (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::BeginsWith, 1);
+  m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::EndsWith, 1);
+  m_offlineMailTable->SetEnabled   (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::EndsWith, 1);
+  m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::IsInAB, 1);
+  m_offlineMailTable->SetEnabled   (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::IsInAB, 1);
+  m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::IsntInAB, 1);
+  m_offlineMailTable->SetEnabled   (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::IsntInAB, 1);
+
   m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::Subject, nsMsgSearchOp::Contains, 1);
   m_offlineMailTable->SetEnabled   (nsMsgSearchAttrib::Subject, nsMsgSearchOp::Contains, 1);
   m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::Subject, nsMsgSearchOp::DoesntContain, 1);
   m_offlineMailTable->SetEnabled   (nsMsgSearchAttrib::Subject, nsMsgSearchOp::DoesntContain, 1);
   m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::Subject, nsMsgSearchOp::Is, 1);
   m_offlineMailTable->SetEnabled   (nsMsgSearchAttrib::Subject, nsMsgSearchOp::Is, 1);
   m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::Subject, nsMsgSearchOp::Isnt, 1);
   m_offlineMailTable->SetEnabled   (nsMsgSearchAttrib::Subject, nsMsgSearchOp::Isnt, 1);
@@ -642,16 +655,29 @@ nsMsgSearchValidityManager::InitOfflineM
   m_offlineMailFilterTable->SetEnabled   (nsMsgSearchAttrib::ToOrCC, nsMsgSearchOp::BeginsWith, 1);
   m_offlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::ToOrCC, nsMsgSearchOp::EndsWith, 1);
   m_offlineMailFilterTable->SetEnabled   (nsMsgSearchAttrib::ToOrCC, nsMsgSearchOp::EndsWith, 1);
   m_offlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::ToOrCC, nsMsgSearchOp::IsInAB, 1);
   m_offlineMailFilterTable->SetEnabled   (nsMsgSearchAttrib::ToOrCC, nsMsgSearchOp::IsInAB, 1);
   m_offlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::ToOrCC, nsMsgSearchOp::IsntInAB, 1);
   m_offlineMailFilterTable->SetEnabled   (nsMsgSearchAttrib::ToOrCC, nsMsgSearchOp::IsntInAB, 1);
   
+  m_offlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::Contains, 1);
+  m_offlineMailFilterTable->SetEnabled   (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::Contains, 1);
+  m_offlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::DoesntContain, 1);
+  m_offlineMailFilterTable->SetEnabled   (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::DoesntContain, 1);
+  m_offlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::BeginsWith, 1);
+  m_offlineMailFilterTable->SetEnabled   (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::BeginsWith, 1);
+  m_offlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::EndsWith, 1);
+  m_offlineMailFilterTable->SetEnabled   (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::EndsWith, 1);
+  m_offlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::IsInAB, 1);
+  m_offlineMailFilterTable->SetEnabled   (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::IsInAB, 1);
+  m_offlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::IsntInAB, 1);
+  m_offlineMailFilterTable->SetEnabled   (nsMsgSearchAttrib::AllAddresses, nsMsgSearchOp::IsntInAB, 1);
+  
   m_offlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::Subject, nsMsgSearchOp::Contains, 1);
   m_offlineMailFilterTable->SetEnabled   (nsMsgSearchAttrib::Subject, nsMsgSearchOp::Contains, 1);
   m_offlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::Subject, nsMsgSearchOp::DoesntContain, 1);
   m_offlineMailFilterTable->SetEnabled   (nsMsgSearchAttrib::Subject, nsMsgSearchOp::DoesntContain, 1);
   m_offlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::Subject, nsMsgSearchOp::Is, 1);
   m_offlineMailFilterTable->SetEnabled   (nsMsgSearchAttrib::Subject, nsMsgSearchOp::Is, 1);
   m_offlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::Subject, nsMsgSearchOp::Isnt, 1);
   m_offlineMailFilterTable->SetEnabled   (nsMsgSearchAttrib::Subject, nsMsgSearchOp::Isnt, 1);
--- a/mailnews/base/search/src/nsMsgLocalSearch.cpp
+++ b/mailnews/base/search/src/nsMsgLocalSearch.cpp
@@ -489,16 +489,34 @@ nsresult nsMsgSearchOfflineMail::Process
         err = aTerm->MatchRfc822String (recipients.get(), charset, charsetOverride, &result);
         if (boolKeepGoing == result)
         {
           msgToMatch->GetCcList(getter_Copies(ccList));
           err = aTerm->MatchRfc822String (ccList.get(), charset, charsetOverride, &result);
         }
         break;
       }
+      case nsMsgSearchAttrib::AllAddresses:
+      {
+        PRBool boolKeepGoing;
+        aTerm->GetMatchAllBeforeDeciding(&boolKeepGoing);
+        msgToMatch->GetRecipients(getter_Copies(recipients));
+        err = aTerm->MatchRfc822String (recipients.get(), charset, charsetOverride, &result);
+        if (boolKeepGoing == result)
+        {
+          msgToMatch->GetCcList(getter_Copies(ccList));
+          err = aTerm->MatchRfc822String (ccList.get(), charset, charsetOverride, &result);
+        }
+        if (boolKeepGoing == result)
+        {
+          msgToMatch->GetAuthor(getter_Copies(matchString));
+          err = aTerm->MatchRfc822String (matchString.get(), charset, charsetOverride, &result);
+        }
+        break;
+      }
       case nsMsgSearchAttrib::Body:
        {
          nsMsgKey messageOffset;
          PRUint32 lineCount;
          msgToMatch->GetMessageOffset(&messageOffset);
          msgToMatch->GetLineCount(&lineCount);
          err = aTerm->MatchBody (scope, messageOffset, lineCount, charset, msgToMatch, db, &result);
          break;
--- a/mailnews/base/search/src/nsMsgSearchTerm.cpp
+++ b/mailnews/base/search/src/nsMsgSearchTerm.cpp
@@ -98,16 +98,17 @@ nsMsgSearchAttribEntry SearchAttribEntry
     {nsMsgSearchAttrib::Sender,     "from"},
     {nsMsgSearchAttrib::Body,       "body"},
     {nsMsgSearchAttrib::Date,       "date"},
     {nsMsgSearchAttrib::Priority,   "priority"},
     {nsMsgSearchAttrib::MsgStatus,  "status"},
     {nsMsgSearchAttrib::To,         "to"},
     {nsMsgSearchAttrib::CC,         "cc"},
     {nsMsgSearchAttrib::ToOrCC,     "to or cc"},
+    {nsMsgSearchAttrib::AllAddresses, "all addresses"},
     {nsMsgSearchAttrib::AgeInDays,  "age in days"},
     {nsMsgSearchAttrib::Label,      "label"},
     {nsMsgSearchAttrib::Keywords,   "tag"},
     {nsMsgSearchAttrib::Size,       "size"},
     // this used to be nsMsgSearchAttrib::SenderInAddressBook
     // we used to have two Sender menuitems
     // for backward compatability, we can still parse
     // the old style.  see bug #179803
--- a/mailnews/base/test/unit/test_searchAddressInAb.js
+++ b/mailnews/base/test/unit/test_searchAddressInAb.js
@@ -30,16 +30,17 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Testing of to, cc, toorcc in addressbook search features added in bug 187768
+// Added testing of AllAddresses from bug 310359
 
 do_import_script("../mailnews/test/resources/searchTestUtils.js");
 
 // add address book setup
 do_import_script("../mailnews/addrbook/test/resources/abSetup.js");
 
 const ABUri = kPABData.URI;
 
@@ -59,78 +60,92 @@ const onlineMail = nsMsgSearchScope.onli
 const offlineMailFilter = nsMsgSearchScope.offlineMailFilter;
 const onlineMailFilter = nsMsgSearchScope.onlineMailFilter;
 const news = nsMsgSearchScope.news; // control entry that is not enabled
 
 const Sender = nsMsgSearchAttrib.Sender;
 const To = nsMsgSearchAttrib.To;
 const CCopy = nsMsgSearchAttrib.CC;
 const ToOrCC = nsMsgSearchAttrib.ToOrCC;
+const AllAddresses = nsMsgSearchAttrib.AllAddresses;
 const Keywords = nsMsgSearchAttrib.Keywords; // control entry that is not enabled
 
 /*
  * The address available in the test address book is "PrimaryEmail1@test.invalid"
  * Test emails may also include the address "invalid@example.com"
  *
+ *
  * Map of test email contents: (P is "Prim...", I is "inva.." address)
  *
  *  Email      From       To      CC
+ *    1         P         I       I
  *    2         P         P       P
  *    3         I         P       I
  *    4         I         I       P
  *    5         P         I       P
  *    6         I         I,P     P,I
  *    7         I         I       I
+ *    8         I         P       P
  *
  */
  
 var Tests =
 [
   { value: ABUri,
     attrib: Sender,
     op: IsInAB,
-    count: 2 },
-  { value: ABUri,
-    attrib: To,
-    op: IsInAB,
     count: 3 },
   { value: ABUri,
-    attrib: ToOrCC,
-    op: IsInAB,
-    count: 5 },
-  { value: ABUri,
-    attrib: CCopy,
+    attrib: To,
     op: IsInAB,
     count: 4 },
   { value: ABUri,
+    attrib: ToOrCC,
+    op: IsInAB,
+    count: 6 },
+  { value: ABUri,
+    attrib: AllAddresses,
+    op: IsInAB,
+    count: 7 },
+  { value: ABUri,
+    attrib: CCopy,
+    op: IsInAB,
+    count: 5 },
+  { value: ABUri,
     attrib: Sender,
     op: IsntInAB,
-    count: 4 },
+    count: 5 },
   { value: ABUri,
     attrib: To,
     op: IsntInAB,
-    count: 4 },
+    count: 5 },
   { value: ABUri,
     attrib: ToOrCC,
     op: IsntInAB,
-    count: 5 },
+    count: 6 },
+  { value: ABUri,
+    attrib: AllAddresses,
+    op: IsntInAB,
+    count: 7 },
   { value: ABUri,
     attrib: CCopy,
     op: IsntInAB,
-    count: 3 },
+    count: 4 },
 ];
 
 var Files = 
 [
+  "../mailnews/test/data/bugmail1",
   "../mailnews/test/data/bugmail2",
   "../mailnews/test/data/bugmail3",
   "../mailnews/test/data/bugmail4",
   "../mailnews/test/data/bugmail5",
   "../mailnews/test/data/bugmail6",
-  "../mailnews/test/data/bugmail7"
+  "../mailnews/test/data/bugmail7",
+  "../mailnews/test/data/bugmail8"
 ]
 
 var messageKey, hdr;
 
 function run_test()
 {
   // Setup local mail accounts.
 
@@ -143,43 +158,49 @@ function run_test()
   testAB.copyTo(gProfileDir, kPABData.fileName);
 
   // test that validity table terms are valid
 
   // offline mail table
   testValidityTable(offlineMail, IsInAB, Sender, true);
   testValidityTable(offlineMail, IsInAB, To, true);
   testValidityTable(offlineMail, IsInAB, ToOrCC, true);
+  testValidityTable(offlineMail, IsInAB, AllAddresses, true);
   testValidityTable(offlineMail, IsInAB, CCopy, true);
   testValidityTable(offlineMail, IsInAB, Keywords, false);
   testValidityTable(offlineMail, IsntInAB, Sender, true);
   testValidityTable(offlineMail, IsntInAB, To, true);
   testValidityTable(offlineMail, IsntInAB, ToOrCC, true);
+  testValidityTable(offlineMail, IsntInAB, AllAddresses, true);
   testValidityTable(offlineMail, IsntInAB, CCopy, true);
   testValidityTable(offlineMail, IsntInAB, Keywords, false);
   testValidityTable(offlineMail, IsBefore, Sender, false);
   testValidityTable(offlineMail, IsBefore, To, false);
   testValidityTable(offlineMail, IsBefore, ToOrCC, false);
+  testValidityTable(offlineMail, IsBefore, AllAddresses, false);
   testValidityTable(offlineMail, IsBefore, CCopy, false);
   testValidityTable(offlineMail, IsBefore, Keywords, false);
 
   // offline mail filter table
   testValidityTable(offlineMailFilter, IsInAB, Sender, true);
   testValidityTable(offlineMailFilter, IsInAB, To, true);
   testValidityTable(offlineMailFilter, IsInAB, ToOrCC, true);
+  testValidityTable(offlineMailFilter, IsInAB, AllAddresses, true);
   testValidityTable(offlineMailFilter, IsInAB, CCopy, true);
   testValidityTable(offlineMailFilter, IsInAB, Keywords, false);
   testValidityTable(offlineMailFilter, IsntInAB, Sender, true);
   testValidityTable(offlineMailFilter, IsntInAB, To, true);
+  testValidityTable(offlineMailFilter, IsntInAB, AllAddresses, true);
   testValidityTable(offlineMailFilter, IsntInAB, ToOrCC, true);
   testValidityTable(offlineMailFilter, IsntInAB, CCopy, true);
   testValidityTable(offlineMailFilter, IsntInAB, Keywords, false);
   testValidityTable(offlineMailFilter, IsBefore, Sender, false);
   testValidityTable(offlineMailFilter, IsBefore, To, false);
   testValidityTable(offlineMailFilter, IsBefore, ToOrCC, false);
+  testValidityTable(offlineMailFilter, IsBefore, AllAddresses, false);
   testValidityTable(offlineMailFilter, IsBefore, CCopy, false);
   testValidityTable(offlineMailFilter, IsBefore, Keywords, false);
 
   // online mail
   testValidityTable(onlineMail, IsInAB, Sender, false);
   testValidityTable(onlineMail, IsInAB, To, false);
   testValidityTable(onlineMail, IsInAB, ToOrCC, false);
   testValidityTable(onlineMail, IsInAB, CCopy, false);
--- a/mailnews/test/data/bugmail1
+++ b/mailnews/test/data/bugmail1
@@ -22,18 +22,19 @@ Received: from webapp01.sj.mozilla.com (
 Received: from mrapp51.mozilla.org (mrapp51.mozilla.org [127.0.0.1])
 	by webapp-out.mozilla.org (8.13.8/8.13.8) with ESMTP id m47LtAFJ007547
 	for <kent@example.com>; Wed, 7 May 2008 14:55:10 -0700
 Received: (from root@localhost)
 	by mrapp51.mozilla.org (8.13.8/8.13.8/Submit) id m47LtAEf007542;
 	Wed, 7 May 2008 14:55:10 -0700
 Date: Wed, 7 May 2008 14:55:10 -0700
 Message-Id: <200805072155.m47LtAEf007542@mrapp51.mozilla.org>
-From: bugzilla-daemon@mozilla.org
-To: kent@example.com
+To: invalid@example.com
+From: PrimaryEmail1@test.invalid
+Cc: invalid@example.com
 Subject: [Bug 397009] A filter will let me tag, but not untag
 X-Bugzilla-Reason: None
 X-Bugzilla-Type: newchanged
 X-Bugzilla-Watch-Reason: QAcontact filters@mail.bugs
 X-Bugzilla-Product: Core
 X-Bugzilla-Component: MailNews: Filters
 X-Bugzilla-Keywords: 
 X-Bugzilla-Severity: enhancement
new file mode 100644
--- /dev/null
+++ b/mailnews/test/data/bugmail8
@@ -0,0 +1,72 @@
+From - Tue Oct 02 00:26:47 2007
+X-Account-Key: account2
+X-UIDL: UID18345-1161858178
+X-Mozilla-Status: 0001
+X-Mozilla-Status2: 00000000
+X-Mozilla-Keys: $label4                                                                         
+Received: from example by host29.example.com with local-bsmtp (Exim 4.68)
+	(envelope-from <bugzilla-daemon@mozilla.org>)
+	id 1JtrbR-0001Kc-Nf
+	for invalid@example.com; Wed, 07 May 2008 15:55:21 -0600
+X-Spam-Checker-Version: SpamAssassin 3.2.3 (2007-08-08) on
+	host29.example.com
+X-Spam-Level: 
+X-Spam-Status: No, score=-2.4 required=5.0 tests=AWL,BAYES_00 autolearn=ham
+	version=3.2.3
+Received: from webapp01.sj.mozilla.com ([10.3.4.5] helo=webapp-out.mozilla.org)
+	by host29.example.com with esmtps (TLSv1:AES256-SHA:256)
+	(Exim 4.68)
+	(envelope-from <bugzilla-daemon@mozilla.org>)
+	id 1JtrbR-0001KT-FP
+	for invalid@example.com; Wed, 07 May 2008 15:55:09 -0600
+Received: from mrapp51.mozilla.org (mrapp51.mozilla.org [127.0.0.1])
+	by webapp-out.mozilla.org (8.13.8/8.13.8) with ESMTP id m47LtAFJ007547
+	for <invalid@example.com>; Wed, 7 May 2008 14:55:10 -0700
+Received: (from root@localhost)
+	by mrapp51.mozilla.org (8.13.8/8.13.8/Submit) id m47LtAEf007542;
+	Wed, 7 May 2008 14:55:10 -0700
+Date: Wed, 7 May 2008 14:55:10 -0700
+Message-Id: <bugmail7.m47LtAEf007542@mrapp51.mozilla.org>
+From: invalid@example.com
+To: PrimaryEmail1@test.invalid
+Cc: PrimaryEmail1@test.invalid
+Subject: [Bug 397009] A filter will let me tag, but not untag
+X-Bugzilla-Reason: None
+X-Bugzilla-Type: newchanged
+X-Bugzilla-Watch-Reason: QAcontact filters@mail.bugs
+X-Bugzilla-Product: Core
+X-Bugzilla-Component: MailNews: Filters
+X-Bugzilla-Keywords: 
+X-Bugzilla-Severity: enhancement
+X-Bugzilla-Who: bugmail@example.org
+X-Bugzilla-Status: NEW
+X-Bugzilla-Priority: --
+X-Bugzilla-Assigned-To: nobody@mozilla.org
+X-Bugzilla-Target-Milestone: ---
+X-Bugzilla-Changed-Fields: Blocks
+In-Reply-To: <bug-397009-254728@https.bugzilla.mozilla.org/>
+References: <bug-397009-254728@https.bugzilla.mozilla.org/>
+Content-Type: text/plain; charset="UTF-8"
+MIME-Version: 1.0
+X-user: ::::10.0.1.2:host29.example.net::::::
+DomainKey-Status: no signature
+
+Do not reply to this email.  You can add comments to this bug at
+https://bugzilla.mozilla.org/show_bug.cgi?id=397009
+
+
+Some User <bugmail@example.org> changed:
+
+           What    |Removed                     |Added
+----------------------------------------------------------------------------
+             Blocks|                            |432710
+
+
+
+
+-- 
+Configure bugmail: https://bugzilla.mozilla.org/userprefs.cgi?tab=email
+------- You are receiving this mail because: -------
+You are watching the QA contact of the bug.
+
+
--- a/suite/locales/en-US/chrome/mailnews/search-attributes.properties
+++ b/suite/locales/en-US/chrome/mailnews/search-attributes.properties
@@ -42,16 +42,16 @@ 34=reserved for AB
 35=reserved for AB
 36=reserved for AB
 37=reserved for AB
 38=reserved for AB
 39=reserved for AB
 40=reserved for AB
 41=reserved for AB
 42=reserved for AB
-43=reserved for AB
+43=From, To or CC
 44=Junk Score Origin
 45=Junk Percent
 46=Attachment Status
 47=Junk Status 
 48=Label
 # don't use above 49
 49=Customize…
--- a/suite/mailnews/mailWidgets.xml
+++ b/suite/mailnews/mailWidgets.xml
@@ -1086,20 +1086,21 @@
             // Keywords has the null field IsEmpty
             if (this.searchAttribute == Components.interfaces.nsMsgSearchAttrib.Keywords) {
               if (val == Components.interfaces.nsMsgSearchOp.IsEmpty)
                 this.setAttribute("selectedIndex", "-1");
               else
                 this.setAttribute("selectedIndex", "5");
             }
 
-              // if it's not sender, to, cc, or toorcc, we don't care
+              // if it's not sender, to, cc, alladdresses, or toorcc, we don't care
               if (this.searchAttribute != Components.interfaces.nsMsgSearchAttrib.Sender && 
                 this.searchAttribute != Components.interfaces.nsMsgSearchAttrib.To && 
                 this.searchAttribute != Components.interfaces.nsMsgSearchAttrib.ToOrCC && 
+                this.searchAttribute != Components.interfaces.nsMsgSearchAttrib.AllAddresses &&
                 this.searchAttribute != Components.interfaces.nsMsgSearchAttrib.CC ) {
               this.internalOperator = val;
               return val;
             }
 
             var children = document.getAnonymousNodes(this);
             if (val == Components.interfaces.nsMsgSearchOp.IsntInAB ||
                 val == Components.interfaces.nsMsgSearchOp.IsInAB) {
@@ -1205,16 +1206,17 @@
           }
           else if (attrib == nsMsgSearchAttrib.AgeInDays)
             children[0].value = val.age;
           else if (attrib == nsMsgSearchAttrib.Date)
             children[3].value = convertPRTimeToString(val.date);
           else if (attrib == nsMsgSearchAttrib.Sender || 
                    attrib == nsMsgSearchAttrib.To ||
                    attrib == nsMsgSearchAttrib.CC ||
+                   attrib == nsMsgSearchAttrib.AllAddresses ||
                    attrib == nsMsgSearchAttrib.ToOrCC)
           {
             if (this.internalOperator == Components.interfaces.nsMsgSearchOp.IsntInAB ||
                 this.internalOperator == Components.interfaces.nsMsgSearchOp.IsInAB) {
               var abs = children[4].getElementsByAttribute("value", val.str);
               if (abs.item(0))
                 children[4].selectedItem = abs[0];
             }
@@ -1276,16 +1278,17 @@
                searchValue.status = children[2].value;
             else if (searchAttribute == nsMsgSearchAttrib.AgeInDays)
                searchValue.age = children[0].value;
             else if (searchAttribute == nsMsgSearchAttrib.Date)
                searchValue.date = convertStringToPRTime(children[3].value);
             else if (searchAttribute == nsMsgSearchAttrib.Sender ||
                    searchAttribute == nsMsgSearchAttrib.To ||
                    searchAttribute == nsMsgSearchAttrib.CC ||
+                   searchAttribute == nsMsgSearchAttrib.AllAddresses ||
                    searchAttribute == nsMsgSearchAttrib.ToOrCC)
             {
               if (this.internalOperator == Components.interfaces.nsMsgSearchOp.IsntInAB ||
                   this.internalOperator == Components.interfaces.nsMsgSearchOp.IsInAB)
                 searchValue.str = children[4].selectedItem.value;
               else
                 searchValue.str = children[0].value;
             }