Last active
July 21, 2023 09:35
-
-
Save flameoftheforest/83b398d386c458d86c504cf09d1e07e2 to your computer and use it in GitHub Desktop.
MailGun Netcore Multipart-Form Data Example (with attachment handling)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Amazon; | |
using Amazon.S3; | |
using Amazon.S3.Model; | |
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Net; | |
using System.Net.Http; | |
using System.Net.Http.Headers; | |
using System.Text; | |
namespace TEST00 | |
{ | |
public class TestClass | |
{ | |
private IAmazonS3 S3; | |
const string DOMAIN = "theBigRobot.org"; | |
const string API_KEY = "key-bigrobotkey"; | |
public void Test00() | |
{ | |
PostToMailGun("[email protected]", "The Big Robot", "[email protected]", "Greeting from Big Robot", "hello, Big Robot greets you.", "<html>hello, <b>Big Robot</b> greets you.</html>"); | |
} | |
/// <summary> | |
/// This sample code demonstrates a few things: | |
/// - Using HttpClient to POST a multipart form. | |
/// - POST the said form to MailGun. | |
/// - Attaching files to the MailGun submission. | |
/// - Using Amazon S3 Client. | |
/// | |
/// Implementation References (with thanks): | |
/// https://github.com/restsharp/RestSharp/wiki/Recommended-Usage | |
/// https://stackoverflow.com/questions/16906711/httpclient-how-to-upload-multiple-files-at-once | |
/// https://github.com/Vodurden/Http-Multipart-Data-Parser | |
/// | |
/// </summary> | |
/// <param name="recipientEmail"></param> | |
/// <param name="senderName"></param> | |
/// <param name="senderEmail"></param> | |
/// <param name="subject"></param> | |
/// <param name="textBody"></param> | |
/// <param name="htmlBody"></param> | |
private void PostToMailGun(string recipientEmail, string senderName, string senderEmail, string subject, string textBody, string htmlBody) | |
{ | |
HttpClient client = new HttpClient(); | |
var encoded = Convert.ToBase64String(Encoding.ASCII.GetBytes($"api:{API_KEY}")); | |
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", encoded); | |
var content = new MultipartFormDataContent(); | |
content.Add(new StringContent(DOMAIN), "domain"); // may need url-encode | |
content.Add(new StringContent($"{senderName} <{senderEmail}>"), "from"); | |
content.Add(new StringContent($"{recipientEmail}"), "to"); | |
content.Add(new StringContent($"{subject}"), "subject"); | |
content.Add(new StringContent($"{htmlBody}"), "html"); | |
content.Add(new StringContent($"{textBody}"), "text"); | |
// The arrangement of how attachments should be managed is heavily subjected to discussion. | |
// This only serves as a starting point and totally lacks flexibility. | |
S3Returns file1 = GetStreamFromS3("BUCKET", "Jesus.jpg"); | |
content.Add(CreateAttachmentContent(file1.Stream, "Jesus.jpg", file1.ContentType)); | |
S3Returns file2 = GetStreamFromS3("BUCKET", "why seek ye the living among the dead.jpg"); | |
content.Add(CreateAttachmentContent(file2.Stream, "why_seek_ye.jpg", file2.ContentType)); | |
HttpResponseMessage response = client.PostAsync($"https://api.mailgun.net/v3/{DOMAIN}/messages", content).Result; | |
if (!response.IsSuccessStatusCode) | |
{ | |
throw new Exception($"{response.ReasonPhrase}"); | |
} | |
} | |
private StreamContent CreateAttachmentContent(Stream stream, string fileName, string contentType) | |
{ | |
var fileContent = new StreamContent(stream); | |
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") | |
{ | |
Name = "\"attachment[]\"", | |
FileName = "\"" + fileName + "\"" | |
}; // the extra quotes are key here | |
fileContent.Headers.ContentType = new MediaTypeHeaderValue(contentType); | |
return fileContent; | |
} | |
private S3Returns GetStreamFromS3(string bucket, string key) | |
{ | |
GetObjectRequest req = new GetObjectRequest | |
{ | |
BucketName = bucket, | |
Key = key | |
}; | |
GetObjectResponse resp = S3.GetObjectAsync(req).Result; | |
if (resp.HttpStatusCode != HttpStatusCode.OK) | |
{ | |
throw new Exception("something's wrong"); | |
} | |
return new S3Returns | |
{ | |
Stream = resp.ResponseStream, | |
ContentType = resp.Headers.ContentType | |
}; | |
} | |
public TestClass() | |
{ | |
S3 = new AmazonS3Client("KEY", "SECRET", RegionEndpoint.SIBERIA); | |
} | |
} | |
internal class S3Returns | |
{ | |
public Stream Stream { get; set; } | |
public string ContentType { get; set; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Perfect! Thanks for sharing.