Excel file send through Send grid attachment C# is corrupted - sendgrid

I'm using sendgrid to send mails with attachments. But seems like excel file is corrupted in the mail. This is the code I'm using
byte[] byteData = System.Text.Encoding.ASCII.GetBytes(File.ReadAllText(#"fullpath\test.xlsx"));
msg.Attachments = new List<SendGrid.Helpers.Mail.Attachment>
{
new SendGrid.Helpers.Mail.Attachment
{
Content = Convert.ToBase64String(byteData),
Filename = "test.xlsx",
Type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
Disposition = "attachment"
}
};
On opening of excel file, I'm getting a popup "We found a problem with content...If you trust click "Yes". On Yes, Excel cannot open this file. Can anyone please help me on this
#Sendgrid

Twilio SendGrid developer evangelist here.
I think the issue may be that you are getting the byte data by reading the file as text and then converting that text to bytes through the lens of ASCII encoding. It may work better to just read the file as bytes initially.
Try:
byte[] byteData = File.ReadAllBytes(#"fullpath\test.xlsx");
msg.Attachments = new List<SendGrid.Helpers.Mail.Attachment>
{
new SendGrid.Helpers.Mail.Attachment
{
Content = Convert.ToBase64String(byteData),
Filename = "test.xlsx",
Type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
Disposition = "attachment"
}
};

Try below
msg.AddAttachment("test.xlsx"); // Physical file path
Make assure file path is relevant
or You try with Bytes as well,
var bytes = File.ReadAllBytes(filePath);
var file = Convert.ToBase64String(bytes);
msg.AddAttachment("Name.xls", file);

Related

How to attach a google doc file as Microsoft Word doc

My first time here in Stack overflow. I'm just an amateur programmer trying to learn Google Apps script. I created a google form to get answers from users. I have transferred the answers to a google doc formatted according to our use in the office. I need to email the google doc back to the for user in microsoft word format. Sending as pdf is not a problem, but msword is a bit tricky.
I tried copying the recommendations i found here but I can't seem to get it to run. I hope someone can tell me what i'm doing wrong and what i need to doe. here's the relevant portion of the code:
`doc.saveAndClose(); // end of the transfer from google sheet to google doc. now to email...
var filename= ts+"-"+c_name1;
var compfile = DriveApp.getFilesByName(filename);
if (!compfile.hasNext())
{
console.error("Could not open file "+filename);
return;
}
var template = HtmlService.createTemplateFromFile('email_message');
var message = template.evaluate().getContent();
MailApp.sendEmail({
to:em,
subject: "Automated Complaint Assistant",
htmlBody: message,
attachments: compfile.next()}) // attachment is pdf file type. HOW TO SEND AS WORD?
`
I tried this function i found here:
`function EmailCompAsWordDoc(email, name, newCopyID) {
var subject = "Word version of Complaint";
var body = "\n\nHere is the Microsoft Word version of the draft Complaint";
var url = 'https://docs.google.com/feeds/download/documents/export/Export?id=' + newCopyID + '&exportFormat=docx';
var options = {
headers: {
Authorization: "Bearer " + ScriptApp.getOAuthToken()
},
muteHttpExceptions: true
}
var response = UrlFetchApp.fetch(url, options);
var doc = response.getBlob();
//Create the docx file in my TEMP folder in Google Drive and send
var file = DriveApp.createFile(doc).setName('Draft Complaint '+ name + '.docx');
DriveApp.getFolderById('<ID of my TEMP folder in Google Drive>').addFile(file);
var blob = DriveApp.getFileById(file.getId());
if (MailApp.getRemainingDailyQuota() > 0)
GmailApp.sendEmail(email, subject, body, {
Body: body,
attachments:[blob]
});
//Remove the docx file from the TEMP folder
DriveApp.getFileById(file.getId()).setTrashed(true);
}
var compid = DriveApp.getFileById(filename.getId()) // error here. How to get the file ID for use by this custom function??
EmailCompAsWordDoc(em, c_name1, compid)
`
From your provided script, I understood that the value of filename is the string value of var filename = ts + "-" + c_name1;. I thought that this is the reason for your current issue of filename.getId is not a function.
In this case, how about the following modification?
From:
var compid = DriveApp.getFileById(filename.getId())
To:
var compid = DriveApp.getFilesByName(filename).next().getId();
In this case, it supposes that the values of filename and em and c_name1 of EmailCompAsWordDoc(em, c_name1, compid) are valid values. Please be careful about this.

Download PDF from URL not ending on pdf generating corrupted PDF file

I am downloading PDF files from URLs using scala using below code and it is working fine
var out: OutputStream = null;
var in: InputStream = null;
val url = new URL( """http://www.pdf995.com/samples/pdf.pdf""")
val connection = url.openConnection().asInstanceOf[HttpURLConnection]
connection.setRequestMethod("GET")
in = connection.getInputStream
val localfile = "sample2.pdf"
out = new BufferedOutputStream(new FileOutputStream(localfile))
val byteArray = Stream.continually(in.read).takeWhile(-1 !=).map(_.toByte).toArray
out.write(byteArray)
but when I give URLs which does not end with "PDF" for example URL given below
https://www.google.com.pk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=51&ved=0ahUKEwjq19ah8MbKAhXEj44KHeWAB6g4MhAWCBgwAA&url=http%3A%2F%2Fwww.us.fulbrightonline.org%2Fuploads%2Ffiles%2Fapplication_samples%2FForm9B_ETA_Reference_Form-Sample.pdf&usg=AFQjCNGZnon3ygHDJnW12Te8JrBR-o6jyw&sig2=OgSgD4HnUXZ9l_VS0AwGFg&bvm=bv.112454388,d.c2E&cad=rja
it does not generate PDF file properly. While opening that PDF "Not a PDF or corrupted error" comes.
If you read your URL and chop off the hash at the end (all that comes after .pdf, you'll see the link that Google is pointing to embedded in there:
https://www.google.com.pk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=51&ved=0ahUKEwjq19ah8MbKAhXEj44KHeWAB6g4MhAWCBgwAA&url=http%3A%2F%2Fwww.us.fulbrightonline.org%2Fuploads%2Ffiles%2Fapplication_samples%2FForm9B_ETA_Reference_Form-Sample.pdf
Here's the direct link (use this for your project):
http://www.us.fulbrightonline.org/uploads/files/application_samples/Form9B_ETA_Reference_Form-Sample.pdf

Open xml encoding

Im using Open XML SDK to read and write information to custom xml parts in a Word document.
Im serializing a xml structure into a class , modifying the data and serializing it back into the document.
Example code
DocumentFormat.OpenXml.Packaging.CustomXmlPart myPart = GetCustomXmlPart(mainPart, AITNamespaces.SiteDataNameSpace);
StreamReader myStrR = new System.IO.StreamReader(myPart.GetStream());
string myXML = myStrR.ReadToEnd();
sitedata = ObjectXMLSerializer<WDSiteData>.LoadString(myXML);
Site selSite = _applicationService.GetApplicationData().Sites.Find(item => item.Id == siteId);
sitedata.SiteId= selSite.Id;
sitedata.SiteName = "ööööaaaaaåååå"; // selSite.SiteName;
myXML = ObjectXMLSerializer<WDSiteData>.GetXMLString(sitedata);
myPart = GetCustomXmlPart(wordProcDocument.MainDocumentPart, AITNamespaces.SiteDataNameSpace);
using (StreamWriter sw = new StreamWriter(myPart.GetStream(FileMode.Create)))
{
sw.Write(myXML);
}
My problem is that the national characters become encoded and the text "ööööaaaaaåååå" is displayed in the word document as "????????aaaaa????????"
The actual encoding is done
myXML = ObjectXMLSerializer<WDSiteData>.GetXMLString(sitedata);
Anyone has a clue on how to go about handling national characters this way.
For whom it concerns , my trouble was that in my serializer the encoding was fixed
return ASCIIEncoding.ASCII.GetString(memStream.ToArray());
When i changed to
return ASCIIEncoding.UTF8.GetString(memStream.ToArray());
all is well.

Sending an email attachment in memory using OpenXML

I've got an Excel file that's built using OpenXML 2 and I want to send it as an email attachment. e.g.
System.IO.MemoryStream stream = new System.IO.MemoryStream();
SpreadsheetDocument package = SpreadsheetDocument.Create(stream, SpreadsheetDocumentType.Workbook))
AddParts(package); //created using document reflector
Saving the spreadsheet to a temp file using
stream.WriteTo(new System.IO.FileStream(#"c:\test.xlsx", System.IO.FileMode.Create));
works fine. But trying to send the stream directly as an email attachment fails - just get an empty file attached to the email when I do
System.Net.Mail.Attachment file = new System.Net.Mail.Attachment(stream, "MobileBill.xlsx", "application/vnd.ms-excel");
Anbody know how to do this?
Ok, I got this working, though through some effort. To create the stream:
MemoryStream stream = new MemoryStream();
using (SpreadsheetDocument package = SpreadsheetDocument.Create(stream, SpreadsheetDocumentType.Workbook))
{
Excel.CreateSpreadsheet(package, Excel_Methods.CreateSpotQuoteOut(), true);
}
stream.Seek(0, SeekOrigin.Begin);
System.Net.Mail.Attachment attach = new System.Net.Mail.Attachment(stream, "spreadsheet.xlsx");
attach.ContentDisposition.CreationDate = DateTime.Now;
attach.ContentDisposition.ModificationDate = DateTime.Now;
attach.ContentDisposition.Inline = false;
attach.ContentDisposition.Size = stream.Length;
attach.ContentType.MediaType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Also, I found that mine were not being sent right after I created them, and the reason for that is "standalone=yes" was not being added to the xml declaration of all the pages, so in my AddParts function, after adding the parts, I passed them into this function:
private static void AddXMLStandalone(OpenXmlPart part)
{
System.IO.StreamWriter writer = new System.IO.StreamWriter(part.GetStream());
XmlDocument doc = new XmlDocument();
doc.Load(part.GetStream());
doc.InnerXml = doc.InnerXml.Substring(doc.InnerXml.IndexOf("?>") + 2);
doc.InnerXml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + doc.InnerXml;
part.GetStream().SetLength(doc.InnerXml.Length);
doc.Save(writer);
writer.Flush();
writer.Close();
}
Good luck!
do this:
System.Net.Mail.Attachment file = new System.Net.Mail.Attachment(new MemoryStream(stream.ToArray()), "MobileBill.xlsx", "application/vnd.ms-excel");
Apparently the memory stream doesn't get flushed or something
For your "content unreadable" problem, make sure to Save() your Workbooks and Worksheets and enclose your SpreadsheetDocument in a using statement to ensure all packages and zipped streams are flushed, closed and so on.
System.IO.MemoryStream stream = new System.IO.MemoryStream();
using (SpreadsheetDocument package = SpreadsheetDocument.Create(stream, SpreadsheetDocumentType.Workbook)))
{
AddParts(package);
//Save if AddParts hasn't done it
}
System.Net.Mail.Attachment file = ...
Thinking out load: could it be, that the Attachment class expects to read from the current possition in the provided stream? If this is the case, you would probably have to "seek" back to the beginning of the stream, before feeding it to the Attachment constructor:
AddParts(package); //created using document reflector
stream.Seek(0, SeekOrigin.Begin);
System.Net.Mail.Attachment file = new System.Net.Mail.Attachment(stream, "MobileBill.xlsx", "application/vnd.ms-excel");

Custom clipboard data format accross RDC (.NET)

I'm trying to copy a custom object from a RDC window into host (my local) machine. It fails.
Here's the code that i'm using to 1) copy and 2) paste:
1) Remote (client running on Windows XP accessed via RDC):
//copy entry
IDataObject ido = new DataObject();
XmlSerializer x = new XmlSerializer(typeof(EntryForClipboard));
StringWriter sw = new StringWriter();
x.Serialize(sw, new EntryForClipboard(entry));
ido.SetData(typeof(EntryForClipboard).FullName, sw.ToString());
Clipboard.SetDataObject(ido, true);
2) Local (client running on local Windows XP x64 workstation):
//paste entry
IDataObject ido = Clipboard.GetDataObject();
DataFormats.Format cdf = DataFormats.GetFormat(typeof(EntryForClipboard).FullName);
if (ido.GetDataPresent(cdf.Name)) //<- this always returns false
{
//can never get here!
XmlSerializer x = new XmlSerializer(typeof(EntryForClipboard));
string xml = (string)ido.GetData(cdf.Name);
StringReader sr = new StringReader(xml);
EntryForClipboard data = (EntryForClipboard)x.Deserialize(sr);
}
It works perfectly on the same machine though.
Any hints?
There are a couple of things you could look into:
Are you sure the serialization of the object truely converts it into XML? Perhaps the outputted XML have references to your memory space? Try looking at the text of the XML to see.
If you really have a serialized XML version of the object, why not store the value as plain-vanilla text and not using typeof(EntryForClipboard) ? Something like:
XmlSerializer x = new XmlSerializer(typeof(EntryForClipboard));
StringWriter sw = new StringWriter();
x.Serialize(sw, new EntryForClipboard(entry));
Clipboard.SetText(sw.ToString(), TextDataFormat.UnicodeText);
And then, all you'd have to do in the client-program is check if the text in the clipboard can be de-serialized back into your object.
Ok, found what the issue was.
Custom format names get truncated to 16 characters when copying over RDC using custom format.
In the line
ido.SetData(typeof(EntryForClipboard).FullName, sw.ToString());
the format name was quite long.
When i was receiving the copied data on the host machine the formats available had my custom format, but truncated to 16 characters.
IDataObject ido = Clipboard.GetDataObject();
ido.GetFormats(); //used to see available formats.
So i just used a shorter format name:
//to copy
ido.SetData("MyFormat", sw.ToString());
...
//to paste
DataFormats.Format cdf = DataFormats.GetFormat("MyFormat");
if (ido.GetDataPresent(cdf.Name)) {
//this not works
...