Add support for distribution lists (groups)
authorAndre Heinecke <aheinecke@intevation.de>
Tue, 10 Jul 2018 10:25:45 +0000 (12:25 +0200)
committerAndre Heinecke <aheinecke@intevation.de>
Tue, 10 Jul 2018 10:28:55 +0000 (12:28 +0200)
* src/oomhelp.cpp (get_recipient_addr_fallbacks):
Handle distributionb lists and plit into
(get_recipient_addr_entry_fallbacks_ex): New. Handle
the exchange stuff.
(try_resolve_group): Resolve distribution lists.
(get_oom_recipients): Check for distribution lists.
* src/oomhelp.h: Add some new defines.

--
This adds support for contact groups / distribution lists.
Not tested with exchange yet but it should work as the code
for the exchange fallbacks is still used.

GnuPG-Bug-Id: T4065

src/oomhelp.cpp
src/oomhelp.h

index 8ed1842..7884752 100644 (file)
@@ -1105,23 +1105,10 @@ get_pa_int (LPDISPATCH pDisp, const char *property, int *rInt)
   return 0;
 }
 
-/* Helper for additional fallbacks in recipient lookup */
+/* Helper for exchange address lookup. */
 static char *
-get_recipient_addr_fallbacks (LPDISPATCH recipient)
+get_recipient_addr_entry_fallbacks_ex (LPDISPATCH addr_entry)
 {
-  if (!recipient)
-    {
-      return nullptr;
-    }
-  LPDISPATCH addr_entry = get_oom_object (recipient, "AddressEntry");
-
-  if (!addr_entry)
-    {
-      log_debug ("%s:%s: Failed to find AddressEntry",
-                 SRCNAME, __func__);
-      return nullptr;
-    }
-
   /* Maybe check for type here? We are pretty sure that we are exchange */
 
   /* According to MSDN Message Boards the PR_EMS_AB_PROXY_ADDRESSES_DASL
@@ -1137,7 +1124,6 @@ get_recipient_addr_fallbacks (LPDISPATCH recipient)
         {
           ret += 5;
         }
-      gpgol_release (addr_entry);
       return ret;
     }
   else
@@ -1147,7 +1133,6 @@ get_recipient_addr_fallbacks (LPDISPATCH recipient)
     }
 
   LPDISPATCH ex_user = get_oom_object (addr_entry, "GetExchangeUser");
-  gpgol_release (addr_entry);
   if (!ex_user)
     {
       log_debug ("%s:%s: Failed to find ExchangeUser",
@@ -1163,10 +1148,153 @@ get_recipient_addr_fallbacks (LPDISPATCH recipient)
                  SRCNAME, __func__, ret);
       return ret;
     }
-
   return nullptr;
 }
 
+/* Helper for additional fallbacks in recipient lookup */
+static char *
+get_recipient_addr_fallbacks (LPDISPATCH recipient)
+{
+  if (!recipient)
+    {
+      return nullptr;
+    }
+  LPDISPATCH addr_entry = get_oom_object (recipient, "AddressEntry");
+
+  if (!addr_entry)
+    {
+      log_debug ("%s:%s: Failed to find AddressEntry",
+                 SRCNAME, __func__);
+      return nullptr;
+    }
+
+  char *ret = get_recipient_addr_entry_fallbacks_ex (addr_entry);
+
+  gpgol_release (addr_entry);
+
+  return ret;
+}
+
+/* Try to resolve a recipient group and add it to the recipients vector.
+
+   returns true on success.
+*/
+static bool
+try_resolve_group (LPDISPATCH addrEntry, std::vector<std::string> &ret)
+{
+  /* Get the name for debugging */
+  std::string name;
+  char *cname = get_oom_string (addrEntry, "Name");
+  if (cname)
+    {
+      name = cname;
+    }
+  xfree (cname);
+
+  int type = get_oom_int (addrEntry, "AddressEntryUserType");
+
+  if (type != DISTRIBUTION_LIST_ADDRESS_ENTRY_TYPE)
+    {
+      log_mime_parser ("%s:%s: type of %s is %i",
+                       SRCNAME, __func__, name.c_str(), type);
+      return false;
+    }
+
+  LPDISPATCH members = get_oom_object (addrEntry, "Members");
+  addrEntry = nullptr;
+
+  if (!members)
+    {
+      TRACEPOINT;
+      return false;
+    }
+
+  int count = get_oom_int (members, "Count");
+
+  if (!count)
+    {
+      TRACEPOINT;
+      gpgol_release (members);
+      return false;
+    }
+
+  bool foundOne = false;
+  for (int i = 1; i <= count; i++)
+    {
+      auto item_str = std::string("Item(") + std::to_string (i) + ")";
+      LPDISPATCH entry = get_oom_object (members, item_str.c_str());
+      if (!entry)
+        {
+          TRACEPOINT;
+          continue;
+        }
+      std::string entryName;
+      char *entry_name = get_oom_string (entry, "Name");
+      if (entry_name)
+        {
+          entryName = entry_name;
+          xfree (entry_name);
+        }
+
+      int subType = get_oom_int (entry, "AddressEntryUserType");
+      /* Resolve recursively, yeah fun. */
+      if (subType == DISTRIBUTION_LIST_ADDRESS_ENTRY_TYPE)
+        {
+          log_debug ("%s:%s: recursive address entry %s",
+                     SRCNAME, __func__,
+                     (opt.enable_debug & DBG_MIME_PARSER) ?
+                     entryName.c_str() : "omitted");
+          if (try_resolve_group (entry, ret))
+            {
+              foundOne = true;
+              gpgol_release (entry);
+              continue;
+            }
+        }
+
+      /* Resolve directly ? */
+      char *addrtype = get_pa_string (entry, PR_ADDRTYPE_DASL);
+      if (addrtype && !strcmp (addrtype, "SMTP"))
+        {
+          xfree (addrtype);
+          char *resolved = get_pa_string (entry, PR_EMAIL_ADDRESS_DASL);
+          if (resolved)
+            {
+              ret.push_back(resolved);
+              foundOne = true;
+              gpgol_release (entry);
+              continue;
+            }
+        }
+      xfree (addrtype);
+
+      /* Resolve through Exchange API */
+      char *ex_resolved = get_recipient_addr_entry_fallbacks_ex (entry);
+      if (ex_resolved)
+        {
+          ret.push_back (ex_resolved);
+          foundOne = true;
+          gpgol_release (entry);
+          continue;
+        }
+
+      gpgol_release (entry);
+      log_debug ("%s:%s: failed to resolve name %s",
+                 SRCNAME, __func__,
+                 (opt.enable_debug & DBG_MIME_PARSER) ?
+                 entryName.c_str() : "omitted");
+    }
+  gpgol_release (members);
+  if (!foundOne)
+    {
+      log_debug ("%s:%s: failed to resolve group %s",
+                 SRCNAME, __func__,
+                 (opt.enable_debug & DBG_MIME_PARSER) ?
+                 name.c_str() : "omitted");
+    }
+  return foundOne;
+}
+
 /* Gets the resolved smtp addresses of the recpients. */
 std::vector<std::string>
 get_oom_recipients (LPDISPATCH recipients, bool *r_err)
@@ -1198,6 +1326,17 @@ get_oom_recipients (LPDISPATCH recipients, bool *r_err)
             }
           break;
         }
+
+      LPDISPATCH addrEntry = get_oom_object (recipient, "AddressEntry");
+      if (addrEntry && try_resolve_group (addrEntry, ret))
+        {
+          log_debug ("%s:%s: Resolved recipient group",
+                     SRCNAME, __func__);
+          gpgol_release (recipient);
+          gpgol_release (addrEntry);
+          continue;
+        }
+
       char *resolved = get_pa_string (recipient, PR_SMTP_ADDRESS_DASL);
       if (resolved)
         {
index 2fea2ce..4430b0c 100644 (file)
@@ -99,6 +99,16 @@ DEFINE_OLEGUID(IID_IOleWindow,                0x00000114, 0, 0);
   "http://schemas.microsoft.com/mapi/proptag/0x7FFE000B"
 #endif
 
+#ifndef PR_ADDRTYPE_DASL
+#define PR_ADDRTYPE_DASL \
+  "http://schemas.microsoft.com/mapi/proptag/0x3002001E"
+#endif
+
+#ifndef PR_EMAIL_ADDRESS_DASL
+#define PR_EMAIL_ADDRESS_DASL \
+  "http://schemas.microsoft.com/mapi/proptag/0x3003001E"
+#endif
+
 #define PR_MESSAGE_CLASS_W_DASL \
   "http://schemas.microsoft.com/mapi/proptag/0x001A001F"
 #define GPGOL_ATTACHTYPE_DASL \
@@ -126,6 +136,8 @@ DEFINE_OLEGUID(IID_IOleWindow,                0x00000114, 0, 0);
 #define PR_BLOCK_STATUS_DASL \
   "http://schemas.microsoft.com/mapi/proptag/0x10960003"
 
+#define DISTRIBUTION_LIST_ADDRESS_ENTRY_TYPE 11
+
 /* Return the malloced name of an COM+ object.  */
 char *get_object_name (LPUNKNOWN obj);