diff --git a/sparkpost-net-core-compact.png b/sparkpost-net-core-compact.png
new file mode 100644
index 0000000..5c0f969
Binary files /dev/null and b/sparkpost-net-core-compact.png differ
diff --git a/sparkpost-net-core.png b/sparkpost-net-core.png
new file mode 100644
index 0000000..5c0f969
Binary files /dev/null and b/sparkpost-net-core.png differ
diff --git a/src/SparkPost.Acceptance/SparkPost.Acceptance.csproj b/src/SparkPost.Acceptance/SparkPost.Acceptance.csproj
index b1c6d6b..d16c5e2 100644
--- a/src/SparkPost.Acceptance/SparkPost.Acceptance.csproj
+++ b/src/SparkPost.Acceptance/SparkPost.Acceptance.csproj
@@ -1,20 +1,28 @@
+
- net6.0
- SparkPost.Acceptance
- Library
+ netcoreapp2.1
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
-
-
-
-
-
+
-
- Always
-
+
-
\ No newline at end of file
+
+
diff --git a/src/SparkPost.Acceptance/TransmissionsSteps.cs b/src/SparkPost.Acceptance/TransmissionsSteps.cs
new file mode 100644
index 0000000..7553e3c
--- /dev/null
+++ b/src/SparkPost.Acceptance/TransmissionsSteps.cs
@@ -0,0 +1,63 @@
+using System;
+using TechTalk.SpecFlow;
+
+namespace SparkPost.Acceptance
+{
+ [Binding]
+ public class TransmissionsSteps
+ {
+ [Given(@"I have a new transmission")]
+ public void GivenIHaveANewTransmission()
+ {
+ ScenarioContext.Current.Pending();
+ }
+
+ [Given(@"the transmission is meant to be sent from '(.*)'")]
+ public void GivenTheTransmissionIsMeantToBeSentFrom(string p0)
+ {
+ ScenarioContext.Current.Pending();
+ }
+
+ [Given(@"the transmission is meant to be sent to '(.*)'")]
+ public void GivenTheTransmissionIsMeantToBeSentTo(string p0)
+ {
+ ScenarioContext.Current.Pending();
+ }
+
+ [Given(@"the transmission content is")]
+ public void GivenTheTransmissionContentIs(Table table)
+ {
+ ScenarioContext.Current.Pending();
+ }
+
+ [Given(@"the transmission has a text file attachment")]
+ public void GivenTheTransmissionHasATextFileAttachment()
+ {
+ ScenarioContext.Current.Pending();
+ }
+
+ [Given(@"the transmission template id is set to '(.*)'")]
+ public void GivenTheTransmissionTemplateIdIsSetTo(string p0)
+ {
+ ScenarioContext.Current.Pending();
+ }
+
+ [Given(@"the transmission is meant to be CCd to '(.*)'")]
+ public void GivenTheTransmissionIsMeantToBeCCdTo(string p0)
+ {
+ ScenarioContext.Current.Pending();
+ }
+
+ [Given(@"the transmission is meant to be BCCd to '(.*)'")]
+ public void GivenTheTransmissionIsMeantToBeBCCdTo(string p0)
+ {
+ ScenarioContext.Current.Pending();
+ }
+
+ [When(@"I send the transmission")]
+ public void WhenISendTheTransmission()
+ {
+ ScenarioContext.Current.Pending();
+ }
+ }
+}
diff --git a/src/SparkPost.Tests/SparkPost.Tests.csproj b/src/SparkPost.Tests/SparkPost.Tests.csproj
index 1ebd7b3..95dea2a 100644
--- a/src/SparkPost.Tests/SparkPost.Tests.csproj
+++ b/src/SparkPost.Tests/SparkPost.Tests.csproj
@@ -1,19 +1,32 @@
+
- net6.0
- SparkPost.Tests
+ netcoreapp2.1
+
Library
+
+
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
-
\ No newline at end of file
+
+
diff --git a/src/SparkPost.Tests/SuppressionTests.cs b/src/SparkPost.Tests/SuppressionTests.cs
index a77ed0b..e7f141c 100644
--- a/src/SparkPost.Tests/SuppressionTests.cs
+++ b/src/SparkPost.Tests/SuppressionTests.cs
@@ -35,14 +35,14 @@ public DeleteTests()
email = Guid.NewGuid().ToString();
}
- [Fact]
+ [Test]
public async Task It_should_return_true_if_the_web_request_returns_no_content()
{
var result = await suppressions.Delete(email);
Assert.True(result);
}
- [Fact]
+ [Test]
public async Task It_should_return_false_if_the_web_request_returns_anything_but_no_content()
{
response.StatusCode = HttpStatusCode.Accepted;
@@ -58,7 +58,7 @@ public async Task It_should_return_false_if_the_web_request_returns_anything_but
Assert.False(deleted);
}
- [Fact]
+ [Test]
public async Task It_should_build_the_web_request_parameters_correctly()
{
var version = Guid.NewGuid().ToString();
@@ -79,7 +79,7 @@ public async Task It_should_build_the_web_request_parameters_correctly()
await suppressions.Delete(email);
}
- [Fact]
+ [Test]
public async Task It_should_encode_the_email_address()
{
var version = Guid.NewGuid().ToString();
@@ -127,14 +127,14 @@ public CreateOrUpdateTests()
suppressions = new Suppressions(client.Object, requestSender.Object, dataMapper.Object);
}
- [Fact]
+ [Test]
public async Task It_should_return_a_response_when_the_web_request_is_ok()
{
var result = await suppressions.CreateOrUpdate(suppressionsList);
Assert.NotNull(result);
}
- [Fact]
+ [Test]
public async Task It_should_return_the_reason_phrase()
{
response.ReasonPhrase = Guid.NewGuid().ToString();
@@ -142,7 +142,7 @@ public async Task It_should_return_the_reason_phrase()
Assert.Equal(response.ReasonPhrase, result.ReasonPhrase);
}
- [Fact]
+ [Test]
public async Task It_should_return_the_content()
{
response.Content = Guid.NewGuid().ToString();
@@ -150,7 +150,7 @@ public async Task It_should_return_the_content()
Assert.Equal(response.Content, result.Content);
}
- [Fact]
+ [Test]
public async Task It_should_make_a_properly_formed_request()
{
client.Setup(x => x.Version).Returns(Guid.NewGuid().ToString());
@@ -168,7 +168,7 @@ public async Task It_should_make_a_properly_formed_request()
await suppressions.CreateOrUpdate(suppressionsList);
}
- [Fact]
+ [Test]
public async Task It_should_throw_if_the_http_status_code_is_not_ok()
{
response.StatusCode = HttpStatusCode.Accepted;
diff --git a/src/SparkPost/File.cs b/src/SparkPost/File.cs
index 120cc14..4bba4cd 100644
--- a/src/SparkPost/File.cs
+++ b/src/SparkPost/File.cs
@@ -1,6 +1,6 @@
using System;
using System.IO;
-using System.Web;
+using SparkPost.Utilities;
namespace SparkPost
{
@@ -25,7 +25,7 @@ public abstract class File
public static T Create(byte[] content) where T : File, new()
{
- return Create(content, String.Empty);
+ return Create(content, string.Empty);
}
public static T Create(byte[] content, string name) where T : File, new()
@@ -34,7 +34,7 @@ public abstract class File
if (content != null)
{
result.Data = Convert.ToBase64String(content);
- result.Type = MimeMapping.MimeUtility.GetMimeMapping(name);
+ result.Type = MimeMapping.GetContentType(name);
result.Name = name;
}
;
@@ -43,7 +43,7 @@ public abstract class File
public static T Create(Stream content) where T : File, new()
{
- return Create(content, String.Empty);
+ return Create(content, string.Empty);
}
public static T Create(Stream content, string name) where T : File, new()
diff --git a/src/SparkPost/ITemplates.cs b/src/SparkPost/ITemplates.cs
index c3cf830..a5d5a85 100644
--- a/src/SparkPost/ITemplates.cs
+++ b/src/SparkPost/ITemplates.cs
@@ -1,4 +1,5 @@
-using System.Threading.Tasks;
+using System.Collections.Generic;
+using System.Threading.Tasks;
namespace SparkPost
{
@@ -25,5 +26,7 @@ public interface ITemplates
Task List();
Task Delete(string templateId);
+
+ Task Preview(string templateId, IDictionary substitutionData, bool? draft = null);
}
}
diff --git a/src/SparkPost/RequestMethods/Get.cs b/src/SparkPost/RequestMethods/Get.cs
index f6eec35..60a3c3c 100644
--- a/src/SparkPost/RequestMethods/Get.cs
+++ b/src/SparkPost/RequestMethods/Get.cs
@@ -1,6 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
+using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
diff --git a/src/SparkPost/SendingDomains.cs b/src/SparkPost/SendingDomains.cs
index f08a598..6a56688 100644
--- a/src/SparkPost/SendingDomains.cs
+++ b/src/SparkPost/SendingDomains.cs
@@ -1,7 +1,5 @@
using System.Net;
using System.Threading.Tasks;
-using System.Web;
-using Microsoft.AspNetCore.WebUtilities;
using SparkPost.RequestSenders;
using SparkPost.Utilities;
@@ -109,7 +107,7 @@ public async Task Delete(string domain)
if (response.StatusCode == HttpStatusCode.NoContent)
{
response.StatusCode = HttpStatusCode.OK;
- response.ReasonPhrase = ReasonPhrases.GetReasonPhrase((int)HttpStatusCode.OK);
+ response.ReasonPhrase = nameof(HttpStatusCode.OK);
}
if (response.StatusCode != HttpStatusCode.OK)
diff --git a/src/SparkPost/SparkPost.csproj b/src/SparkPost/SparkPost.csproj
index fa8500a..220f44c 100644
--- a/src/SparkPost/SparkPost.csproj
+++ b/src/SparkPost/SparkPost.csproj
@@ -1,33 +1,36 @@
-
+
+
- SparkPost
- SparkPost
- SparkPost
- SparkPost API
- Copyright 2022
- 2.0.2
- 2.0.2
- 2.0.2
- Darren Cauthon; Adam Hathcock
- https://www.sparkpost.com/sites/default/files/attachments/SparkPost_Logo_2-Color_Gray-Orange_RGB.svg
- SparkPost
- https://github.com/darrencauthon/csharp-sparkpost/blob/master/LICENSE.md
- https://github.com/SparkPost/csharp-sparkpost
- LICENSE.md
- Added support to pass a user-agent.
- email
netstandard2.0
- 10
+
+ Library
+
+ 1.14.0.5
+ true
+ SparkPost.NetCore
+ Lean Sparkpost API client port to .net standard 2.0
+ Apache-2.0
+ https://github.com/maxlego/csharp-sparkpost
+ https://github.com/maxlego/csharp-sparkpost
+ sparkpost-net-core.png
+
+ Added template preview functionality
+
-
-
-
-
+
+
+
-
- LICENSE.md
+
+
+
+
+
+ True
+
+
diff --git a/src/SparkPost/Templates.cs b/src/SparkPost/Templates.cs
index 735d574..2e2d4bf 100644
--- a/src/SparkPost/Templates.cs
+++ b/src/SparkPost/Templates.cs
@@ -4,6 +4,7 @@
using System.Reflection;
using Newtonsoft.Json;
using SparkPost.RequestSenders;
+using SparkPost.Utilities;
namespace SparkPost
{
@@ -136,5 +137,54 @@ public async Task Delete(string templateId)
var response = await requestSender.Send(request);
return response.StatusCode == HttpStatusCode.OK;
}
+
+ public async Task Preview(string templateId, IDictionary substitutionData, bool? draft = null)
+ {
+ var transmission = new Transmission
+ {
+ SubstitutionData = substitutionData
+ };
+
+ var url = $"api/{client.Version}/templates/{templateId}/preview";
+ if (draft.HasValue)
+ {
+ url += $"?draft={draft.ToString().ToLower()}";
+ }
+
+ var request = new Request
+ {
+ Url = url,
+ Method = "POST",
+ Data = dataMapper.ToDictionary(transmission)
+ };
+
+ var response = await requestSender.Send(request);
+ if (response.StatusCode != HttpStatusCode.OK) throw new ResponseException(response);
+
+ var results = Jsonification.DeserializeObject(response.Content).results;
+
+ Dictionary Headers = new Dictionary();
+ if (results.headers != null)
+ {
+ foreach (var property in results.headers.GetType().GetProperties())
+ {
+ Headers[property.Name] = (string)property.GetValue(results.headers);
+ }
+ }
+
+ return new TemplateContent
+ {
+ From = new Address
+ {
+ Email = results.from.email,
+ Name = results.from.name
+ },
+ Subject = results.subject,
+ ReplyTo = results.reply_to ?? null,
+ Text = results.text ?? null,
+ Html = results.html ?? null,
+ Headers = Headers
+ };
+ }
}
}
diff --git a/src/SparkPost/Utilities/FileExtensionContentTypeProvider.cs b/src/SparkPost/Utilities/FileExtensionContentTypeProvider.cs
new file mode 100644
index 0000000..c78d989
--- /dev/null
+++ b/src/SparkPost/Utilities/FileExtensionContentTypeProvider.cs
@@ -0,0 +1,422 @@
+using System;
+using System.Collections.Generic;
+
+namespace SparkPost.Utilities
+{
+ ///
+ /// Provides a mapping between file extensions and MIME types.
+ ///
+ internal static class MimeMapping
+ {
+ private const string DEFAULT_CONTENT_TYPE = "application/octet-stream";
+
+ private static readonly IDictionary _map =
+ new Dictionary(StringComparer.OrdinalIgnoreCase)
+ {
+ {".323", "text/h323"},
+ {".3g2", "video/3gpp2"},
+ {".3gp2", "video/3gpp2"},
+ {".3gp", "video/3gpp"},
+ {".3gpp", "video/3gpp"},
+ {".aac", "audio/aac"},
+ {".aaf", "application/octet-stream"},
+ {".aca", "application/octet-stream"},
+ {".accdb", "application/msaccess"},
+ {".accde", "application/msaccess"},
+ {".accdt", "application/msaccess"},
+ {".acx", "application/internet-property-stream"},
+ {".adt", "audio/vnd.dlna.adts"},
+ {".adts", "audio/vnd.dlna.adts"},
+ {".afm", "application/octet-stream"},
+ {".ai", "application/postscript"},
+ {".aif", "audio/x-aiff"},
+ {".aifc", "audio/aiff"},
+ {".aiff", "audio/aiff"},
+ {".appcache", "text/cache-manifest"},
+ {".application", "application/x-ms-application"},
+ {".art", "image/x-jg"},
+ {".asd", "application/octet-stream"},
+ {".asf", "video/x-ms-asf"},
+ {".asi", "application/octet-stream"},
+ {".asm", "text/plain"},
+ {".asr", "video/x-ms-asf"},
+ {".asx", "video/x-ms-asf"},
+ {".atom", "application/atom+xml"},
+ {".au", "audio/basic"},
+ {".avi", "video/x-msvideo"},
+ {".axs", "application/olescript"},
+ {".bas", "text/plain"},
+ {".bcpio", "application/x-bcpio"},
+ {".bin", "application/octet-stream"},
+ {".bmp", "image/bmp"},
+ {".c", "text/plain"},
+ {".cab", "application/vnd.ms-cab-compressed"},
+ {".calx", "application/vnd.ms-office.calx"},
+ {".cat", "application/vnd.ms-pki.seccat"},
+ {".cdf", "application/x-cdf"},
+ {".chm", "application/octet-stream"},
+ {".class", "application/x-java-applet"},
+ {".clp", "application/x-msclip"},
+ {".cmx", "image/x-cmx"},
+ {".cnf", "text/plain"},
+ {".cod", "image/cis-cod"},
+ {".cpio", "application/x-cpio"},
+ {".cpp", "text/plain"},
+ {".crd", "application/x-mscardfile"},
+ {".crl", "application/pkix-crl"},
+ {".crt", "application/x-x509-ca-cert"},
+ {".csh", "application/x-csh"},
+ {".css", "text/css"},
+ {".csv", "application/octet-stream"},
+ {".cur", "application/octet-stream"},
+ {".dcr", "application/x-director"},
+ {".deploy", "application/octet-stream"},
+ {".der", "application/x-x509-ca-cert"},
+ {".dib", "image/bmp"},
+ {".dir", "application/x-director"},
+ {".disco", "text/xml"},
+ {".dlm", "text/dlm"},
+ {".doc", "application/msword"},
+ {".docm", "application/vnd.ms-word.document.macroEnabled.12"},
+ {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
+ {".dot", "application/msword"},
+ {".dotm", "application/vnd.ms-word.template.macroEnabled.12"},
+ {".dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template"},
+ {".dsp", "application/octet-stream"},
+ {".dtd", "text/xml"},
+ {".dvi", "application/x-dvi"},
+ {".dvr-ms", "video/x-ms-dvr"},
+ {".dwf", "drawing/x-dwf"},
+ {".dwp", "application/octet-stream"},
+ {".dxr", "application/x-director"},
+ {".eml", "message/rfc822"},
+ {".emz", "application/octet-stream"},
+ {".eot", "application/vnd.ms-fontobject"},
+ {".eps", "application/postscript"},
+ {".etx", "text/x-setext"},
+ {".evy", "application/envoy"},
+ {".fdf", "application/vnd.fdf"},
+ {".fif", "application/fractals"},
+ {".fla", "application/octet-stream"},
+ {".flr", "x-world/x-vrml"},
+ {".flv", "video/x-flv"},
+ {".gif", "image/gif"},
+ {".gtar", "application/x-gtar"},
+ {".gz", "application/x-gzip"},
+ {".h", "text/plain"},
+ {".hdf", "application/x-hdf"},
+ {".hdml", "text/x-hdml"},
+ {".hhc", "application/x-oleobject"},
+ {".hhk", "application/octet-stream"},
+ {".hhp", "application/octet-stream"},
+ {".hlp", "application/winhlp"},
+ {".hqx", "application/mac-binhex40"},
+ {".hta", "application/hta"},
+ {".htc", "text/x-component"},
+ {".htm", "text/html"},
+ {".html", "text/html"},
+ {".htt", "text/webviewhtml"},
+ {".hxt", "text/html"},
+ {".ical", "text/calendar"},
+ {".icalendar", "text/calendar"},
+ {".ico", "image/x-icon"},
+ {".ics", "text/calendar"},
+ {".ief", "image/ief"},
+ {".ifb", "text/calendar"},
+ {".iii", "application/x-iphone"},
+ {".inf", "application/octet-stream"},
+ {".ins", "application/x-internet-signup"},
+ {".isp", "application/x-internet-signup"},
+ {".IVF", "video/x-ivf"},
+ {".jar", "application/java-archive"},
+ {".java", "application/octet-stream"},
+ {".jck", "application/liquidmotion"},
+ {".jcz", "application/liquidmotion"},
+ {".jfif", "image/pjpeg"},
+ {".jpb", "application/octet-stream"},
+ {".jpe", "image/jpeg"},
+ {".jpeg", "image/jpeg"},
+ {".jpg", "image/jpeg"},
+ {".js", "application/javascript"},
+ {".json", "application/json"},
+ {".jsx", "text/jscript"},
+ {".latex", "application/x-latex"},
+ {".lit", "application/x-ms-reader"},
+ {".lpk", "application/octet-stream"},
+ {".lsf", "video/x-la-asf"},
+ {".lsx", "video/x-la-asf"},
+ {".lzh", "application/octet-stream"},
+ {".m13", "application/x-msmediaview"},
+ {".m14", "application/x-msmediaview"},
+ {".m1v", "video/mpeg"},
+ {".m2ts", "video/vnd.dlna.mpeg-tts"},
+ {".m3u", "audio/x-mpegurl"},
+ {".m4a", "audio/mp4"},
+ {".m4v", "video/mp4"},
+ {".man", "application/x-troff-man"},
+ {".manifest", "application/x-ms-manifest"},
+ {".map", "text/plain"},
+ {".markdown", "text/markdown"},
+ {".md", "text/markdown"},
+ {".mdb", "application/x-msaccess"},
+ {".mdp", "application/octet-stream"},
+ {".me", "application/x-troff-me"},
+ {".mht", "message/rfc822"},
+ {".mhtml", "message/rfc822"},
+ {".mid", "audio/mid"},
+ {".midi", "audio/mid"},
+ {".mix", "application/octet-stream"},
+ {".mmf", "application/x-smaf"},
+ {".mno", "text/xml"},
+ {".mny", "application/x-msmoney"},
+ {".mov", "video/quicktime"},
+ {".movie", "video/x-sgi-movie"},
+ {".mp2", "video/mpeg"},
+ {".mp3", "audio/mpeg"},
+ {".mp4", "video/mp4"},
+ {".mp4v", "video/mp4"},
+ {".mpa", "video/mpeg"},
+ {".mpe", "video/mpeg"},
+ {".mpeg", "video/mpeg"},
+ {".mpg", "video/mpeg"},
+ {".mpp", "application/vnd.ms-project"},
+ {".mpv2", "video/mpeg"},
+ {".ms", "application/x-troff-ms"},
+ {".msi", "application/octet-stream"},
+ {".mso", "application/octet-stream"},
+ {".mvb", "application/x-msmediaview"},
+ {".mvc", "application/x-miva-compiled"},
+ {".nc", "application/x-netcdf"},
+ {".nsc", "video/x-ms-asf"},
+ {".nws", "message/rfc822"},
+ {".ocx", "application/octet-stream"},
+ {".oda", "application/oda"},
+ {".odc", "text/x-ms-odc"},
+ {".ods", "application/oleobject"},
+ {".oga", "audio/ogg"},
+ {".ogg", "video/ogg"},
+ {".ogv", "video/ogg"},
+ {".ogx", "application/ogg"},
+ {".one", "application/onenote"},
+ {".onea", "application/onenote"},
+ {".onetoc", "application/onenote"},
+ {".onetoc2", "application/onenote"},
+ {".onetmp", "application/onenote"},
+ {".onepkg", "application/onenote"},
+ {".osdx", "application/opensearchdescription+xml"},
+ {".otf", "font/otf"},
+ {".p10", "application/pkcs10"},
+ {".p12", "application/x-pkcs12"},
+ {".p7b", "application/x-pkcs7-certificates"},
+ {".p7c", "application/pkcs7-mime"},
+ {".p7m", "application/pkcs7-mime"},
+ {".p7r", "application/x-pkcs7-certreqresp"},
+ {".p7s", "application/pkcs7-signature"},
+ {".pbm", "image/x-portable-bitmap"},
+ {".pcx", "application/octet-stream"},
+ {".pcz", "application/octet-stream"},
+ {".pdf", "application/pdf"},
+ {".pfb", "application/octet-stream"},
+ {".pfm", "application/octet-stream"},
+ {".pfx", "application/x-pkcs12"},
+ {".pgm", "image/x-portable-graymap"},
+ {".pko", "application/vnd.ms-pki.pko"},
+ {".pma", "application/x-perfmon"},
+ {".pmc", "application/x-perfmon"},
+ {".pml", "application/x-perfmon"},
+ {".pmr", "application/x-perfmon"},
+ {".pmw", "application/x-perfmon"},
+ {".png", "image/png"},
+ {".pnm", "image/x-portable-anymap"},
+ {".pnz", "image/png"},
+ {".pot", "application/vnd.ms-powerpoint"},
+ {".potm", "application/vnd.ms-powerpoint.template.macroEnabled.12"},
+ {".potx", "application/vnd.openxmlformats-officedocument.presentationml.template"},
+ {".ppam", "application/vnd.ms-powerpoint.addin.macroEnabled.12"},
+ {".ppm", "image/x-portable-pixmap"},
+ {".pps", "application/vnd.ms-powerpoint"},
+ {".ppsm", "application/vnd.ms-powerpoint.slideshow.macroEnabled.12"},
+ {".ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow"},
+ {".ppt", "application/vnd.ms-powerpoint"},
+ {".pptm", "application/vnd.ms-powerpoint.presentation.macroEnabled.12"},
+ {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
+ {".prf", "application/pics-rules"},
+ {".prm", "application/octet-stream"},
+ {".prx", "application/octet-stream"},
+ {".ps", "application/postscript"},
+ {".psd", "application/octet-stream"},
+ {".psm", "application/octet-stream"},
+ {".psp", "application/octet-stream"},
+ {".pub", "application/x-mspublisher"},
+ {".qt", "video/quicktime"},
+ {".qtl", "application/x-quicktimeplayer"},
+ {".qxd", "application/octet-stream"},
+ {".ra", "audio/x-pn-realaudio"},
+ {".ram", "audio/x-pn-realaudio"},
+ {".rar", "application/octet-stream"},
+ {".ras", "image/x-cmu-raster"},
+ {".rf", "image/vnd.rn-realflash"},
+ {".rgb", "image/x-rgb"},
+ {".rm", "application/vnd.rn-realmedia"},
+ {".rmi", "audio/mid"},
+ {".roff", "application/x-troff"},
+ {".rpm", "audio/x-pn-realaudio-plugin"},
+ {".rtf", "application/rtf"},
+ {".rtx", "text/richtext"},
+ {".scd", "application/x-msschedule"},
+ {".sct", "text/scriptlet"},
+ {".sea", "application/octet-stream"},
+ {".setpay", "application/set-payment-initiation"},
+ {".setreg", "application/set-registration-initiation"},
+ {".sgml", "text/sgml"},
+ {".sh", "application/x-sh"},
+ {".shar", "application/x-shar"},
+ {".sit", "application/x-stuffit"},
+ {".sldm", "application/vnd.ms-powerpoint.slide.macroEnabled.12"},
+ {".sldx", "application/vnd.openxmlformats-officedocument.presentationml.slide"},
+ {".smd", "audio/x-smd"},
+ {".smi", "application/octet-stream"},
+ {".smx", "audio/x-smd"},
+ {".smz", "audio/x-smd"},
+ {".snd", "audio/basic"},
+ {".snp", "application/octet-stream"},
+ {".spc", "application/x-pkcs7-certificates"},
+ {".spl", "application/futuresplash"},
+ {".spx", "audio/ogg"},
+ {".src", "application/x-wais-source"},
+ {".ssm", "application/streamingmedia"},
+ {".sst", "application/vnd.ms-pki.certstore"},
+ {".stl", "application/vnd.ms-pki.stl"},
+ {".sv4cpio", "application/x-sv4cpio"},
+ {".sv4crc", "application/x-sv4crc"},
+ {".svg", "image/svg+xml"},
+ {".svgz", "image/svg+xml"},
+ {".swf", "application/x-shockwave-flash"},
+ {".t", "application/x-troff"},
+ {".tar", "application/x-tar"},
+ {".tcl", "application/x-tcl"},
+ {".tex", "application/x-tex"},
+ {".texi", "application/x-texinfo"},
+ {".texinfo", "application/x-texinfo"},
+ {".tgz", "application/x-compressed"},
+ {".thmx", "application/vnd.ms-officetheme"},
+ {".thn", "application/octet-stream"},
+ {".tif", "image/tiff"},
+ {".tiff", "image/tiff"},
+ {".toc", "application/octet-stream"},
+ {".tr", "application/x-troff"},
+ {".trm", "application/x-msterminal"},
+ {".ts", "video/vnd.dlna.mpeg-tts"},
+ {".tsv", "text/tab-separated-values"},
+ {".ttc", "application/x-font-ttf"},
+ {".ttf", "application/x-font-ttf"},
+ {".tts", "video/vnd.dlna.mpeg-tts"},
+ {".txt", "text/plain"},
+ {".u32", "application/octet-stream"},
+ {".uls", "text/iuls"},
+ {".ustar", "application/x-ustar"},
+ {".vbs", "text/vbscript"},
+ {".vcf", "text/x-vcard"},
+ {".vcs", "text/plain"},
+ {".vdx", "application/vnd.ms-visio.viewer"},
+ {".vml", "text/xml"},
+ {".vsd", "application/vnd.visio"},
+ {".vss", "application/vnd.visio"},
+ {".vst", "application/vnd.visio"},
+ {".vsto", "application/x-ms-vsto"},
+ {".vsw", "application/vnd.visio"},
+ {".vsx", "application/vnd.visio"},
+ {".vtx", "application/vnd.visio"},
+ {".wasm", "application/wasm"},
+ {".wav", "audio/wav"},
+ {".wax", "audio/x-ms-wax"},
+ {".wbmp", "image/vnd.wap.wbmp"},
+ {".wcm", "application/vnd.ms-works"},
+ {".wdb", "application/vnd.ms-works"},
+ {".webm", "video/webm"},
+ {".webp", "image/webp"},
+ {".wks", "application/vnd.ms-works"},
+ {".wm", "video/x-ms-wm"},
+ {".wma", "audio/x-ms-wma"},
+ {".wmd", "application/x-ms-wmd"},
+ {".wmf", "application/x-msmetafile"},
+ {".wml", "text/vnd.wap.wml"},
+ {".wmlc", "application/vnd.wap.wmlc"},
+ {".wmls", "text/vnd.wap.wmlscript"},
+ {".wmlsc", "application/vnd.wap.wmlscriptc"},
+ {".wmp", "video/x-ms-wmp"},
+ {".wmv", "video/x-ms-wmv"},
+ {".wmx", "video/x-ms-wmx"},
+ {".wmz", "application/x-ms-wmz"},
+ {".woff", "application/font-woff"}, // https://www.w3.org/TR/WOFF/#appendix-b
+ {".woff2", "font/woff2"}, // https://www.w3.org/TR/WOFF2/#IMT
+ {".wps", "application/vnd.ms-works"},
+ {".wri", "application/x-mswrite"},
+ {".wrl", "x-world/x-vrml"},
+ {".wrz", "x-world/x-vrml"},
+ {".wsdl", "text/xml"},
+ {".wtv", "video/x-ms-wtv"},
+ {".wvx", "video/x-ms-wvx"},
+ {".x", "application/directx"},
+ {".xaf", "x-world/x-vrml"},
+ {".xaml", "application/xaml+xml"},
+ {".xap", "application/x-silverlight-app"},
+ {".xbap", "application/x-ms-xbap"},
+ {".xbm", "image/x-xbitmap"},
+ {".xdr", "text/plain"},
+ {".xht", "application/xhtml+xml"},
+ {".xhtml", "application/xhtml+xml"},
+ {".xla", "application/vnd.ms-excel"},
+ {".xlam", "application/vnd.ms-excel.addin.macroEnabled.12"},
+ {".xlc", "application/vnd.ms-excel"},
+ {".xlm", "application/vnd.ms-excel"},
+ {".xls", "application/vnd.ms-excel"},
+ {".xlsb", "application/vnd.ms-excel.sheet.binary.macroEnabled.12"},
+ {".xlsm", "application/vnd.ms-excel.sheet.macroEnabled.12"},
+ {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
+ {".xlt", "application/vnd.ms-excel"},
+ {".xltm", "application/vnd.ms-excel.template.macroEnabled.12"},
+ {".xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template"},
+ {".xlw", "application/vnd.ms-excel"},
+ {".xml", "text/xml"},
+ {".xof", "x-world/x-vrml"},
+ {".xpm", "image/x-xpixmap"},
+ {".xps", "application/vnd.ms-xpsdocument"},
+ {".xsd", "text/xml"},
+ {".xsf", "text/xml"},
+ {".xsl", "text/xml"},
+ {".xslt", "text/xml"},
+ {".xsn", "application/octet-stream"},
+ {".xtp", "application/octet-stream"},
+ {".xwd", "image/x-xwindowdump"},
+ {".z", "application/x-compress"},
+ {".zip", "application/x-zip-compressed"},
+ };
+
+ ///
+ /// The cross reference table of file extensions and content-types.
+ ///
+
+ ///
+ /// Given a file path, determine the MIME type
+ ///
+ /// A file path
+ /// The resulting MIME type
+ /// True if MIME type could be determined
+ public static bool TryGetKnownContentType(string path, out string contentType)
+ {
+ string extension = System.IO.Path.GetExtension(path);
+ if (extension == null)
+ {
+ contentType = null;
+ return false;
+ }
+ return _map.TryGetValue(extension, out contentType);
+ }
+
+ public static string GetContentType(string path)
+ {
+ return TryGetKnownContentType(path, out var contentType) ? contentType : DEFAULT_CONTENT_TYPE;
+ }
+ }
+}