using System; using System.Collections.Generic; using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Linq; using System.Reflection; using C4IT.Logging; using static C4IT.Logging.cLogManager; using System.Threading.Tasks; using System.Collections; using System.DirectoryServices.AccountManagement; using System.DirectoryServices.ActiveDirectory; using System.DirectoryServices; using System.ComponentModel; using System.Security.AccessControl; using System.Threading; namespace C4IT.LIAM { /// /// Manages Exchange operations using PowerShell remoting /// public partial class ExchangeManager { private static readonly TimeSpan RunspaceOpenTimeout = TimeSpan.FromSeconds(30); private readonly cLiamProviderBase _provider; private readonly string _exchangeUri; private readonly PSCredential _credential; private readonly string _organizationalUnit; private readonly string _domain; /// /// Constructor with explicit credentials, Exchange URI and OU path /// /// URL of the Exchange PowerShell endpoint (e.g. "http://exchangeserver/PowerShell") /// Explicit credentials /// OU path where objects should be created public ExchangeManager(cLiamProviderBase provider, string exchangeUri, PSCredential credential, string domain, string organizationalUnit) { _provider = provider ?? throw new ArgumentNullException(nameof(provider)); _exchangeUri = exchangeUri; _credential = credential; _domain = domain; _organizationalUnit = organizationalUnit; } /// /// Creates a runspace connected to the Exchange PowerShell endpoint /// private Runspace CreateRunspace() { LogMethodBegin(MethodBase.GetCurrentMethod()); try { var connectionInfo = new WSManConnectionInfo( new Uri(_exchangeUri), "http://schemas.microsoft.com/powershell/Microsoft.Exchange", _credential); connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Kerberos; var runspace = RunspaceFactory.CreateRunspace(connectionInfo); LogEntry($"Opening Exchange runspace (timeout: {RunspaceOpenTimeout.TotalSeconds:0}s) for endpoint '{_exchangeUri}'", LogLevels.Debug); var openTask = Task.Run(() => runspace.Open()); if (!openTask.Wait(RunspaceOpenTimeout)) { try { runspace.Dispose(); } catch (Exception disposeEx) { LogException(disposeEx); } throw new TimeoutException( $"Timeout while opening Exchange runspace after {RunspaceOpenTimeout.TotalSeconds:0} seconds."); } openTask.GetAwaiter().GetResult(); LogEntry("Exchange runspace opened successfully", LogLevels.Debug); return runspace; } catch (Exception ex) { LogException(ex); throw; } finally { LogMethodEnd(MethodBase.GetCurrentMethod()); } } // Internal helper for creation details private class CreationResult { public Guid ObjectGuid { get; set; } public List> Groups { get; private set; } public CreationResult() { Groups = new List>(); } } private DirectoryEntry FindAdObject(string ldapFilter) { using (DirectoryEntry root = new DirectoryEntry("LDAP://" + _organizationalUnit, _credential.UserName, SecureStringToString(_credential.Password), AuthenticationTypes.Secure)) { using (DirectorySearcher ds = new DirectorySearcher(root)) { ds.Filter = ldapFilter; ds.PropertiesToLoad.Add("objectGUID"); ds.PropertiesToLoad.Add("objectSid"); ds.PropertiesToLoad.Add("cn"); ds.PropertiesToLoad.Add("sAMAccountName"); SearchResult searchResult = ds.FindOne(); if (searchResult != null) return searchResult.GetDirectoryEntry(); return null; } } } /// /// Creates a distribution group (mailing list). Optionally members can be added initially. /// public void CreateDistributionGroup(string name, string alias, List initialMembers = null) { LogMethodBegin(MethodBase.GetCurrentMethod()); try { using (var runspace = CreateRunspace()) using (var ps = PowerShell.Create()) { ps.Runspace = runspace; ps.AddCommand("New-DistributionGroup") .AddParameter("Name", name) .AddParameter("Alias", alias) .AddParameter("OrganizationalUnit", _organizationalUnit); ps.Invoke(); if (initialMembers != null) { foreach (var member in initialMembers) { ps.Commands.Clear(); ps.AddCommand("Add-DistributionGroupMember") .AddParameter("Identity", name) .AddParameter("Member", member); ps.Invoke(); } } } } catch (Exception ex) { LogException(ex); throw; } finally { LogMethodEnd(MethodBase.GetCurrentMethod()); } } /// /// Creates a security group in Active Directory that can be used for Exchange permissions /// – direkt per LDAP und mit den im Konstruktor übergebenen Credentials & Domain. /// public bool CreateSecurityGroup(eLiamAccessRoles accessRole, string baseName, string baseDescription="") { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { // Find the naming convention for this role var namingConvention = _provider.NamingConventions .FirstOrDefault(nc => nc.AccessRole == accessRole); if (namingConvention == null) throw new InvalidOperationException($"No naming convention found for role '{accessRole}'"); // Generate group name and description from templates string groupName = namingConvention.NamingTemplate .Replace("{Name}", baseName); string groupDescription = namingConvention.DescriptionTemplate .Replace("{Name}", baseDescription); // Determine scope bit for groupType int scopeBit; switch (namingConvention.Scope) { case eLiamAccessRoleScopes.Global: scopeBit = 0x2; break; case eLiamAccessRoleScopes.DomainLocal: scopeBit = 0x4; break; case eLiamAccessRoleScopes.Universal: scopeBit = 0x8; break; default: scopeBit = 0x8; break; } int groupType = unchecked((int)(0x80000000 | scopeBit)); // Create the group in AD string ldapPath = $"LDAP://{_organizationalUnit}"; string password = new System.Net.NetworkCredential(string.Empty, _credential.Password).Password; using (var root = new DirectoryEntry( ldapPath, _credential.UserName, password, AuthenticationTypes.Secure)) { var newGroup = root.Children.Add($"CN={groupName}", "group"); newGroup.Properties["sAMAccountName"].Value = groupName; newGroup.Properties["displayName"].Value = groupName; newGroup.Properties["groupType"].Value = groupType; newGroup.Properties["description"].Value = groupDescription; newGroup.CommitChanges(); } return true; } catch (Exception ex) { LogException(ex); return false; } finally { LogMethodEnd(CM); } } /// /// Gets all shared mailboxes matching an optional filter /// public IEnumerable GetSharedMailboxes(string filter = null) { var result = GetSharedMailboxes(filter, out _, out _); return result ?? Enumerable.Empty(); } /// /// Gets all shared mailboxes matching an optional filter. /// Returns null on failure and exposes an error code/message. /// public IEnumerable GetSharedMailboxes(string filter, out string errorCode, out string errorMessage) { LogMethodBegin(MethodBase.GetCurrentMethod()); errorCode = "OK"; errorMessage = string.Empty; try { using (var runspace = CreateRunspace()) using (var ps = PowerShell.Create()) { ps.Runspace = runspace; ps.AddCommand("Get-Mailbox") .AddParameter("RecipientTypeDetails", "SharedMailbox"); if (!string.IsNullOrEmpty(filter)) { ps.AddParameter("Filter", filter); } return InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"Get-Mailbox SharedMailbox filter='{filter ?? string.Empty}'"); } } catch (TimeoutException ex) { LogException(ex); errorCode = "EXCH_GET_SHAREDMAILBOXES_TIMEOUT"; errorMessage = ex.Message; return null; } catch (Exception ex) { LogException(ex); errorCode = "EXCH_GET_SHAREDMAILBOXES_FAILED"; errorMessage = ex.Message; return null; } finally { LogMethodEnd(MethodBase.GetCurrentMethod()); } } /// /// Gets a shared mailbox by primary SMTP address /// public PSObject GetSharedMailboxByAddress(string primarySmtpAddress) { LogMethodBegin(MethodBase.GetCurrentMethod()); try { using (var runspace = CreateRunspace()) using (var ps = PowerShell.Create()) { ps.Runspace = runspace; ps.AddCommand("Get-Mailbox") .AddParameter("RecipientTypeDetails", "SharedMailbox") .AddParameter("PrimarySmtpAddress", primarySmtpAddress); var results = InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"Get-Mailbox SharedMailbox address='{primarySmtpAddress}'"); return results.Count > 0 ? results[0] : null; } } catch (Exception ex) { LogException(ex); return null; } finally { LogMethodEnd(MethodBase.GetCurrentMethod()); } } /// /// Gets all distribution groups matching an optional filter /// public IEnumerable GetDistributionGroups(string filter = null) { var result = GetDistributionGroups(filter, out _, out _); return result ?? Enumerable.Empty(); } /// /// Gets all distribution groups matching an optional filter. /// Returns null on failure and exposes an error code/message. /// public IEnumerable GetDistributionGroups(string filter, out string errorCode, out string errorMessage) { LogMethodBegin(MethodBase.GetCurrentMethod()); errorCode = "OK"; errorMessage = string.Empty; try { using (var runspace = CreateRunspace()) using (var ps = PowerShell.Create()) { ps.Runspace = runspace; ps.AddCommand("Get-DistributionGroup"); if (!string.IsNullOrEmpty(filter)) { ps.AddParameter("Filter", filter); } return InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"Get-DistributionGroup filter='{filter ?? string.Empty}'"); } } catch (TimeoutException ex) { LogException(ex); errorCode = "EXCH_GET_DISTRIBUTIONGROUPS_TIMEOUT"; errorMessage = ex.Message; return null; } catch (Exception ex) { LogException(ex); errorCode = "EXCH_GET_DISTRIBUTIONGROUPS_FAILED"; errorMessage = ex.Message; return null; } finally { LogMethodEnd(MethodBase.GetCurrentMethod()); } } /// /// Gets a distribution group by primary SMTP address. /// Die Methode bleibt unverändert. /// public PSObject GetDistributionGroupByAddress(string primarySmtpAddress) { LogMethodBegin(MethodBase.GetCurrentMethod()); try { using (var runspace = CreateRunspace()) using (var ps = PowerShell.Create()) { ps.Runspace = runspace; ps.AddCommand("Get-DistributionGroup") .AddParameter("PrimarySmtpAddress", primarySmtpAddress); var results = InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"Get-DistributionGroup address='{primarySmtpAddress}'"); return results.Count > 0 ? results[0] : null; } } catch (Exception ex) { LogException(ex); return null; } finally { LogMethodEnd(MethodBase.GetCurrentMethod()); } } /// /// Gets members of a distribution group /// public IEnumerable GetDistributionGroupMembers(string distributionListIdentity) { using (var runspace = CreateRunspace()) using (var ps = PowerShell.Create()) { ps.Runspace = runspace; // alle Members des DL holen ps.AddCommand("Get-DistributionGroupMember") .AddParameter("Identity", distributionListIdentity) .AddParameter("ResultSize", "Unlimited") .AddParameter("ErrorAction", "Stop"); var members = InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"Get-DistributionGroupMember '{distributionListIdentity}'"); if (ps.HadErrors || members.Count == 0) return Enumerable.Empty(); var result = new List(); foreach (var member in members) { // nur Gruppen (Security- oder Distributions-Gruppen) var rt = member.Properties["RecipientTypeDetails"]?.Value?.ToString() ?? ""; if (rt.IndexOf("Group", StringComparison.OrdinalIgnoreCase) <= 0) continue; // SamAccountName auslesen var name = member.Properties["Name"]?.Value?.ToString(); if (string.IsNullOrEmpty(name)) continue; // AD-Gruppe per .NET auflösen using (var ctx = new PrincipalContext(ContextType.Domain)) using (var grp = GroupPrincipal.FindByIdentity(ctx, IdentityType.Name, name)) { if (grp == null) continue; // PSObject bauen var obj = new PSObject(); obj.Properties.Add(new PSNoteProperty("SamAccountName", grp.SamAccountName)); obj.Properties.Add(new PSNoteProperty("Name", grp.Name)); obj.Properties.Add(new PSNoteProperty("Sid", grp.Sid.Value)); obj.Properties.Add(new PSNoteProperty("DistinguishedName", grp.DistinguishedName)); obj.Properties.Add(new PSNoteProperty("GroupPrincipal", grp)); result.Add(obj); } } return result; } } public IEnumerable GetSendAsPermissionMembers(string mailboxIdentity) { LogMethodBegin(MethodBase.GetCurrentMethod()); try { using (var runspace = CreateRunspace()) using (var ps = PowerShell.Create()) { ps.Runspace = runspace; // 1) Alle AD-Permissions holen ps.AddCommand("Get-ADPermission") .AddParameter("Identity", mailboxIdentity); var perms = ps.Invoke(); if (ps.HadErrors) return Enumerable.Empty(); var result = new List(); using (var ps2 = PowerShell.Create()) { ps2.Runspace = runspace; foreach (var perm in perms) { // 2) Nur explizite (nicht geerbte) Rechte var inherited = perm.Properties["IsInherited"]?.Value as bool? ?? true; if (inherited) continue; // 3) ExtendedRights robust auslesen var rawVal = perm.Properties["ExtendedRights"]?.Value; IEnumerable rights = null; if (rawVal is IEnumerable seq && !(rawVal is string)) rights = seq.Cast(); else if (rawVal is PSObject pso && pso.BaseObject is IEnumerable baseSeq) rights = baseSeq.Cast(); else if (rawVal != null) rights = new[] { rawVal }; // wenn gar keine Rechte da sind, weiter if (rights == null) continue; // die Liste der Recht‑Strings extrahieren var rightStrings = rights .Select(r => (r as PSObject)?.Properties["RawIdentity"]?.Value?.ToString() ?? r.ToString()) .ToList(); // UND jetzt prüfen, ob *genau* "Send-As" (normaler Bindestrich) enthalten ist if (!rightStrings .Any(rs => string.Equals(rs.Trim(), "Send-As", StringComparison.OrdinalIgnoreCase))) { continue; // kein Send‑As, nächste Permission } // 4) System‑Accounts rausfiltern var userName = perm.Properties["User"]?.Value?.ToString() ?? ""; if (userName.StartsWith("NT AUTHORITY", StringComparison.OrdinalIgnoreCase) || userName.IndexOf("SELF", StringComparison.OrdinalIgnoreCase) >= 0 || userName.IndexOf("Administrator", StringComparison.OrdinalIgnoreCase) >= 0) continue; // 5) Get-User auflösen ps2.Commands.Clear(); ps2.AddCommand("Get-User") .AddParameter("Identity", userName); var users = ps2.Invoke(); if (users.Count > 0) result.Add(users[0]); } } return result; } } catch (Exception ex) { LogException(ex); return Enumerable.Empty(); } finally { LogMethodEnd(MethodBase.GetCurrentMethod()); } } /// /// Liefert pro Send‑As‑Gruppe ein PSObject mit Name, SID und dem GroupPrincipal selbst. /// public IEnumerable GetSendAsPermissionGroups(string mailboxIdentity) { LogMethodBegin(MethodBase.GetCurrentMethod()); try { using (var runspace = CreateRunspace()) using (var ps = PowerShell.Create()) { ps.Runspace = runspace; ps.AddCommand("Get-ADPermission") .AddParameter("Identity", mailboxIdentity) .AddParameter("ErrorAction", "Stop"); var perms = InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"Get-ADPermission (SendAsGroups) '{mailboxIdentity}'"); if (ps.HadErrors || perms.Count == 0) return Enumerable.Empty(); var result = new List(); foreach (var perm in perms) { // 1) Nur explizite Rechte var inherited = perm.Properties["IsInherited"]?.Value as bool? ?? true; if (inherited) continue; // 2) ExtendedRights auf "Send‑As" prüfen (nur via ToString) var rawVal = perm.Properties["ExtendedRights"]?.Value; IEnumerable rights; if (rawVal is System.Collections.IEnumerable seq && !(rawVal is string)) rights = seq.Cast(); else if (rawVal is PSObject pso && pso.BaseObject is System.Collections.IEnumerable baseSeq) rights = baseSeq.Cast(); else if (rawVal != null) rights = new[] { rawVal }; else continue; // ganz einfach: jede Rechte-Instanz zu String machen var rightStrings = rights.Select(r => r.ToString().Trim()); if (!rightStrings.Any(s => string.Equals(s, "Send-As", StringComparison.OrdinalIgnoreCase))) { continue; } // 3) Nur Gruppen‑Principals (DOMAIN\Name) und keine System‑Accounts var userName = perm.Properties["User"]?.Value?.ToString() ?? ""; var low = userName.ToLowerInvariant(); if (!userName.Contains("\\") || low.StartsWith("nt authority") || low.Contains("self") || low.Contains("administrator")) continue; // 4) Gruppe im AD auflösen var sam = userName.Split('\\').Last(); using (var ctx = new PrincipalContext(ContextType.Domain)) using (var grp = GroupPrincipal.FindByIdentity(ctx, sam)) { if (grp == null) continue; // 5) PSObject mit allen gewünschten Properties anlegen var obj = new PSObject(); obj.Properties.Add(new PSNoteProperty("SamAccountName", grp.SamAccountName)); obj.Properties.Add(new PSNoteProperty("Name", grp.Name)); obj.Properties.Add(new PSNoteProperty("Sid", grp.Sid.Value)); obj.Properties.Add(new PSNoteProperty("DistinguishedName", grp.DistinguishedName)); obj.Properties.Add(new PSNoteProperty("GroupPrincipal", grp)); result.Add(obj); } } return result; } } catch (Exception ex) { LogException(ex); return Enumerable.Empty(); } finally { LogMethodEnd(MethodBase.GetCurrentMethod()); } } /// /// Liefert pro Gruppe, die FullAccess auf das angegebene Postfach hat, /// ein PSObject mit Name, SID, DistinguishedName und dem GroupPrincipal. /// public IEnumerable GetFullAccessPermissionGroups(string mailboxIdentity) { LogMethodBegin(MethodBase.GetCurrentMethod()); try { using (var runspace = CreateRunspace()) using (var ps = PowerShell.Create()) { ps.Runspace = runspace; // 1) Alle FullAccess-Berechtigungen für das Postfach holen ps.AddCommand("Get-MailboxPermission") .AddParameter("Identity", mailboxIdentity) .AddParameter("ErrorAction", "Stop"); var perms = InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"Get-MailboxPermission (FullAccessGroups) '{mailboxIdentity}'"); if (ps.HadErrors || perms.Count == 0) return Enumerable.Empty(); var result = new List(); foreach (var perm in perms) { // 2) Eingebettete Properties ziehen // - IsInherited // - AccessRights (MultiValuedProperty) var inherited = perm.Properties["IsInherited"]?.Value as bool? ?? true; if (inherited) continue; var rawVal = perm.Properties["AccessRights"]?.Value; IEnumerable rights = null; if (rawVal is System.Collections.IEnumerable seq && !(rawVal is string)) rights = seq.Cast(); else if (rawVal is PSObject pso && pso.BaseObject is System.Collections.IEnumerable baseSeq) rights = baseSeq.Cast(); else if (rawVal != null) rights = new[] { rawVal }; // 3) Nur FullAccess durchlassen if (rights == null || !rights.Any(r => { var s = (r as PSObject)?.BaseObject?.ToString() ?? r.ToString(); return string.Equals(s, "FullAccess", StringComparison.OrdinalIgnoreCase); })) { continue; } // 4) Nur Security-Principals im DOMAIN\Name-Format und keine System‑Accounts var userName = perm.Properties["User"]?.Value?.ToString() ?? ""; var low = userName.ToLowerInvariant(); if (!userName.Contains("\\") || low.StartsWith("nt authority") || low.Contains("self") || low.Contains("administrator")) { continue; } // 5) Gruppe im AD auflösen und PSObject bauen var sam = userName.Split('\\').Last(); using (var ctx = new PrincipalContext(ContextType.Domain)) using (var grp = GroupPrincipal.FindByIdentity(ctx, sam)) { if (grp == null) continue; var obj = new PSObject(); obj.Properties.Add(new PSNoteProperty("SamAccountName", grp.SamAccountName)); obj.Properties.Add(new PSNoteProperty("Name", grp.Name)); obj.Properties.Add(new PSNoteProperty("Sid", grp.Sid.Value)); obj.Properties.Add(new PSNoteProperty("DistinguishedName", grp.DistinguishedName)); obj.Properties.Add(new PSNoteProperty("GroupPrincipal", grp)); result.Add(obj); } } return result; } } catch (Exception ex) { LogException(ex); return Enumerable.Empty(); } finally { LogMethodEnd(MethodBase.GetCurrentMethod()); } } /// /// Gets users who have permissions on a mailbox /// public IEnumerable GetMailboxPermissionMembers(string id) { LogMethodBegin(MethodBase.GetCurrentMethod()); try { using (var runspace = CreateRunspace()) using (var ps = PowerShell.Create()) { ps.Runspace = runspace; ps.AddCommand("Get-MailboxPermission") .AddParameter("Identity", id) .AddParameter("AccessRights", "FullAccess"); var results = ps.Invoke().Where(p => !p.Properties["User"].Value.ToString().Contains("NT AUTHORITY") && !p.Properties["User"].Value.ToString().Contains("Administrator")); var userList = new List(); using (var ps2 = PowerShell.Create()) { ps2.Runspace = runspace; foreach (var perm in results) { ps2.Commands.Clear(); ps2.AddCommand("Get-User") .AddParameter("Identity", perm.Properties["User"].Value.ToString()); var users = ps2.Invoke(); if (users.Count > 0) userList.Add(users[0]); } } return userList; } } catch (Exception ex) { LogException(ex); return Enumerable.Empty(); } finally { LogMethodEnd(MethodBase.GetCurrentMethod()); } } /// /// Sucht im angegebenen AD‑Domain/OU nach Security‑Gruppen, deren Name zum Wildcard passt. /// Nutzt hierfür die übergebenen Anmeldeinformationen. /// public IEnumerable GetSecurityGroups(string nameWildcard) { var result = GetSecurityGroups(nameWildcard, out _, out _); return result ?? new List(); } /// /// Sucht im angegebenen AD‑Domain/OU nach Security‑Gruppen, deren Name zum Wildcard passt. /// Returns null on failure and exposes an error code/message. /// public IEnumerable GetSecurityGroups(string nameWildcard, out string errorCode, out string errorMessage) { LogMethodBegin(MethodBase.GetCurrentMethod()); errorCode = "OK"; errorMessage = string.Empty; try { // Credentials in NetworkCredential konvertieren var netCred = _credential.GetNetworkCredential(); // PrincipalContext auf Domain oder OU using (var ctx = new PrincipalContext( ContextType.Domain, _domain, // ← real domain or DC hostname _organizationalUnit, // ← the OU‑DN to scope your search netCred.UserName, netCred.Password)) { { // QBE‑Gruppe für Wildcard‑Suche using (var qbe = new GroupPrincipal(ctx) { Name = nameWildcard }) using (var searcher = new PrincipalSearcher(qbe)) { var result = new List(); var findTask = Task.Run(() => searcher.FindAll().OfType().ToList()); if (!findTask.Wait(PowerShellInvokeTimeout)) { throw new TimeoutException( $"Directory search operation 'GetSecurityGroups' timed out after {PowerShellInvokeTimeout.TotalSeconds:0} seconds."); } foreach (var principal in findTask.Result) { // DirectoryEntry benötigt man, um DistinguishedName auszulesen var de = principal.GetUnderlyingObject() as DirectoryEntry; var obj = new PSObject(); obj.Properties.Add(new PSNoteProperty("SamAccountName", principal.SamAccountName)); obj.Properties.Add(new PSNoteProperty("DisplayName", principal.Name)); obj.Properties.Add(new PSNoteProperty("Sid", principal.Sid?.Value ?? string.Empty)); obj.Properties.Add(new PSNoteProperty("DistinguishedName", de?.Properties["distinguishedName"]?.Value?.ToString() ?? string.Empty)); result.Add(obj); } return result; } } } } catch (TimeoutException ex) { LogException(ex); errorCode = "EXCH_GET_SECURITYGROUPS_TIMEOUT"; errorMessage = ex.Message; return null; } catch (Exception ex) { LogException(ex); errorCode = "EXCH_GET_SECURITYGROUPS_FAILED"; errorMessage = ex.Message; return null; } finally { LogMethodEnd(MethodBase.GetCurrentMethod()); } } /// /// Adds a member to a distribution group /// public void AddMemberToDistributionGroup(string groupName, string member) { LogMethodBegin(MethodBase.GetCurrentMethod()); try { using (var runspace = CreateRunspace()) using (var ps = PowerShell.Create()) { ps.Runspace = runspace; ps.AddCommand("Add-DistributionGroupMember") .AddParameter("Identity", groupName) .AddParameter("Member", member); ps.Invoke(); } } catch (Exception ex) { LogException(ex); throw; } finally { LogMethodEnd(MethodBase.GetCurrentMethod()); } } /// /// Removes a member from a distribution group /// public void RemoveMemberFromDistributionGroup(string groupName, string member) { LogMethodBegin(MethodBase.GetCurrentMethod()); try { using (var runspace = CreateRunspace()) using (var ps = PowerShell.Create()) { ps.Runspace = runspace; ps.AddCommand("Remove-DistributionGroupMember") .AddParameter("Identity", groupName) .AddParameter("Member", member) .AddParameter("Confirm", false); ps.Invoke(); } } catch (Exception ex) { LogException(ex); throw; } finally { LogMethodEnd(MethodBase.GetCurrentMethod()); } } /// /// Adds mailbox permission for a user /// public void AddMailboxPermission(string mailboxName, string user, string accessRight = "FullAccess") { LogMethodBegin(MethodBase.GetCurrentMethod()); try { using (var runspace = CreateRunspace()) using (var ps = PowerShell.Create()) { ps.Runspace = runspace; ps.AddCommand("Add-MailboxPermission") .AddParameter("Identity", mailboxName) .AddParameter("User", user) .AddParameter("AccessRights", accessRight) .AddParameter("InheritanceType", "All"); ps.Invoke(); } } catch (Exception ex) { LogException(ex); throw; } finally { LogMethodEnd(MethodBase.GetCurrentMethod()); } } /// /// Removes mailbox permission for a user /// public void RemoveMailboxPermission(string mailboxName, string user, string accessRight = "FullAccess") { LogMethodBegin(MethodBase.GetCurrentMethod()); try { using (var runspace = CreateRunspace()) using (var ps = PowerShell.Create()) { ps.Runspace = runspace; ps.AddCommand("Remove-MailboxPermission") .AddParameter("Identity", mailboxName) .AddParameter("User", user) .AddParameter("AccessRights", accessRight) .AddParameter("InheritanceType", "All") .AddParameter("Confirm", false); ps.Invoke(); } } catch (Exception ex) { LogException(ex); throw; } finally { LogMethodEnd(MethodBase.GetCurrentMethod()); } } /// /// Adds Send As permission for a mailbox /// public async Task AddSendAsPermission(string mailboxName, string user) { LogMethodBegin(MethodBase.GetCurrentMethod()); try { using (var runspace = CreateRunspace()) using (var ps = PowerShell.Create()) { ps.Runspace = runspace; ps.AddCommand("Add-ADPermission") .AddParameter("Identity", mailboxName) .AddParameter("User", user) .AddParameter("ExtendedRights", "Send-As") .AddParameter("AccessRights", "ExtendedRight"); var results = ps.Invoke(); return results.Count > 0; } } catch (Exception ex) { LogException(ex); return false; } finally { LogMethodEnd(MethodBase.GetCurrentMethod()); } } /// /// Removes Send As permission for a mailbox /// public async Task RemoveSendAsPermission(string mailboxName, string user) { LogMethodBegin(MethodBase.GetCurrentMethod()); try { using (var runspace = CreateRunspace()) using (var ps = PowerShell.Create()) { ps.Runspace = runspace; ps.AddCommand("Remove-ADPermission") .AddParameter("Identity", mailboxName) .AddParameter("User", user) .AddParameter("ExtendedRights", "Send-As") .AddParameter("AccessRights", "ExtendedRight") .AddParameter("Confirm", false); var results = ps.Invoke(); return results.Count > 0; } } catch (Exception ex) { LogException(ex); return false; } finally { LogMethodEnd(MethodBase.GetCurrentMethod()); } } /// /// Creates a shared mailbox. Optionally initial permissions (e.g. FullAccess) can be set for members. /// public void CreateSharedMailbox(string name, string alias, List initialMembers = null) { LogMethodBegin(MethodBase.GetCurrentMethod()); try { using (var runspace = CreateRunspace()) using (var ps = PowerShell.Create()) { ps.Runspace = runspace; ps.AddCommand("New-Mailbox") .AddParameter("Name", name) .AddParameter("Alias", alias) .AddParameter("Shared", true) .AddParameter("OrganizationalUnit", _organizationalUnit); ps.Invoke(); if (initialMembers != null) { foreach (var member in initialMembers) { ps.Commands.Clear(); ps.AddCommand("Add-MailboxPermission") .AddParameter("Identity", name) .AddParameter("User", member) .AddParameter("AccessRights", "FullAccess") .AddParameter("InheritanceType", "All"); ps.Invoke(); } } } } catch (Exception ex) { LogException(ex); throw; } finally { LogMethodEnd(MethodBase.GetCurrentMethod()); } } } }