Skip to content

Commit 5b355fb

Browse files
Implement pull #127, add api key constructors
1 parent d685ac8 commit 5b355fb

File tree

3 files changed

+239
-211
lines changed

3 files changed

+239
-211
lines changed

SendGrid/Example/Program.cs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,9 @@ private static void Main()
2222

2323
private static void SendAsync(SendGrid.SendGridMessage message)
2424
{
25-
// Create credentials, specifying your user Name and password.
26-
var username = Environment.GetEnvironmentVariable("SENDGRID_USERNAME");
27-
var password = Environment.GetEnvironmentVariable("SENDGRID_PASSWORD");
28-
//string apikey = Environment.GetEnvironmentVariable("SENDGRID_APIKEY");
29-
var credentials = new NetworkCredential(username, password);
30-
25+
string apikey = Environment.GetEnvironmentVariable("SENDGRID_APIKEY");
3126
// Create a Web transport for sending email.
32-
var transportWeb = new SendGrid.Web(credentials);
33-
//var transportWeb2 = new SendGrid.Web(apikey);
27+
var transportWeb = new SendGrid.Web(apikey);
3428

3529
// Send the email.
3630
try

SendGrid/SendGridMail/Transport/Web.cs

Lines changed: 160 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -14,154 +14,175 @@
1414
// ReSharper disable MemberCanBePrivate.Global
1515
namespace SendGrid
1616
{
17-
public class Web : ITransport
18-
{
19-
#region Properties
20-
21-
//TODO: Make this configurable
22-
public const String Endpoint = "https://api.sendgrid.com/api/mail.send.xml";
23-
24-
private readonly NetworkCredential _credentials;
25-
private readonly HttpClient _client;
26-
27-
#endregion
28-
29-
/// <summary>
30-
/// Creates a new Web interface for sending mail
31-
/// </summary>
32-
/// <param name="credentials">SendGridMessage user parameters</param>
17+
public class Web : ITransport
18+
{
19+
#region Properties
20+
21+
//TODO: Make this configurable
22+
public const String Endpoint = "https://api.sendgrid.com/api/mail.send.xml";
23+
private readonly NetworkCredential _credentials;
24+
private readonly HttpClient _client;
25+
private readonly string _apiKey;
26+
27+
#endregion
28+
29+
/// <summary>
30+
/// Creates a new Web interface for sending mail
31+
/// </summary>
32+
/// <param name="apiKey">The API Key with which to send</param>
33+
public Web(string apiKey)
34+
: this(apiKey, null, TimeSpan.FromSeconds(100)) { }
35+
36+
/// <summary>
37+
/// Creates a new Web interface for sending mail
38+
/// </summary>
39+
/// <param name="credentials">SendGridMessage user parameters</param>
3340
public Web(NetworkCredential credentials)
34-
: this(credentials, TimeSpan.FromSeconds(100)) { }
41+
: this(null, credentials, TimeSpan.FromSeconds(100)) { }
3542

3643
/// <summary>
3744
/// Creates a new Web interface for sending mail.
3845
/// </summary>
46+
/// <param name="apKey">The API Key with which to send</param>
3947
/// <param name="credentials">SendGridMessage user parameters</param>
4048
/// <param name="httpTimeout">HTTP request timeout</param>
41-
public Web(NetworkCredential credentials, TimeSpan httpTimeout)
42-
{
43-
_credentials = credentials;
49+
public Web(string apiKey, NetworkCredential credentials, TimeSpan httpTimeout)
50+
{
51+
_credentials = credentials;
4452
_client = new HttpClient();
45-
53+
_apiKey = apiKey;
54+
4655
var version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
56+
if (credentials == null)
57+
{
58+
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _apiKey);
59+
}
4760
_client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "sendgrid/" + version + ";csharp");
4861
_client.Timeout = httpTimeout;
49-
}
50-
51-
/// <summary>
52-
/// Asynchronously delivers a message over SendGrid's Web interface
53-
/// </summary>
54-
/// <param name="message"></param>
55-
public async Task DeliverAsync(ISendGrid message)
56-
{
57-
var content = new MultipartFormDataContent();
58-
AttachFormParams(message, content);
59-
AttachFiles(message, content);
60-
var response = await _client.PostAsync(Endpoint, content);
61-
await ErrorChecker.CheckForErrorsAsync(response);
62-
}
63-
64-
#region Support Methods
65-
66-
private void AttachFormParams(ISendGrid message, MultipartFormDataContent content)
67-
{
68-
var formParams = FetchFormParams(message);
69-
foreach (var keyValuePair in formParams)
70-
{
71-
content.Add(new StringContent(keyValuePair.Value), keyValuePair.Key);
72-
}
73-
}
74-
75-
private void AttachFiles(ISendGrid message, MultipartFormDataContent content)
76-
{
77-
var files = FetchFileBodies(message);
78-
foreach (var file in files)
79-
{
80-
var fs = new FileStream(file.Key, FileMode.Open, FileAccess.Read);
81-
var fileContent = new StreamContent(fs);
82-
83-
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
84-
{
85-
Name = "files[" + Path.GetFileName(file.Key) + "]",
86-
FileName = Path.GetFileName(file.Key)
87-
};
88-
89-
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
90-
content.Add(fileContent);
91-
}
92-
93-
var streamingFiles = FetchStreamingFileBodies(message);
94-
foreach (var file in streamingFiles)
95-
{
96-
var stream = file.Value;
97-
var fileContent = new StreamContent(stream);
98-
99-
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
100-
{
101-
Name = "files[" + Path.GetFileName(file.Key) + "]",
102-
FileName = Path.GetFileName(file.Key)
103-
};
104-
105-
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
106-
content.Add(fileContent);
107-
}
108-
}
109-
110-
111-
112-
internal List<KeyValuePair<String, String>> FetchFormParams(ISendGrid message)
113-
{
114-
var result = new List<KeyValuePair<string, string>>
115-
{
116-
new KeyValuePair<String, String>("api_user", _credentials.UserName),
117-
new KeyValuePair<String, String>("api_key", _credentials.Password),
118-
new KeyValuePair<String, String>("headers",
119-
message.Headers.Count == 0 ? null : Utils.SerializeDictionary(message.Headers)),
120-
new KeyValuePair<String, String>("replyto",
121-
message.ReplyTo.Length == 0 ? null : message.ReplyTo.ToList().First().Address),
122-
new KeyValuePair<String, String>("from", message.From.Address),
123-
new KeyValuePair<String, String>("fromname", message.From.DisplayName),
124-
new KeyValuePair<String, String>("subject", message.Subject),
125-
new KeyValuePair<String, String>("text", message.Text),
126-
new KeyValuePair<String, String>("html", message.Html),
127-
new KeyValuePair<String, String>("x-smtpapi", message.Header.JsonString() ?? "")
128-
};
129-
if (message.To != null)
130-
{
131-
result = result.Concat(message.To.ToList().Select(a => new KeyValuePair<String, String>("to[]", a.Address)))
132-
.Concat(message.To.ToList().Select(a => new KeyValuePair<String, String>("toname[]", a.DisplayName)))
133-
.ToList();
134-
}
135-
136-
if (message.Cc != null)
137-
{
138-
result.AddRange(message.Cc.Select(c => new KeyValuePair<string, string>("cc[]", c.Address)));
139-
}
140-
141-
if (message.Bcc != null)
142-
{
143-
result.AddRange(message.Bcc.Select(c => new KeyValuePair<string, string>("bcc[]", c.Address)));
144-
}
145-
146-
if (message.GetEmbeddedImages().Count > 0) {
147-
result = result.Concat(message.GetEmbeddedImages().ToList().Select(x => new KeyValuePair<String, String>(string.Format("content[{0}]", x.Key), x.Value)))
148-
.ToList();
149-
}
150-
return result.Where(r => !String.IsNullOrEmpty(r.Value)).ToList();
151-
}
152-
153-
internal IEnumerable<KeyValuePair<string, MemoryStream>> FetchStreamingFileBodies(ISendGrid message)
154-
{
155-
return message.StreamedAttachments.Select(kvp => kvp).ToList();
156-
}
157-
158-
internal List<KeyValuePair<String, FileInfo>> FetchFileBodies(ISendGrid message)
159-
{
160-
return message.Attachments == null
161-
? new List<KeyValuePair<string, FileInfo>>()
162-
: message.Attachments.Select(name => new KeyValuePair<String, FileInfo>(name, new FileInfo(name))).ToList();
163-
}
164-
165-
#endregion
166-
}
62+
}
63+
64+
/// <summary>
65+
/// Asynchronously delivers a message over SendGrid's Web interface
66+
/// </summary>
67+
/// <param name="message"></param>
68+
public async Task DeliverAsync(ISendGrid message)
69+
{
70+
var content = new MultipartFormDataContent();
71+
AttachFormParams(message, content);
72+
AttachFiles(message, content);
73+
var response = await _client.PostAsync(Endpoint, content);
74+
await ErrorChecker.CheckForErrorsAsync(response);
75+
}
76+
77+
#region Support Methods
78+
79+
private void AttachFormParams(ISendGrid message, MultipartFormDataContent content)
80+
{
81+
var formParams = FetchFormParams(message);
82+
foreach (var keyValuePair in formParams)
83+
{
84+
content.Add(new StringContent(keyValuePair.Value), keyValuePair.Key);
85+
}
86+
}
87+
88+
private void AttachFiles(ISendGrid message, MultipartFormDataContent content)
89+
{
90+
var files = FetchFileBodies(message);
91+
foreach (var file in files)
92+
{
93+
var fs = new FileStream(file.Key, FileMode.Open, FileAccess.Read);
94+
var fileContent = new StreamContent(fs);
95+
96+
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
97+
{
98+
Name = "files[" + Path.GetFileName(file.Key) + "]",
99+
FileName = Path.GetFileName(file.Key)
100+
};
101+
102+
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
103+
content.Add(fileContent);
104+
}
105+
106+
var streamingFiles = FetchStreamingFileBodies(message);
107+
foreach (var file in streamingFiles)
108+
{
109+
var stream = file.Value;
110+
var fileContent = new StreamContent(stream);
111+
112+
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
113+
{
114+
Name = "files[" + Path.GetFileName(file.Key) + "]",
115+
FileName = Path.GetFileName(file.Key)
116+
};
117+
118+
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
119+
content.Add(fileContent);
120+
}
121+
}
122+
123+
internal List<KeyValuePair<String, String>> FetchFormParams(ISendGrid message)
124+
{
125+
var result = new List<KeyValuePair<string, string>>
126+
{
127+
new KeyValuePair<String, String>("headers",
128+
message.Headers.Count == 0 ? null : Utils.SerializeDictionary(message.Headers)),
129+
new KeyValuePair<String, String>("replyto",
130+
message.ReplyTo.Length == 0 ? null : message.ReplyTo.ToList().First().Address),
131+
new KeyValuePair<String, String>("from", message.From.Address),
132+
new KeyValuePair<String, String>("fromname", message.From.DisplayName),
133+
new KeyValuePair<String, String>("subject", message.Subject),
134+
new KeyValuePair<String, String>("text", message.Text),
135+
new KeyValuePair<String, String>("html", message.Html),
136+
new KeyValuePair<String, String>("x-smtpapi", message.Header.JsonString() ?? "")
137+
};
138+
139+
//If the API key is not specified, use the username and password
140+
if (_credentials != null)
141+
{
142+
var creds = new List<KeyValuePair<string, string>>
143+
{
144+
new KeyValuePair<string, string>("api_user", _credentials.UserName),
145+
new KeyValuePair<string, string>("api_key", _credentials.Password)
146+
};
147+
result.AddRange(creds);
148+
}
149+
150+
if (message.To != null)
151+
{
152+
result = result.Concat(message.To.ToList().Select(a => new KeyValuePair<String, String>("to[]", a.Address)))
153+
.Concat(message.To.ToList().Select(a => new KeyValuePair<String, String>("toname[]", a.DisplayName)))
154+
.ToList();
155+
}
156+
157+
if (message.Cc != null)
158+
{
159+
result.AddRange(message.Cc.Select(c => new KeyValuePair<string, string>("cc[]", c.Address)));
160+
}
161+
162+
if (message.Bcc != null)
163+
{
164+
result.AddRange(message.Bcc.Select(c => new KeyValuePair<string, string>("bcc[]", c.Address)));
165+
}
166+
167+
if (message.GetEmbeddedImages().Count > 0) {
168+
result = result.Concat(message.GetEmbeddedImages().ToList().Select(x => new KeyValuePair<String, String>(string.Format("content[{0}]", x.Key), x.Value)))
169+
.ToList();
170+
}
171+
return result.Where(r => !String.IsNullOrEmpty(r.Value)).ToList();
172+
}
173+
174+
internal IEnumerable<KeyValuePair<string, MemoryStream>> FetchStreamingFileBodies(ISendGrid message)
175+
{
176+
return message.StreamedAttachments.Select(kvp => kvp).ToList();
177+
}
178+
179+
internal List<KeyValuePair<String, FileInfo>> FetchFileBodies(ISendGrid message)
180+
{
181+
return message.Attachments == null
182+
? new List<KeyValuePair<string, FileInfo>>()
183+
: message.Attachments.Select(name => new KeyValuePair<String, FileInfo>(name, new FileInfo(name))).ToList();
184+
}
185+
186+
#endregion
187+
}
167188
}

0 commit comments

Comments
 (0)