summaryrefslogtreecommitdiffstats
path: root/SendGrid/SendGridMail/Transport/REST.cs
blob: 3bb23a68e8d8e7632f2b26f0a8b160455d1a6097 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Mail;
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 List<KeyValuePair<String, String>> _query;
        private readonly NameValueCollection _queryParameters;
        private readonly String _restEndpoint;
        private readonly String _format;

        private WebFileUpload _fileUpload;


        public static REST GetInstance(NetworkCredential credentials, String url = Endpoint)
        {
            return new REST(credentials, url);
        }

        internal REST(NetworkCredential credentials, String url = Endpoint)
        {
            _query = new List<KeyValuePair<string, string>>();
            _queryParameters = HttpUtility.ParseQueryString(String.Empty);

            addQueryParam("api_user", credentials.UserName);
            addQueryParam("api_key", credentials.Password);

            _format = XmlFormat;
            _restEndpoint = url + "." + _format;
        }

        private void addQueryParam(String key, String value)
        {
            _query.Add(new KeyValuePair<string, string>(key, value));
        }

        public void TestDeliver(ISendGrid Message)
        {
            new WebFileUpload(null).SendAttachments();
        }

        public void Deliver(ISendGrid message)
        {
            // TODO Fix this to include all recipients
            message.To.ToList().ForEach(a => addQueryParam("to[]", a.Address));
            message.Bcc.ToList().ForEach(a => addQueryParam("bcc[]", a.Address));
            message.Cc.ToList().ForEach(a => addQueryParam("cc[]", a.Address));

            message.To.ToList().ForEach(a => addQueryParam("toname[]", a.DisplayName));

            addQueryParam("headers", Utils.SerializeDictionary(message.Headers));

            message.ReplyTo.ToList().ForEach(a => addQueryParam("replyto", a.Address));
            //addQueryParam("", message.From.Address);

            addQueryParam("from", message.From.Address);
            addQueryParam("fromname", message.From.DisplayName);

            addQueryParam("subject", message.Subject);
            addQueryParam("text", message.Text);
            addQueryParam("html", message.Html);

            String smtpapi = message.Header.AsJson();

            if (!String.IsNullOrEmpty(smtpapi))
                addQueryParam("x-smtpapi", smtpapi);

            var queryString = FetchQueryString();

            var restCommand = new Uri(_restEndpoint + "?" + queryString);

            var request = (HttpWebRequest)WebRequest.Create(restCommand.AbsoluteUri);

            Console.WriteLine(restCommand.AbsoluteUri);

            //if we have message attachments, we'll send them via the WebFileUpload
            /*if(message.Attachments.Length > 0)
            {
                Console.WriteLine("Initializing the File Upload Library");
                new WebFileUpload(request).testNoAttach(message.Attachments.First());
            }*/
            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);
                        }
                    }
                }
            }
        }

        private string FetchQueryString()
        {
            return String.Join("&", _query.Where(kvp => !String.IsNullOrEmpty(kvp.Value)).Select(kvp => kvp.Key + "=" + kvp.Value));
        }
    }
}