diff --git a/Example Projects/dotNetCoreExample/Examples/Basic/BasicComplexExample.cs b/Example Projects/dotNetCoreExample/Examples/Basic/BasicComplexExample.cs index 47846d3..ad5372b 100644 --- a/Example Projects/dotNetCoreExample/Examples/Basic/BasicComplexExample.cs +++ b/Example Projects/dotNetCoreExample/Examples/Basic/BasicComplexExample.cs @@ -51,11 +51,7 @@ public SendResponse RunExample() var metadata = new List() { new Metadata("example-type", "basic-send-complex"), - new Metadata() - { - Key = "message-contains", - Value = "attachments, headers" - } + new Metadata("message-contains","attachments, headers") }; message.Metadata.Add(metadata); message.Metadata.Add("x-mycustommetadata", "I am custom metadata"); diff --git a/Example Projects/dotNetCoreExample/Examples/Bulk/BulkSendComplexExample.cs b/Example Projects/dotNetCoreExample/Examples/Bulk/BulkSendComplexExample.cs index 06dfb12..de8222d 100644 --- a/Example Projects/dotNetCoreExample/Examples/Bulk/BulkSendComplexExample.cs +++ b/Example Projects/dotNetCoreExample/Examples/Bulk/BulkSendComplexExample.cs @@ -45,11 +45,7 @@ public SendResponse RunExample() var metadata = new List() { new Metadata("example-type", "bulk-send-complex"), - new Metadata() - { - Key = "message-contains", - Value = "attachments, headers" - } + new Metadata("message-contains","attachments, headers") }; message.Metadata.Add(metadata); message.Metadata.Add("x-mycustommetadata", "I am custom metadata"); diff --git a/README.md b/README.md index 6ca03d9..da2806f 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,9 @@ The SocketLabs Email Delivery C# library allows you to easily send email message # Prerequisites and Installation ## Prerequisites * A supported .NET version - * .NET version 4.5 or higher - * .NET Core 1.0 or higher - * .NET Standard 1.3 or higher + * .NET Framework version 4.8 or higher + * .NET 8.0 or higher + * .NET Standard 2.0 or higher * A SocketLabs account. If you don't have one yet, you can [sign up for a free account](https://signup.socketlabs.com/step-1?plan=free) to get started. ## Installation @@ -36,7 +36,7 @@ PM> Install-Package SocketLabs.EmailDelivery Adding a Package Reference to your project: ``` - + ``` .NET CLI users can also use the following command: diff --git a/docs/release-notes/2.0.0.md b/docs/release-notes/2.0.0.md new file mode 100644 index 0000000..380cd99 --- /dev/null +++ b/docs/release-notes/2.0.0.md @@ -0,0 +1,10 @@ +## 2.0.0 + +* Fix issue with ApiKey being unset for bearer type keys +* Add explicit support for .NET 8.0 and .NET 9.0 +* Update dependencies +* Implement nullable pattern + +```note +This is a breaking change. Some objects require constructor initialization now. +``` \ No newline at end of file diff --git a/src/SocketLabs/InjectionApi/AddressResult.cs b/src/SocketLabs/InjectionApi/AddressResult.cs index 9ef9ff5..7b2849f 100644 --- a/src/SocketLabs/InjectionApi/AddressResult.cs +++ b/src/SocketLabs/InjectionApi/AddressResult.cs @@ -8,7 +8,7 @@ public class AddressResult /// /// The recipient's email address. /// - public string EmailAddress { get; set; } + public string? EmailAddress { get; set; } /// /// Whether the recipient was accepted for delivery. @@ -18,7 +18,7 @@ public class AddressResult /// /// An error code detailing why the recipient was not accepted. /// - public string ErrorCode { get; set; } + public string? ErrorCode { get; set; } /// /// Represents the AddressResult as a string. Useful for debugging. diff --git a/src/SocketLabs/InjectionApi/Core/ApiKeyParser.cs b/src/SocketLabs/InjectionApi/Core/ApiKeyParser.cs index c5023d0..7618fad 100644 --- a/src/SocketLabs/InjectionApi/Core/ApiKeyParser.cs +++ b/src/SocketLabs/InjectionApi/Core/ApiKeyParser.cs @@ -5,7 +5,7 @@ namespace SocketLabs.InjectionApi.Core /// /// Parses a provided api key and provides a result /// - public class ApiKeyParser : IApiKeyParser + internal class ApiKeyParser : IApiKeyParser { /// /// Parses the provided Api key. diff --git a/src/SocketLabs/InjectionApi/Core/IApiKeyParser.cs b/src/SocketLabs/InjectionApi/Core/IApiKeyParser.cs index 345a61f..d615174 100644 --- a/src/SocketLabs/InjectionApi/Core/IApiKeyParser.cs +++ b/src/SocketLabs/InjectionApi/Core/IApiKeyParser.cs @@ -2,7 +2,7 @@ namespace SocketLabs.InjectionApi.Core { - public interface IApiKeyParser + internal interface IApiKeyParser { ApiKeyParseResult Parse(string wholeApiKey); } diff --git a/src/SocketLabs/InjectionApi/Core/InjectionRequestFactory.cs b/src/SocketLabs/InjectionApi/Core/InjectionRequestFactory.cs index 2e38dbe..f7f6eb0 100644 --- a/src/SocketLabs/InjectionApi/Core/InjectionRequestFactory.cs +++ b/src/SocketLabs/InjectionApi/Core/InjectionRequestFactory.cs @@ -12,14 +12,14 @@ namespace SocketLabs.InjectionApi.Core internal class InjectionRequestFactory : IInjectionRequestFactory { private readonly int _serverId; - private readonly string _apiKey; + private readonly string? _apiKey; /// /// Creates a new instance of the InjectionRequestFactory. /// /// Your SocketLabs ServerId number. - /// Your SocketLabs Injection API key. - public InjectionRequestFactory(int serverId, string apiKey) + /// Your SocketLabs Injection API key. Set to null if using Bearer token. + public InjectionRequestFactory(int serverId, string? apiKey) { _serverId = serverId; _apiKey = apiKey; @@ -41,7 +41,7 @@ public InjectionRequest GenerateRequest(IBasicMessage message) request.Messages.Add(jsonMsg); - if (message.ReplyTo != null) + if (message.ReplyTo?.Email is not null) jsonMsg.ReplyTo = new AddressJson(message.ReplyTo.Email, message.ReplyTo.FriendlyName); return request; @@ -63,10 +63,13 @@ public InjectionRequest GenerateRequest(IBulkMessage message) // handle merge data per recipient for message var mergeDataForEmail = GetBulkMergeFields(message.To); - jsonMsg.MergeData.PerMessage = mergeDataForEmail; + jsonMsg.MergeData = new() + { + PerMessage = mergeDataForEmail, - // handle global (per message) merge data - jsonMsg.MergeData.Global = PopulateMergeData(message.GlobalMergeData); + // handle global (per message) merge data + Global = PopulateMergeData(message.GlobalMergeData) + }; request.Messages.Add(jsonMsg); @@ -90,18 +93,19 @@ internal virtual MessageJson GenerateBaseMessageJson(IMessageBase message) MailingId = message.MailingId, MessageId = message.MessageId, CharSet = message.CharSet, - CustomHeaders = PopulateCustomHeaders(message.CustomHeaders), - From = new AddressJson(message.From.Email, message.From.FriendlyName), + CustomHeaders = PopulateCustomHeaders(message.CustomHeaders), Attachments = PopulateList(message.Attachments), Metadata = PopulateMetadata(message.Metadata), Tags = PopulateTags(message.Tags) }; + if (message.From?.Email is not null) + jsonMsg.From = new AddressJson(message.From.Email, message.From.FriendlyName); - if (message.ReplyTo != null) + if (message.ReplyTo?.Email is not null) jsonMsg.ReplyTo = new AddressJson(message.ReplyTo.Email, message.ReplyTo.FriendlyName); if (message.ApiTemplate.HasValue) - jsonMsg.ApiTemplate = message.ApiTemplate.ToString(); + jsonMsg.ApiTemplate = message.ApiTemplate?.ToString(); return jsonMsg; } @@ -113,9 +117,6 @@ internal virtual MessageJson GenerateBaseMessageJson(IMessageBase message) /// A ]]> used in generating an InjectionRequest internal virtual List PopulateList(IEnumerable attachments) { - if (attachments == null) - return null; - var results = new List(); foreach (var attachment in attachments) @@ -140,8 +141,8 @@ internal virtual List PopulateList(IEnumerable atta /// A ]]> used in generating an InjectionRequest internal virtual List PopulateCustomHeaders(IList customHeaders) { - var result = customHeaders?.Select(item => new CustomHeadersJson(item.Name, item.Value)); - return result?.ToList(); + var result = customHeaders.Select(item => new CustomHeadersJson(item.Name, item.Value)); + return result.ToList(); } /// @@ -151,8 +152,10 @@ internal virtual List PopulateCustomHeaders(IListA ]]> used in generating an InjectionRequest internal virtual List PopulateList(IEnumerable recipients) { - var result = recipients?.Select(item => new AddressJson(item.Email, item.FriendlyName)); - return result?.ToList(); + var result = recipients.Where(x => x.Email is not null) + .Select(item => new AddressJson(item.Email!, item.FriendlyName)); + + return result.ToList(); } /// @@ -160,24 +163,26 @@ internal virtual List PopulateList(IEnumerable recip /// /// A ]]> from the message /// A > ]]> used in generating an InjectionRequest - internal virtual List> GetBulkMergeFields(IEnumerable recipients) + internal virtual List> GetBulkMergeFields(IEnumerable? recipients) { var result = new List>(); - - //each recipient get's their own list of merge fields - foreach (var recipient in recipients) + if (recipients is not null) { - // Get any merge data associated with the Recipients and put it in the MergeData section - var recipientMergeFields = recipient.MergeData?.Select(mergeField => new MergeFieldJson(mergeField.Key, mergeField.Value)).ToList() ?? - new List(); + //each recipient get's their own list of merge fields + foreach (var recipient in recipients) + { + // Get any merge data associated with the Recipients and put it in the MergeData section + var recipientMergeFields = recipient.MergeData?.Select(mergeField => new MergeFieldJson(mergeField.Key, mergeField.Value)).ToList() ?? + new List(); - recipientMergeFields.Add(new MergeFieldJson("DeliveryAddress", recipient.Email)); + recipientMergeFields.Add(new MergeFieldJson("DeliveryAddress", recipient.Email)); - //don't include friendly name if it hasn't been provided - if (!string.IsNullOrWhiteSpace(recipient.FriendlyName)) - recipientMergeFields.Add(new MergeFieldJson("RecipientName", recipient.FriendlyName)); + //don't include friendly name if it hasn't been provided + if (!string.IsNullOrWhiteSpace(recipient.FriendlyName)) + recipientMergeFields.Add(new MergeFieldJson("RecipientName", recipient.FriendlyName!)); - result.Add(recipientMergeFields); + result.Add(recipientMergeFields); + } } return result; @@ -191,8 +196,8 @@ internal virtual List> GetBulkMergeFields(IEnumerable PopulateMergeData(IDictionary mergeData) { - var result = mergeData?.Select(item => new MergeFieldJson(item.Key, item.Value)); - return result?.ToList(); + var result = mergeData.Select(item => new MergeFieldJson(item.Key, item.Value)); + return result.ToList(); } @@ -203,8 +208,8 @@ internal virtual List PopulateMergeData(IDictionaryA ]]> used in generating an InjectionRequest internal virtual List PopulateMetadata(IList metadata) { - var result = metadata?.Select(item => new MetadataHeaderJson(item.Key, item.Value)); - return result?.ToList(); + var result = metadata.Select(item => new MetadataHeaderJson(item.Key, item.Value)); + return result.ToList(); } /// @@ -215,7 +220,7 @@ internal virtual List PopulateMetadata(IList meta internal virtual List PopulateTags(IList tags) { var result = tags.ToList(); - return result?.ToList(); + return result; } } } diff --git a/src/SocketLabs/InjectionApi/Core/InjectionResponseParser.cs b/src/SocketLabs/InjectionApi/Core/InjectionResponseParser.cs index e41fc98..fed4148 100644 --- a/src/SocketLabs/InjectionApi/Core/InjectionResponseParser.cs +++ b/src/SocketLabs/InjectionApi/Core/InjectionResponseParser.cs @@ -23,6 +23,14 @@ public SendResponse Parse(HttpResponseMessage httpResponse) var injectionResponse = JsonConvert.DeserializeObject(contentString); + if (injectionResponse is null) + { + return new SendResponse() + { + Result = SendResult.UnknownError + }; + } + var resultEnum = DetermineSendResult(injectionResponse, httpResponse); var newResponse = new SendResponse { diff --git a/src/SocketLabs/InjectionApi/Core/SendValidator.cs b/src/SocketLabs/InjectionApi/Core/SendValidator.cs index 56a3427..2388ecc 100644 --- a/src/SocketLabs/InjectionApi/Core/SendValidator.cs +++ b/src/SocketLabs/InjectionApi/Core/SendValidator.cs @@ -290,7 +290,7 @@ internal virtual List HasInvalidRecipients(IBulkMessage message) /// A ]]> if an invalid email address is found. /// /// - internal virtual List FindInvalidRecipients(IList recipients) + internal virtual List? FindInvalidRecipients(IList? recipients) { var invalid = recipients?.Where(item => !item.IsValid).Select(x => new AddressResult() { @@ -312,7 +312,7 @@ internal virtual List FindInvalidRecipients(IList /// A ]]> if an invalid email address is found. /// /// - internal virtual List FindInvalidRecipients(IList recipients) + internal virtual List? FindInvalidRecipients(IList recipients) { var invalid = recipients?.Where(item => !item.IsValid).Select(x => new AddressResult() { diff --git a/src/SocketLabs/InjectionApi/Core/Serialization/AddressJson.cs b/src/SocketLabs/InjectionApi/Core/Serialization/AddressJson.cs index a14de90..0e64f58 100644 --- a/src/SocketLabs/InjectionApi/Core/Serialization/AddressJson.cs +++ b/src/SocketLabs/InjectionApi/Core/Serialization/AddressJson.cs @@ -11,7 +11,7 @@ internal class AddressJson /// /// A valid email address /// The friendly or display name for the recipient. - public AddressJson(string emailAddress, string friendlyName = null) + public AddressJson(string emailAddress, string? friendlyName = null) { EmailAddress = emailAddress; FriendlyName = friendlyName; @@ -25,6 +25,6 @@ public AddressJson(string emailAddress, string friendlyName = null) /// /// The friendly or display name for the recipient. /// - public string FriendlyName { get; set; } + public string? FriendlyName { get; set; } } } \ No newline at end of file diff --git a/src/SocketLabs/InjectionApi/Core/Serialization/AttachmentJson.cs b/src/SocketLabs/InjectionApi/Core/Serialization/AttachmentJson.cs index 94deea9..b47bc46 100644 --- a/src/SocketLabs/InjectionApi/Core/Serialization/AttachmentJson.cs +++ b/src/SocketLabs/InjectionApi/Core/Serialization/AttachmentJson.cs @@ -11,27 +11,27 @@ internal class AttachmentJson /// /// Name of attachment (displayed in email clients) /// - public string Name { get; set; } + public string? Name { get; set; } /// /// The BASE64 encoded string containing the contents of an attachment. /// - public string Content { get; set; } + public string? Content { get; set; } /// /// When set, used to embed an image within the body of an email message. /// - public string ContentId { get; set; } + public string? ContentId { get; set; } /// /// The ContentType (MIME type) of the attachment. /// /// text/plain, image/jpeg, - public string ContentType { get; set; } + public string? ContentType { get; set; } /// /// A list of custom headers added to the attachment. /// - public List CustomHeaders { get; set; } + public List CustomHeaders { get; set; } = new(); } } \ No newline at end of file diff --git a/src/SocketLabs/InjectionApi/Core/Serialization/InjectionRequest.cs b/src/SocketLabs/InjectionApi/Core/Serialization/InjectionRequest.cs index 9f0ed48..4807ea2 100644 --- a/src/SocketLabs/InjectionApi/Core/Serialization/InjectionRequest.cs +++ b/src/SocketLabs/InjectionApi/Core/Serialization/InjectionRequest.cs @@ -13,29 +13,29 @@ internal class InjectionRequest /// /// Your SocketLabs ServerId number. /// - public int ServerId { get; internal set; } + public readonly int _serverId; /// /// Your SocketLabs Injection API key. /// - public string ApiKey { get; internal set; } + public readonly string? _apiKey; /// /// Creates a new instance of the InjectionRequest class. /// /// Your SocketLabs ServerId number. /// Your SocketLabs Injection API key. - public InjectionRequest(int serverId, string apiKey) + public InjectionRequest(int serverId, string? apiKey) { - ServerId = serverId; - ApiKey = apiKey; + _serverId = serverId; + _apiKey = apiKey; Messages = new List(); } /// /// Gets or sets the list of messages to be sent. /// - public List Messages { get; set; } + public List Messages { get; set; } = new(); /// /// Get the InjectionRequest object serialized into a JSON string diff --git a/src/SocketLabs/InjectionApi/Core/Serialization/InjectionResponseDto.cs b/src/SocketLabs/InjectionApi/Core/Serialization/InjectionResponseDto.cs index f9e1d02..f2401ab 100644 --- a/src/SocketLabs/InjectionApi/Core/Serialization/InjectionResponseDto.cs +++ b/src/SocketLabs/InjectionApi/Core/Serialization/InjectionResponseDto.cs @@ -1,4 +1,6 @@ -namespace SocketLabs.InjectionApi.Core.Serialization +using System; + +namespace SocketLabs.InjectionApi.Core.Serialization { /// /// Data transfer object representing the Injection Api response. @@ -8,17 +10,17 @@ internal class InjectionResponseDto /// /// The resulting response ErrorCode of the Injection Api send request /// - public string ErrorCode { get; set; } + public string? ErrorCode { get; set; } /// /// A unique key generated by the Injection API if an unexpected error occurs during the SocketLabsClient send request. /// This unique key can be used by SocketLabs support to troubleshoot the issue. /// - public string TransactionReceipt { get; set; } + public string? TransactionReceipt { get; set; } /// /// An array of MessageResultDto objects that contain the status of each message sent. /// - public MessageResultDto[] MessageResults { get; set; } + public MessageResultDto[] MessageResults { get; set; } = Array.Empty(); } } \ No newline at end of file diff --git a/src/SocketLabs/InjectionApi/Core/Serialization/MergeDataJson.cs b/src/SocketLabs/InjectionApi/Core/Serialization/MergeDataJson.cs index 898d321..1d44027 100644 --- a/src/SocketLabs/InjectionApi/Core/Serialization/MergeDataJson.cs +++ b/src/SocketLabs/InjectionApi/Core/Serialization/MergeDataJson.cs @@ -20,12 +20,12 @@ public MergeDataJson() /// /// Defines merge field data for each message. /// - public List> PerMessage { get; set; } + public List> PerMessage { get; set; } = new(); /// /// Defines merge field data for all messages in the request. /// - public List Global { get; set; } + public List Global { get; set; } = new(); #region Conditional Property Serialization @@ -39,7 +39,7 @@ public MergeDataJson() /// bool result public bool ShouldSerializePerMessage() { - return PerMessage == null || PerMessage.Count > 0; + return PerMessage.Count > 0; } /// @@ -52,7 +52,7 @@ public bool ShouldSerializePerMessage() /// bool result public bool ShouldSerializeGlobal() { - return Global == null || Global.Count > 0; + return Global.Count > 0; } #endregion diff --git a/src/SocketLabs/InjectionApi/Core/Serialization/MessageJson.cs b/src/SocketLabs/InjectionApi/Core/Serialization/MessageJson.cs index dfe60e7..359b8c5 100644 --- a/src/SocketLabs/InjectionApi/Core/Serialization/MessageJson.cs +++ b/src/SocketLabs/InjectionApi/Core/Serialization/MessageJson.cs @@ -27,97 +27,97 @@ public MessageJson() /// Gets or sets the list of To recipients. /// [JsonProperty("To", NullValueHandling = NullValueHandling.Ignore)] - public List To { get; set; } + public List To { get; set; } = new(); /// /// Gets or sets the From address. /// - public AddressJson From { get; set; } + public AddressJson? From { get; set; } /// /// Gets or sets the instance of the message Subject. /// - public string Subject { get; set; } + public string? Subject { get; set; } /// /// Gets or sets the plain text portion of the message body. /// - public string TextBody { get; set; } + public string? TextBody { get; set; } /// /// Gets or sets the HTML portion of the message body. /// - public string HtmlBody { get; set; } + public string? HtmlBody { get; set; } /// /// Gets or sets the AMP portion of the message body. /// - public string AmpBody { get; set; } + public string? AmpBody { get; set; } /// /// Gets or sets the Api Template for the message. /// - public string ApiTemplate { get; set; } + public string? ApiTemplate { get; set; } /// /// Gets or sets the custom MailingId for the message. /// - public string MailingId { get; set; } + public string? MailingId { get; set; } /// /// Gets or sets the custom MessageId for the message. /// - public string MessageId { get; set; } + public string? MessageId { get; set; } /// /// The optional character set for your message. /// - public string CharSet { get; set; } + public string? CharSet { get; set; } /// /// A list of custom message headers added to the message. /// - public List CustomHeaders { get; set; } - + public List CustomHeaders { get; set; } = new(); + /// /// Gets or sets the list of CC recipients. /// - public List Cc { get; set; } + public List Cc { get; set; } = new(); /// /// Gets or sets the list of BCC recipients. /// - public List Bcc { get; set; } - + public List Bcc { get; set; } = new(); + /// /// Gets or sets the Reply To address. /// - public AddressJson ReplyTo { get; set; } + public AddressJson? ReplyTo { get; set; } /// /// Gets or sets the list of attachments. /// - public List Attachments { get; set; } + public List Attachments { get; set; } = new(); /// /// Gets or sets the list of merge data. /// - public MergeDataJson MergeData { get; set; } - + public MergeDataJson? MergeData { get; set; } + /// /// A list of metadata headers added to the message. /// - public List Metadata { get; set; } + public List Metadata { get; set; } = new(); /// /// A list of tag headers added to the message. /// - public List Tags { get; set; } + public List Tags { get; set; } = new(); #region Conditional Property Serialization /// - /// Check if ro recipients should be serialized. + /// Check if no recipients should be serialized. /// /// /// Don't serialize the collection if they are null or empty. @@ -126,7 +126,7 @@ public MessageJson() /// bool result public bool ShouldSerializeTo() { - return To == null || To.Count > 0; + return To.Count > 0; } /// @@ -139,7 +139,7 @@ public bool ShouldSerializeTo() /// bool result public bool ShouldSerializeCc() { - return Cc == null || Cc.Count > 0; + return Cc.Count > 0; } /// @@ -152,7 +152,7 @@ public bool ShouldSerializeCc() /// bool result public bool ShouldSerializeBcc() { - return Bcc == null || Bcc.Count > 0; + return Bcc.Count > 0; } /// @@ -178,7 +178,7 @@ public bool ShouldSerializeMergeData() /// bool result public bool ShouldSerializeAttachment() { - return Attachments == null || Attachments.Count > 0; + return Attachments.Count > 0; } #endregion diff --git a/src/SocketLabs/InjectionApi/Core/Serialization/MessageResultDto.cs b/src/SocketLabs/InjectionApi/Core/Serialization/MessageResultDto.cs index 3755665..12b7b3f 100644 --- a/src/SocketLabs/InjectionApi/Core/Serialization/MessageResultDto.cs +++ b/src/SocketLabs/InjectionApi/Core/Serialization/MessageResultDto.cs @@ -1,4 +1,6 @@ -namespace SocketLabs.InjectionApi.Core.Serialization +using System; + +namespace SocketLabs.InjectionApi.Core.Serialization { /// /// Data transfer object representing a message result from the Injection Api. @@ -13,11 +15,11 @@ internal class MessageResultDto /// /// The resulting response ErrorCode of the Injection Api send request /// - public string ErrorCode { get; set; } + public string? ErrorCode { get; set; } /// /// An array of AddressResult objects that contain the status of each address that failed. If no messages failed this array is empty. /// - public AddressResult[] AddressResults { get; set; } + public AddressResult[] AddressResults { get; set; } = Array.Empty(); } } diff --git a/src/SocketLabs/InjectionApi/Message/Attachment.cs b/src/SocketLabs/InjectionApi/Message/Attachment.cs index 11e0506..1179736 100644 --- a/src/SocketLabs/InjectionApi/Message/Attachment.cs +++ b/src/SocketLabs/InjectionApi/Message/Attachment.cs @@ -26,20 +26,6 @@ namespace SocketLabs.InjectionApi.Message /// public class Attachment : IAttachment { - /// - /// Initializes a new instance of the class - /// - /// - /// - /// var attachment = new Attachment(); - /// attachment.Name = Path.GetFileName(@"c:\bus.png"); - /// attachment.Content = File.ReadAllBytes(@"c:\bus.png"); - /// attachment.MimeType = "image/png"; - /// - /// - public Attachment() : this(null, null, (byte[]) null) { } - - /// /// Initializes a new instance of the class /// @@ -131,7 +117,7 @@ public Attachment(string name, string mimeType, Stream stream) /// /// When set, used to embed an image within the body of an email message. /// - public string ContentId { get; set; } + public string? ContentId { get; set; } /// /// The byte array containing the contents of an attachment. diff --git a/src/SocketLabs/InjectionApi/Message/BasicMessage.cs b/src/SocketLabs/InjectionApi/Message/BasicMessage.cs index c12902d..f97a721 100644 --- a/src/SocketLabs/InjectionApi/Message/BasicMessage.cs +++ b/src/SocketLabs/InjectionApi/Message/BasicMessage.cs @@ -50,7 +50,7 @@ public class BasicMessage : IBasicMessage /// /// (Required ) /// - public string Subject { get; set; } + public string? Subject { get; set; } /// /// Gets or sets the plain text portion of the message body. @@ -59,7 +59,7 @@ public class BasicMessage : IBasicMessage /// (Optional) /// Either PlainTextBody or HtmlBody must be used with the AmpBody or use a ApiTemplate /// - public string PlainTextBody { get; set; } + public string? PlainTextBody { get; set; } /// /// Gets or sets the HTML portion of the message body. @@ -68,7 +68,7 @@ public class BasicMessage : IBasicMessage /// (Optional) /// Either PlainTextBody or HtmlBody must be used with the AmpBody or use a ApiTemplate /// - public string HtmlBody { get; set; } + public string? HtmlBody { get; set; } /// /// Gets or sets the AMP portion of the message body. @@ -78,7 +78,7 @@ public class BasicMessage : IBasicMessage /// Either PlainTextBody or HtmlBody must be used with the AmpBody or use a ApiTemplate /// See https://amp.dev/documentation/ for more information on AMP implementation /// - public string AmpBody { get; set; } + public string? AmpBody { get; set; } /// /// Gets or sets the Api Template for the message. @@ -96,7 +96,7 @@ public class BasicMessage : IBasicMessage /// (Optional) /// See https://www.socketlabs.com/blog/best-practices-for-using-custom-mailingids-and-messageids/ for more information. /// - public string MailingId { get; set; } + public string? MailingId { get; set; } /// /// Gets or sets the custom MessageId for the message. @@ -104,7 +104,7 @@ public class BasicMessage : IBasicMessage /// /// (Optional) /// - public string MessageId { get; set; } + public string? MessageId { get; set; } /// /// Gets or sets the From address. @@ -160,7 +160,7 @@ public class BasicMessage : IBasicMessage /// /// (Optional) Default is UTF8 /// - public string CharSet { get; set; } + public string CharSet { get; set; } = "utf-8"; /// /// A list of custom message headers added to the message. diff --git a/src/SocketLabs/InjectionApi/Message/BulkMessage.cs b/src/SocketLabs/InjectionApi/Message/BulkMessage.cs index d4cb2f1..67c9903 100644 --- a/src/SocketLabs/InjectionApi/Message/BulkMessage.cs +++ b/src/SocketLabs/InjectionApi/Message/BulkMessage.cs @@ -55,7 +55,7 @@ public class BulkMessage : IBulkMessage /// /// (Required ) /// - public string Subject { get; set; } + public string? Subject { get; set; } /// /// Gets or sets the plain text portion of the message body. @@ -64,7 +64,7 @@ public class BulkMessage : IBulkMessage /// (Optional) /// Either PlainTextBody or HtmlBody must be used with the AmpBody or use a ApiTemplate /// - public string PlainTextBody { get; set; } + public string? PlainTextBody { get; set; } /// /// Gets or sets the HTML portion of the message body. @@ -73,7 +73,7 @@ public class BulkMessage : IBulkMessage /// (Optional) /// Either PlainTextBody or HtmlBody must be used with the AmpBody or use a ApiTemplate /// - public string HtmlBody { get; set; } + public string? HtmlBody { get; set; } /// /// Gets or sets the AMP HTML portion of the message body. @@ -83,7 +83,7 @@ public class BulkMessage : IBulkMessage /// Either PlainTextBody or HtmlBody must be used with the AmpBody or use a ApiTemplate /// See https://amp.dev/documentation/ for more information on AMP implementation /// - public string AmpBody { get; set; } + public string? AmpBody { get; set; } /// /// Gets or sets the Api Template for the message. @@ -101,7 +101,7 @@ public class BulkMessage : IBulkMessage /// (Optional) /// See https://www.socketlabs.com/blog/best-practices-for-using-custom-mailingids-and-messageids/ for more information. /// - public string MailingId { get; set; } + public string? MailingId { get; set; } /// /// Gets or sets the custom MessageId for the message. @@ -109,7 +109,7 @@ public class BulkMessage : IBulkMessage /// /// (Optional) /// - public string MessageId { get; set; } + public string? MessageId { get; set; } /// /// Gets or sets the From address of the message. @@ -157,7 +157,7 @@ public class BulkMessage : IBulkMessage /// /// (Optional) Default is UTF8 /// - public string CharSet { get; set; } + public string CharSet { get; set; } = "utf-8"; /// /// A list of custom message headers added to the message. diff --git a/src/SocketLabs/InjectionApi/Message/BulkRecipient.cs b/src/SocketLabs/InjectionApi/Message/BulkRecipient.cs index d823bac..7dd9438 100644 --- a/src/SocketLabs/InjectionApi/Message/BulkRecipient.cs +++ b/src/SocketLabs/InjectionApi/Message/BulkRecipient.cs @@ -95,7 +95,7 @@ public BulkRecipient(string email, IDictionary mergeData) /// var email = new BulkRecipient("recipient@example.com", "Recipient", mergeData); /// /// - public BulkRecipient(string email, string friendlyName, IDictionary mergeData) + public BulkRecipient(string email, string? friendlyName, IDictionary? mergeData) { Email = email; FriendlyName = friendlyName; @@ -111,7 +111,7 @@ public BulkRecipient(string email, string friendlyName, IDictionary /// The friendly or display name for the recipient. /// - public string FriendlyName { get; set; } + public string? FriendlyName { get; set; } /// /// A dictionary containing MergeData items unique to the recipient. diff --git a/src/SocketLabs/InjectionApi/Message/CustomHeader.cs b/src/SocketLabs/InjectionApi/Message/CustomHeader.cs index e9cebfd..3ecf084 100644 --- a/src/SocketLabs/InjectionApi/Message/CustomHeader.cs +++ b/src/SocketLabs/InjectionApi/Message/CustomHeader.cs @@ -23,18 +23,6 @@ /// public class CustomHeader : ICustomHeader { - /// - /// Creates a new instance of the CustomHeader class. - /// - /// - /// - /// var header1 = new CustomHeader(); - /// header1.Name = "name1"; - /// header1.Value = "value1"; - /// - /// - public CustomHeader() { } - /// /// Creates a new instance of the CustomHeader class and sets the name and value pair. /// diff --git a/src/SocketLabs/InjectionApi/Message/EmailAddress.cs b/src/SocketLabs/InjectionApi/Message/EmailAddress.cs index 38ec573..8fd2e77 100644 --- a/src/SocketLabs/InjectionApi/Message/EmailAddress.cs +++ b/src/SocketLabs/InjectionApi/Message/EmailAddress.cs @@ -31,7 +31,7 @@ public class EmailAddress : IEmailAddress /// var email = new EmailAddress(); /// /// - public EmailAddress() : this(null, null) { } + public EmailAddress() { } /// /// Creates a new instance of the class and sets the email address. @@ -43,7 +43,7 @@ public EmailAddress() : this(null, null) { } /// var email = new EmailAddress("recipient@example.com"); /// /// - public EmailAddress(string email):this(email, null) { } + public EmailAddress(string? email):this(email, null) { } /// /// Creates a new instance of the email address class and sets the email address and the friendly name. @@ -56,7 +56,7 @@ public EmailAddress(string email):this(email, null) { } /// var email = new EmailAddress("recipient@example.com", "Recipient"); /// /// - public EmailAddress(string email, string friendlyName) + public EmailAddress(string? email, string? friendlyName) { Email = email; FriendlyName = friendlyName; @@ -65,12 +65,12 @@ public EmailAddress(string email, string friendlyName) /// /// A valid email address /// - public string Email { get; set; } + public string? Email { get; set; } /// /// The friendly or display name for the recipient. /// - public string FriendlyName { get; set; } + public string? FriendlyName { get; set; } internal readonly char[] BadEmailCharacters = { ',', ' ', ';', (char)191 }; @@ -88,7 +88,7 @@ public bool IsValid if (string.IsNullOrWhiteSpace(Email)) return false; - var parts = Email.Split('@'); + var parts = Email!.Split('@'); if (parts.Length != 2) return false; @@ -109,12 +109,12 @@ public bool IsValid /// Represents the email address as a string similar to how it would look in an email client. Useful for debugging. /// /// - public override string ToString() + public override string? ToString() { if (!string.IsNullOrWhiteSpace(FriendlyName)) return $"{FriendlyName} <{Email}>"; - return Email; + return Email ?? base.ToString(); } } } \ No newline at end of file diff --git a/src/SocketLabs/InjectionApi/Message/IAttachment.cs b/src/SocketLabs/InjectionApi/Message/IAttachment.cs index 6676fbf..156d05b 100644 --- a/src/SocketLabs/InjectionApi/Message/IAttachment.cs +++ b/src/SocketLabs/InjectionApi/Message/IAttachment.cs @@ -29,7 +29,7 @@ public interface IAttachment /// /// When set, used to embed an image within the body of an email message. /// - string ContentId { get; set; } + string? ContentId { get; set; } /// /// The MIME type of the attachment. diff --git a/src/SocketLabs/InjectionApi/Message/IBulkRecipient.cs b/src/SocketLabs/InjectionApi/Message/IBulkRecipient.cs index 2978237..5b5d549 100644 --- a/src/SocketLabs/InjectionApi/Message/IBulkRecipient.cs +++ b/src/SocketLabs/InjectionApi/Message/IBulkRecipient.cs @@ -41,7 +41,7 @@ public interface IBulkRecipient /// /// The friendly or display name for the recipient. /// - string FriendlyName { get; set; } + string? FriendlyName { get; set; } /// /// Determines if the Email Address is valid. diff --git a/src/SocketLabs/InjectionApi/Message/IEmailAddress.cs b/src/SocketLabs/InjectionApi/Message/IEmailAddress.cs index cbfe752..3da5440 100644 --- a/src/SocketLabs/InjectionApi/Message/IEmailAddress.cs +++ b/src/SocketLabs/InjectionApi/Message/IEmailAddress.cs @@ -20,12 +20,12 @@ public interface IEmailAddress /// /// A valid email address /// - string Email { get; set; } + string? Email { get; set; } /// /// The friendly or display name for the recipient. /// - string FriendlyName { get; set; } + string? FriendlyName { get; set; } /// /// Determines if the Email Address is valid. diff --git a/src/SocketLabs/InjectionApi/Message/IMessageBase.cs b/src/SocketLabs/InjectionApi/Message/IMessageBase.cs index 1b46e89..5cb2b51 100644 --- a/src/SocketLabs/InjectionApi/Message/IMessageBase.cs +++ b/src/SocketLabs/InjectionApi/Message/IMessageBase.cs @@ -13,7 +13,7 @@ public interface IMessageBase /// /// (Required ) /// - string Subject { get; set; } + string? Subject { get; set; } /// /// Gets or sets the plain text portion of the message body. @@ -22,7 +22,7 @@ public interface IMessageBase /// (Optional) /// Either PlainTextBody or HtmlBody must be used with the AmpBody or use a ApiTemplate /// - string PlainTextBody { get; set; } + string? PlainTextBody { get; set; } /// /// Gets or sets the HTML portion of the message body. @@ -31,7 +31,7 @@ public interface IMessageBase /// (Optional) /// Either PlainTextBody or HtmlBody must be used with the AmpBody or use a ApiTemplate /// - string HtmlBody { get; set; } + string? HtmlBody { get; set; } /// /// Gets or sets the AMP HTML portion of the message body. @@ -41,7 +41,7 @@ public interface IMessageBase /// Either PlainTextBody or HtmlBody must be used with the AmpBody or use a ApiTemplate /// See https://amp.dev/documentation/ for more information on AMP implementation /// - string AmpBody { get; set; } + string? AmpBody { get; set; } /// /// Gets or sets the Api Template for the message. @@ -59,7 +59,7 @@ public interface IMessageBase /// (Optional) /// See https://www.socketlabs.com/blog/best-practices-for-using-custom-mailingids-and-messageids/ for more information. /// - string MailingId { get; set; } + string? MailingId { get; set; } /// /// Gets or sets the custom MessageId for the message. @@ -67,7 +67,7 @@ public interface IMessageBase /// /// (Optional) /// - string MessageId { get; set; } + string? MessageId { get; set; } /// /// Gets or sets the From address. diff --git a/src/SocketLabs/InjectionApi/Message/Metadata.cs b/src/SocketLabs/InjectionApi/Message/Metadata.cs index 7356b66..2d4e1ed 100644 --- a/src/SocketLabs/InjectionApi/Message/Metadata.cs +++ b/src/SocketLabs/InjectionApi/Message/Metadata.cs @@ -23,18 +23,6 @@ /// public class Metadata : IMetadata { - /// - /// Creates a new instance of the Metadata class. - /// - /// - /// - /// var metadata = new Metadata(); - /// metadata.Name = "key1"; - /// metadata.Value = "value1"; - /// - /// - public Metadata() { } - /// /// Creates a new instance of the Metadata class and sets the name and value pair. /// diff --git a/src/SocketLabs/InjectionApi/SendResponse.cs b/src/SocketLabs/InjectionApi/SendResponse.cs index 7687c14..b44bc8a 100644 --- a/src/SocketLabs/InjectionApi/SendResponse.cs +++ b/src/SocketLabs/InjectionApi/SendResponse.cs @@ -14,12 +14,12 @@ public class SendResponse /// A unique key generated by the Injection API if an unexpected error occurs during the SocketLabsClient send request. /// This unique key can be used by SocketLabs support to troubleshoot the issue. /// - public string TransactionReceipt { get; set; } + public string? TransactionReceipt { get; set; } /// /// An array of AddressResult objects that contain the status of each address that failed. If no messages failed this array is empty. /// - public AddressResult[] AddressResults { get; set; } + public AddressResult[]? AddressResults { get; set; } /// /// A message detailing why the SocketLabsClient send request failed. diff --git a/src/SocketLabs/InjectionApi/SocketLabsClient.cs b/src/SocketLabs/InjectionApi/SocketLabsClient.cs index 50c099c..c0e56ee 100644 --- a/src/SocketLabs/InjectionApi/SocketLabsClient.cs +++ b/src/SocketLabs/InjectionApi/SocketLabsClient.cs @@ -37,8 +37,8 @@ public class SocketLabsClient : ISocketLabsClient, IDisposable private readonly int _serverId; private readonly HttpClient _httpClient; - private string _apiKey; - + private readonly string _apiKey; + private readonly IInjectionRequestFactory _injectionRequestFactory; /// /// The SocketLabs Injection API endpoint Url @@ -60,20 +60,45 @@ public SocketLabsClient(int serverId, string apiKey) _serverId = serverId; _apiKey = apiKey; _httpClient = BuildHttpClient(null); + + var apiKeyParser = new ApiKeyParser(); + var parseResult = apiKeyParser.Parse(_apiKey); + + if (parseResult == ApiKeyParseResult.Success) + { + _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _apiKey); + _injectionRequestFactory = new InjectionRequestFactory(_serverId, null); + } + else + { + _injectionRequestFactory = new InjectionRequestFactory(_serverId, _apiKey); + } } - + /// /// Creates a new instance of the SocketLabsClient with a proxy. /// /// Your SocketLabs ServerId number. /// Your SocketLabs Injection API key. /// The WebProxy you would like to use. - public SocketLabsClient(int serverId, string apiKey, IWebProxy optionalProxy) + public SocketLabsClient(int serverId, string apiKey, IWebProxy optionalProxy) { _serverId = serverId; _apiKey = apiKey; _httpClient = BuildHttpClient(optionalProxy); + var apiKeyParser = new ApiKeyParser(); + var parseResult = apiKeyParser.Parse(_apiKey); + + if (parseResult == ApiKeyParseResult.Success) + { + _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _apiKey); + _injectionRequestFactory = new InjectionRequestFactory(_serverId, null); + } + else + { + _injectionRequestFactory = new InjectionRequestFactory(_serverId, _apiKey); + } } /// @@ -89,9 +114,22 @@ public SocketLabsClient(int serverId, string apiKey, HttpClient httpClient) _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); ConfigureHttpClient(httpClient); + + var apiKeyParser = new ApiKeyParser(); + var parseResult = apiKeyParser.Parse(_apiKey); + + if (parseResult == ApiKeyParseResult.Success) + { + _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _apiKey); + _injectionRequestFactory = new InjectionRequestFactory(_serverId, null); + } + else + { + _injectionRequestFactory = new InjectionRequestFactory(_serverId, _apiKey); + } } - private HttpClient BuildHttpClient(IWebProxy optionalProxy) + private HttpClient BuildHttpClient(IWebProxy? optionalProxy) { var httpClient = optionalProxy != null ? new HttpClient(new HttpClientHandler() { UseProxy = true, Proxy = optionalProxy}) : new HttpClient(); ConfigureHttpClient(httpClient); @@ -134,8 +172,8 @@ public static SendResponse QuickSend( string toAddress, string fromAddress, string subject, - string htmlContent, - string textContent) + string? htmlContent, + string? textContent) { var client = new SocketLabsClient(serverId, apiKey); @@ -230,18 +268,7 @@ public async Task SendAsync(IBasicMessage message, CancellationTok validationResult = validator.ValidateMessage(message); if (validationResult.Result != SendResult.Success) return validationResult; - var apiKeyParser = new ApiKeyParser(); - var parseResult = apiKeyParser.Parse(_apiKey); - - if (parseResult == ApiKeyParseResult.Success) - { - _httpClient.DefaultRequestHeaders.Authorization = - new AuthenticationHeaderValue("Bearer", _apiKey); - _apiKey = string.Empty; - } - - var factory = new InjectionRequestFactory(_serverId, _apiKey); - var injectionRequest = factory.GenerateRequest(message); + var injectionRequest = _injectionRequestFactory.GenerateRequest(message); var json = injectionRequest.GetAsJson(); var retryHandler = new RetryHandler(_httpClient, EndpointUrl, new RetrySettings(NumberOfRetries)); @@ -296,15 +323,7 @@ public async Task SendAsync(IBulkMessage message, CancellationToke var apiKeyParser = new ApiKeyParser(); var parseResult = apiKeyParser.Parse(_apiKey); - if (parseResult == ApiKeyParseResult.Success) - { - _httpClient.DefaultRequestHeaders.Authorization = - new AuthenticationHeaderValue("Bearer", _apiKey); - _apiKey = string.Empty; - } - - var factory = new InjectionRequestFactory(_serverId, _apiKey); - var injectionRequest = factory.GenerateRequest(message); + var injectionRequest = _injectionRequestFactory.GenerateRequest(message); var json = injectionRequest.GetAsJson(); var retryHandler = new RetryHandler(_httpClient, EndpointUrl, new RetrySettings(NumberOfRetries)); @@ -419,7 +438,5 @@ public void Dispose() { _httpClient?.Dispose(); } - - } } \ No newline at end of file diff --git a/src/SocketLabs/InjectionApi/SocketLabsExtensions.cs b/src/SocketLabs/InjectionApi/SocketLabsExtensions.cs index ecb93a0..9760c14 100644 --- a/src/SocketLabs/InjectionApi/SocketLabsExtensions.cs +++ b/src/SocketLabs/InjectionApi/SocketLabsExtensions.cs @@ -103,7 +103,7 @@ public static IBulkRecipient AddMergeFields(this IBulkRecipient recipient, strin /// emailList.Add("recipient@example.com", "Recipient", mergeData); /// /// - public static IBulkRecipient Add(this IList source, string emailAddress, string friendlyName, IDictionary mergeData) + public static IBulkRecipient Add(this IList source, string emailAddress, string? friendlyName, IDictionary mergeData) { var recipient = new BulkRecipient(emailAddress, friendlyName, mergeData); source.Add(recipient); @@ -147,9 +147,9 @@ public static IBulkRecipient Add(this IList source, string email /// emailList.Add("recipient@example.com", "Recipient"); /// /// - public static IBulkRecipient Add(this IList source, string emailAddress, string friendlyName) + public static IBulkRecipient Add(this IList source, string emailAddress, string? friendlyName) { - return Add(source, emailAddress, friendlyName, null); + return Add(source, emailAddress, friendlyName, new Dictionary()); } /// @@ -166,7 +166,7 @@ public static IBulkRecipient Add(this IList source, string email /// public static IBulkRecipient Add(this IList source, string emailAddress) { - return Add(source, emailAddress, (string)null); + return Add(source, emailAddress, (string?)null); } #endregion @@ -186,7 +186,7 @@ public static IBulkRecipient Add(this IList source, string email /// emailList.Add("recipient@example.com", "Recipient"); /// /// - public static IEmailAddress Add(this IList source, string emailAddress, string friendlyName) + public static IEmailAddress Add(this IList source, string emailAddress, string? friendlyName) { var recipient = new EmailAddress(emailAddress, friendlyName); source.Add(recipient); diff --git a/src/SocketLabs/SocketLabs.csproj b/src/SocketLabs/SocketLabs.csproj index ba9efda..02de6e1 100644 --- a/src/SocketLabs/SocketLabs.csproj +++ b/src/SocketLabs/SocketLabs.csproj @@ -1,19 +1,19 @@  - netstandard2.0;net48;net5.0;net6.0 + netstandard2.0;net48;net8.0;net9.0 anycpu true SocketLabs SocketLabs.EmailDelivery false false - 1.4.3 - Copyright © 2018-2023 SocketLabs Acquisition LLC - Joe Cooper, David Schrenker, Matt Reibach, Ryan Lydzinski, Mike Goodfellow, Saranya Kavuri, Mike Boshuyzen + 2.0.0 + Copyright © 2018-2025 SocketLabs Acquisition LLC + Matt Soler, David Schrenker, Mike Boshuyzen, Joe Cooper, Matt Reibach, Ryan Lydzinski, Mike Goodfellow, Saranya Kavuri SocketLabs .Net Client Library - 1.4.3 - 1.4.3 + 2.0.0 + 2.0.0 Easily send email messages using the SocketLabs Injection API. https://github.com/socketlabs/socketlabs-csharp https://inject.docs.socketlabs.com/ @@ -21,6 +21,8 @@ README.md LICENSE.md email;injection;api;library;client; + Enable + 9 @@ -39,7 +41,10 @@ - + + + + diff --git a/test/SocketLabs.Tests/InjectionApi/SocketLabsClientTests.cs b/test/SocketLabs.Tests/InjectionApi/SocketLabsClientTests.cs new file mode 100644 index 0000000..800d785 --- /dev/null +++ b/test/SocketLabs.Tests/InjectionApi/SocketLabsClientTests.cs @@ -0,0 +1,38 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SocketLabs.InjectionApi; +using SocketLabs.InjectionApi.Message; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace SocketLabs.InjectionApi.Tests +{ + [TestClass()] + public class SocketLabsClientTests + { + [TestMethod()] + public async Task SendAsyncTest() + { + int serverId = 999; + string bearerApiKey = "abcdefjhijklmnopqrst.uvwxyzabcdefghijklmnopqrstuvwxyz12345678"; + + var client = new SocketLabsClient(serverId, bearerApiKey); + client.EndpointUrl = "https://example.local"; + client.NumberOfRetries = 1; + + var message = new BasicMessage(); + message.To.Add("test@example.local"); + message.From = new EmailAddress("test@example.local"); + message.Subject = "Test"; + message.HtmlBody = "

This is a test!

"; + + await Assert.ThrowsExceptionAsync(async () => await client.SendAsync(message, CancellationToken.None)); + + // The client should throw the same exception on subsequent calls. + await Assert.ThrowsExceptionAsync(async () => await client.SendAsync(message, CancellationToken.None)); + } + } +} \ No newline at end of file diff --git a/test/SocketLabs.Tests/SocketLabs.Tests.csproj b/test/SocketLabs.Tests/SocketLabs.Tests.csproj index 3c80746..f87c001 100644 --- a/test/SocketLabs.Tests/SocketLabs.Tests.csproj +++ b/test/SocketLabs.Tests/SocketLabs.Tests.csproj @@ -2,23 +2,22 @@ SocketLabs.Tests SocketLabs.Tests - net6.0 + net9.0 SocketLabs.Tests false SocketLabs.Tests - Copyright © 2018-2023 SocketLabs Acquisition LLC + Copyright © 2018-2025 SocketLabs Acquisition LLC - - - - - - - - - - + + + + + + + + + all runtime; build; native; contentfiles; analyzers @@ -26,4 +25,7 @@ + + +
\ No newline at end of file