I have looked through the questions i can find on here about attaching a file to a sendgrid email but none seem to have the issue I am.
My question is is this. How do you send an email with an attachment in sendgrid using the api?
dynamic sg = new SendGridAPIClient(apiKey);
var from = new SendGrid.Helpers.Mail.Email("jkennedy#domain.com");
var subject = "Hello World from the SendGrid C# Library!";
var to = new SendGrid.Helpers.Mail.Email(toAddress);
var content = new Content("multipart/form-data", "Textual content");
var attachment = new Attachment {Filename = attachmentPath };
var mail = new Mail(from, subject, to, content);
var ret = mail.Get();
mail.AddAttachment(attachment);
dynamic response = await sg.client.mail.send.post(requestBody: ret);
If i put the mail.attachment after the get the mail sends but there is no attachment. If i put the addattachment line before the get i get a "bad request" message.
I have yet to find an example of exactly how to do this.
Also, the path to the file is c:\tblaccudatacounts.csv
After struggling with this for a couple hours, I found an answer using sendgrid's V3 API. Here's what I learned.
In your example, you call var ret = mail.Get(); before adding the attachment. Since mail.Get() is essentially serializing the mail object into the Json format SendGrid is expecting, adding the attachment after the mail.Get() call will not actually add it to the mail object.
The other thing you should know is that the API doesn't have a way of simply taking the file path as an input (At least that I can find, I hope someone can correct me). You need to manually set at least the content (as a base 64 string) and filename. You can find more information here.
Here is my working solution:
string apiKey = "your API Key";
dynamic sg = new SendGridAPIClient(apiKey);
Email from = new Email("your#domain.com");
string subject = "Hello World from the SendGrid CSharp Library!";
Email to = new Email("destination#there.com");
Content body = new Content("text/plain", "Hello, Email!");
Mail mail = new Mail(from, subject, to, body);
byte[] bytes = File.ReadAllBytes("C:/dev/datafiles/testData.txt");
string fileContentsAsBase64 = Convert.ToBase64String(bytes);
var attachment = new Attachment
{
Filename = "YourFile.txt",
Type = "txt/plain",
Content = fileContentsAsBase64
};
mail.AddAttachment(attachment);
dynamic response = await sg.client.mail.send.post(requestBody: mail.Get());
I figure it out. I was using a helper written by a third party. I went with what with SendGrid actually suggested. See code below that is now working.
var myMessage = new SendGridMessage {From = new MailAddress("info#email.com")};
myMessage.AddTo("Jeff Kennedy <info#info.com>");
myMessage.Subject = "test email";
myMessage.Html = "<p>See Attachedment for Lead</p>";
myMessage.Text = "Hello World plain text!";
myMessage.AddAttachment("C:\\tblaccudatacounts.csv");
var apiKey = "apikey given by sendgrid";
var transportWeb = new Web(apiKey);
await transportWeb.DeliverAsync(myMessage);
Related
I tried the following code and it didn't worked out.
Byte[] bytes = System.IO.File.ReadAllBytes(filePath);
String file = Convert.ToBase64String(bytes);
chatMessage = new ChatMessage
{
Body = new ItemBody
{
ContentType = BodyType.Html,
Content ="this is test message, <attachment id=" + "someguid ID" + "></attachment>"
},
Attachments = new List<ChatMessageAttachment>()
{
new ChatMessageAttachment
{
Id = "someguid ID",
ContentType = "application/pdf",
Name = Path.GetFileName(x),
Content = file
}
}
};
await graphClient.Teams[cbTeam.SelectedValue.ToString()].Channels[cbChannel.SelectedValue.ToString()].Messages
.Request()
.AddAsync(chatMessage);
The error I am getting from graph is unable to process the content
From the chatMessage resource type documentation, attachments property is currently read-only and sending attachments is not supported - which would explain the error above. Kindly consider filing a feature request so this can be looked into.
Let me know if this helps.
I am using the SendGrid v3 API and C# library (v7) to send an email.
In my email I have a header which is a png. The header is embedded like this:
<img src="cid:emailheader"/>
In the C# code I send the image as an attachment with with the same ContentId
var mail = new Mail(from, subject, to, content);
var headerPath = HttpContext.Current.Server.MapPath("~/Resources/email-header.png");
var attachment = new SendGrid.Helpers.Mail.Attachment();
attachment.ContentId = "emailheader";
attachment.Content = Convert.ToBase64String(File.ReadAllBytes(headerPath));
attachment.Type = "image/png";
attachment.Filename = "email-header.png";
mail.AddAttachment(attachment);
var send = sg.client.mail.send.post(requestBody: mail.Get());
Yet when I open the email it says the source is not found, even though the image is correctly displayed in the attachment
I'm not the expert for Sendgrid, but I found on there blog post
that this suggest to do inline encoding in your html directly. this way you don't need to add an attachment. (I'm use this quite a lot)
<img alt="My Image" src="data:image/jpeg;base64,/9j/4S/+RXhpZgAATU0AKgA...more encoding" />
Maybe this is a work around for you.
As an second alternative:
for sending out emails with pictures I'm using
System.Net.Mail
here I do add an AlternateView with a linked resource.
AlternateView htmlView = AlternateView.CreateAlternateViewFromString(html, null, "text/html");
LinkedResource imageResource = new LinkedResource(Imagepath + "Monitoring.png", "image/png")
{
ContentId = "1",
TransferEncoding = System.Net.Mime.TransferEncoding.Base64
};
htmlView.LinkedResources.Add(imageResource);
message.AlternateViews.Add(htmlView);
the syntax in html is the same as you use
<img src="cid:1">
I hope this help.
Butti
node
//imageData= "data:image/png;base64,ine793nfdsf......."
imageb64 = imageData.replace('data:image/png;base64,' , '');
//remove data:image/png;base64,
const msg = {
to: 'example#gmail.com',
from: 'test#gmail.com',
subject: "image attached",
html :'<img src="cid:myimagecid"/>',
attachments: [
{
filename: "imageattachment.png",
content: imageb64,
content_id: "myimagecid",
}
]
};
sgMail.send(msg);
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.
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.
I want to know the best way for sending emails with attachment between Thread OR Async in ASP.net MVC C#.
OR
Do I need to use other library for sending email with attachments.
If someone provide sample working code. It would be great.
Thanks
using(var client = new SmtpClient())
{
var message = new MailMessage(from, to);
message.body = "body text";
message.subject = "subject text";
message.Attachments.Add(new Attachment("path to file"));
await client.SendAsync(message);
}