refactor: Remove MailKit and windream DMS dependencies
- Remove IDmsService interface (DMS integration deferred to Phase 5) - Remove MailKitEmailService implementation - Remove WindreamDmsService implementation - Simplify IEmailService to SMTP-only operations - Preparing for Limilabs Mail.dll migration BREAKING CHANGE: IEmailService no longer supports IMAP/POP3 operations Reason: Migrating from MailKit to Limilabs Mail.dll
This commit is contained in:
@@ -1,11 +0,0 @@
|
||||
namespace DigitalData.EmailProfiler.Application.Common.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// DMS service interface for windream integration.
|
||||
/// </summary>
|
||||
public interface IDmsService
|
||||
{
|
||||
Task<string> ImportDocumentAsync(string filePath, string objectType, Dictionary<string, string> metadata, CancellationToken cancellationToken = default);
|
||||
Task<bool> DocumentExistsAsync(string documentId, CancellationToken cancellationToken = default);
|
||||
Task<bool> UpdateMetadataAsync(string documentId, Dictionary<string, string> metadata, CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -3,14 +3,16 @@ using DigitalData.EmailProfiler.Application.Common.Dtos;
|
||||
namespace DigitalData.EmailProfiler.Application.Common.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// Email service interface for IMAP/SMTP operations.
|
||||
/// Implementation uses MailKit.
|
||||
/// Throws AuthenticationFailedException when OAuth2/password auth fails.
|
||||
/// Email service interface for SMTP operations.
|
||||
/// Implementation uses Limilabs Mail.dll for production email sending.
|
||||
/// SMTP configuration is injected via IOptions<EmailAccountDto> in appsettings.json.
|
||||
/// Throws AuthenticationFailedException when SMTP authentication fails.
|
||||
/// </summary>
|
||||
public interface IEmailService
|
||||
{
|
||||
Task<IEnumerable<object>> ReceiveEmailsAsync(EmailAccountDto account, CancellationToken cancellationToken = default);
|
||||
Task SendEmailAsync(EmailAccountDto account, string to, string subject, string body, bool isHtml = true, CancellationToken cancellationToken = default);
|
||||
Task DeleteEmailAsync(EmailAccountDto account, int imapUid, CancellationToken cancellationToken = default);
|
||||
Task<string> GetOAuth2TokenAsync(string tenantId, string clientId, string clientSecret, CancellationToken cancellationToken = default);
|
||||
/// <summary>
|
||||
/// Sends an email using the configured SMTP account.
|
||||
/// SMTP credentials are configured in appsettings.json (EmailAccount section).
|
||||
/// </summary>
|
||||
Task SendEmailAsync(string to, string subject, string body, bool isHtml = true, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
@@ -1,259 +0,0 @@
|
||||
using DigitalData.EmailProfiler.Application.Common.Dtos;
|
||||
using DigitalData.EmailProfiler.Application.Common.Interfaces;
|
||||
using DigitalData.EmailProfiler.Domain.Exceptions;
|
||||
using MailKit;
|
||||
using MailKit.Net.Imap;
|
||||
using MailKit.Net.Smtp;
|
||||
using MailKit.Search;
|
||||
using MailKit.Security;
|
||||
using Microsoft.Identity.Client;
|
||||
using MimeKit;
|
||||
|
||||
namespace DigitalData.EmailProfiler.Infrastructure.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Email service using MailKit/MimeKit for IMAP/SMTP operations.
|
||||
/// Supports OAuth2 authentication via Microsoft.Identity.Client (MSAL).
|
||||
/// </summary>
|
||||
public class MailKitEmailService(IEncryptionService encryptionService) : IEmailService
|
||||
{
|
||||
private readonly IEncryptionService _encryptionService = encryptionService;
|
||||
|
||||
public async Task<IEnumerable<object>> ReceiveEmailsAsync(
|
||||
EmailAccountDto account,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
using var imap = new ImapClient();
|
||||
|
||||
try
|
||||
{
|
||||
await ConnectAndAuthenticateImapAsync(imap, account, cancellationToken);
|
||||
|
||||
var inbox = imap.Inbox;
|
||||
await inbox.OpenAsync(FolderAccess.ReadWrite, cancellationToken);
|
||||
|
||||
var uids = await inbox.SearchAsync(SearchQuery.NotSeen, cancellationToken);
|
||||
var messages = new List<object>();
|
||||
|
||||
foreach (var uid in uids)
|
||||
{
|
||||
var message = await inbox.GetMessageAsync(uid, cancellationToken);
|
||||
|
||||
var emailMessage = new
|
||||
{
|
||||
MessageId = message.MessageId,
|
||||
Sender = message.From.Mailboxes.FirstOrDefault()?.Address ?? string.Empty,
|
||||
Subject = message.Subject ?? string.Empty,
|
||||
Date = message.Date.DateTime,
|
||||
BodyHtml = message.HtmlBody ?? string.Empty,
|
||||
BodyText = message.TextBody ?? string.Empty,
|
||||
Attachments = message.Attachments.Select(a => new
|
||||
{
|
||||
FileName = a.ContentDisposition?.FileName ?? "attachment",
|
||||
FileSize = a is MimePart part ? (int)part.Content.Stream.Length : 0,
|
||||
Content = a is MimePart mimePart ? ReadPartContent(mimePart) : Array.Empty<byte>()
|
||||
}).ToList(),
|
||||
ImapUid = (int)uid.Id
|
||||
};
|
||||
|
||||
messages.Add(emailMessage);
|
||||
}
|
||||
|
||||
await imap.DisconnectAsync(true, cancellationToken);
|
||||
return messages;
|
||||
}
|
||||
catch (AuthenticationException ex)
|
||||
{
|
||||
await DisconnectSafelyAsync(imap, cancellationToken);
|
||||
throw new AuthenticationFailedException("IMAP authentication failed. Check credentials or OAuth2 configuration.", ex);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await DisconnectSafelyAsync(imap, cancellationToken);
|
||||
throw new InvalidOperationException("Failed to receive emails from IMAP server.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SendEmailAsync(
|
||||
EmailAccountDto account,
|
||||
string to,
|
||||
string subject,
|
||||
string body,
|
||||
bool isHtml = true,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
using var smtp = new SmtpClient();
|
||||
|
||||
try
|
||||
{
|
||||
await ConnectAndAuthenticateSmtpAsync(smtp, account, cancellationToken);
|
||||
|
||||
var message = new MimeMessage();
|
||||
message.From.Add(MailboxAddress.Parse(account.Username));
|
||||
message.To.Add(MailboxAddress.Parse(to));
|
||||
message.Subject = subject;
|
||||
|
||||
var builder = new BodyBuilder
|
||||
{
|
||||
HtmlBody = isHtml ? body : null,
|
||||
TextBody = isHtml ? null : body
|
||||
};
|
||||
|
||||
message.Body = builder.ToMessageBody();
|
||||
|
||||
await smtp.SendAsync(message, cancellationToken);
|
||||
await smtp.DisconnectAsync(true, cancellationToken);
|
||||
}
|
||||
catch (AuthenticationException ex)
|
||||
{
|
||||
await DisconnectSafelyAsync(smtp, cancellationToken);
|
||||
throw new AuthenticationFailedException("SMTP authentication failed. Check credentials or OAuth2 configuration.", ex);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await DisconnectSafelyAsync(smtp, cancellationToken);
|
||||
throw new InvalidOperationException("Failed to send email via SMTP server.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DeleteEmailAsync(
|
||||
EmailAccountDto account,
|
||||
int imapUid,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
using var imap = new ImapClient();
|
||||
|
||||
try
|
||||
{
|
||||
await ConnectAndAuthenticateImapAsync(imap, account, cancellationToken);
|
||||
|
||||
var inbox = imap.Inbox;
|
||||
await inbox.OpenAsync(FolderAccess.ReadWrite, cancellationToken);
|
||||
|
||||
var uid = new UniqueId((uint)imapUid);
|
||||
await inbox.AddFlagsAsync(uid, MessageFlags.Deleted, true, cancellationToken);
|
||||
await inbox.ExpungeAsync(cancellationToken);
|
||||
|
||||
await imap.DisconnectAsync(true, cancellationToken);
|
||||
}
|
||||
catch (AuthenticationException ex)
|
||||
{
|
||||
await DisconnectSafelyAsync(imap, cancellationToken);
|
||||
throw new AuthenticationFailedException("IMAP authentication failed. Check credentials or OAuth2 configuration.", ex);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await DisconnectSafelyAsync(imap, cancellationToken);
|
||||
throw new InvalidOperationException($"Failed to delete email with UID {imapUid}.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> GetOAuth2TokenAsync(
|
||||
string tenantId,
|
||||
string clientId,
|
||||
string clientSecret,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var decryptedSecret = _encryptionService.Decrypt(clientSecret);
|
||||
|
||||
var app = ConfidentialClientApplicationBuilder
|
||||
.Create(clientId)
|
||||
.WithTenantId(tenantId)
|
||||
.WithClientSecret(decryptedSecret)
|
||||
.Build();
|
||||
|
||||
// Microsoft Graph scope for mail access
|
||||
var scopes = new[] { "https://graph.microsoft.com/.default" };
|
||||
var result = await app
|
||||
.AcquireTokenForClient(scopes)
|
||||
.ExecuteAsync(cancellationToken);
|
||||
|
||||
return result.AccessToken;
|
||||
}
|
||||
catch (MsalException ex)
|
||||
{
|
||||
throw new AuthenticationFailedException("Failed to acquire OAuth2 token from Microsoft Identity Platform.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Private Helper Methods ---
|
||||
|
||||
private async Task ConnectAndAuthenticateImapAsync(
|
||||
ImapClient imap,
|
||||
EmailAccountDto account,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var secureSocketOptions = account.ImapUseSsl
|
||||
? SecureSocketOptions.SslOnConnect
|
||||
: SecureSocketOptions.None;
|
||||
|
||||
await imap.ConnectAsync(account.ImapServer, account.ImapPort, secureSocketOptions, cancellationToken);
|
||||
|
||||
if (account.UseOAuth2)
|
||||
{
|
||||
var token = await GetOAuth2TokenAsync(
|
||||
account.TenantId!,
|
||||
account.ClientId!,
|
||||
account.EncryptedClientSecret!,
|
||||
cancellationToken);
|
||||
|
||||
var oauth2 = new SaslMechanismOAuth2(account.Username, token);
|
||||
await imap.AuthenticateAsync(oauth2, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
var password = _encryptionService.Decrypt(account.EncryptedPassword!);
|
||||
await imap.AuthenticateAsync(account.Username, password, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ConnectAndAuthenticateSmtpAsync(
|
||||
SmtpClient smtp,
|
||||
EmailAccountDto account,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var secureSocketOptions = account.SmtpUseSsl
|
||||
? SecureSocketOptions.SslOnConnect
|
||||
: SecureSocketOptions.None;
|
||||
|
||||
await smtp.ConnectAsync(account.SmtpServer, account.SmtpPort, secureSocketOptions, cancellationToken);
|
||||
|
||||
if (account.UseOAuth2)
|
||||
{
|
||||
var token = await GetOAuth2TokenAsync(
|
||||
account.TenantId!,
|
||||
account.ClientId!,
|
||||
account.EncryptedClientSecret!,
|
||||
cancellationToken);
|
||||
|
||||
var oauth2 = new SaslMechanismOAuth2(account.Username, token);
|
||||
await smtp.AuthenticateAsync(oauth2, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
var password = _encryptionService.Decrypt(account.EncryptedPassword!);
|
||||
await smtp.AuthenticateAsync(account.Username, password, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task DisconnectSafelyAsync(ImapClient imap, CancellationToken cancellationToken)
|
||||
{
|
||||
if (imap.IsConnected)
|
||||
await imap.DisconnectAsync(true, cancellationToken);
|
||||
}
|
||||
|
||||
private static async Task DisconnectSafelyAsync(SmtpClient smtp, CancellationToken cancellationToken)
|
||||
{
|
||||
if (smtp.IsConnected)
|
||||
await smtp.DisconnectAsync(true, cancellationToken);
|
||||
}
|
||||
|
||||
private static byte[] ReadPartContent(MimePart part)
|
||||
{
|
||||
using var memory = new MemoryStream();
|
||||
part.Content.DecodeTo(memory);
|
||||
return memory.ToArray();
|
||||
}
|
||||
}
|
||||
@@ -1,316 +0,0 @@
|
||||
using DigitalData.EmailProfiler.Application.Common.Interfaces;
|
||||
using DigitalData.EmailProfiler.Domain.Exceptions;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace DigitalData.EmailProfiler.Infrastructure.Services;
|
||||
|
||||
/// <summary>
|
||||
/// windream DMS service using COM Interop.
|
||||
///
|
||||
/// IMPORTANT: Requires windream COM Interop DLLs to be registered on the system.
|
||||
/// Throws DmsNotAvailableException if COM objects cannot be created.
|
||||
///
|
||||
/// COM ProgIDs used:
|
||||
/// - Windream.WMSession (WINDREAMLib)
|
||||
/// - Windream.WMConnect (WINDREAMLib)
|
||||
///
|
||||
/// Legacy reference: M:\Bibliotheken\3rdParty\windream\Interop.WINDREAMLib.dll
|
||||
///
|
||||
/// NOTE: This service is OBSOLETE. The application now only provides email sending functionality.
|
||||
/// This class is kept for reference but should not be used in new code.
|
||||
/// </summary>
|
||||
[Obsolete("WindreamDmsService is obsolete. The application now only provides email sending functionality.")]
|
||||
public class WindreamDmsService : IDmsService
|
||||
{
|
||||
private readonly string _windreamServer;
|
||||
private readonly ILogger<WindreamDmsService> _logger;
|
||||
private readonly object _sessionLock = new();
|
||||
|
||||
private object? _wmSession;
|
||||
private object? _wmConnect;
|
||||
private bool _isInitialized;
|
||||
|
||||
public WindreamDmsService(IConfiguration configuration, ILogger<WindreamDmsService> logger)
|
||||
{
|
||||
_windreamServer = configuration["Windream:Server"] ?? throw new ArgumentNullException(nameof(configuration), "Windream:Server configuration is required.");
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public Task<string> ImportDocumentAsync(
|
||||
string filePath,
|
||||
string objectType,
|
||||
Dictionary<string, string> metadata,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(filePath);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(objectType);
|
||||
|
||||
if (!File.Exists(filePath))
|
||||
throw new FileNotFoundException($"File not found: {filePath}", filePath);
|
||||
|
||||
lock (_sessionLock)
|
||||
{
|
||||
EnsureSessionInitialized();
|
||||
|
||||
try
|
||||
{
|
||||
var fileName = Path.GetFileName(filePath);
|
||||
|
||||
// CreateWMObject(1, fileName) - 1 = WMEntityDocument
|
||||
var oDocument = InvokeMember(_wmSession!, "CreateWMObject", 1, fileName);
|
||||
|
||||
// Lock document
|
||||
var isLocked = (bool)GetProperty(oDocument, "aLocked");
|
||||
if (!isLocked)
|
||||
{
|
||||
InvokeMember(oDocument, "lock");
|
||||
}
|
||||
|
||||
// Set object type
|
||||
var oObjectType = InvokeMember(_wmSession!, "GetWMObjectByName", 2, objectType); // 2 = WMEntityObjectType
|
||||
SetProperty(oDocument, "aObjectType", oObjectType);
|
||||
|
||||
InvokeMember(oDocument, "Save");
|
||||
|
||||
// Import file from disk
|
||||
InvokeMember(oDocument, "FromDisk", filePath);
|
||||
|
||||
// Index metadata
|
||||
foreach (var (key, value) in metadata)
|
||||
{
|
||||
var indexValue = value.Length > 512 ? value[..512] : value;
|
||||
|
||||
try
|
||||
{
|
||||
InvokeMember(oDocument, "SetVariableValue", key, indexValue);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Failed to set windream index '{IndexName}' to '{IndexValue}'", key, indexValue);
|
||||
}
|
||||
}
|
||||
|
||||
InvokeMember(oDocument, "Save");
|
||||
InvokeMember(oDocument, "unlock");
|
||||
|
||||
// Return windream document ID
|
||||
var documentId = (int)GetProperty(oDocument, "aID");
|
||||
return Task.FromResult($"WD_{documentId}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to import document to windream: {FilePath}", filePath);
|
||||
throw new InvalidOperationException($"Failed to import document to windream: {filePath}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Task<bool> DocumentExistsAsync(
|
||||
string documentId,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(documentId);
|
||||
|
||||
if (!documentId.StartsWith("WD_"))
|
||||
return Task.FromResult(false);
|
||||
|
||||
lock (_sessionLock)
|
||||
{
|
||||
EnsureSessionInitialized();
|
||||
|
||||
var idString = documentId.Replace("WD_", "");
|
||||
if (!int.TryParse(idString, out var id))
|
||||
return Task.FromResult(false);
|
||||
|
||||
try
|
||||
{
|
||||
// GetWMObjectByID(1, id) - 1 = WMEntityDocument
|
||||
var oDocument = InvokeMember(_wmSession!, "GetWMObjectByID", 1, id);
|
||||
return Task.FromResult(oDocument != null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Task<bool> UpdateMetadataAsync(
|
||||
string documentId,
|
||||
Dictionary<string, string> metadata,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(documentId);
|
||||
|
||||
if (!documentId.StartsWith("WD_"))
|
||||
throw new ArgumentException($"Invalid windream document ID: {documentId}", nameof(documentId));
|
||||
|
||||
lock (_sessionLock)
|
||||
{
|
||||
EnsureSessionInitialized();
|
||||
|
||||
var idString = documentId.Replace("WD_", "");
|
||||
if (!int.TryParse(idString, out var id))
|
||||
throw new ArgumentException($"Invalid windream document ID: {documentId}", nameof(documentId));
|
||||
|
||||
try
|
||||
{
|
||||
var oDocument = InvokeMember(_wmSession!, "GetWMObjectByID", 1, id);
|
||||
if (oDocument == null)
|
||||
throw new NotFoundException($"windream document with ID '{documentId}' not found.");
|
||||
|
||||
var isLocked = (bool)GetProperty(oDocument, "aLocked");
|
||||
if (!isLocked)
|
||||
{
|
||||
InvokeMember(oDocument, "lock");
|
||||
}
|
||||
|
||||
foreach (var (key, value) in metadata)
|
||||
{
|
||||
var indexValue = value.Length > 512 ? value[..512] : value;
|
||||
|
||||
try
|
||||
{
|
||||
InvokeMember(oDocument, "SetVariableValue", key, indexValue);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Failed to update windream index '{IndexName}' to '{IndexValue}'", key, indexValue);
|
||||
}
|
||||
}
|
||||
|
||||
InvokeMember(oDocument, "Save");
|
||||
InvokeMember(oDocument, "unlock");
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
catch (NotFoundException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to update windream document metadata: {DocumentId}", documentId);
|
||||
throw new InvalidOperationException($"Failed to update windream document metadata: {documentId}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
lock (_sessionLock)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_wmConnect != null && _wmSession != null && _isInitialized)
|
||||
{
|
||||
InvokeMember(_wmConnect, "Disconnect");
|
||||
}
|
||||
|
||||
if (_wmConnect != null && Marshal.IsComObject(_wmConnect))
|
||||
{
|
||||
Marshal.ReleaseComObject(_wmConnect);
|
||||
}
|
||||
|
||||
if (_wmSession != null && Marshal.IsComObject(_wmSession))
|
||||
{
|
||||
Marshal.ReleaseComObject(_wmSession);
|
||||
}
|
||||
|
||||
_wmConnect = null;
|
||||
_wmSession = null;
|
||||
_isInitialized = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Error during windream COM cleanup");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Private Helper Methods ---
|
||||
|
||||
private void EnsureSessionInitialized()
|
||||
{
|
||||
if (_isInitialized && _wmSession != null && _wmConnect != null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
// Create WMSession object
|
||||
var wmSessionType = Type.GetTypeFromProgID("Windream.WMSession")
|
||||
?? throw new DmsNotAvailableException("windream COM type 'Windream.WMSession' not found. Ensure windream is installed and COM components are registered.");
|
||||
|
||||
_wmSession = Activator.CreateInstance(wmSessionType, _windreamServer)
|
||||
?? throw new DmsNotAvailableException("Failed to create WMSession instance.");
|
||||
|
||||
// Create WMConnect object
|
||||
var wmConnectType = Type.GetTypeFromProgID("Windream.WMConnect")
|
||||
?? throw new DmsNotAvailableException("windream COM type 'Windream.WMConnect' not found. Ensure windream is installed and COM components are registered.");
|
||||
|
||||
_wmConnect = Activator.CreateInstance(wmConnectType)
|
||||
?? throw new DmsNotAvailableException("Failed to create WMConnect instance.");
|
||||
|
||||
// Configure and login
|
||||
SetProperty(_wmConnect, "ModuleID", 0);
|
||||
SetProperty(_wmConnect, "MinReqVersion", "3");
|
||||
InvokeMember(_wmConnect, "LoginSession", _wmSession);
|
||||
|
||||
var isLoggedIn = (bool)GetProperty(_wmSession, "aLoggedin");
|
||||
if (!isLoggedIn)
|
||||
throw new DmsNotAvailableException("windream login failed. Check server configuration and connectivity.");
|
||||
|
||||
_isInitialized = true;
|
||||
_logger.LogInformation("windream session initialized successfully (Server: {Server})", _windreamServer);
|
||||
}
|
||||
catch (DmsNotAvailableException)
|
||||
{
|
||||
_isInitialized = false;
|
||||
throw;
|
||||
}
|
||||
catch (COMException ex)
|
||||
{
|
||||
_isInitialized = false;
|
||||
_logger.LogError(ex, "windream COM error during initialization");
|
||||
throw new DmsNotAvailableException("windream COM components are not available or not properly registered.", ex);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_isInitialized = false;
|
||||
_logger.LogError(ex, "windream initialization failed");
|
||||
throw new DmsNotAvailableException("windream initialization failed. See inner exception for details.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static object InvokeMember(object obj, string memberName, params object[] args)
|
||||
{
|
||||
return obj.GetType().InvokeMember(
|
||||
memberName,
|
||||
System.Reflection.BindingFlags.InvokeMethod,
|
||||
null,
|
||||
obj,
|
||||
args)!;
|
||||
}
|
||||
|
||||
private static object GetProperty(object obj, string propertyName)
|
||||
{
|
||||
return obj.GetType().InvokeMember(
|
||||
propertyName,
|
||||
System.Reflection.BindingFlags.GetProperty,
|
||||
null,
|
||||
obj,
|
||||
null)!;
|
||||
}
|
||||
|
||||
private static void SetProperty(object obj, string propertyName, object value)
|
||||
{
|
||||
obj.GetType().InvokeMember(
|
||||
propertyName,
|
||||
System.Reflection.BindingFlags.SetProperty,
|
||||
null,
|
||||
obj,
|
||||
[value]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user