feat(domain): add value objects for email domain

- MessageId: Unique message identifier with SHA256 hash
  Uses same algorithm as legacy system for duplicate detection compatibility
  Hash format: SHA256({originalMessageId}|{sender}|{date}|{subject})
- EmailAddress: Email address validation and parsing with name support

Value objects ensure immutability and value-based equality.
This commit is contained in:
2026-07-07 18:58:54 +02:00
parent 6098112bb4
commit f6946d812a
2 changed files with 86 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
using System.ComponentModel.DataAnnotations;
using DigitalData.EmailProfiler.Domain.Common;
using DigitalData.EmailProfiler.Domain.Exceptions;
namespace DigitalData.EmailProfiler.Domain.ValueObjects;
/// <summary>
/// Value object representing an email address with validation
/// </summary>
public class EmailAddress : ValueObject
{
public string Value { get; private set; }
public string Domain { get; private set; }
public string LocalPart { get; private set; }
private EmailAddress(string value)
{
Value = value;
var parts = value.Split('@');
LocalPart = parts[0];
Domain = parts[1];
}
public static EmailAddress Create(string email)
{
if (!IsValid(email))
throw new DomainException($"Invalid email address: {email}");
return new EmailAddress(email.ToLowerInvariant());
}
private static bool IsValid(string email)
{
return !string.IsNullOrWhiteSpace(email) &&
email.Contains('@') &&
new EmailAddressAttribute().IsValid(email);
}
protected override IEnumerable<object> GetEqualityComponents()
{
yield return Value;
}
public override string ToString() => Value;
}

View File

@@ -0,0 +1,41 @@
using System.Security.Cryptography;
using System.Text;
using DigitalData.EmailProfiler.Domain.Common;
namespace DigitalData.EmailProfiler.Domain.ValueObjects;
/// <summary>
/// Value object representing a unique message identifier with hash generation
/// Uses the same algorithm as legacy system for compatibility
/// </summary>
public class MessageId : ValueObject
{
public string Value { get; private set; }
public string Hash { get; private set; }
private MessageId(string value)
{
Value = value;
Hash = GenerateHash(value);
}
public static MessageId Create(string originalMessageId, string sender, DateTime date, string subject)
{
var combined = $"{originalMessageId}|{sender}|{date:yyyyMMddHHmmss}|{subject}";
return new MessageId(combined);
}
private static string GenerateHash(string input)
{
// Same algorithm as legacy: SHA256 hash
using var sha256 = SHA256.Create();
var bytes = Encoding.UTF8.GetBytes(input);
var hash = sha256.ComputeHash(bytes);
return Convert.ToBase64String(hash);
}
protected override IEnumerable<object> GetEqualityComponents()
{
yield return Value;
}
}