I’ve recently implemented a feature that was supposed to send emails to all users selected by multi people picker in SharePoint, in one of our projects. Of course SharePoint groups as well as AD groups could be selected too.
It’s not extremely hard to do, but it’s handy to have it up for other coworkers and people use.
public static class SPFieldUserValueCollectionExtensions
{
public static IEnumerable<string> GetAllEmails(this SPFieldUserValueCollection collection, SPWeb web)
{
var emails = new HashSet<string>();
foreach (var item in collection)
{
if (item.User == null)
{
try
{
// is it a SharePoint group?
var group = web.SiteGroups.GetByID(item.LookupId);
emails.AddEmailsFromSPGroup(group);
}
catch
{
// ad group
var group = web.EnsureUser(item.LookupValue);
emails.AddIfNotNull(group.Email);
}
}
else
{
emails.AddIfNotNull(item.User.Email);
}
}
return emails;
}
private static void AddEmailsFromSPGroup(this HashSet<string> emails, SPGroup group)
{
if (!string.IsNullOrEmpty(group.DistributionGroupEmail))
{
emails.Add(group.DistributionGroupEmail);
}
else
{
foreach (SPUser user in group.Users)
{
emails.AddIfNotNull(user.Email);
}
}
}
private static void AddIfNotNull(this HashSet<string> set, string s)
{
if(!string.IsNullOrEmpty(s))
{
set.Add(s);
}
}
}
So basically you iterate through a SPFieldUserValueCollection
, checking
if User property is null first. If it is, it means one of two things:
either it’s a SharePoint group or it’s an AD group that wasn’t loaded
into SharePoint yet. If the group is found in SiteGroups, it’s a
SharePoint group, otherwise AD group must be loaded using EnsureUser
method.
Also for SharePoint group, if DistributionGroupEmail
property is not
set, the code drills into the group, and adds emails of all members.
One thing this method doesn’t do is drill into AD groups when email is not set on that group. While it would be possible to do this, it is way easier to convince customer to setup distribution emails on AD groups or pass it onto your IT department (or theirs).
If your data doesn’t come from built in people picker field, but rather
from custom form with people picker, you can parse content into
SPFieldUserValueCollection
like this:
var mailUsers = new SPFieldUserValueCollection();
mailUsers.AddRange(from PickerEntity entity in UsersEditor.ResolvedEntities
select
new SPFieldUserValue(web, Convert.ToInt32(entity.EntityData["SPUserID"] ??
entity.EntityData["SPGroupID"]),
(string) entity.EntityData["AccountName"]));
emails = mailUsers.GetAllEmails(elevatedWeb).ToList();
Run with elevated privileges to access the SiteGroup property.