summaryrefslogtreecommitdiffstats
path: root/SendGrid/SendGridMail
diff options
context:
space:
mode:
authorTyler Bischel <tyler.bischel@sendgrid.com>2012-01-10 13:40:15 -0800
committerTyler Bischel <tyler.bischel@sendgrid.com>2012-01-10 13:40:15 -0800
commite7e7ea043de835793b9d65e6176e6148d0b51e29 (patch)
tree04490de0b36b3fcbdc4433a678b30cd18f31dc8c /SendGrid/SendGridMail
parente40ecaea2026a525650c02f6b84526c68762fbcb (diff)
downloadsendgrid-csharp-e7e7ea043de835793b9d65e6176e6148d0b51e29.zip
sendgrid-csharp-e7e7ea043de835793b9d65e6176e6148d0b51e29.tar.gz
sendgrid-csharp-e7e7ea043de835793b9d65e6176e6148d0b51e29.tar.bz2
fixed namespace weirdness, made changes to .gitignore
Diffstat (limited to 'SendGrid/SendGridMail')
-rwxr-xr-xSendGrid/SendGridMail/Header.cs56
-rwxr-xr-xSendGrid/SendGridMail/IHeader.cs21
-rwxr-xr-xSendGrid/SendGridMail/ISendGrid.cs83
-rwxr-xr-xSendGrid/SendGridMail/Mail.csproj62
-rwxr-xr-xSendGrid/SendGridMail/Properties/AssemblyInfo.cs38
-rwxr-xr-xSendGrid/SendGridMail/SendGrid.cs466
-rwxr-xr-xSendGrid/SendGridMail/Transport/ITransport.cs14
-rwxr-xr-xSendGrid/SendGridMail/Transport/REST.cs82
-rwxr-xr-xSendGrid/SendGridMail/Transport/SMTP.cs132
9 files changed, 954 insertions, 0 deletions
diff --git a/SendGrid/SendGridMail/Header.cs b/SendGrid/SendGridMail/Header.cs
new file mode 100755
index 0000000..2af4acd
--- /dev/null
+++ b/SendGrid/SendGridMail/Header.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Mail;
+using System.Text;
+
+namespace SendGridMail
+{
+ public class Header : IHeader
+ {
+ public void AddTo(IEnumerable<string> recipients)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void AddSubVal(string tag, IEnumerable<string> substitutions)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void AddUniqueIdentifier(IDictionary<string, string> identifiers)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SetCategory(string category)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Enable(string filter)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Disable(string filter)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void AddFilterSetting(string filter, IEnumerable<string> settings, string value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void AddHeader(MailMessage mime)
+ {
+ throw new NotImplementedException();
+ }
+
+ public String AsJson()
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/SendGrid/SendGridMail/IHeader.cs b/SendGrid/SendGridMail/IHeader.cs
new file mode 100755
index 0000000..a9464ed
--- /dev/null
+++ b/SendGrid/SendGridMail/IHeader.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Mail;
+using System.Text;
+
+namespace SendGridMail
+{
+ public interface IHeader
+ {
+ void AddTo(IEnumerable<String> recipients);
+ void AddSubVal(String tag, IEnumerable<String> substitutions);
+ void AddUniqueIdentifier(IDictionary<String, String> identifiers);
+ void SetCategory(String category);
+ void Enable(String filter);
+ void Disable(String filter);
+ void AddFilterSetting(String filter, IEnumerable<String> settings, String value);
+ void AddHeader(MailMessage mime);
+ String AsJson();
+ }
+}
diff --git a/SendGrid/SendGridMail/ISendGrid.cs b/SendGrid/SendGridMail/ISendGrid.cs
new file mode 100755
index 0000000..e8e5fb2
--- /dev/null
+++ b/SendGrid/SendGridMail/ISendGrid.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net.Mail;
+using System.Net.Mime;
+using System.Text;
+
+namespace SendGridMail
+{
+ public enum TransportType
+ {
+ SMTP,
+ REST
+ };
+
+ public interface ISendGrid
+ {
+ #region Properties
+ MailAddress From { get; set; }
+ MailAddress[] To { get; set; }
+ MailAddress[] Cc { get; }
+ MailAddress[] Bcc { get; }
+ String Subject { get; set; }
+ IHeader Header { get; set; }
+ String Html { get; set; }
+ String Text { get; set; }
+ TransportType Transport { get; set; }
+ #endregion
+
+ #region Interface for ITransport
+ MailMessage CreateMimeMessage();
+ #endregion
+
+ #region Methods for setting data
+ void AddTo(String address);
+ void AddTo(IEnumerable<String> addresses);
+ void AddTo(IDictionary<String, IDictionary<String, String>> addresssInfo);
+
+ void AddCc(String address);
+ void AddCc(IEnumerable<String> addresses);
+ void AddCc(IDictionary<String, IDictionary<String, String>> addresssInfo);
+
+ void AddBcc(String address);
+ void AddBcc(IEnumerable<String> addresses);
+ void AddBcc(IDictionary<String, IDictionary<String, String>> addresssInfo);
+
+ void AddSubVal(String tag, String value);
+
+ void AddAttachment(String filePath);
+ void AddAttachment(Attachment attachment);
+ void AddAttachment(Stream attachment, ContentType type);
+
+ IEnumerable<String> GetRecipients();
+ #endregion
+
+ #region SMTP API Functions
+ void DisableGravatar();
+ void DisableOpenTracking();
+ void DisableClickTracking();
+ void DisableSpamCheck();
+ void DisableUnsubscribe();
+ void DisableFooter();
+ void DisableGoogleAnalytics();
+ void DisableTemplate();
+ void DisableBcc();
+ void DisableBypassListManagement();
+
+ void EnableGravatar();
+ void EnableOpenTracking();
+ void EnableClickTracking(String text = null);
+ void EnableSpamCheck(int score = 5, String url = null);
+ void EnableUnsubscribe(String text, String html, String replace, String url, String landing);
+ void EnableFooter(String text = null, String html = null);
+ void EnableGoogleAnalytics(String source, String medium, String term, String content = null, String campaign = null);
+ void EnableTemplate(String html = null);
+ void EnableBcc(String email = null);
+ void EnableBypassListManagement();
+ #endregion
+
+ void Mail();
+ }
+}
diff --git a/SendGrid/SendGridMail/Mail.csproj b/SendGrid/SendGridMail/Mail.csproj
new file mode 100755
index 0000000..b5a9a9d
--- /dev/null
+++ b/SendGrid/SendGridMail/Mail.csproj
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{3C687BEF-FF50-44AD-8315-2D4237281AF8}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>SendGridMail</RootNamespace>
+ <AssemblyName>SendGridMail</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Net" />
+ <Reference Include="System.Web" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Header.cs" />
+ <Compile Include="IHeader.cs" />
+ <Compile Include="ISendGrid.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="SendGrid.cs" />
+ <Compile Include="Transport\ITransport.cs" />
+ <Compile Include="Transport\REST.cs" />
+ <Compile Include="Transport\SMTP.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/SendGrid/SendGridMail/Properties/AssemblyInfo.cs b/SendGrid/SendGridMail/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..0cefaba
--- /dev/null
+++ b/SendGrid/SendGridMail/Properties/AssemblyInfo.cs
@@ -0,0 +1,38 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("SendGridMail")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("SendGridMail")]
+[assembly: AssemblyCopyright("Copyright © 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("193fa200-8430-4206-aacd-2d2bb2dfa6cf")]
+
+[assembly: InternalsVisibleTo("Tests")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/SendGrid/SendGridMail/SendGrid.cs b/SendGrid/SendGridMail/SendGrid.cs
new file mode 100755
index 0000000..33f809b
--- /dev/null
+++ b/SendGrid/SendGridMail/SendGrid.cs
@@ -0,0 +1,466 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Net.Mail;
+using System.Net.Mime;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+
+namespace SendGridMail
+{
+ public class SendGrid : ISendGrid
+ {
+ private IHeader header;
+
+ private Dictionary<String, String> _filters;
+
+ //apps list and settings
+ private const String ReText = @"<\%\s*\%>";
+ private const String ReHtml = @"<\%\s*[^\s]+\s*\%>";
+
+ public SendGrid(IHeader header)
+ {
+ this.header = header;
+
+ //initialize the filters, for use within the library
+ this.InitializeFilters();
+ }
+
+ public void InitializeFilters()
+ {
+ this._filters =
+ new Dictionary<string, string>
+ {
+ {"Gravatar", "gravatar"},
+ {"OpenTracking", "opentrack"},
+ {"ClickTracking", "clicktrack"},
+ {"SpamCheck", "spamcheck"},
+ {"Unsubscribe", "subscriptiontrack"},
+ {"Footer", "footer"},
+ {"GoogleAnalytics", "ganalytics"},
+ {"Template", "template"},
+ {"Bcc", "bcc"},
+ {"BypassListManagement", "bypass_list_management"}
+ };
+ }
+
+ private MailMessage message;
+
+ // TODO find appropriate types for these
+ const string encoding = "quoted-printable";
+ const string charset = "utf-8";
+
+ /*
+ if (Html != null )
+ {
+ AlternateView htmlView = AlternateView.CreateAlternateViewFromString(html, null, "text/html");
+ message.AlternateViews.Add(htmlView);
+ }
+
+ if (Text != null )
+ {
+ AlternateView plainView = AlternateView.CreateAlternateViewFromString(Text, null, "text/plain");
+ message.AlternateViews.Add(plainView);
+ }
+
+ message.BodyEncoding = Encoding.GetEncoding(charset);
+ */
+
+ public SendGrid(MailAddress from, MailAddress[] to, MailAddress[] cc, MailAddress[] bcc,
+ String subject, String html, String text, TransportType transport, IHeader header = null )
+ {
+ message = new MailMessage();
+ Header = header;
+
+ From = from;
+ To = to;
+
+ _subs = new Dictionary<string, string>();
+
+ message.Subject = subject;
+ message.SubjectEncoding = Encoding.GetEncoding(charset);
+
+ Text = text;
+ Html = html;
+ }
+
+ #region Properties
+ public MailAddress From
+ {
+ get
+ {
+ return message.From;
+ }
+ set
+ {
+ if (value != null) message.From = value;
+ }
+ }
+
+ public MailAddress[] To
+ {
+ get
+ {
+ return message.To.ToArray();
+ }
+ set
+ {
+ message.To.Clear();
+ foreach (var mailAddress in value)
+ {
+ message.To.Add(mailAddress);
+ }
+ }
+ }
+
+ public MailAddress[] Cc
+ {
+ get
+ {
+ return message.CC.ToArray();
+ }
+ set
+ {
+ message.CC.Clear();
+ foreach (var mailAddress in value)
+ {
+ message.CC.Add(mailAddress);
+ }
+ }
+ }
+
+ public MailAddress[] Bcc
+ {
+ get
+ {
+ return message.Bcc.ToArray();
+ }
+ set
+ {
+ message.Bcc.Clear();
+ foreach (var mailAddress in value)
+ {
+ message.Bcc.Add(mailAddress);
+ }
+ }
+ }
+
+ public String Subject
+ {
+ get
+ {
+ return message.Subject;
+ }
+ set
+ {
+ if (value != null) message.Subject = value;
+ }
+ }
+
+ public IHeader Header
+ {
+ get { throw new NotImplementedException(); }
+ set { throw new NotImplementedException(); }
+ }
+
+ public String Html { get; set; }
+ public String Text { get; set; }
+
+ public TransportType Transport { get; set; }
+ #endregion
+
+ #region Methods for setting data
+ public void AddTo(String address)
+ {
+ var mailAddress = new MailAddress(address);
+ message.To.Add(mailAddress);
+ }
+
+ public void AddTo(IEnumerable<String> addresses)
+ {
+ if (addresses != null)
+ {
+ foreach (var address in addresses)
+ {
+ if (address != null) AddTo(address);
+ }
+ }
+ }
+
+ public void AddTo(IDictionary<String, IDictionary<String, String>> addresssInfo)
+ {
+ foreach (var address in addresssInfo.Keys)
+ {
+ var table = addresssInfo[address];
+ //DisplayName is the only option that this implementation of MailAddress implements.
+ var mailAddress = new MailAddress(address, table.ContainsKey("DisplayName") ? table["DisplayName"] : null);
+ message.To.Add(mailAddress);
+ }
+ }
+
+ public void AddCc(String address)
+ {
+ var mailAddress = new MailAddress(address);
+ message.CC.Add(mailAddress);
+ }
+
+ public void AddCc(IEnumerable<String> addresses)
+ {
+ if (addresses != null)
+ {
+ foreach (var address in addresses)
+ {
+ if (address != null) AddCc(address);
+ }
+ }
+ }
+
+ public void AddCc(IDictionary<String, IDictionary<String, String>> addresssInfo)
+ {
+ foreach (var address in addresssInfo.Keys)
+ {
+ var table = addresssInfo[address];
+ //DisplayName is the only option that this implementation of MailAddress implements.
+ var mailAddress = new MailAddress(address, table.ContainsKey("DisplayName") ? table["DisplayName"] : null);
+ message.CC.Add(mailAddress);
+ }
+ }
+
+ public void AddBcc(String address)
+ {
+ var mailAddress = new MailAddress(address);
+ message.Bcc.Add(mailAddress);
+ }
+
+ public void AddBcc(IEnumerable<String> addresses)
+ {
+ if (addresses != null)
+ {
+ foreach (var address in addresses)
+ {
+ if (address != null) AddBcc(address);
+ }
+ }
+ }
+
+ public void AddBcc(IDictionary<String, IDictionary<String, String>> addresssInfo)
+ {
+ foreach (var address in addresssInfo.Keys)
+ {
+ var table = addresssInfo[address];
+ //DisplayName is the only option that this implementation of MailAddress implements.
+ var mailAddress = new MailAddress(address, table.ContainsKey("DisplayName") ? table["DisplayName"] : null);
+ message.Bcc.Add(mailAddress);
+ }
+ }
+
+ private Dictionary<string, string> _subs;
+
+ public void AddSubVal(string tag, string value)
+ {
+ //let the system complain if they do something bad, since the function returns null
+ _subs[tag] = value;
+ }
+
+ public void AddAttachment(string filePath)
+ {
+ var data = new Attachment(filePath, MediaTypeNames.Application.Octet);
+ message.Attachments.Add(data);
+ }
+
+ public void AddAttachment(Attachment attachment)
+ {
+ message.Attachments.Add(attachment);
+ }
+
+ public void AddAttachment(Stream attachment, ContentType type)
+ {
+ var data = new Attachment(attachment, type);
+ }
+
+ public IEnumerable<string> GetRecipients()
+ {
+ List<MailAddress> tos = message.To.ToList();
+ List<MailAddress> ccs = message.CC.ToList();
+ List<MailAddress> bccs = message.Bcc.ToList();
+
+ var rcpts = tos.Union(ccs.Union(bccs)).Select(address => address.Address);
+ return rcpts;
+ }
+
+ private string Get(string field)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void Set(string field, string value)
+ {
+ throw new NotImplementedException();
+ }
+ #endregion
+
+ #region SMTP API Functions
+ public void DisableGravatar()
+ {
+ this.header.Disable(this._filters["Gravatar"]);
+ }
+
+ public void DisableOpenTracking()
+ {
+ this.header.Disable(this._filters["OpenTracking"]);
+ }
+
+ public void DisableClickTracking()
+ {
+ this.header.Disable(this._filters["ClickTracking"]);
+ }
+
+ public void DisableSpamCheck()
+ {
+ this.header.Disable(this._filters["SpamCheck"]);
+ }
+
+ public void DisableUnsubscribe()
+ {
+ this.header.Disable(this._filters["Unsubscribe"]);
+ }
+
+ public void DisableFooter()
+ {
+ this.header.Disable(this._filters["Footer"]);
+ }
+
+ public void DisableGoogleAnalytics()
+ {
+ this.header.Disable(this._filters["GoogleAnalytics"]);
+ }
+
+ public void DisableTemplate()
+ {
+ this.header.Disable(this._filters["Template"]);
+ }
+
+ public void DisableBcc()
+ {
+ this.header.Disable(this._filters["Bcc"]);
+ }
+
+ public void DisableBypassListManagement()
+ {
+ this.header.Disable(this._filters["BypassListManagement"]);
+ }
+
+ public void EnableGravatar()
+ {
+ this.header.Enable(this._filters["Gravatar"]);
+ }
+
+ public void EnableOpenTracking()
+ {
+ this.header.Enable(this._filters["OpenTracking"]);
+ }
+
+ public void EnableClickTracking(string text = null)
+ {
+ var filter = this._filters["ClickTracking"];
+
+ this.header.Enable(filter);
+ this.header.AddFilterSetting(filter, new List<string>(){ "text" }, text);
+ }
+
+ public void EnableSpamCheck(int score = 5, string url = null)
+ {
+ var filter = this._filters["SpamCheck"];
+
+ this.header.Enable(filter);
+ this.header.AddFilterSetting(filter, new List<string>(){ "score" }, score.ToString(CultureInfo.InvariantCulture));
+ this.header.AddFilterSetting(filter, new List<string>(){ "url" }, url);
+ }
+
+ public void EnableUnsubscribe(string text, string html, string replace, string url, string landing)
+ {
+ var filter = this._filters["Unsubscribe"];
+
+ if(!System.Text.RegularExpressions.Regex.IsMatch(text, SendGrid.ReText))
+ {
+ throw new Exception("Missing substitution tag in text");
+ }
+
+ if(!System.Text.RegularExpressions.Regex.IsMatch(html, SendGrid.ReHtml))
+ {
+ throw new Exception("Missing substitution tag in html");
+ }
+
+ this.header.Enable(filter);
+ this.header.AddFilterSetting(filter, new List<string>(){ "text" }, text);
+ this.header.AddFilterSetting(filter, new List<string>(){ "html" }, html);
+ this.header.AddFilterSetting(filter, new List<string>(){ "replace"}, replace);
+ this.header.AddFilterSetting(filter, new List<string>(){ "landing" }, landing);
+ }
+
+ public void EnableFooter(string text = null, string html = null)
+ {
+ var filter = this._filters["Footer"];
+
+ this.header.Enable(filter);
+ this.header.AddFilterSetting(filter, new List<string>(){ "text" }, text);
+ this.header.AddFilterSetting(filter, new List<string>(){ "html" }, html);
+ }
+
+ public void EnableGoogleAnalytics(string source, string medium, string term, string content = null, string campaign = null)
+ {
+ var filter = this._filters["GoogleAnalytics"];
+
+ this.header.Enable(filter);
+ this.header.AddFilterSetting(filter, new List<string>(){ "source " }, source);
+ this.header.AddFilterSetting(filter, new List<string>(){ "medium" }, medium);
+ this.header.AddFilterSetting(filter, new List<string>(){ "term" }, term);
+ this.header.AddFilterSetting(filter, new List<string>(){ "content" }, content);
+ this.header.AddFilterSetting(filter, new List<string>(){ "compaign" }, campaign);
+ }
+
+ public void EnableTemplate(string html)
+ {
+ var filter = this._filters["Template"];
+
+ if (!System.Text.RegularExpressions.Regex.IsMatch(html, SendGrid.ReHtml))
+ {
+ throw new Exception("Missing substitution tag in html");
+ }
+
+ this.header.Enable(filter);
+ this.header.AddFilterSetting(filter, new List<string>(){ "html" }, html);
+ }
+
+ public void EnableBcc(string email)
+ {
+ var filter = this._filters["Bcc"];
+
+ this.header.Enable(filter);
+ this.header.AddFilterSetting(filter, new List<string>(){ "email" }, email);
+ }
+
+ public void EnableBypassListManagement()
+ {
+ this.header.Enable(this._filters["BypassListManagement"]);
+ }
+ #endregion
+
+ public MailMessage CreateMimeMessage()
+ {
+ String smtpapi = Header.AsJson();
+
+ if (!String.IsNullOrEmpty(smtpapi))
+ message.Headers.Add("X-SmtpApi", "{" + smtpapi + "}");
+
+ return message;
+ }
+
+ public void Mail()
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/SendGrid/SendGridMail/Transport/ITransport.cs b/SendGrid/SendGridMail/Transport/ITransport.cs
new file mode 100755
index 0000000..26fccf4
--- /dev/null
+++ b/SendGrid/SendGridMail/Transport/ITransport.cs
@@ -0,0 +1,14 @@
+namespace SendGridMail.Transport
+{
+ /// <summary>
+ ///
+ /// </summary>
+ public interface ITransport
+ {
+ /// <summary>
+ /// Delivers a message using the protocol of the derived class
+ /// </summary>
+ /// <param name="message">the message to be delivered</param>
+ void Deliver(ISendGrid message);
+ }
+}
diff --git a/SendGrid/SendGridMail/Transport/REST.cs b/SendGrid/SendGridMail/Transport/REST.cs
new file mode 100755
index 0000000..dd37567
--- /dev/null
+++ b/SendGrid/SendGridMail/Transport/REST.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Web;
+using System.Xml;
+
+namespace SendGridMail.Transport
+{
+ public class REST : ITransport
+ {
+ // REST delivery settings
+ public const String Endpoint = "https://sendgrid.com/api/mail.send";
+ public const String JsonFormat = "json";
+ public const String XmlFormat = "xml";
+
+ private readonly NameValueCollection _queryParameters;
+ private readonly String _restEndpoint;
+ private readonly String _format;
+
+ public REST(NetworkCredential credentials, String url = Endpoint)
+ {
+ _queryParameters = HttpUtility.ParseQueryString(String.Empty);
+ _queryParameters["api_user"] = credentials.UserName;
+ _queryParameters["api_key"] = credentials.Password;
+
+ _format = XmlFormat;
+ _restEndpoint = url + "." + _format;
+ }
+
+ public void Deliver(ISendGrid message)
+ {
+ // TODO Fix this to include all recipients
+ _queryParameters["to"] = message.To.First().ToString();
+ _queryParameters["from"] = message.From.ToString();
+ _queryParameters["subject"] = message.Subject;
+ _queryParameters["text"] = message.Text;
+ _queryParameters["html"] = message.Html;
+
+ String smtpapi = message.Header.AsJson();
+
+ if (!String.IsNullOrEmpty(smtpapi))
+ _queryParameters["x-smtpapi"] = smtpapi;
+
+ var restCommand = new Uri(_restEndpoint + "?" + _queryParameters);
+
+ var request = (HttpWebRequest)WebRequest.Create(restCommand.AbsoluteUri);
+ var response = (HttpWebResponse)request.GetResponse();
+
+ // Basically, read the entire message out before we parse the XML.
+ // That way, if we detect an error, we can give the whole response to the client.
+ var r = new StreamReader(response.GetResponseStream());
+ var status = r.ReadToEnd();
+ var bytes = Encoding.ASCII.GetBytes(status);
+ var stream = new MemoryStream(bytes);
+
+ using (var reader = XmlReader.Create(stream))
+ {
+ while (reader.Read())
+ {
+ if (reader.IsStartElement())
+ {
+ switch (reader.Name)
+ {
+ case "result":
+ break;
+ case "message": // success
+ return;
+ case "error": // failure
+ throw new ProtocolViolationException(status);
+ default:
+ throw new ArgumentException("Unknown element: " + reader.Name);
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/SendGrid/SendGridMail/Transport/SMTP.cs b/SendGrid/SendGridMail/Transport/SMTP.cs
new file mode 100755
index 0000000..606afcd
--- /dev/null
+++ b/SendGrid/SendGridMail/Transport/SMTP.cs
@@ -0,0 +1,132 @@
+using System;
+using System.Net;
+using System.Net.Mail;
+
+namespace SendGridMail.Transport
+{
+ /// <summary>
+ /// Transport class for delivering messages via SMTP
+ /// </summary>
+ public class SMTP : ITransport
+ {
+ /// <summary>
+ /// SendGrid's host name
+ /// </summary>
+ public const String SmtpServer = "smtp.sendgrid.net";
+
+ /// <summary>
+ /// Port for Simple Mail Transfer Protocol
+ /// </summary>
+ public const Int32 Port = 25;
+
+ /// <summary>
+ /// Port for Secure SMTP
+ /// </summary>
+ public const Int32 SslPort = 465;
+
+ /// <summary>
+ /// Port for TLS (currently not supported)
+ /// </summary>
+ public const Int32 TlsPort = 571;
+
+ /// <summary>
+ /// Client used to deliver SMTP message
+ /// </summary>
+ private readonly ISmtpClient _client;
+
+ /// <summary>
+ /// Transport created to deliver messages to SendGrid using SMTP
+ /// </summary>
+ /// <param name="client">SMTP client we are wrapping</param>
+ /// <param name="credentials">Sendgrid user credentials</param>
+ /// <param name="host">MTA recieving this message. By default, sent through SendGrid.</param>
+ /// <param name="port">SMTP port 25 is the default. Port 465 can be used for Secure SMTP.</param>
+ private SMTP(ISmtpClient client, NetworkCredential credentials, string host = SmtpServer, int port = Port)
+ {
+ _client = client;
+ switch (port)
+ {
+ case Port:
+ break;
+ case SslPort:
+ _client.EnableSsl = true;
+ break;
+ case TlsPort:
+ throw new NotSupportedException("TLS not supported");
+ }
+ }
+
+ /// <summary>
+ /// Deliver an email using SMTP protocol
+ /// </summary>
+ /// <param name="message"></param>
+ public void Deliver(ISendGrid message)
+ {
+ var mime = message.CreateMimeMessage();
+ _client.Send(mime);
+ }
+
+ /// <summary>
+ /// Transport created to deliver messages to SendGrid using SMTP
+ /// </summary>
+ /// <param name="credentials">Sendgrid user credentials</param>
+ /// <param name="host">MTA recieving this message. By default, sent through SendGrid.</param>
+ /// <param name="port">SMTP port 25 is the default. Port 465 can be used for Secure SMTP.</param>
+ public static SMTP GenerateInstance(NetworkCredential credentials, String host = SmtpServer, Int32 port = Port)
+ {
+ var client = new SmtpWrapper(host, port, credentials, SmtpDeliveryMethod.Network);
+ return new SMTP(client, credentials, host, port);
+ }
+
+ /// <summary>
+ /// For Unit Testing Only!
+ /// </summary>
+ /// <param name="client"></param>
+ /// <param name="credentials"></param>
+ /// <param name="host"></param>
+ /// <param name="port"></param>
+ /// <returns></returns>
+ internal static SMTP GenerateInstance(ISmtpClient client, NetworkCredential credentials, String host = SmtpServer, Int32 port = Port)
+ {
+ return new SMTP(client, credentials, host, port);
+ }
+
+ /// <summary>
+ /// Interface to allow testing
+ /// </summary>
+ internal interface ISmtpClient
+ {
+ bool EnableSsl { get; set; }
+ void Send(MailMessage mime);
+ }
+
+ /// <summary>
+ /// Implementation of SmtpClient wrapper, separated to allow dependency injection
+ /// </summary>
+ internal class SmtpWrapper : ISmtpClient
+ {
+ private readonly SmtpClient _client;
+ public bool EnableSsl
+ {
+ get
+ {
+ return _client.EnableSsl;
+ }
+ set
+ {
+ _client.EnableSsl = value;
+ }
+ }
+
+ public SmtpWrapper(String host, Int32 port, NetworkCredential credentials, SmtpDeliveryMethod deliveryMethod)
+ {
+ _client = new SmtpClient(host, port) { Credentials = credentials, DeliveryMethod = deliveryMethod };
+ }
+
+ public void Send(MailMessage mime)
+ {
+ _client.Send(mime);
+ }
+ }
+ }
+}