diff --git a/src/WireMock.Net.Abstractions/IRequestMessage.cs b/src/WireMock.Net.Abstractions/IRequestMessage.cs index 63a52a6e6..c2e7144a9 100644 --- a/src/WireMock.Net.Abstractions/IRequestMessage.cs +++ b/src/WireMock.Net.Abstractions/IRequestMessage.cs @@ -123,7 +123,7 @@ public interface IRequestMessage /// The original body as MimeMessage. /// Convenience getter for Handlebars and WireMockAssertions. /// - object? BodyAsMimeMessage { get; } + Models.Mime.IMimeMessageData? BodyAsMimeMessage { get; } #endif /// diff --git a/src/WireMock.Net.Abstractions/Models/Mime/IContentDispositionData.cs b/src/WireMock.Net.Abstractions/Models/Mime/IContentDispositionData.cs new file mode 100644 index 000000000..396639eef --- /dev/null +++ b/src/WireMock.Net.Abstractions/Models/Mime/IContentDispositionData.cs @@ -0,0 +1,60 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; + +namespace WireMock.Models.Mime; + +/// +/// An interface exposing the public, readable properties of a ContentDisposition. +/// +public interface IContentDispositionData +{ + /// + /// Get the disposition. + /// + /// The disposition. + string Disposition { get; } + + /// + /// Get a value indicating whether the is an attachment. + /// + /// if the is an attachment; otherwise, . + bool IsAttachment { get; } + + /// + /// Get the list of parameters on the ContentDisposition. + /// + /// The parameters. + public IList Parameters { get; } + + /// + /// Get the name of the file. + /// + /// The name of the file. + string FileName { get; } + + /// + /// Get the creation-date parameter. + /// + /// The creation date. + DateTimeOffset? CreationDate { get; } + + /// + /// Get the modification-date parameter. + /// + /// The modification date. + DateTimeOffset? ModificationDate { get; } + + /// + /// Get the read-date parameter. + /// + /// The read date. + DateTimeOffset? ReadDate { get; } + + /// + /// Get the size parameter. + /// + /// The size. + long? Size { get; } +} \ No newline at end of file diff --git a/src/WireMock.Net.Abstractions/Models/Mime/IContentTypeData.cs b/src/WireMock.Net.Abstractions/Models/Mime/IContentTypeData.cs new file mode 100644 index 000000000..a5c4af5d2 --- /dev/null +++ b/src/WireMock.Net.Abstractions/Models/Mime/IContentTypeData.cs @@ -0,0 +1,67 @@ +// Copyright © WireMock.Net + +using System.Collections.Generic; +using System.Text; + +namespace WireMock.Models.Mime; + +/// +/// An interface exposing the public, readable properties of a ContentType +/// with complex types simplified to a generic object. +/// +public interface IContentTypeData +{ + /// + /// Get the type of the media. + /// + /// The type of the media. + string MediaType { get; } + + /// + /// Get the media subtype. + /// + /// The media subtype. + string MediaSubtype { get; } + + /// + /// Get the list of parameters on the ContentType. + /// + /// The parameters. + IList Parameters { get; } + + /// + /// Get the boundary parameter. + /// + /// The boundary. + string Boundary { get; } + + /// + /// Get the charset parameter. + /// + /// The charset. + string Charset { get; } + + /// + /// Get the charset parameter as an Encoding. + /// + /// The charset encoding. + Encoding CharsetEncoding { get; } + + /// + /// Get the format parameter. + /// + /// The format. + string Format { get; } + + /// + /// Get the simple mime-type. + /// + /// The mime-type. + string MimeType { get; } + + /// + /// Get the name parameter. + /// + /// The name. + string Name { get; } +} diff --git a/src/WireMock.Net.Abstractions/Models/Mime/IMimeEntityData.cs b/src/WireMock.Net.Abstractions/Models/Mime/IMimeEntityData.cs new file mode 100644 index 000000000..004e5205f --- /dev/null +++ b/src/WireMock.Net.Abstractions/Models/Mime/IMimeEntityData.cs @@ -0,0 +1,54 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; + +namespace WireMock.Models.Mime; + +/// +/// A simplified interface exposing the public, readable properties of MimeEntity. +/// +public interface IMimeEntityData +{ + /// + /// Get the list of headers. + /// + /// The list of headers. + IList Headers { get; } + + /// + /// Get the content disposition. + /// + /// The content disposition. + IContentDispositionData? ContentDisposition { get; } + + /// + /// Get the type of the content. + /// + /// The type of the content. + IContentTypeData? ContentType { get; } + + /// + /// Get the base content URI. + /// + /// The base content URI or . + Uri ContentBase { get; } + + /// + /// Get the content location. + /// + /// The content location or . + Uri ContentLocation { get; } + + /// + /// Get the Content-Id. + /// + /// The content identifier. + string ContentId { get; } + + /// + /// Get a value indicating whether this is an attachment. + /// + /// if this is an attachment; otherwise, . + bool IsAttachment { get; } +} \ No newline at end of file diff --git a/src/WireMock.Net.Abstractions/Models/Mime/IMimeMessageData.cs b/src/WireMock.Net.Abstractions/Models/Mime/IMimeMessageData.cs new file mode 100644 index 000000000..391d01bd9 --- /dev/null +++ b/src/WireMock.Net.Abstractions/Models/Mime/IMimeMessageData.cs @@ -0,0 +1,186 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; + +namespace WireMock.Models.Mime; + +/// +/// A simplified interface exposing the public, readable properties of a MIME message. +/// +public interface IMimeMessageData +{ + /// + /// Get the list of headers. + /// + /// The list of headers. + IList Headers { get; } + + /// + /// Get the value of the Importance header. + /// + /// The importance, as an integer. + int Importance { get; } + + /// + /// Get the value of the Priority header. + /// + /// The priority, as an integer. + int Priority { get; } + + /// + /// Get the value of the X-Priority header. + /// + /// The X-priority, as an integer. + int XPriority { get; } + + /// + /// Get the address in the Sender header. + /// + /// The address in the Sender header. + string Sender { get; } + + /// + /// Get the address in the Resent-Sender header. + /// + /// The address in the Resent-Sender header. + string ResentSender { get; } + + /// + /// Get the list of addresses in the From header. + /// + /// The list of addresses in the From header. + IList From { get; } + + /// + /// Get the list of addresses in the Resent-From header. + /// + /// The list of addresses in the Resent-From header. + IList ResentFrom { get; } + + /// + /// Get the list of addresses in the Reply-To header. + /// + /// The list of addresses in the Reply-To header. + IList ReplyTo { get; } + + /// + /// Get the list of addresses in the Resent-Reply-To header. + /// + /// The list of addresses in the Resent-Reply-To header. + IList ResentReplyTo { get; } + + /// + /// Get the list of addresses in the To header. + /// + /// The list of addresses in the To header. + IList To { get; } + + /// + /// Get the list of addresses in the Resent-To header. + /// + /// The list of addresses in the Resent-To header. + IList ResentTo { get; } + + /// + /// Get the list of addresses in the Cc header. + /// + /// The list of addresses in the Cc header. + IList Cc { get; } + + /// + /// Get the list of addresses in the Resent-Cc header. + /// + /// The list of addresses in the Resent-Cc header. + IList ResentCc { get; } + + /// + /// Get the list of addresses in the Bcc header. + /// + /// The list of addresses in the Bcc header. + IList Bcc { get; } + + /// + /// Get the list of addresses in the Resent-Bcc header. + /// + /// The list of addresses in the Resent-Bcc header. + IList ResentBcc { get; } + + /// + /// Get the subject of the message. + /// + /// The subject of the message. + string Subject { get; } + + /// + /// Get the date of the message. + /// + /// The date of the message. + DateTimeOffset Date { get; } + + /// + /// Get the Resent-Date of the message. + /// + /// The Resent-Date of the message. + DateTimeOffset ResentDate { get; } + + /// + /// Get the list of references to other messages. + /// + /// The references. + IList References { get; } + + /// + /// Get the Message-Id that this message is replying to. + /// + /// The message id that this message is in reply to. + string InReplyTo { get; } + + /// + /// Get the message identifier. + /// + /// The message identifier. + string MessageId { get; } + + /// + /// Get the Resent-Message-Id header. + /// + /// The Resent-Message-Id. + string ResentMessageId { get; } + + /// + /// Get the MIME-Version. + /// + /// The MIME version. + Version MimeVersion { get; } + + /// + /// Get the body of the message. + /// + /// The body of the message. + IMimeEntityData Body { get; } + + /// + /// Get the text body of the message if it exists. + /// + /// The text body if it exists; otherwise, . + string TextBody { get; } + + /// + /// Get the html body of the message if it exists. + /// + /// The html body if it exists; otherwise, . + string HtmlBody { get; } + + /// + /// Get the body parts of the message. + /// + /// The body parts. + IList BodyParts { get; } + + /// + /// Get the attachments. + /// + /// The attachments. + IList Attachments { get; } +} \ No newline at end of file diff --git a/src/WireMock.Net.Abstractions/Models/Mime/IMimePartData.cs b/src/WireMock.Net.Abstractions/Models/Mime/IMimePartData.cs new file mode 100644 index 000000000..27259da58 --- /dev/null +++ b/src/WireMock.Net.Abstractions/Models/Mime/IMimePartData.cs @@ -0,0 +1,57 @@ +// Copyright © WireMock.Net + +using System.Collections.Generic; +using System.IO; + +namespace WireMock.Models.Mime; + +/// +/// A simplified interface exposing the public, readable properties of MimePart. +/// +public interface IMimePartData : IMimeEntityData +{ + /// + /// Get the description of the content if available. + /// + /// The description of the content. + string ContentDescription { get; } + + /// + /// Get the duration of the content if available. + /// + /// The duration of the content. + int? ContentDuration { get; } + + /// + /// Get the md5sum of the content. + /// + /// The md5sum of the content. + string ContentMd5 { get; } + + /// + /// Get the content transfer encoding. + /// + /// The content transfer encoding as a string. + string ContentTransferEncoding { get; } + + /// + /// Get the name of the file. + /// + /// The name of the file. + string FileName { get; } + + /// + /// Get the MIME content. + /// + /// The MIME content. + IDictionary Content { get; } + + /// + /// Open the decoded content stream. + /// + /// + /// Provides a means of reading the decoded content without having to first write it to another stream. + /// + /// The decoded content stream. + Stream Open(); +} \ No newline at end of file diff --git a/src/WireMock.Net.MimePart/Matchers/MimePartMatcher.cs b/src/WireMock.Net.MimePart/Matchers/MimePartMatcher.cs index 6ad739ffa..fe17cdd47 100644 --- a/src/WireMock.Net.MimePart/Matchers/MimePartMatcher.cs +++ b/src/WireMock.Net.MimePart/Matchers/MimePartMatcher.cs @@ -1,8 +1,8 @@ // Copyright © WireMock.Net using System; -using MimeKit; using WireMock.Matchers.Helpers; +using WireMock.Models.Mime; using WireMock.Util; namespace WireMock.Matchers; @@ -12,7 +12,7 @@ namespace WireMock.Matchers; /// public class MimePartMatcher : IMimePartMatcher { - private readonly Func[] _funcs; + private readonly Func[] _funcs; /// public string Name => nameof(MimePartMatcher); @@ -52,21 +52,21 @@ public MimePartMatcher( _funcs = [ mp => ContentTypeMatcher?.IsMatch(GetContentTypeAsString(mp.ContentType)) ?? MatchScores.Perfect, - mp => ContentDispositionMatcher?.IsMatch(mp.ContentDisposition.ToString().Replace("Content-Disposition: ", string.Empty)) ?? MatchScores.Perfect, - mp => ContentTransferEncodingMatcher?.IsMatch(mp.ContentTransferEncoding.ToString().ToLowerInvariant()) ?? MatchScores.Perfect, + mp => ContentDispositionMatcher?.IsMatch(mp.ContentDisposition?.ToString()?.Replace("Content-Disposition: ", string.Empty)) ?? MatchScores.Perfect, + mp => ContentTransferEncodingMatcher?.IsMatch(mp.ContentTransferEncoding.ToLowerInvariant()) ?? MatchScores.Perfect, MatchOnContent ]; } /// - public MatchResult IsMatch(object value) + public MatchResult IsMatch(IMimePartData value) { var score = MatchScores.Mismatch; Exception? exception = null; try { - if (value is MimePart mimePart && Array.TrueForAll(_funcs, func => func(mimePart).IsPerfect())) + if (Array.TrueForAll(_funcs, func => func(value).IsPerfect())) { score = MatchScores.Perfect; } @@ -85,7 +85,7 @@ public string GetCSharpCodeArguments() return "NotImplemented"; } - private MatchResult MatchOnContent(MimePart mimePart) + private MatchResult MatchOnContent(IMimePartData mimePart) { if (ContentMatcher == null) { @@ -94,10 +94,10 @@ private MatchResult MatchOnContent(MimePart mimePart) var bodyParserSettings = new BodyParserSettings { - Stream = mimePart.Content.Open(), + Stream = mimePart.Open(), ContentType = GetContentTypeAsString(mimePart.ContentType), DeserializeJson = true, - ContentEncoding = null, // mimePart.ContentType.CharsetEncoding.ToString(), + ContentEncoding = null, // mimePart.ContentType?.CharsetEncoding.ToString(), DecompressGZipAndDeflate = true }; @@ -105,8 +105,8 @@ private MatchResult MatchOnContent(MimePart mimePart) return BodyDataMatchScoreCalculator.CalculateMatchScore(bodyData, ContentMatcher); } - private static string? GetContentTypeAsString(ContentType? contentType) + private static string? GetContentTypeAsString(IContentTypeData? contentType) { - return contentType?.ToString().Replace("Content-Type: ", string.Empty); + return contentType?.ToString()?.Replace("Content-Type: ", string.Empty); } } \ No newline at end of file diff --git a/src/WireMock.Net.MimePart/Models/ContentDispositionDataWrapper.cs b/src/WireMock.Net.MimePart/Models/ContentDispositionDataWrapper.cs new file mode 100644 index 000000000..a663f7e31 --- /dev/null +++ b/src/WireMock.Net.MimePart/Models/ContentDispositionDataWrapper.cs @@ -0,0 +1,63 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; +using System.Linq; +using MimeKit; +using Stef.Validation; +using WireMock.Models.Mime; + +namespace WireMock.Models; + +/// +/// A wrapper class that implements the IContentDispositionData interface +/// by wrapping a ContentDisposition object. +/// +/// +/// This class provides a simplified, read-only view of a ContentDisposition. +/// +public class ContentDispositionDataWrapper : IContentDispositionData +{ + private readonly ContentDisposition _contentDisposition; + + /// + /// Initializes a new instance of the class. + /// + /// The ContentDisposition to wrap. + public ContentDispositionDataWrapper(ContentDisposition contentDisposition) + { + _contentDisposition = Guard.NotNull(contentDisposition); + + Parameters = _contentDisposition.Parameters.Select(p => p.ToString()).ToList(); + } + + /// + public string Disposition => _contentDisposition.Disposition; + + /// + public bool IsAttachment => _contentDisposition.IsAttachment; + + /// + public IList Parameters { get; private set; } + + /// + public string FileName => _contentDisposition.FileName; + + /// + public DateTimeOffset? CreationDate => _contentDisposition.CreationDate; + + /// + public DateTimeOffset? ModificationDate => _contentDisposition.ModificationDate; + + /// + public DateTimeOffset? ReadDate => _contentDisposition.ReadDate; + + /// + public long? Size => _contentDisposition.Size; + + /// + public override string ToString() + { + return _contentDisposition.ToString(); + } +} diff --git a/src/WireMock.Net.MimePart/Models/ContentTypeDataWrapper.cs b/src/WireMock.Net.MimePart/Models/ContentTypeDataWrapper.cs new file mode 100644 index 000000000..b68e0e2c1 --- /dev/null +++ b/src/WireMock.Net.MimePart/Models/ContentTypeDataWrapper.cs @@ -0,0 +1,65 @@ +// Copyright © WireMock.Net + +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MimeKit; +using Stef.Validation; +using WireMock.Models.Mime; + +namespace WireMock.Models; + +/// +/// A wrapper class that implements the interface by wrapping a object. +/// +/// +/// This class provides a simplified, read-only view of a . +/// +public class ContentTypeDataWrapper : IContentTypeData +{ + private readonly ContentType _contentType; + + /// + /// Initializes a new instance of the class. + /// + /// The ContentType to wrap. + public ContentTypeDataWrapper(ContentType contentType) + { + _contentType = Guard.NotNull(contentType); + + Parameters = _contentType.Parameters.Select(p => p.ToString()).ToList(); + } + + /// + public string MediaType => _contentType.MediaType; + + /// + public string MediaSubtype => _contentType.MediaSubtype; + + /// + public IList Parameters { get; private set; } + + /// + public string Boundary => _contentType.Boundary; + + /// + public string Charset => _contentType.Charset; + + /// + public Encoding CharsetEncoding => _contentType.CharsetEncoding; + + /// + public string Format => _contentType.Format; + + /// + public string MimeType => _contentType.MimeType; + + /// + public string Name => _contentType.Name; + + /// + public override string ToString() + { + return _contentType.ToString(); + } +} \ No newline at end of file diff --git a/src/WireMock.Net.MimePart/Models/MimeEntityDataWrapper.cs b/src/WireMock.Net.MimePart/Models/MimeEntityDataWrapper.cs new file mode 100644 index 000000000..d7a52a04a --- /dev/null +++ b/src/WireMock.Net.MimePart/Models/MimeEntityDataWrapper.cs @@ -0,0 +1,61 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; +using System.Linq; +using MimeKit; +using Stef.Validation; +using WireMock.Models.Mime; + +namespace WireMock.Models; + +/// +/// A wrapper class that implements the interface by wrapping an interface. +/// +/// +/// This class provides a simplified, read-only view of an . +/// +public class MimeEntityDataWrapper : IMimeEntityData +{ + private readonly IMimeEntity _entity; + + /// + /// Initializes a new instance of the class. + /// + /// The MIME entity to wrap. + public MimeEntityDataWrapper(IMimeEntity entity) + { + _entity = Guard.NotNull(entity); + + ContentDisposition = _entity.ContentDisposition != null ? new ContentDispositionDataWrapper(_entity.ContentDisposition) : null; + ContentType = _entity.ContentType != null ? new ContentTypeDataWrapper(_entity.ContentType) : null; + Headers = _entity.Headers.Select(h => h.ToString()).ToList(); + } + + /// + public IList Headers { get; private set; } + + /// + public IContentDispositionData? ContentDisposition { get; private set; } + + /// + public IContentTypeData? ContentType { get; private set; } + + /// + public Uri ContentBase => _entity.ContentBase; + + /// + public Uri ContentLocation => _entity.ContentLocation; + + /// + public string ContentId => _entity.ContentId; + + /// + public bool IsAttachment => _entity.IsAttachment; + + /// + public override string ToString() + { + return _entity.ToString()!; + } +} diff --git a/src/WireMock.Net.MimePart/Models/MimeMessageDataWrapper.cs b/src/WireMock.Net.MimePart/Models/MimeMessageDataWrapper.cs new file mode 100644 index 000000000..a4463f207 --- /dev/null +++ b/src/WireMock.Net.MimePart/Models/MimeMessageDataWrapper.cs @@ -0,0 +1,140 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; +using System.Linq; +using MimeKit; +using Stef.Validation; +using WireMock.Models.Mime; + +namespace WireMock.Models; + +/// +/// A wrapper class that implements the interface by wrapping an interface. +/// +/// +/// This class provides a simplified, read-only view of an . +/// +internal class MimeMessageDataWrapper : IMimeMessageData +{ + private readonly IMimeMessage _message; + + /// + /// Initializes a new instance of the class. + /// + /// The MIME message to wrap. + public MimeMessageDataWrapper(IMimeMessage message) + { + _message = Guard.NotNull(message); + + Bcc = _message.Bcc.Select(h => h.ToString()).ToList(); + Cc = _message.Cc.Select(h => h.ToString()).ToList(); + From = _message.From.Select(h => h.ToString()).ToList(); + Headers = _message.Headers.Select(h => h.ToString()).ToList(); + References = _message.References.ToList(); + ReplyTo = _message.ReplyTo.Select(h => h.ToString()).ToList(); + ResentBcc = _message.ResentBcc.Select(h => h.ToString()).ToList(); + ResentCc = _message.ResentCc.Select(h => h.ToString()).ToList(); + ResentFrom = _message.ResentFrom.Select(h => h.ToString()).ToList(); + ResentReplyTo = _message.ResentReplyTo.Select(h => h.ToString()).ToList(); + ResentTo = _message.ResentTo.Select(h => h.ToString()).ToList(); + To = _message.To.Select(h => h.ToString()).ToList(); + + Body = new MimeEntityDataWrapper(_message.Body); + BodyParts = _message.BodyParts.OfType().Select(mp => new MimePartDataWrapper(mp)).ToList(); + Attachments = _message.Attachments.Select(me => new MimeEntityDataWrapper(me)).ToList(); + } + + /// + public IList Headers { get; private set; } + + /// + public int Importance => (int)_message.Importance; + + /// + public int Priority => (int)_message.Priority; + + /// + public int XPriority => (int)_message.XPriority; + + /// + public string Sender => _message.Sender.Address; + + /// + public string ResentSender => _message.ResentSender.ToString(); + + /// + public IList From { get; private set; } + + /// + public IList ResentFrom { get; private set; } + + /// + public IList ReplyTo { get; private set; } + + /// + public IList ResentReplyTo { get; private set; } + + /// + public IList To { get; private set; } + + /// + public IList ResentTo { get; private set; } + + /// + public IList Cc { get; private set; } + + /// + public IList ResentCc { get; private set; } + + /// + public IList Bcc { get; private set; } + + /// + public IList ResentBcc { get; private set; } + + /// + public string Subject => _message.Subject; + + /// + public DateTimeOffset Date => _message.Date; + + /// + public DateTimeOffset ResentDate => _message.ResentDate; + + /// + public IList References { get; private set; } + + /// + public string InReplyTo => _message.InReplyTo; + + /// + public string MessageId => _message.MessageId; + + /// + public string ResentMessageId => _message.ResentMessageId; + + /// + public Version MimeVersion => _message.MimeVersion; + + /// + public IMimeEntityData Body { get; private set; } + + /// + public string TextBody => _message.TextBody; + + /// + public string HtmlBody => _message.HtmlBody; + + /// + public IList BodyParts { get; private set; } + + /// + public IList Attachments { get; private set; } + + /// + public override string ToString() + { + return _message.ToString(); + } +} \ No newline at end of file diff --git a/src/WireMock.Net.MimePart/Models/MimePartDataWrapper.cs b/src/WireMock.Net.MimePart/Models/MimePartDataWrapper.cs new file mode 100644 index 000000000..cdcc4175c --- /dev/null +++ b/src/WireMock.Net.MimePart/Models/MimePartDataWrapper.cs @@ -0,0 +1,64 @@ +// Copyright © WireMock.Net + +using System.Collections.Generic; +using System.IO; +using MimeKit; +using Stef.Validation; +using WireMock.Models.Mime; + +namespace WireMock.Models; + +/// +/// A wrapper class that implements the interface by wrapping an interface. +/// +/// +/// This class provides a simplified, read-only view of an . +/// +public class MimePartDataWrapper : MimeEntityDataWrapper, IMimePartData +{ + private readonly IMimePart _part; + + /// + /// Initializes a new instance of the class. + /// + /// The MIME part to wrap. + /// + /// is . + /// + public MimePartDataWrapper(IMimePart part) : base(part) + { + _part = Guard.NotNull(part); + } + + /// + public string ContentDescription => _part.ContentDescription; + + /// + public int? ContentDuration => _part.ContentDuration; + + /// + public string ContentMd5 => _part.ContentMd5; + + /// + public string ContentTransferEncoding => _part.ContentTransferEncoding.ToString(); + + /// + public string FileName => _part.FileName; + + /// + public IDictionary Content => new Dictionary() + { + { nameof(MimePart.Content.Encoding), _part.Content.Encoding }, + { nameof(MimePart.Content.NewLineFormat), _part.Content.NewLineFormat }, + { nameof(MimePart.Content.Stream), _part.Content.Stream } + }; + + /// + public Stream Open() => _part.Content.Open(); + + /// + public override string ToString() + { + return _part.ToString()!; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.MimePart/Util/MimeKitUtils.cs b/src/WireMock.Net.MimePart/Util/MimeKitUtils.cs index e0bd93ca1..f97d9232f 100644 --- a/src/WireMock.Net.MimePart/Util/MimeKitUtils.cs +++ b/src/WireMock.Net.MimePart/Util/MimeKitUtils.cs @@ -9,6 +9,8 @@ using MimeKit; using Stef.Validation; using WireMock.Http; +using WireMock.Models; +using WireMock.Models.Mime; using WireMock.Types; namespace WireMock.Util; @@ -16,13 +18,13 @@ namespace WireMock.Util; internal class MimeKitUtils : IMimeKitUtils { /// - public object LoadFromStream(Stream stream) + public IMimeMessageData LoadFromStream(Stream stream) { - return MimeMessage.Load(Guard.NotNull(stream)); + return new MimeMessageDataWrapper(MimeMessage.Load(Guard.NotNull(stream))); } /// - public bool TryGetMimeMessage(IRequestMessage requestMessage, [NotNullWhen(true)] out object? mimeMessage) + public bool TryGetMimeMessage(IRequestMessage requestMessage, [NotNullWhen(true)] out IMimeMessageData? mimeMessageData) { Guard.NotNull(requestMessage); @@ -44,26 +46,14 @@ public bool TryGetMimeMessage(IRequestMessage requestMessage, [NotNullWhen(true) var fixedBytes = FixBytes(bytes, contentTypeHeader[0]); - mimeMessage = LoadFromStream(new MemoryStream(fixedBytes)); + mimeMessageData = LoadFromStream(new MemoryStream(fixedBytes)); return true; } - mimeMessage = null; + mimeMessageData = null; return false; } - /// - public IReadOnlyList GetBodyParts(object mimeMessage) - { - if (mimeMessage is not MimeMessage mm) - { - throw new ArgumentException($"The mimeMessage must be of type {nameof(MimeMessage)}", nameof(mimeMessage)); - } - - return mm.BodyParts - .OfType() - .ToArray(); - } private static bool StartsWithMultiPart(WireMockList contentTypeHeader) { diff --git a/src/WireMock.Net.Minimal/Matchers/Request/RequestMessageMultiPartMatcher.cs b/src/WireMock.Net.Minimal/Matchers/Request/RequestMessageMultiPartMatcher.cs index 6ec3934d2..84a23ce74 100644 --- a/src/WireMock.Net.Minimal/Matchers/Request/RequestMessageMultiPartMatcher.cs +++ b/src/WireMock.Net.Minimal/Matchers/Request/RequestMessageMultiPartMatcher.cs @@ -72,7 +72,8 @@ public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResu foreach (var mimePartMatcher in Matchers.OfType().ToArray()) { score = MatchScores.Mismatch; - foreach (var mimeBodyPart in MimeKitUtils.GetBodyParts(message)) + + foreach (var mimeBodyPart in message.BodyParts) { var matchResult = mimePartMatcher.IsMatch(mimeBodyPart); if (matchResult.IsPerfect()) diff --git a/src/WireMock.Net.Minimal/RequestMessage.cs b/src/WireMock.Net.Minimal/RequestMessage.cs index aa93b6829..e7fd8a706 100644 --- a/src/WireMock.Net.Minimal/RequestMessage.cs +++ b/src/WireMock.Net.Minimal/RequestMessage.cs @@ -85,7 +85,7 @@ public class RequestMessage : IRequestMessage #if MIMEKIT /// [Newtonsoft.Json.JsonIgnore] // Issue 1001 - public object? BodyAsMimeMessage { get; } + public Models.Mime.IMimeMessageData? BodyAsMimeMessage { get; } #endif /// diff --git a/src/WireMock.Net.Shared/Matchers/IMimePartMatcher.cs b/src/WireMock.Net.Shared/Matchers/IMimePartMatcher.cs index 37fa21688..1eff8bd9a 100644 --- a/src/WireMock.Net.Shared/Matchers/IMimePartMatcher.cs +++ b/src/WireMock.Net.Shared/Matchers/IMimePartMatcher.cs @@ -1,5 +1,7 @@ // Copyright © WireMock.Net +using WireMock.Models.Mime; + namespace WireMock.Matchers; /// @@ -33,5 +35,5 @@ public interface IMimePartMatcher : IMatcher /// /// The MimePart. /// A value between 0.0 - 1.0 of the similarity. - public MatchResult IsMatch(object value); + public MatchResult IsMatch(IMimePartData value); } \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Util/IMimeKitUtils.cs b/src/WireMock.Net.Shared/Util/IMimeKitUtils.cs index 35d5adbb6..2d2a739f6 100644 --- a/src/WireMock.Net.Shared/Util/IMimeKitUtils.cs +++ b/src/WireMock.Net.Shared/Util/IMimeKitUtils.cs @@ -1,8 +1,8 @@ // Copyright © WireMock.Net -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; +using WireMock.Models.Mime; namespace WireMock.Util; @@ -12,24 +12,16 @@ namespace WireMock.Util; public interface IMimeKitUtils { /// - /// Loads the MimeKit.MimeMessage from the stream. + /// Loads the from the stream. /// /// The stream - /// MimeKit.MimeMessage - object LoadFromStream(Stream stream); + IMimeMessageData LoadFromStream(Stream stream); /// - /// Tries to get the MimeKit.MimeMessage from the request message. + /// Tries to get the from the request message. /// /// The request message. - /// The MimeKit.MimeMessage + /// A class MimeMessageDataWrapper which wraps a MimeKit.MimeMessage. /// true when parsed correctly, else false - bool TryGetMimeMessage(IRequestMessage requestMessage, [NotNullWhen(true)] out object? mimeMessage); - - /// - /// Gets the body parts from the MimeKit.MimeMessage. - /// - /// The MimeKit.MimeMessage. - /// A list of MimeParts. - IReadOnlyList GetBodyParts(object mimeMessage); + bool TryGetMimeMessage(IRequestMessage requestMessage, [NotNullWhen(true)] out IMimeMessageData? mimeMessageData); } \ No newline at end of file diff --git a/test/WireMock.Net.Tests/Matchers/MimePartMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/MimePartMatcherTests.cs index 2f9e02e34..c6b6596b8 100644 --- a/test/WireMock.Net.Tests/Matchers/MimePartMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/MimePartMatcherTests.cs @@ -48,7 +48,7 @@ public void MimePartMatcher_IsMatch_Part_TextPlain() { // Arrange var message = MimeKitUtils.LoadFromStream(StreamUtils.CreateStream(TestMultiPart)); - var part = MimeKitUtils.GetBodyParts(message)[0]; + var part = message.BodyParts[0]; // Act var contentTypeMatcher = new ContentTypeMatcher("text/plain"); @@ -67,7 +67,7 @@ public void MimePartMatcher_IsMatch_Part_TextJson() { // Arrange var message = MimeKitUtils.LoadFromStream(StreamUtils.CreateStream(TestMultiPart)); - var part = MimeKitUtils.GetBodyParts(message)[1]; + var part = message.BodyParts[1]; // Act var contentTypeMatcher = new ContentTypeMatcher("text/json"); @@ -85,7 +85,7 @@ public void MimePartMatcher_IsMatch_Part_ImagePng() { // Arrange var message = MimeKitUtils.LoadFromStream(StreamUtils.CreateStream(TestMultiPart)); - var part = MimeKitUtils.GetBodyParts(message)[2]; + var part = message.BodyParts[2]; // Act var contentTypeMatcher = new ContentTypeMatcher("image/png");