diff --git a/src/DigitalData.EmailProfiler.Application/DigitalData.EmailProfiler.Application.csproj b/src/DigitalData.EmailProfiler.Application/DigitalData.EmailProfiler.Application.csproj
index 52ab069..2fbd34d 100644
--- a/src/DigitalData.EmailProfiler.Application/DigitalData.EmailProfiler.Application.csproj
+++ b/src/DigitalData.EmailProfiler.Application/DigitalData.EmailProfiler.Application.csproj
@@ -14,6 +14,7 @@
+
diff --git a/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IEmailAccountRepository.cs b/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IEmailAccountRepository.cs
new file mode 100644
index 0000000..3101a20
--- /dev/null
+++ b/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IEmailAccountRepository.cs
@@ -0,0 +1,24 @@
+using DigitalData.EmailProfiler.Domain.Entities;
+
+namespace DigitalData.EmailProfiler.Application.Interfaces.Repositories;
+
+///
+/// Repository interface for EmailAccount entity.
+///
+public interface IEmailAccountRepository : IRepository
+{
+ ///
+ /// Get all active email accounts.
+ ///
+ Task> GetActiveAccountsAsync(CancellationToken cancellationToken = default);
+
+ ///
+ /// Get email account by account name.
+ ///
+ Task GetByAccountNameAsync(string accountName, CancellationToken cancellationToken = default);
+
+ ///
+ /// Get email account with its profiles.
+ ///
+ Task GetWithProfilesAsync(int id, CancellationToken cancellationToken = default);
+}
diff --git a/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IEmailHistoryRepository.cs b/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IEmailHistoryRepository.cs
new file mode 100644
index 0000000..02068e4
--- /dev/null
+++ b/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IEmailHistoryRepository.cs
@@ -0,0 +1,47 @@
+using DigitalData.EmailProfiler.Domain.Entities;
+
+namespace DigitalData.EmailProfiler.Application.Interfaces.Repositories;
+
+///
+/// Repository interface for EmailHistory entity.
+///
+public interface IEmailHistoryRepository : IRepository
+{
+ ///
+ /// Get email history by message ID hash.
+ ///
+ Task GetByMessageIdHashAsync(string messageIdHash, CancellationToken cancellationToken = default);
+
+ ///
+ /// Get email history with attachments.
+ ///
+ Task GetWithAttachmentsAsync(int id, CancellationToken cancellationToken = default);
+
+ ///
+ /// Get email history by profile ID with pagination.
+ ///
+ Task<(IEnumerable Items, int TotalCount)> GetByProfileIdAsync(
+ int profileId,
+ int pageNumber = 1,
+ int pageSize = 50,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Get failed emails that need retry.
+ ///
+ Task> GetFailedEmailsAsync(int? profileId = null, CancellationToken cancellationToken = default);
+
+ ///
+ /// Get emails processed within date range.
+ ///
+ Task> GetByDateRangeAsync(
+ DateTime startDate,
+ DateTime endDate,
+ int? profileId = null,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Check if email with given message ID hash already exists.
+ ///
+ Task IsDuplicateAsync(string messageIdHash, CancellationToken cancellationToken = default);
+}
diff --git a/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IEmailOutboxRepository.cs b/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IEmailOutboxRepository.cs
new file mode 100644
index 0000000..3dbf000
--- /dev/null
+++ b/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IEmailOutboxRepository.cs
@@ -0,0 +1,34 @@
+using DigitalData.EmailProfiler.Domain.Entities;
+
+namespace DigitalData.EmailProfiler.Application.Interfaces.Repositories;
+
+///
+/// Repository interface for EmailOutbox entity.
+///
+public interface IEmailOutboxRepository : IRepository
+{
+ ///
+ /// Get all pending emails (not yet sent).
+ ///
+ Task> GetPendingEmailsAsync(int maxCount = 100, CancellationToken cancellationToken = default);
+
+ ///
+ /// Get failed emails that need retry (RetryCount < MaxRetryCount).
+ ///
+ Task> GetFailedEmailsForRetryAsync(int maxCount = 100, CancellationToken cancellationToken = default);
+
+ ///
+ /// Mark email as sent.
+ ///
+ Task MarkAsSentAsync(int id, CancellationToken cancellationToken = default);
+
+ ///
+ /// Mark email as failed with error details.
+ ///
+ Task MarkAsFailedAsync(int id, string errorMessage, CancellationToken cancellationToken = default);
+
+ ///
+ /// Delete old sent emails (cleanup).
+ ///
+ Task DeleteOldSentEmailsAsync(int daysToKeep, CancellationToken cancellationToken = default);
+}
diff --git a/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IEmailProcessRepository.cs b/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IEmailProcessRepository.cs
new file mode 100644
index 0000000..7e262f0
--- /dev/null
+++ b/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IEmailProcessRepository.cs
@@ -0,0 +1,24 @@
+using DigitalData.EmailProfiler.Domain.Entities;
+
+namespace DigitalData.EmailProfiler.Application.Interfaces.Repositories;
+
+///
+/// Repository interface for EmailProcess entity.
+///
+public interface IEmailProcessRepository : IRepository
+{
+ ///
+ /// Get process with all steps (ProcessSteps and IndexingSteps).
+ ///
+ Task GetWithStepsAsync(int id, CancellationToken cancellationToken = default);
+
+ ///
+ /// Get process by profile ID.
+ ///
+ Task GetByProfileIdAsync(int profileId, CancellationToken cancellationToken = default);
+
+ ///
+ /// Get all processes by type.
+ ///
+ Task> GetByProcessTypeAsync(string processType, CancellationToken cancellationToken = default);
+}
diff --git a/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IEmailProfileRepository.cs b/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IEmailProfileRepository.cs
new file mode 100644
index 0000000..f3e3ae6
--- /dev/null
+++ b/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IEmailProfileRepository.cs
@@ -0,0 +1,29 @@
+using DigitalData.EmailProfiler.Domain.Entities;
+
+namespace DigitalData.EmailProfiler.Application.Interfaces.Repositories;
+
+///
+/// Repository interface for EmailProfile entity.
+///
+public interface IEmailProfileRepository : IRepository
+{
+ ///
+ /// Get all active profiles.
+ ///
+ Task> GetActiveProfilesAsync(CancellationToken cancellationToken = default);
+
+ ///
+ /// Get profiles that should be polled now (based on PollIntervalMinutes).
+ ///
+ Task> GetProfilesDueForPollingAsync(CancellationToken cancellationToken = default);
+
+ ///
+ /// Get profile with all related entities (EmailAccount, EmailProcess, ProcessSteps).
+ ///
+ Task GetWithRelatedEntitiesAsync(int id, CancellationToken cancellationToken = default);
+
+ ///
+ /// Get profiles by email account ID.
+ ///
+ Task> GetByEmailAccountIdAsync(int emailAccountId, CancellationToken cancellationToken = default);
+}
diff --git a/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IRepository.cs b/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IRepository.cs
new file mode 100644
index 0000000..32ab791
--- /dev/null
+++ b/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IRepository.cs
@@ -0,0 +1,19 @@
+using System.Linq.Expressions;
+
+namespace DigitalData.EmailProfiler.Application.Interfaces.Repositories;
+
+///
+/// Base repository interface for common CRUD operations.
+///
+/// Entity type
+public interface IRepository where T : class
+{
+ Task GetByIdAsync(int id, CancellationToken cancellationToken = default);
+ Task> GetAllAsync(CancellationToken cancellationToken = default);
+ Task> FindAsync(Expression> predicate, CancellationToken cancellationToken = default);
+ Task AddAsync(T entity, CancellationToken cancellationToken = default);
+ Task UpdateAsync(T entity, CancellationToken cancellationToken = default);
+ Task DeleteAsync(T entity, CancellationToken cancellationToken = default);
+ Task ExistsAsync(Expression> predicate, CancellationToken cancellationToken = default);
+ Task CountAsync(Expression>? predicate = null, CancellationToken cancellationToken = default);
+}
diff --git a/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IUnitOfWork.cs b/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IUnitOfWork.cs
new file mode 100644
index 0000000..58d9c9d
--- /dev/null
+++ b/src/DigitalData.EmailProfiler.Application/Interfaces/Repositories/IUnitOfWork.cs
@@ -0,0 +1,33 @@
+namespace DigitalData.EmailProfiler.Application.Interfaces.Repositories;
+
+///
+/// Unit of Work pattern for transaction management.
+///
+public interface IUnitOfWork : IDisposable
+{
+ IEmailAccountRepository EmailAccounts { get; }
+ IEmailProfileRepository EmailProfiles { get; }
+ IEmailProcessRepository EmailProcesses { get; }
+ IEmailHistoryRepository EmailHistories { get; }
+ IEmailOutboxRepository EmailOutbox { get; }
+
+ ///
+ /// Save all changes to the database.
+ ///
+ Task SaveChangesAsync(CancellationToken cancellationToken = default);
+
+ ///
+ /// Begin a database transaction.
+ ///
+ Task BeginTransactionAsync(CancellationToken cancellationToken = default);
+
+ ///
+ /// Commit the current transaction.
+ ///
+ Task CommitTransactionAsync(CancellationToken cancellationToken = default);
+
+ ///
+ /// Rollback the current transaction.
+ ///
+ Task RollbackTransactionAsync(CancellationToken cancellationToken = default);
+}
diff --git a/src/DigitalData.EmailProfiler.Application/Interfaces/Services/IDmsService.cs b/src/DigitalData.EmailProfiler.Application/Interfaces/Services/IDmsService.cs
new file mode 100644
index 0000000..7897f47
--- /dev/null
+++ b/src/DigitalData.EmailProfiler.Application/Interfaces/Services/IDmsService.cs
@@ -0,0 +1,71 @@
+namespace DigitalData.EmailProfiler.Application.Interfaces.Services;
+
+///
+/// windream DMS integration service interface.
+///
+public interface IDmsService
+{
+ ///
+ /// Connect to windream DMS.
+ ///
+ Task ConnectAsync(string server, string username, string password, CancellationToken cancellationToken = default);
+
+ ///
+ /// Archive document to windream DMS with indexing fields.
+ ///
+ Task ArchiveDocumentAsync(
+ string filePath,
+ string documentType,
+ Dictionary indexFields,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Archive document from stream to windream DMS.
+ ///
+ Task ArchiveDocumentAsync(
+ Stream fileStream,
+ string fileName,
+ string documentType,
+ Dictionary indexFields,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Check if document already exists in windream DMS.
+ ///
+ Task DocumentExistsAsync(string documentId, CancellationToken cancellationToken = default);
+
+ ///
+ /// Get document from windream DMS.
+ ///
+ Task GetDocumentAsync(string documentId, CancellationToken cancellationToken = default);
+
+ ///
+ /// Update document indexing fields.
+ ///
+ Task UpdateIndexFieldsAsync(
+ string documentId,
+ Dictionary indexFields,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Search documents by index fields.
+ ///
+ Task> SearchDocumentsAsync(
+ Dictionary searchCriteria,
+ int maxResults = 100,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Disconnect from windream DMS.
+ ///
+ Task DisconnectAsync(CancellationToken cancellationToken = default);
+}
+
+///
+/// Represents a windream DMS search result.
+///
+public record DmsSearchResult(
+ string DocumentId,
+ string FileName,
+ DateTime CreatedDate,
+ Dictionary IndexFields);
diff --git a/src/DigitalData.EmailProfiler.Application/Interfaces/Services/IEmailQueue.cs b/src/DigitalData.EmailProfiler.Application/Interfaces/Services/IEmailQueue.cs
new file mode 100644
index 0000000..4578c2e
--- /dev/null
+++ b/src/DigitalData.EmailProfiler.Application/Interfaces/Services/IEmailQueue.cs
@@ -0,0 +1,27 @@
+using DigitalData.EmailProfiler.Domain.Entities;
+
+namespace DigitalData.EmailProfiler.Application.Interfaces.Services;
+
+///
+/// Email queue interface for asynchronous email sending.
+/// Current implementation: In-memory Channel<T>
+/// Future: RabbitMQ (see agents.md)
+///
+public interface IEmailQueue
+{
+ ///
+ /// Enqueue an email for sending.
+ ///
+ Task EnqueueAsync(EmailOutbox email, CancellationToken cancellationToken = default);
+
+ ///
+ /// Dequeue an email for sending.
+ /// Returns null if queue is empty.
+ ///
+ Task DequeueAsync(CancellationToken cancellationToken = default);
+
+ ///
+ /// Get current queue depth (number of pending emails).
+ ///
+ Task GetQueueDepthAsync(CancellationToken cancellationToken = default);
+}
diff --git a/src/DigitalData.EmailProfiler.Application/Interfaces/Services/IEmailService.cs b/src/DigitalData.EmailProfiler.Application/Interfaces/Services/IEmailService.cs
new file mode 100644
index 0000000..9fcd404
--- /dev/null
+++ b/src/DigitalData.EmailProfiler.Application/Interfaces/Services/IEmailService.cs
@@ -0,0 +1,59 @@
+using MimeKit;
+
+namespace DigitalData.EmailProfiler.Application.Interfaces.Services;
+
+///
+/// Email service interface for IMAP/SMTP operations with OAuth2 support.
+///
+public interface IEmailService
+{
+ ///
+ /// Connect to IMAP server and authenticate.
+ ///
+ Task ConnectImapAsync(string server, int port, string username, string password, bool useSsl = true, CancellationToken cancellationToken = default);
+
+ ///
+ /// Connect to IMAP server using OAuth2.
+ ///
+ Task ConnectImapOAuth2Async(string server, int port, string username, string accessToken, bool useSsl = true, CancellationToken cancellationToken = default);
+
+ ///
+ /// Fetch unread emails from inbox.
+ ///
+ Task> FetchUnreadEmailsAsync(int maxCount = 100, CancellationToken cancellationToken = default);
+
+ ///
+ /// Mark email as read.
+ ///
+ Task MarkAsReadAsync(int uid, CancellationToken cancellationToken = default);
+
+ ///
+ /// Move email to specified folder.
+ ///
+ Task MoveToFolderAsync(int uid, string folderName, CancellationToken cancellationToken = default);
+
+ ///
+ /// Delete email.
+ ///
+ Task DeleteEmailAsync(int uid, CancellationToken cancellationToken = default);
+
+ ///
+ /// Disconnect from IMAP server.
+ ///
+ Task DisconnectImapAsync(CancellationToken cancellationToken = default);
+
+ ///
+ /// Send email via SMTP.
+ ///
+ Task SendEmailAsync(MimeMessage message, string smtpServer, int smtpPort, string username, string password, bool useSsl = true, CancellationToken cancellationToken = default);
+
+ ///
+ /// Send email via SMTP using OAuth2.
+ ///
+ Task SendEmailOAuth2Async(MimeMessage message, string smtpServer, int smtpPort, string username, string accessToken, bool useSsl = true, CancellationToken cancellationToken = default);
+
+ ///
+ /// Get OAuth2 access token for Microsoft 365.
+ ///
+ Task GetOAuth2AccessTokenAsync(string tenantId, string clientId, string clientSecret, string[] scopes, CancellationToken cancellationToken = default);
+}
diff --git a/src/DigitalData.EmailProfiler.Application/Interfaces/Services/IEncryptionService.cs b/src/DigitalData.EmailProfiler.Application/Interfaces/Services/IEncryptionService.cs
new file mode 100644
index 0000000..63a83a5
--- /dev/null
+++ b/src/DigitalData.EmailProfiler.Application/Interfaces/Services/IEncryptionService.cs
@@ -0,0 +1,28 @@
+namespace DigitalData.EmailProfiler.Application.Interfaces.Services;
+
+///
+/// Encryption service interface for sensitive data (passwords, OAuth tokens).
+/// Uses ASP.NET Core Data Protection API.
+///
+public interface IEncryptionService
+{
+ ///
+ /// Encrypt a string value.
+ ///
+ string Encrypt(string plainText);
+
+ ///
+ /// Decrypt an encrypted string value.
+ ///
+ string Decrypt(string cipherText);
+
+ ///
+ /// Encrypt a byte array.
+ ///
+ byte[] Encrypt(byte[] plainData);
+
+ ///
+ /// Decrypt an encrypted byte array.
+ ///
+ byte[] Decrypt(byte[] cipherData);
+}
diff --git a/src/DigitalData.EmailProfiler.Application/Interfaces/Services/IPdfProcessingService.cs b/src/DigitalData.EmailProfiler.Application/Interfaces/Services/IPdfProcessingService.cs
new file mode 100644
index 0000000..db7907b
--- /dev/null
+++ b/src/DigitalData.EmailProfiler.Application/Interfaces/Services/IPdfProcessingService.cs
@@ -0,0 +1,59 @@
+namespace DigitalData.EmailProfiler.Application.Interfaces.Services;
+
+///
+/// PDF processing service interface for validation and embedded file extraction.
+///
+public interface IPdfProcessingService
+{
+ ///
+ /// Validate if file is a valid PDF.
+ ///
+ Task IsValidPdfAsync(string filePath, CancellationToken cancellationToken = default);
+
+ ///
+ /// Validate if stream contains a valid PDF.
+ ///
+ Task IsValidPdfAsync(Stream stream, CancellationToken cancellationToken = default);
+
+ ///
+ /// Extract embedded files from PDF (e.g., ZUGFeRD XML).
+ ///
+ Task> ExtractEmbeddedFilesAsync(string pdfPath, CancellationToken cancellationToken = default);
+
+ ///
+ /// Extract embedded files from PDF stream.
+ ///
+ Task> ExtractEmbeddedFilesAsync(Stream pdfStream, CancellationToken cancellationToken = default);
+
+ ///
+ /// Check if PDF contains ZUGFeRD data.
+ ///
+ Task HasZugFeRDDataAsync(string pdfPath, CancellationToken cancellationToken = default);
+
+ ///
+ /// Extract ZUGFeRD XML from PDF.
+ ///
+ Task ExtractZugFeRDXmlAsync(string pdfPath, CancellationToken cancellationToken = default);
+
+ ///
+ /// Get PDF metadata (title, author, creation date, etc.).
+ ///
+ Task GetMetadataAsync(string pdfPath, CancellationToken cancellationToken = default);
+}
+
+///
+/// Represents an embedded file extracted from a PDF.
+///
+public record EmbeddedFile(string FileName, byte[] Content, string? Description = null);
+
+///
+/// Represents PDF metadata.
+///
+public record PdfMetadata(
+ string? Title,
+ string? Author,
+ string? Subject,
+ string? Keywords,
+ DateTime? CreationDate,
+ DateTime? ModificationDate,
+ int PageCount);