Files
LIAM/LiamExchange/C4IT.LIAM.ExchangeManager.cs.txt
Drechsler, Meik f563d78417 initial
2025-10-15 14:56:07 +02:00

671 lines
24 KiB
Plaintext

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;
namespace C4IT.LIAM
{
/// <summary>
/// Manages Exchange operations using PowerShell remoting
/// </summary>
public class ExchangeManager
{
private readonly string _exchangeUri;
private readonly PSCredential _credential;
private readonly string _organizationalUnit;
/// <summary>
/// Constructor with explicit credentials, Exchange URI and OU path
/// </summary>
/// <param name="exchangeUri">URL of the Exchange PowerShell endpoint (e.g. "http://exchangeserver/PowerShell")</param>
/// <param name="credential">Explicit credentials</param>
/// <param name="organizationalUnit">OU path where objects should be created</param>
public ExchangeManager(string exchangeUri, PSCredential credential, string organizationalUnit)
{
_exchangeUri = exchangeUri;
_credential = credential;
_organizationalUnit = organizationalUnit;
}
/// <summary>
/// Creates a runspace connected to the Exchange PowerShell endpoint
/// </summary>
private Runspace CreateRunspace()
{
LogMethodBegin(MethodBase.GetCurrentMethod());
try
{
var connectionInfo = new WSManConnectionInfo(
new Uri(_exchangeUri),
"http://schemas.microsoft.com/powershell/Microsoft.Exchange",
_credential);
// Set authentication mechanism to Kerberos by default
connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Kerberos;
var runspace = RunspaceFactory.CreateRunspace(connectionInfo);
runspace.Open();
return runspace;
}
catch (Exception ex)
{
LogException(ex);
throw;
}
finally
{
LogMethodEnd(MethodBase.GetCurrentMethod());
}
}
/// <summary>
/// Creates a distribution group (mailing list). Optionally members can be added initially.
/// </summary>
/// <param name="name">Name of the group</param>
/// <param name="alias">Alias of the group</param>
/// <param name="initialMembers">List of members to be added to the group (optional)</param>
public void CreateDistributionGroup(string name, string alias, List<string> initialMembers = null)
{
LogMethodBegin(MethodBase.GetCurrentMethod());
try
{
using (var runspace = CreateRunspace())
using (var ps = PowerShell.Create())
{
ps.Runspace = runspace;
// Create the distribution group
ps.AddCommand("New-DistributionGroup")
.AddParameter("Name", name)
.AddParameter("Alias", alias)
.AddParameter("OrganizationalUnit", _organizationalUnit);
ps.Invoke();
// Add initial members if specified
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());
}
}
/// <summary>
/// Creates a security group in Active Directory that can be used for Exchange permissions
/// </summary>
/// <param name="name">Name of the security group</param>
/// <param name="description">Description of the security group</param>
/// <returns>True if successful</returns>
public bool CreateSecurityGroup(string name, string description)
{
LogMethodBegin(MethodBase.GetCurrentMethod());
try
{
using (var runspace = CreateRunspace())
using (var ps = PowerShell.Create())
{
ps.Runspace = runspace;
// Create the security group using New-ADGroup cmdlet
ps.AddCommand("New-ADGroup")
.AddParameter("Name", name)
.AddParameter("GroupScope", "Universal")
.AddParameter("GroupCategory", "Security")
.AddParameter("DisplayName", name)
.AddParameter("Path", _organizationalUnit)
.AddParameter("Description", description);
var result = ps.Invoke();
return result.Count > 0;
}
}
catch (Exception ex)
{
LogException(ex);
return false;
}
finally
{
LogMethodEnd(MethodBase.GetCurrentMethod());
}
}
/// <summary>
/// Gets all shared mailboxes matching an optional filter
/// </summary>
/// <param name="filter">Optional filter string</param>
/// <returns>Collection of shared mailboxes as PSObjects</returns>
public IEnumerable<PSObject> GetSharedMailboxes(string filter = null)
{
LogMethodBegin(MethodBase.GetCurrentMethod());
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 ps.Invoke();
}
}
catch (Exception ex)
{
LogException(ex);
return Enumerable.Empty<PSObject>();
}
finally
{
LogMethodEnd(MethodBase.GetCurrentMethod());
}
}
/// <summary>
/// Gets a shared mailbox by primary SMTP address
/// </summary>
/// <param name="primarySmtpAddress">The primary SMTP address of the mailbox</param>
/// <returns>The mailbox as a PSObject, or null if not found</returns>
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 = ps.Invoke();
return results.Count > 0 ? results[0] : null;
}
}
catch (Exception ex)
{
LogException(ex);
return null;
}
finally
{
LogMethodEnd(MethodBase.GetCurrentMethod());
}
}
/// <summary>
/// Gets all distribution groups matching an optional filter
/// </summary>
/// <param name="filter">Optional filter string</param>
/// <returns>Collection of distribution groups as PSObjects</returns>
public IEnumerable<PSObject> GetDistributionGroups(string filter = null)
{
LogMethodBegin(MethodBase.GetCurrentMethod());
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 ps.Invoke();
}
}
catch (Exception ex)
{
LogException(ex);
return Enumerable.Empty<PSObject>();
}
finally
{
LogMethodEnd(MethodBase.GetCurrentMethod());
}
}
/// <summary>
/// Gets a distribution group by primary SMTP address
/// </summary>
/// <param name="primarySmtpAddress">The primary SMTP address of the group</param>
/// <returns>The distribution group as a PSObject, or null if not found</returns>
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 = ps.Invoke();
return results.Count > 0 ? results[0] : null;
}
}
catch (Exception ex)
{
LogException(ex);
return null;
}
finally
{
LogMethodEnd(MethodBase.GetCurrentMethod());
}
}
/// <summary>
/// Gets members of a distribution group
/// </summary>
/// <param name="groupName">The name of the distribution group</param>
/// <returns>Collection of members as PSObjects</returns>
public IEnumerable<PSObject> GetDistributionGroupMembers(string groupName)
{
LogMethodBegin(MethodBase.GetCurrentMethod());
try
{
using (var runspace = CreateRunspace())
using (var ps = PowerShell.Create())
{
ps.Runspace = runspace;
ps.AddCommand("Get-DistributionGroupMember")
.AddParameter("Identity", groupName);
return ps.Invoke();
}
}
catch (Exception ex)
{
LogException(ex);
return Enumerable.Empty<PSObject>();
}
finally
{
LogMethodEnd(MethodBase.GetCurrentMethod());
}
}
/// <summary>
/// Gets users who have permissions on a mailbox
/// </summary>
/// <param name="mailboxName">The name of the mailbox</param>
/// <returns>Collection of users as PSObjects</returns>
public IEnumerable<PSObject> GetMailboxPermissionMembers(string mailboxName)
{
LogMethodBegin(MethodBase.GetCurrentMethod());
try
{
using (var runspace = CreateRunspace())
using (var ps = PowerShell.Create())
{
ps.Runspace = runspace;
ps.AddCommand("Get-MailboxPermission")
.AddParameter("Identity", mailboxName)
.AddParameter("AccessRights", "FullAccess");
// Filter out default permissions like NT AUTHORITY\SELF
var results = ps.Invoke().Where(p =>
!p.Properties["User"].Value.ToString().Contains("NT AUTHORITY") &&
!p.Properties["User"].Value.ToString().Contains("Administrator"));
// Now, get the full user objects for each permission
var userList = new List<PSObject>();
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<PSObject>();
}
finally
{
LogMethodEnd(MethodBase.GetCurrentMethod());
}
}
/// <summary>
/// Gets security groups matching a filter
/// </summary>
/// <param name="filter">LDAP filter to match groups</param>
/// <returns>Collection of security groups as PSObjects</returns>
public IEnumerable<PSObject> GetSecurityGroups(string filter)
{
LogMethodBegin(MethodBase.GetCurrentMethod());
try
{
using (var runspace = CreateRunspace())
using (var ps = PowerShell.Create())
{
ps.Runspace = runspace;
ps.AddCommand("Get-ADGroup")
.AddParameter("Filter", filter)
.AddParameter("Properties", new string[] { "DisplayName", "DistinguishedName", "Sid" });
return ps.Invoke();
}
}
catch (Exception ex)
{
LogException(ex);
return Enumerable.Empty<PSObject>();
}
finally
{
LogMethodEnd(MethodBase.GetCurrentMethod());
}
}
/// <summary>
/// Adds a member to a distribution group
/// </summary>
/// <param name="groupName">Name of the distribution group</param>
/// <param name="member">User to be added as a member</param>
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());
}
}
/// <summary>
/// Removes a member from a distribution group
/// </summary>
/// <param name="groupName">Name of the distribution group</param>
/// <param name="member">User to be removed</param>
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());
}
}
/// <summary>
/// Adds mailbox permission for a user
/// </summary>
/// <param name="mailboxName">Name of the mailbox</param>
/// <param name="user">User or group to be granted permission</param>
/// <param name="accessRight">Access right (default: FullAccess)</param>
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());
}
}
/// <summary>
/// Removes mailbox permission for a user
/// </summary>
/// <param name="mailboxName">Name of the mailbox</param>
/// <param name="user">User or group to have permission removed</param>
/// <param name="accessRight">Access right (default: FullAccess)</param>
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());
}
}
/// <summary>
/// Adds Send As permission for a mailbox
/// </summary>
/// <param name="mailboxName">Name of the mailbox</param>
/// <param name="user">User or group to be granted permission</param>
/// <returns>True if successful</returns>
public async Task<bool> 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());
}
}
/// <summary>
/// Removes Send As permission for a mailbox
/// </summary>
/// <param name="mailboxName">Name of the mailbox</param>
/// <param name="user">User or group to have permission removed</param>
/// <returns>True if successful</returns>
public async Task<bool> 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());
}
}
/// <summary>
/// Creates a shared mailbox. Optionally initial permissions (e.g. FullAccess) can be set for members.
/// </summary>
/// <param name="name">Name of the mailbox</param>
/// <param name="alias">Alias of the mailbox</param>
/// <param name="initialMembers">List of users to be added as access rights (optional)</param>
public void CreateSharedMailbox(string name, string alias, List<string> initialMembers = null)
{
LogMethodBegin(MethodBase.GetCurrentMethod());
try
{
using (var runspace = CreateRunspace())
using (var ps = PowerShell.Create())
{
ps.Runspace = runspace;
// Create new shared mailbox
ps.AddCommand("New-Mailbox")
.AddParameter("Name", name)
.AddParameter("Alias", alias)
.AddParameter("Shared", true)
.AddParameter("OrganizationalUnit", _organizationalUnit);
ps.Invoke();
// Add initial members if specified
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());
}
}
}
}