ExchangeWebServices attachment load - email-attachments

I'm using EWS with JScript (I know, not recommended, but I have no choice!)...
I can connect to my Exchange server, log in, retrieve messages, and identify a message with a file attachment. Now I want to save that attachment locally.
I have:
for (x = 0; x < myMessages.Items.Count - 1; x++)
{
thisitem = myMessages.Items.get_Item(x);
if (thisitem.HasAttachments)
{
attachment = thisitem.Attachments.get_Item(0)
attachment.Load("c:\\temp.xls");
But this produces an error:
mscorlib
System.ArgumentException: Object of type "System.String" cannot be converted to type "System.IO.Stream"
....
I know the attachment is an XLS.... and it's something to do with the overloading of the Load method... But beyond that I'm lost.
Help?!

For anyone needing to do something like this, in the end I found this worked (this is Jscript in TestComplete - amend as you need to!):
if (thisitem.HasAttachments)
{
for (y = 0; y < thisitem.Attachments.Count; y++)
{
var attachment = thisitem.Attachments.get_Item(y);
if (attachment.get_IsInline() == false)
{
if (attachment.name.OleValue.indexOf(attachsuffix) == attachment.name.OleValue.length - attachsuffix.length)
{
attachment.Load();
aqFileSystem.CreateFolder(targetfolder)
var filename = targetfolder + attachment.Name.OleValue
var fos = dotNET.System_IO.BinaryWriter.zctor(dotNET.System_IO.File.Open(filename, dotNET.System_IO.FileMode.Create))
fos.write_3(attachment.content)
fos.Close();
Log.Message("Saved: " + filename);
}
}
}
}

Related

Word web addin load whole document from server header/footer

We are trying to load a word document from server using JavaScript. We send the document using a base64 encoding. With our current approach, only the body is loading using the function:
context.document.body.insertFileFromBase64(fileContent, "replace");
Unfortunately, the header and the footer are not loading. Is there another approach to load the whole document including body and footer?
the insertFile operation does not overwrite existing header/footers in the document.
According to my research, I saw this article for using insertFileFromBase64.The article says," if you use insertFileFromBase64 to insert the file it does have this blank page with header and footer." Did you have the same issue for this?
However, another article says it's a design issue. Userform will encode data and will create an appointment on Microsoft Outlook Calendar
The article provides approach:
function getFile(){
Office.context.document.getFileAsync(Office.FileType.Compressed, { sliceSize: 4194304 /*64 KB*/ },
function (result) {
if (result.status == "succeeded") {
// If the getFileAsync call succeeded, then
// result.value will return a valid File Object.
var myFile = result.value;
var sliceCount = myFile.sliceCount;
var slicesReceived = 0, gotAllSlices = true, docdataSlices = [];
console.log("File size:" + myFile.size + " #Slices: " + sliceCount);
// Get the file slices.
getSliceAsync(myFile, 0, sliceCount, gotAllSlices, docdataSlices, slicesReceived);
}
else {
app.showNotification("Error:", result.error.message);
}
});
}
function getSliceAsync(file, nextSlice, sliceCount, gotAllSlices, docdataSlices, slicesReceived) {
file.getSliceAsync(nextSlice, function (sliceResult) {
if (sliceResult.status == "succeeded") {
if (!gotAllSlices) { // Failed to get all slices, no need to continue.
return;
}
// Got one slice, store it in a temporary array.
// (Or you can do something else, such as
// send it to a third-party server.)
docdataSlices[sliceResult.value.index] = sliceResult.value.data;
if (++slicesReceived == sliceCount) {
// All slices have been received.
file.closeAsync();
onGotAllSlices(docdataSlices);
}
else {
getSliceAsync(file, ++nextSlice, sliceCount, gotAllSlices, docdataSlices, slicesReceived);
}
}
else {
gotAllSlices = false;
file.closeAsync();
console.log("getSliceAsync Error:", sliceResult.error.message);
}
});
}
function onGotAllSlices(docdataSlices) {
var docdata = [];
for (var i = 0; i < docdataSlices.length; i++) {
docdata = docdata.concat(docdataSlices[i]);
}
var fileContent = new String();
for (var j = 0; j < docdata.length; j++) {
fileContent += String.fromCharCode(docdata[j]);
}
var mybase64 = window.btoa(fileContent);
console.log("here is the base 64", mybase64);
// Now all the file content is stored in 'fileContent' variable,
// you can do something with it, such as print, fax...
}

How to add a line to a google spreadsheet via email?

I need a google apps script which can do the following:
if I send an email to my alias email, say to myemail+expenses#gmail.com, it adds a line in a specific google spreadsheet with data from that email. E.g. timestamp, subject, the first line of a body - whatever.
I found interesting article describing similar process of sending data to google spreadsheet.
May be there is no any direct way of doing that, however, it should exist some workaround.
P.S. It should be done only by using a google echosystem. No php, servers etc.
There are two step for this.
#1
At first create a trigger to run the mail checker.
function switchTrigger() {
var isExist = false;
var triggers = ScriptApp.getProjectTriggers();
for (var i = 0; i < triggers.length; i++) {
if ( /*<CONDITION>*/ ) {
isExist = true;
ScriptApp.deleteTrigger(triggers[i]);
}
}
if (!isExist) {
ScriptApp.newTrigger( /*<CONDITION>*/ ).create();
Logger.log('create');
}
}
#2
Then you have to check emails. Something like that
function checkMail() {
var sh = SpreadsheetApp.openById(properties.targetSheetId).getSheets()[0];
var query = /* properties.queryString */ ;
var threads = GmailApp.search(query);
if (threads.length < 1) return;
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var j = 0; j < messages.length; j++) {
if (messages[j].isStarred()) {
sh.appendRow([
new Date(),
messages[j].getFrom(),
messages[j].getPlainBody()
]);
messages[j].unstar();
}
}
}
}
Be careful. You have to set up Gmail filters so that all incoming to myemail+expenses#gmail.com would be marked with an star at the beginning.
Working Example

CSV File create in Google Apps

I have tried to Upload .csv file via API using Google Apps (Script).
I give the below property in part of API URL.
"ZOHO_FILE":file.csv
Is there any way to create .csv file in Google Apps Script ?
If possible, pls let us know, how can create .csv file in Google Apps ?
Sorry for my english :-(
You can use this to convert a data range:
function convertRangeToCsvFile(dataRange) {
try {
var data = dataRange.getValues();
var csvFile = undefined;
// Loop through the data in the range and build a string with the CSV data
if (data.length > 1) {
var csv = "";
for (var row = 0; row < data.length; row++) {
for (var col = 0; col < data[row].length; col++) {
if (data[row][col].toString().indexOf(",") != -1) {
data[row][col] = "\"" + data[row][col] + "\"";
}
}
// Join each row's columns
// Add a carriage return to end of each row, except for the last one
if (row < data.length-1) {
csv += data[row].join(",") + "\r\n";
}
else {
csv += data[row];
}
}
csvFile = csv;
}
return csvFile;
}
catch(err) {
Logger.log(err);
Browser.msgBox(err);
}
}
or this to download a whole sheet
function downloadSpreadsheet(){
//This function generates a pdf of your current spreadsheet and emails it to yourself as attachment
//Make sure your spreadsheet is not too big. The pdf size tends to be 200kb/page and if too large
//if the pdf is too large the urlFetch might timeout
var AUTH_TOKEN = "xxxxxxxxxxxxxx"; //Enter your AUTH_TOKEN
//You can receive it from https://appscripts.appspot.com/getAuthToken
var ssID=SpreadsheetApp.getActiveSpreadsheet().getId()+"&gid="+SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getSheetId();
var url = "https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key="
+ ssID + "&exportFormat=csv";
//Add &gid=x at the end of above url if you only want a particular sheet
//gid of a sheet can be obtained by the undocumented function getSheetId()
//ex: SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getSheetId();
//exportFormat=xls did not work when I tried. I dont know why
var auth = "AuthSub token=\"" + AUTH_TOKEN + "\"";
var res = UrlFetchApp.fetch(url, {headers: {Authorization: auth}});
var content=res.getContentText();
return content
}
You asked for Apps Script, I hope;
Section 2 and 3 of the article below tells how to import and export CSV
https://developers.google.com/apps-script/articles/docslist_tutorial#section2

' ', hexadecimal value 0x1F, is an invalid character. Line 1, position 1

I am trying to read a xml file from the web and parse it out using XDocument. It normally works fine but sometimes it gives me this error for day:
**' ', hexadecimal value 0x1F, is an invalid character. Line 1, position 1**
I have tried some solutions from Google but they aren't working for VS 2010 Express Windows Phone 7.
There is a solution which replace the 0x1F character to string.empty but my code return a stream which doesn't have replace method.
s = s.Replace(Convert.ToString((byte)0x1F), string.Empty);
Here is my code:
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
using (var reader = new StreamReader(e.Result))
{
int[] counter = { 1 };
string s = reader.ReadToEnd();
Stream str = e.Result;
// s = s.Replace(Convert.ToString((byte)0x1F), string.Empty);
// byte[] str = Convert.FromBase64String(s);
// Stream memStream = new MemoryStream(str);
str.Position = 0;
XDocument xdoc = XDocument.Load(str);
var data = from query in xdoc.Descendants("user")
select new mobion
{
index = counter[0]++,
avlink = (string)query.Element("user_info").Element("avlink"),
nickname = (string)query.Element("user_info").Element("nickname"),
track = (string)query.Element("track"),
artist = (string)query.Element("artist"),
};
listBox.ItemsSource = data;
}
}
XML file:
http://music.mobion.vn/api/v1/music/userstop?devid=
0x1f is a Windows control character. It is not valid XML. Your best bet is to replace it.
Instead of using reader.ReadToEnd() (which by the way - for a large file - can use up a lot of memory.. though you can definitely use it) why not try something like:
string input;
while ((input = sr.ReadLine()) != null)
{
string = string + input.Replace((char)(0x1F), ' ');
}
you can re-convert into a stream if you'd like, to then use as you please.
byte[] byteArray = Encoding.ASCII.GetBytes( input );
MemoryStream stream = new MemoryStream( byteArray );
Or else you could keep doing readToEnd() and then clean that string of illegal characters, and convert back to a stream.
Here's a good resource for cleaning illegal characters in your xml - chances are, youll have others as well...
https://seattlesoftware.wordpress.com/tag/hexadecimal-value-0x-is-an-invalid-character/
What could be happening is that the content is compressed in which case you need to decompress it.
With HttpHandler you can do this the following way:
var client = new HttpClient(new HttpClientHandler
{
AutomaticDecompression = DecompressionMethods.GZip
| DecompressionMethods.Deflate
});
With the "old" WebClient you have to derive your own class to achieve the similar effect:
class MyWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest;
request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
return request;
}
}
Above taken from here
To use the two you would do something like this:
HttpClient
using (var client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }))
{
using (var stream = client.GetStreamAsync(url))
{
using (var sr = new StreamReader(stream.Result))
{
using (var reader = XmlReader.Create(sr))
{
var feed = System.ServiceModel.Syndication.SyndicationFeed.Load(reader);
foreach (var item in feed.Items)
{
Console.WriteLine(item.Title.Text);
}
}
}
}
}
WebClient
using (var stream = new MyWebClient().OpenRead("http://myrss.url"))
{
using (var sr = new StreamReader(stream))
{
using (var reader = XmlReader.Create(sr))
{
var feed = System.ServiceModel.Syndication.SyndicationFeed.Load(reader);
foreach (var item in feed.Items)
{
Console.WriteLine(item.Title.Text);
}
}
}
}
This way you also recieve the benefit of not having to .ReadToEnd() since you are working with the stream instead.
Consider using System.Web.HttpUtility.HtmlDecode if you're decoding content read from the web.
If you are having issues replacing the character
For me there were some issues if you try to replace using the string instead of the char. I suggest trying some testing values using both to see what they turn up. Also how you reference it has some effect.
var a = x.IndexOf('\u001f'); // 513
var b = x.IndexOf(Convert.ToString((byte)0x1F)); // -1
x = x.Replace(Convert.ToChar((byte)0x1F), ' '); // Works
x = x.Replace(Convert.ToString((byte)0x1F), " "); // Fails
I blagged this
I had the same issue and found that the problem was a  embedded in the xml.
The solution was:
s = s.Replace("", " ")
I'd guess it's probably an encoding issue but without seeing the XML I can't say for sure.
In terms of your plan to simply replace the character but not being able to, because you have a stream rather than a text, simply read the stream into a string and then remove the characters you don't want.
Works for me.........
string.Replace(Chr(31), "")
I used XmlSerializer to parse XML and faced the same exception.
The problem is that the XML string contains HTML codes of invalid characters
This method removes all invalid HTML codes from string (based on this thread - https://forums.asp.net/t/1483793.aspx?Need+a+method+that+removes+illegal+XML+characters+from+a+String):
public static string RemoveInvalidXmlSubstrs(string xmlStr)
{
string pattern = "&#((\\d+)|(x\\S+));";
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
if (regex.IsMatch(xmlStr))
{
xmlStr = regex.Replace(xmlStr, new MatchEvaluator(m =>
{
string s = m.Value;
string unicodeNumStr = s.Substring(2, s.Length - 3);
int unicodeNum = unicodeNumStr.StartsWith("x") ?
Convert.ToInt32(unicodeNumStr.Substring(1), 16)
: Convert.ToInt32(unicodeNumStr);
//according to https://www.w3.org/TR/xml/#charsets
if ((unicodeNum == 0x9 || unicodeNum == 0xA || unicodeNum == 0xD) ||
((unicodeNum >= 0x20) && (unicodeNum <= 0xD7FF)) ||
((unicodeNum >= 0xE000) && (unicodeNum <= 0xFFFD)) ||
((unicodeNum >= 0x10000) && (unicodeNum <= 0x10FFFF)))
{
return s;
}
else
{
return String.Empty;
}
})
);
}
return xmlStr;
}
Nobody can answer if you don't show relevant info - I mean the Xml content.
As a general advice I would put a breakpoint after ReadToEnd() call. Now you can do a couple of things:
Reveal Xml content to this forum.
Test it using VS Xml visualizer.
Copy-paste the string into a txt file and investigate it offline.

How do I send XML as the email body from a native iPhone app?

I am writing an app that ultimately wants to send some XML via email.
I have the mailto/URL thing sussed, thanks to various links on the interweb, including Brandon and Simon Maddox.
So I can send emails with the xml formatted using square brackets ([ ]), rather than the usual angle brackets (< >). But when I send angle brackets, with the XML mangled using the stringByAddingPercentEscapesUsingEncoding call, It treats it as HTML and just prints the values.
If change them to "& lt;" and "& gt;" then it totally strips the XML out... (I know there should not be a space after the & - but the SO formatter turns them into <,>...)
I tried adding some HTML in front to see if that helped, to no avail.
I don't suppose anyone has done this?
Perhaps in-app email is the easy route for me to go... must look into that.
Thanks in advance.
The following code worked for me... I have SIP message data containing <> that needed escaping.
/* remember to call urlEscapeStringDone to free the malloced string.. */
char *urlEscapeString(char *str)
{
int i, l;
char *escStr;
escStr = malloc(strlen(str)*3 + 1);
if(!escStr) return NULL;
memset(escStr, 0, strlen(str)*3);
l = strlen(escStr);
for(i = 0; i < strlen(str); i++)
{
char c = str[i];
/* < and > handling for HTML interpreters.. (apple mail) */
if(c == '<')
{
strcat(escStr, "%26lt%3b");
l += 8;
}
else if(c == '>')
{
strcat(escStr, "%26gt%3b");
l += 8;
}
else if(must_escape(c))
{
char tmp[3];
sprintf(tmp, "%02x", (unsigned) c);
escStr[l] = '%'; l++;
escStr[l] = tmp[0]; l++;
escStr[l] = tmp[1]; l++;
}
else
{
escStr[l] = str[i];
l++;
}
}
printf("escaped: %s\n", escStr);
return escStr;
}
void urlEscapeStringDone(char *str)
{
if(str) free(str);
}
int must_escape(char c)
{
char *allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._";
if(!strchr(allowedChars, c)) return 1;
return 0;
}
Did you try replacing all the '<' and '>' characters with '&lt' and '&gt' after you had wrapped it in the basic HTML headers?
As I understand it, this is the usual technique to display XML on a web page.