EWS - import email into sql database - sql

I've been trying to import the body from emails into a field in a SQL 2005 database but it keeps losing the formatting (carriage returns, tabs, etc)
Anyway of getting around this?

This is the code I used to strip an email body of the html formatting and all the characters so you are left with the actual email content. It looks like a mess, but it works:
foreach (Item item in findResults.Items)
{
MessageBody messageBody = new Microsoft.Exchange.WebServices.Data.MessageBody();
List<Item> items = new List<Item>();
if (findResults.Items.Count > 0) // Prevent the exception
{
foreach (Item item2 in findResults)
{
items.Add(item2);
}
}
service.LoadPropertiesForItems(items, PropertySet.FirstClassProperties);
messageBody = item.Body.ToString().Replace("<html dir=", "").Replace("<head>", "").Replace("<meta http-equiv=", "").Replace("content=", "")
.Replace("<style type=", "").Replace("</style>", "").Replace("</head>", "").Replace("<body fpstyle=", "").Replace("ocsi=", "")
.Replace("<div style=", "").Replace("direction: ltr;font-family: Tahoma;color: #000000;font-size: 10pt;", "").Replace("</div>", "")
.Replace("<div>", "").Replace("</body>", "").Replace("</html>", "").Replace("<br>", "").Replace(">", "").Replace("\"Content-Type", "")
.Replace("\"text/html; charset=utf-8", "").Replace("\"0", "").Replace("\"", "").Replace("text/css", "")
.Replace("id=owaParaStyle", "").Replace("ltr", "").Replace("<meta name=GENERATOR MSHTML 9.00.8112.16470", "").Replace("<style P {", "")
.Replace("MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px", "").Replace("<p", "").Replace("</p>", "").Replace("</p", "").Replace(" ", "")
.Replace("<body fPStyle= ", "").Replace("%", "").Replace("<", "").Replace(">", "").Replace("}", "").Replace("\"","").Replace("body fPStyle=1","");

What data type if your field in SQL? If you're using a "text" field (nvarchar or similar) then this is likely to be the cause.
If you really need the e-mail body intact then you'll probably need to store it as a blob (binary) field. This will have implications (you should read up about storing binary object in SQL) but it will allow you to store the body of the message.
Presumably you have some good reason why these messages need to be stored IN SQL and not outside (on the file system for example) with only pointers to the messages in SQL?

I've managed to find the problem. The dataset I was using was passing the values though as a string. I've changed to char and all formats are preserved. Thanks so much for you help.

Related

String matching in scripts

I have a code to reply to all operator messages in SAP. I need it to be applied specifically based on string match. As i am new to scripts, I don't have much idea in which language it has been orignally written. Please help me with the issue. Thanks.
{
String query = "select OperatorMessage.* from OperatorMessage";
for (OperatorMessage oMessage : jcsSession.executeObjectQuery(OperatorMessage.TYPE, query))
{
//Check the operator message requires a reply
if (oMessage.getReplyStatus() == ReplyStatus.valueOf("Required"))
{
oMessage.setReply("Acknowledge");
jcsSession.persist();
}
}
}
My expected output should be, that it should work only with the provided string for string match. Example of such string can be:
"Please check PROCESS_X_215, 4693422521, in XYZ_Queue with status Error"

In VTD-XML how to add new attribute into tag with existing attributes?

I'm using VTD-XML to update XML files. In this I am trying to get a flexible way of maintaining attributes on an element. So if my original element is:
<MyElement name="myName" existattr="orig" />
I'd like to be able to update it to this:
<MyElement name="myName" existattr="new" newattr="newValue" />
I'm using a Map to manage the attribute/value pairs in my code and when I update the XML I'm doing something like the following:
private XMLModifier xm = new XMLModifier();
xm.bind(vn);
for (String key : attr.keySet()) {
int i = vn.getAttrVal(key);
if (i!=-1) {
xm.updateToken(i, attr.get(key));
} else {
xm.insertAttribute(key+"='"+attr.get(key)+"'");
}
}
vn = xm.outputAndReparse();
This works for updating existing attributes, however when the attribute doesn't already exist, it hits the insert (insertAttribute) and I get "ModifyException"
com.ximpleware.ModifyException: There can be only one insert per offset
at com.ximpleware.XMLModifier.insertBytesAt(XMLModifier.java:341)
at com.ximpleware.XMLModifier.insertAttribute(XMLModifier.java:1833)
My guess is that as I'm not manipulating the offset directly this might be expected. However I can see no function to insert an an attribute at a position in the element (at end).
My suspicion is that I will need to do it at the "offset" level using something like xm.insertBytesAt(int offset, byte[] content) - as this is an area I have needed to get into yet is there a way to calculate the offset at which I can insert (just before the end of the tag)?
Of course I may be mis-using VTD in some way here - if there is a better way of achieving this then happy to be directed.
Thanks
That's an interesting limitation of the API I hadn't encountered yet. It would be great if vtd-xml-author could elaborate on technical details and why this limitation exists.
As a solution to your problem, a simple approach would be to accumulate your key-value pairs to be inserted as a String, and then to insert them in a single call after your for loop has terminated.
I've tested that this works as per your code:
private XMLModifier xm_ = new XMLModifier();
xm.bind(vn);
String insertedAttributes = "";
for (String key : attr.keySet()) {
int i = vn.getAttrVal(key);
if (i!=-1) {
xm.updateToken(i, attr.get(key));
} else {
// Store the key-values to be inserted as attributes
insertedAttributes += " " + key + "='" + attr.get(key) + "'";
}
}
if (!insertedAttributes.equals("")) {
// Insert attributes only once
xm.insertAttribute(insertedAttributes);
}
This will also work if you need to update the attributes of multiple elements, simply nest the above code in while(autoPilot.evalXPath() != -1) and be sure to set insertedAttributes = ""; at the end of each while loop.
Hope this helps.

method for serializing lua tables

I may have missed this, but is there a built-in method for serializing/deserializing lua tables to text files and vice versa?
I had a pair of methods in place to do this on a lua table with fixed format (e.g. 3 columns of data with 5 rows).
Is there a way to do this on lua tables with any arbitrary format?
For an example, given this lua table:
local scenes={
{name="scnSplash",
obj={
{
name="bg",
type="background",
path="scnSplash_bg.png",
},
{
name="bird",
type="image",
path="scnSplash_bird.png",
x=0,
y=682,
},
}
},
}
It would be converted into text like this:
{name="scnSplash",obj={{name="bg",type="background",path="scnSplash_bg.png",},{name="bird", type="image",path="scnSplash_bird.png",x=0,y=682,}},}
The format of the serialized text can be defined in any way, as long as the text string can be deserialized into an empty lua table.
I'm not sure why JSON library was marked as the right answer as it seems to be very limited in serializing "lua tables with any arbitrary format". It doesn't handle boolean/table/function values as keys and doesn't handle circular references. Shared references are not serialized as shared and math.huge values are not serialized correctly on Windows. I realize that most of these are JSON limitations (and hence implemented this way in the library), but this was proposed as a solution for generic Lua table serialization (which it is not).
One would be better off by using one of the implementations from TableSerialization page or my Serpent serializer and pretty-printer.
Lua alone doesn't have any such builtin, but implementing one is not difficult. A number of prebaked implementations are listed here: http://lua-users.org/wiki/TableSerialization
require "json"
local t = json.decode( jsonFile( "sample.json" ) )
reference here for a simple json serializer.
Add json.lua from rxi/json.lua to your project, then use it with:
local json = require("json")
local encoded = json.encode({
name = "J. Doe",
age = 42
})
local decoded = json.decode(encoded)
print(decoded.name)
Note that the code chokes if there are functions in the value you are trying to serialize. You have to fix line 82 and 93 in the code to skip values that have the function type.
Small solution: The key can be done without brackets, but be sure that here is no minuses or other special symbols.
local nl = string.char(10) -- newline
function serialize_list (tabl, indent)
indent = indent and (indent.." ") or ""
local str = ''
str = str .. indent.."{"..nl
for key, value in pairs (tabl) do
local pr = (type(key)=="string") and ('["'..key..'"]=') or ""
if type (value) == "table" then
str = str..pr..serialize_list (value, indent)
elseif type (value) == "string" then
str = str..indent..pr..'"'..tostring(value)..'",'..nl
else
str = str..indent..pr..tostring(value)..','..nl
end
end
str = str .. indent.."},"..nl
return str
end
local str = serialize_list(tables)
print(str)

Index (zero based) must be greater than or... Working with the Bit.ly API

I'm working (actually more like playing) around with the Bit.ly API, and keep getting the error in the title of this question. So I'm going to show you the code and hopefuly someone can help me resolve this. First the client side code.
var x = service.GetClicks(url, service.BitlyLogin, service.BitlyAPIKey);
Console.WriteLine(x);
Console.ReadLine();
And this is the code that's being called
public List<int> GetClicks(string url, string login, string key)
{
List<int> clicks = new List<int>();
url = Uri.EscapeUriString(url);
string reqUri =
String.Format("http://api.bit.ly/v3/clicks?" +
"login={0}&apiKey={1}&shortUrl={2}&format=xml" +
login, key, url);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(reqUri);
req.Timeout = 10000; // 10 seconds
Stream stm = req.GetResponse().GetResponseStream();
XmlDocument doc = new XmlDocument();
doc.Load(stm);
// error checking for xml
if (doc["response"]["status_code"].InnerText != "200")
throw new WebException(doc["response"]["status_txt"].InnerText);
XmlElement el = doc["response"]["data"]["clicks"];
clicks.Add(int.Parse(el["global_clicks"].InnerText));
clicks.Add(int.Parse(el["user_clicks"].InnerText));
return clicks;
}
As you can see it's very simple code, nothing complicated, and I can see nothing that causes this error. Anyone out there who has worked with(the full error is Index (zero based) must be greater than or equal to zero and less than the size of the argument list.) the Bit.ly API and can lend a hand?
Instead this
string reqUri =
String.Format("http://api.bit.ly/v3/clicks?" +
"login={0}&apiKey={1}&shortUrl={2}&format=xml" + login, key, url);
Use this
string reqUri = String.Format("http://api.bit.ly/v3/clicks?login={0}&apiKey={1}&shortUrl={2}&format=xml", login, key, url);
Notice that I just changed the plus sign with the comma before "login, key, url);" at the end of the String.Format().
I narrowed it down to a place where I was using string.Format to build an array and has less in the string.Format than what was supposed to. I had it go to Index 3 but only filled to Index 2
Not for your specific case, but I ran into this: make sure that, if you have multiple parameters, you send them as an array of objects instead of an IEnumerable:
IEnumerable<object> myArgs = ...;
string toFormat = "{0} xyz {1}";
String.Format(toFormat, myArgs);
// ERROR, since myArgs is one argument whereas the string template requires two
String.Format(toFormat, myArgs.ToArray());
// Valid, as the Format() accepts an array of objects to fill all arguments in the string

How to filter out some vulnerability causing characters in query string?

I need to filter out characters like /?-^%{}[];$=*`#|&#'\"<>()+,\. I need replace this with empty string if it is there in the query string. Please help me out. I am using this in ASP pages.
Best idea would be to use a function something along the lines of:
Public Function MakeSQLSafe(ByVal sql As String) As String
'first i'd avoid putting quote chars in as they might be valid? just double them up.
Dim strIllegalChars As String = "/?-^%{}[];$=*`#|&#\<>()+,\"
'replace single quotes with double so they don't cause escape character
If sql.Contains("'") Then
sql = sql.Replace("'", "''")
End If
'need to double up double quotes from what I remember to get them through
If sql.Contains("""") Then
sql = sql.Replace("""", """""")
End If
'remove illegal chars
For Each c As Char In strIllegalChars
If sql.Contains(c.ToString) Then
sql = sql.Replace(c.ToString, "")
End If
Next
Return sql
End Function
This hasn't been tested and it could probably be made more efficient, but it should get you going. Wherever you execute your sql in your app, just wrap the sql in this function to clean the string before execution:
ExecuteSQL(MakeSQLSafe(strSQL))
Hope that helps
As with any string sanitisation, you're much better off working with a whitelist that dictates which characters are allowed, rather than a blacklist of characters that aren't.
This question about filtering HTML tags resulted in an accepted answer suggesting the use of a regular expression to match against a whitelist: How do I filter all HTML tags except a certain whitelist? - I suggest you do something very similar.
I'm using URL Routing and I found this works well, pass each part of your URL to this function. It's more than you need as it converts characters like "&" to "and", but you can modify it to suit:
public static string CleanUrl(this string urlpart) {
// convert accented characters to regular ones
string cleaned = urlpart.Trim().anglicized();
// do some pretty conversions
cleaned = Regex.Replace(cleaned, " ", "-");
cleaned = Regex.Replace(cleaned, "#", "no.");
cleaned = Regex.Replace(cleaned, "&", "and");
cleaned = Regex.Replace(cleaned, "%", "percent");
cleaned = Regex.Replace(cleaned, "#", "at");
// strip all illegal characters like punctuation
cleaned = Regex.Replace(cleaned, "[^A-Za-z0-9- ]", "");
// convert spaces to dashes
cleaned = Regex.Replace(cleaned, " +", "-");
// If we're left with nothing after everything is stripped and cleaned
if (cleaned.Length == 0)
cleaned = "no-description";
// return lowercased string
return cleaned.ToLower();
}
// Convert accented characters to standardized ones
private static string anglicized(this string urlpart) {
string beforeConversion = "àÀâÂäÄáÁéÉèÈêÊëËìÌîÎïÏòÒôÔöÖùÙûÛüÜçÇ’ñ";
string afterConversion = "aAaAaAaAeEeEeEeEiIiIiIoOoOoOuUuUuUcC'n";
string cleaned = urlpart;
for (int i = 0; i < beforeConversion.Length; i++) {
cleaned = Regex.Replace(urlpart, afterConversion[i].ToString(), afterConversion[i].ToString());
}
return cleaned;
// Spanish : ÁÉÍÑÓÚÜ¡¿áéíñóúü"
}