Mailgun sending attachment with RestSharp - c#

I'm using RestSharp to try and send an attachment with the Mailgun API. I have tried attaching from both a file in the system using a hardcoded path and also from a binary file stored in the database using ToArray() method on the varbinary(MAX) (SQL Server) property both with no success.
The attachment technically sends, but when the email arrives in my inbox the file size is always roughly 302bytes big and is always corrupt. I have tried 3 different files and get the same problem each time.
The rest of the email sends, delivers and displays fine. It's just the attachments that are broken.
Breakdown of code:
// Doesnt work(Data property is varbinary(MAX)
request.AddFileBytes("attachment",databaseModel.Data.ToArray(),databaseModel.Filename, "multipart/form-data");
// Also doesnt work(Data property is varbinary(MAX)
request.AddFile("attachment",databaseModel.Data.ToArray(),databaseModel.Filename, "multipart/form-data");
// Also doesnt work
var path = #"D:\Template.pdf";
request.AddFile("attachment",path,"multipart/form-data");

This code works:
public static void Main(string[] args)
{
Console.WriteLine(SendSimpleMessage().Content.ToString());
Console.ReadLine();
}
public static IRestResponse SendSimpleMessage()
{
var path1 = #"C:\Users\User\Pictures\website preview";
var fileName = "Learn.png";
RestClient client = new RestClient();
client.BaseUrl = new Uri("https://api.mailgun.net/v3");
client.Authenticator =
new HttpBasicAuthenticator("api",
"key-934345306fead7de0296ec2fb96a143");
RestRequest request = new RestRequest();
request.AddParameter("domain", "mydomain.info", ParameterType.UrlSegment);
request.Resource = "{domain}/messages";
request.AddParameter("from", "Excited User <example#mydomain.info>");
request.AddParameter("to", "peter.cech#gmail.com");
request.AddParameter("subject", "Hello");
request.AddParameter("text", "Testing some Mailgun awesomness! This is all about the text only. Just testing the text of this email.";
request.AddFile("attachment", Path.Combine(path1,fileName));
request.Method = Method.POST;
return client.Execute(request);
}

I figured it out..
Not supposed to add "multipart/form-data" on the request.AddFile();
Removing this fixes the problem.

Related

The value cannot be null or empty. (Parameter 'mediaType')

I am getting an exception 'The value cannot be null or empty. (Parameter 'mediaType')' when trying to send an attachment using the RestSharp library. For email sending, I am using MailGun api and the solution is on .NET 7 framework
var client = new RestClient(new Uri(BaseUrl))
{
`Authenticator = new HttpBasicAuthenticator("api", ApiKey)
};
var request = new RestRequest();
request.AddParameter("domain", domain, ParameterType.UrlSegment);
request.Resource = $"{domain}/messages";
request.AddParameter("from", "noreply#smartbroker.com");
request.AddParameter("to", "ahuja.dinesh85#gmail.com");
request.AddParameter("subject", "test subject");
request.AddParameter("html", "hello");
//Attachment
const string fileName = "D:\\ebook.pdf";
request.AddFile("attachment", fileName);
request.Method = Method.Post;
var response = await client.ExecuteAsync(request);
If I comment the attachment code the email goes fine. Do you have any idea what I am doing wrong?
Thanks in advance
It seems there is a problem with the version of RestSharp. I couldn't fix that problem, but it works fine on .net 6 and earlier.
I hope it has helped you, greetings!

Send MailGun email with Attachment from Google Drive in C#

I can send emails with attachments from my local computer just fine but can't figure out how to send attachments of files that are in Google Drive.
Can the file be send with a simple path in the below code if sharing permissions are set? If so, how do I get that path?
How can I send a file without sharing permissions?
Here is my MailGun Send code...
public static void Send()
{
RestClient client = new RestClient();
client.BaseUrl = new Uri("https://api.mailgun.net/v3");
client.Authenticator = new HttpBasicAuthenticator("api", "abc123");
RestRequest request = new RestRequest();
request.AddParameter("domain", "mail.dealopo.ly", ParameterType.UrlSegment);
request.Resource = "{domain}/messages";
request.AddParameter("from", "Name <test#sandboxcabc123.mailgun.org>");
request.AddParameter("to", "myemail#msn.com");
request.AddParameter("subject", "Hello");
request.AddParameter("text", "Testing some Mailgun awesomness!");
request.AddParameter("html", "<html>Inline image here: <img src=\"cid:Capture.jpg\"></html>");
request.AddFile("inline", Path.Combine(#"C:\Users\Jeremy\Desktop", "Capture.jpg"));
request.AddFile("attachment", Path.Combine(#"C:\Users\Jeremy\Desktop", "Local File.pdf"));
request.AddFile("attachment", Path.Combine(#"WHAT PATH DO I USE??", "Google Drive File.pdf"));
request.Method = Method.POST;
var response = client.Execute(request);
}

How to send a iCal invite with Mailgun Rest API (C#)

I am attempting to add a calendar invite in iCal format to an email sent via the MailGun API. This is what i have so far:
var request = new RestRequest();
request.AddParameter("domain", this.domain, ParameterType.UrlSegment);
request.Resource = "{domain}/messages";
request.AddParameter("from", contactDetails.SenderAddress);
request.AddParameter("to", contactDetails.RecipientAddress);
request.AddParameter("subject", message.Subject);
request.AddParameter("text", message.TextBody);
request.AddParameter("html", message.HtmlBody);
if (!string.IsNullOrWhiteSpace(message.IcalAttachment))
{
request.AddFileBytes("attachment",
Encoding.UTF8.GetBytes(message.IcalAttachment),
"invite.ics",
"text/calendar");
}
request.Method = Method.POST;
return request;
This results in the calendar being included in the email as an attachment, not an alternative view of the email. The attachment works fine in gmail however in Outlook it appears as an attachment file that you must first click on, then agree to adding the calendar to the Outlook calendar. Is there another way to use the REST api so that the calendar invites are sent correctly, as alternative email views?
To be clear, this is how I would send a calendar invite using .Net SmtpClient:
var contentType = new ContentType("text/calendar");
if (contentType.Parameters != null)
{
contentType.Parameters.Add("method", "REQUEST");
contentType.CharSet = "UTF-8";
}
// this is the same way you add a html view to the message
request.AlternateViews.Add(
AlternateView.CreateAlternateViewFromString(
message.IcalAttachment,
contentType));
Special thanks to Mailgun support for pointing me in the right direction. The relevant part or their response was:
You can use the /message.mime endpoint to construct the MIME for the calendar invite:
https://documentation.mailgun.com/api-sending.html#sending
Creating a mime message isnt as easy as simply using their /message endpoint but there are several .net libraries available to do this. I used MimeKit in this example.
var request = new RestRequest();
request.AddParameter("domain", this.domain, ParameterType.UrlSegment);
request.Resource = "{domain}/messages.mime";
request.AddParameter("to", contactDetails.RecipientAddress);
request.AddFile(
"message",
Encoding.UTF8.GetBytes(BuildMimeContent(message)),
"message.mime");
request.Method = Method.POST;
return request;
The mime content that I want to create will contain a multipart/mixed body, which will in turn contain a multipart/alternative as well as every attachment. The calendar invite will actually be attached twice, as a alternative view and as an attachment. This is to aid in compatibilitiy across different email clients.
The implementation of BuildMimeContent(message) looks like the following:
// create the alternative views
var textBody = new TextPart("plain") { Text = message.TextBody };
var htmlBody = new TextPart("html") { Text = message.HtmlBody };
// add views to the multipart/alternative
var alternative = new Multipart("alternative");
alternative.Add(textBody);
alternative.Add(htmlBody);
if (!string.IsNullOrWhiteSpace(message.CalendarInvite))
{
// also add the calendar as an alternative view
// encoded as base64, but 7bit will also work
var calendarBody = new TextPart("calendar")
{
Text = message.CalendarInvite,
ContentTransferEncoding = ContentEncoding.Base64
};
// most clients wont recognise the alternative view without the
// method=REQUEST header
calendarBody.ContentType.Parameters.Add("method", "REQUEST");
alternative.Add(calendarBody);
}
// create the multipart/mixed that will contain the multipart/alternative
// and all attachments
var multiPart = new Multipart("mixed") { alternative };
if (!string.IsNullOrWhiteSpace(message.CalendarInvite))
{
// add the calendar as an attachment
var calAttachment = new MimePart("application", "ics")
{
ContentDisposition = new ContentDisposition(ContentDisposition.Attachment),
ContentTransferEncoding = ContentEncoding.Base64,
FileName = "invite.ics",
ContentObject = new ContentObject(GenerateStreamFromString(message.CalendarInvite))
};
multiPart.Add(calAttachment);
}
// TODO: Add any other attachements to 'multipart' here.
// build final mime message
var mimeMessage = new MimeMessage();
mimeMessage.From.Add(GetMimeAddress(message.MessageInfo.SenderName, message.MessageInfo.SenderAddress));
mimeMessage.To.Add(GetMimeAddress(message.MessageInfo.RecipientName, message.MessageInfo.RecipientAddress));
mimeMessage.Subject = message.Subject;
mimeMessage.Body = multiPart;
// parse and return mime message
return mimeMessage.ToString();
Warning for people testing with Office 365
Office365 is extremely picky when it comes to validating calendar invites. In order to not get a message like the one below, you will need to ensure that the vCal's organizer email address matches the email's from address. This is not possible if you are using mailgun's sandbox test environment.

Attaching PDF file in email

I need to attach an receipt in the email which has been generated dynamically. I'm unable to attach the pdf file, it denotes me that path is not valid.
Here is my code:
public static IRestResponse SendConfirmationEmail(string emailaddress,string subject,string body)
{
RestClient client = new RestClient();
client.BaseUrl = "https://123456";
client.Authenticator = new HttpBasicAuthenticator("api", "key-abcdef12345huj");
RestRequest request = new RestRequest();
request.AddParameter("domain", "abc.com", ParameterType.UrlSegment);
request.Resource = "{domain}/messages";
request.AddParameter("from", "abc <abc#xyz.com>");
System.Net.Mail.Attachment attachment;
attachment = new System.Net.Mail.Attachment("~/users/Receipts/abc-414.pdf");
request.AddParameter("attachment",attachment);
request.AddParameter("c", emailaddress);
request.AddParameter("to", emailaddress);
request.AddParameter("subject", subject);
request.AddParameter("html", body);
request.Method = Method.POST;
return client.Execute(request);
}
Can any one help me out on this issue?
Thank you
try in this way
attachment = new System.Net.Mail.Attachment(HttpContext.Current.Server.MapPath("~/users/Receipts/abc-414.pdf"));
use Server.MapPath method that returns the physical file path that corresponds to the specified virtual path on the Web server.
I see that you are sending these parameters in a POST request. Did you check the process of serializing-deserializing? maybe there is something wrong in this step and that parameter is ignored

Upload file via POST call with C#, RestSharp, Redmine API

I'm developing a C# app that uses Redmine REST API, it uses RestSharp Client. All other REST calls I make work fine but I cannot find a way to upload attachments. I've widely searched the web and tried many solutions but nothing worked.
Redmine documentiation on attachments: http://www.redmine.org/projects/redmine/wiki/Rest_api#Attaching-files
The code actually looks like:
RestClient client = new RestClient("http://myclient/redmine/");
client.Authenticator = new HttpBasicAuthenticator("myuser", "mypsw");
var request2 = new RestRequest("uploads.json", Method.POST);
request2.AddHeader("Content-Type", "application/octet-stream");
request2.RequestFormat = RestSharp.DataFormat.Json;
byte[] dataToSend = File.ReadAllBytes(AddIssue.attach.Text);
request2.AddBody(dataToSend);
IRestResponse response2 = client.Execute(request2);
resultbox.Text = response2.Content;
If I execute it above nothing happens and the response is empty. If I remove line 7 (the AddBody), it actually works but of course nothing is uploaded, JSON response:
{
"upload": {
"token": "11."
}
}
So actually, the real question is what to punt in AddBody() to send the file as application/octet-stream. Since RestSharp also has a request.AddFile() method, I tried it too in different ways but nothing...
Any help much appreciated!
As I mentioned in my comment, it sounds like Redmine might have requirements similar to Dropbox. Here is the solution that worked for me (based on the question Upload to dropbox using Restsharp PCL):
public static void UploadFileToDropbox(string filePath)
{
RestClient client = new RestClient("https://api-content.dropbox.com/1/");
IRestRequest request = new RestRequest("files_put/auto/{path}", Method.PUT);
FileInfo fileInfo = new FileInfo(filePath);
long fileLength = fileInfo.Length;
request.AddHeader("Authorization", "Bearer INSERT_DEVELOPER_TOKEN_HERE");
request.AddHeader("Content-Length", fileLength.ToString());
request.AddUrlSegment("path", string.Format("Public/{0}", fileInfo.Name));
byte[] data = File.ReadAllBytes(filePath);
var body = new Parameter
{
Name = "file",
Value = data,
Type = ParameterType.RequestBody,
};
request.Parameters.Add(body);
IRestResponse response = client.Execute(request);
}
Also published as a Gist.
I know this isn't your exact situation, but hopefully it gives you some ideas.

Categories