I am trying to read the Out Of Office status and message from other users in the organization from my c# program. We are running Exchange 2013 on premises.
This app is running as an Active Directory account (with it's own exchange mailbox), and I cannot use impersonation.
I have spent some time trying out the solutions to similar questions such as:
Retrieve out of office Status using EWS 2.0 This one uses impersonation
Read out of office from exchange server for other users I'm not using the Outlook Object Model
How to get Out of Office for another mailbox again no impersonation for me
http://gsexdev.blogspot.com/2011/11/using-mailtips-in-ews-to-get-oof-out-of.html I don't have reference to ExchangeServiceBinding, even though I'm using Microsoft.Exchange.WebServices.Data;
http://blogs.msdn.com/b/devmsg/archive/2014/06/03/ews-how-to-retrieve-the-oof-out-of-facility-settings-message-using-ews-for-an-exchange-user.aspx This one takes as a paramater, urlname and I'm not sure where that url is coming from. This one seems the most promising though, any ideas where that comes from?
I'm trying to get something like:
public void checkOOF(string userEmail){
bool isOOF = checkstuff(userEmail);
string message;
if(isOOF)
message = getOOFMessage(userEmail);
}
Please help me understand, thank you.
This is what I ended up using and it works.
public static string getOOM(string emailToCheck) //needs to be full email of user.
{
string EWSurl = String.Format("https://{0}/EWS/Exchange.asmx", ExchangePath);
WebRequest webRequest = WebRequest.Create(EWSurl);
HttpWebRequest httpwebRequest = (HttpWebRequest)webRequest;
httpwebRequest.Method = "POST";
httpwebRequest.ContentType = "text/xml; charset=utf-8";
httpwebRequest.ProtocolVersion = HttpVersion.Version11;
httpwebRequest.Credentials = new NetworkCredential("user", "password", "domain");//service Account
httpwebRequest.Timeout = 60000;
Stream requestStream = httpwebRequest.GetRequestStream();
StreamWriter streamWriter = new StreamWriter(requestStream, Encoding.ASCII);
StringBuilder getMailTipsSoapRequest = new StringBuilder("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
getMailTipsSoapRequest.Append(" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" ");
getMailTipsSoapRequest.Append("xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" ");
getMailTipsSoapRequest.Append("xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\"><soap:Header>");
getMailTipsSoapRequest.Append(" <t:RequestServerVersion Version=\"Exchange2010\"/></soap:Header><soap:Body>");
getMailTipsSoapRequest.Append("<GetMailTips xmlns=\"http://schemas.microsoft.com/exchange/services/2006/messages\">");
getMailTipsSoapRequest.Append("<SendingAs>");
getMailTipsSoapRequest.Append("<t:EmailAddress>accessingemail#domain.com</t:EmailAddress>");
getMailTipsSoapRequest.Append("<t:RoutingType>SMTP</t:RoutingType></SendingAs>");
getMailTipsSoapRequest.Append("<Recipients><t:Mailbox>");
getMailTipsSoapRequest.Append("<t:EmailAddress>" + emailToCheck + "</t:EmailAddress>");
getMailTipsSoapRequest.Append("<t:RoutingType>SMTP</t:RoutingType></t:Mailbox></Recipients>");
getMailTipsSoapRequest.Append(" <MailTipsRequested>OutOfOfficeMessage</MailTipsRequested></GetMailTips>");
getMailTipsSoapRequest.Append("</soap:Body></soap:Envelope>");
streamWriter.Write(getMailTipsSoapRequest.ToString());
streamWriter.Close();
HttpWebResponse webResponse = (HttpWebResponse)httpwebRequest.GetResponse();
StreamReader streamreader = new StreamReader(webResponse.GetResponseStream());
string response = streamreader.ReadToEnd();
if (response.Contains("<t:Message/>"))
return null;
int messageIndex = response.IndexOf("<t:Message>");
response = response.Substring(messageIndex, response.IndexOf("</t:Message>") - messageIndex);
return response;
}
http://blogs.msdn.com/b/devmsg/archive/2014/06/03/ews-how-to-retrieve-the-oof-out-of-facility-settings-message-using-ews-for-an-exchange-user.aspx This one takes as a paramater, urlname and I'm not sure where that url is coming from. This one seems the most promising though, any ideas where that comes from?
urlname is just the EWS URL if you are using the Managed API than just use the value from service.url.
http://gsexdev.blogspot.com/2011/11/using-mailtips-in-ews-to-get-oof-out-of.html I don't have reference to ExchangeServiceBinding, even though I'm using Microsoft.Exchange.WebServices.Data;
This is proxy code generated from the Exchange Web Service WSDL file see https://msdn.microsoft.com/en-us/library/office/dd877040(v=exchg.140).aspx (Microsoft.Exchange.WebServices.Data) is the Managed API.
Solution worked great for me as supplied by Aaron. However returning the substring gave me issues since ours was an html string rather than plain text and it didn't parse correctly. So i replaced the StreamReader down portion with the following. This still returns as a string but correctly parses as the html it was returned as.
XDocument doc;
using (Stream responseStream = response.GetResponseStream())
{
doc = XDocument.Load(responseStream);
}
return doc.Root.Descendants().Where(d => d.Name.LocalName == "Message").Select(d => d.Value).FirstOrDefault();
Related
I'm working with a third party that refuses to fix their scheme for a published WSDL. The issue is the SOAP service is expecting different name spaces than the WSDL is providing. So in my C# app I'm having a lot of trouble using the Proxy by .Net. In an attempt to work around this I want to just send a web-request and package up my data
I just can't figure out how to add my signature to the header of my request.
Microsoft.Web.Services3.SoapEnvelope soapEnvelopeXml = new Microsoft.Web.Services3.SoapEnvelope();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(#"https://Illinois-stage.tylerhost.net/efm/FilingReviewMDEPort.svc");
request.Headers.Add("SOAPAction:\"urn:oasis:names:tc:legalxml-courtfiling:wsdl:WebServicesProfile-Definitions-4.0/FilingReviewMDEPort/ReviewFilingRequest\"");
request.Headers.Add("Accept-Encoding: gzip, deflate");
request.KeepAlive = true;
request.Headers.Add("MIME-Version: 1.0");
request.ContentType = "multipart/related; type=\"application/xop+xml\";start=\"<http://tempuri.org/0>\";boundary=\"uuid:936f2c7e-590a-4f19-b154-ce8285adf18a+id=2\";start-info=\"text/xml\"";
request.Method = "POST";
soapEnvelopeXml.Load(#"c:\temp\ReviewFilingRequest.xml");
System.IdentityModel.Tokens.X509SecurityToken securityToken = new System.IdentityModel.Tokens.X509SecurityToken(X509);
Microsoft.Web.Services3.Security.Tokens.X509SecurityToken signatureToken = new Microsoft.Web.Services3.Security.Tokens.X509SecurityToken(X509);
MessageSignature sig = new MessageSignature(signatureToken);
////////// XmlDocumentFragment xfrag = soapEnvelopeXml.CreateDocumentFragment();
//////////xfrag.InnerXml = messageHeader;
//////////soapEnvelopeXml.DocumentElement.FirstChild.AppendChild(xfrag);
XmlDocument xmlDoc = new XmlDocument();
MemoryStream xmlStream = new MemoryStream();
xmlDoc.Save(xmlStream);
using (var writer = XmlDictionaryWriter.CreateMtomWriter(xmlStream, Encoding.UTF8, int.MaxValue, "text/xml", "uuid:936f2c7e-590a-4f19-b154-ce8285adf18a+id=2", "http://tempuri.org/0",false,false))
{
soapEnvelopeXml.WriteTo(writer);
using (Stream stream = request.GetRequestStream())
{
stream.Write(xmlStream.ToArray(),0, xmlStream.ToArray().Length );
}
}
using (WebResponse response = request.GetResponse())
{
using (StreamReader rd = new StreamReader(response.GetResponseStream()))
{
string soapResult = rd.ReadToEnd();
Console.WriteLine(soapResult);
}
}
A couple things that might be able to help.
What error message are you getting back? Access Denied (or something along those lines)?
Have you tried looking at which headers you are missing? The best way to do this is to download WireShark or Telerik's Fiddler which allows HTTPS decryption. Using one of these, you can access the website in an internet browser and view the headers that are being sent through a normal browser.
I ended up signing it in Node.js Making the switch to node gave me a lot more control over the message. As an added bonus I didn't have to pay the Microsoft Tax.
https://www.npmjs.com/search?q=soap&page=1&ranking=optimal
I can't insert permission to a file with this code:
string URI = String.Format("https://www.googleapis.com/drive/v2/files/{0}/permissions&access_token={1}", fileId, "token");
var request = (HttpWebRequest)HttpWebRequest.Create(URI);
request.Method = "POST";
request.ContentType = "application/json";
string json = "{\"role\": \"reader\",\"type\": \"anyone\"}";
byte[] byteData = new System.Text.ASCIIEncoding().GetBytes(json);
request.ContentLength = byteData.Length;
using (var dataStream = request.GetRequestStream())
{
dataStream.Write(byteData, 0, byteData.Length);
}
var response = (HttpWebResponse)request.GetResponse();
using (var reader = new StreamReader(response.GetResponseStream()))
{
json = reader.ReadToEnd();
}
I al getting a 404 error. What's the problem?
string URI = String.Format("https://www.googleapis.com/drive/v2/files/{0}/permissions&access_token={1}", fileId, "token");
Access token is not a string "token" it must be a valid access token for the user who owns the file.
Update:
permissions?access_token={1}",
You should be using ? and not & to add a parameter to the url. Not even sure you can do it like that with a HTTP Post.
Added info:
If this is not simply a typo on your part you may want to read up on Authorization a little
I also recommend checking out the Google client library instead of writing this yourself. Google.Apis.Drive.v2 Client Library.
There is a newer version of the Google Drive API you might also be interested in looking at rather then writing new code for an older version of the API. Google Drive API v3.
I have been wasting few days on this issue already...
The main problem is - I dont know how to POST data.
I would like to start by getting OrderReferenceDetails.
by looking at MWS Scratchpad (API Section: Off Amazon payments, Operation: GetOferenceDetails).
As I understand, first thing I should do, is to calculate signature. So by using this Amazon developer guide, and taking values in example in scratchpad, I created string, from which I calculated signature. This string looks like this
POST
mws.amazonservices.com
/offamazonpayments_sandbox/2013-01-01
Action=GetOrderReferenceDetails&AmazonOrderReferenceId=[_my order reference id_]&AWSAccessKeyId=[_my access key_]&SellerId=[_my seller id_]&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2014-11-04T12%3a15%3a38.1988397Z&Version=2013-01-01
So I hash this and get a signature, then I should add it to line of query parameters like &Signature=[_my clalculated signature]
Function I use to calculate signature:
private static String sign(String data, String secretKey)
{
String result = null;
KeyedHashAlgorithm algorithm = new HMACSHA256();
Encoding encoding = new UTF8Encoding();
algorithm.Key = encoding.GetBytes(secretKey);
result = Convert.ToBase64String(algorithm.ComputeHash(encoding.GetBytes(data.ToCharArray())));
return result;
}
Problem start here (I think). Scratchpad provides "data" to post, but I cant understand, how to use it (copy-paste from scratchpad):
POST /OffAmazonPayments_Sandbox/2013-01-01?AWSAccessKeyId=
&Action=GetOrderReferenceDetails
&SellerId=
&SignatureVersion=2
&Timestamp=2014-11-04T12%3A37%3A58Z
&Version=2013-01-01
&Signature=rEqRKP27Pklu%2BAmRLR%2ByRpUtfhNsVOWuGTQ7s%2FgkB2w%3D
&SignatureMethod=HmacSHA256
&AmazonOrderReferenceId= HTTP/1.1
Host: mws.amazonservices.com
x-amazon-user-agent: AmazonJavascriptScratchpad/1.0 (Language=Javascript)
Content-Type: text/xml
What is this? I am familiar of making request like this:
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "POST";
request.ContentType = "text/xml";
request.Host = "whatever host I need to use";
request.ContentLength = Encoding.UTF8.GetByteCount(dataAsString);
byte[] byteArray = Encoding.UTF8.GetBytes(dataAsString);
using (Stream dataStream = request.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
}
try
{
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
string responseAsString = streamReader.ReadToEnd();
}
}
catch (WebException exception)
{
HttpWebResponse exceptionalResponse = exception.Response as HttpWebResponse;
using (var streamReader = new StreamReader(exceptionalResponse.GetResponseStream()))
{
String responseAsString = streamReader.ReadToEnd();
}
}
Questions are:
Am I calculating signature properly?
How to construct web request?
Thanks for reading and trying to help!
EDIT:
Well, I finally got a response from MWS Amazon, that is not an error!
Steps I did to make it work:
Construct string that will be signed by hand - order of query parameters is important.
Construct url where I will post data by hand - again, order is important, but different from string signed before. Keys in signed string should be sorted using lexicographic byte ordering. Well, I dont know what kind of animal is that, so thats why I did everything by hand, by example taking scratchpad.
I struggled with this for a few days and it came down to the order of the parameters. I tried to find a solution to order the parameters without doing it by hand and finally found the answer. I created a SortedDictionary() at first still did not work. Then I saw an example from Claytondus nuget package that works with MWS and he had SortedDictionary(StringComparer.Ordinal). Once I did that it sorted correctly and got a good response.
At the moment I am trying to HTTP response request in my Sharepoint WarmUp script, however for this, I will have to use this code
using (System.IO.StreamReader file = new System.IO.StreamReader(filePath))
while ((line = file.ReadLine()) != null)
{
try
{
WebRequest request = WebRequest.Create(line);
request.Proxy = null;
if ((userName == null) || (userName == ""))
{
request.Credentials = CredentialCache.DefaultCredentials;
}
else
{
CredentialCache myCache = new CredentialCache();
myCache.Add(new Uri(line), "NTLM", new NetworkCredential(userName, password, DomainName));
request.Credentials = myCache;
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (Stream dataStream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(dataStream))
{
string responseFromServer = reader.ReadToEnd();
reader.Close();
dataStream.Close();
response.Close();
}
Thread.Sleep(2000);
}
I am not suppose to use any User Account to get response, however I can use Default Credentials that only works when am logged in at server, otherwise they wont gonna work i guess.
Is there any other way of doing it, can't use powershell as its MOSS not sharepoint 2010
cheers
You CAN use Powershell for the warm-up script. You can call stsadm command, make HTTP requests and even use the server object model once you do the proper imports.
This post uses powershell to retrieve available sites using stsadm. Once the script retrieves this list, it instantiates a WebClient object and hits each site URL.
If you only want to hit the sites in a list, you can simply use a WebClient object to do this.
Alternatively, if you have a working Search Service within your SSP, you can configure a scheduled crawl. Not only you'll benefit from up to date crawl results but your site will be warm-up natively without the need of an additional job doing it "just for warming up".
I am trying to read a remote file using HttpWebRequest in a C# Console Application. But for some reason the request is empty - it never finds the URL.
This is my code:
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://uo.neverlandsreborn.org:8000/botticus/status.ecl");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
How come this is not possible?
The file only contains a string. Nothing more!
How are you reading the response data? Does it come back as successful but empty, or is there an error status?
If that doesn't help, try Wireshark, which will let you see what's happening at the network level.
Also, consider using WebClient instead of WebRequest - it does make it incredibly easy when you don't need to do anything sophisticated:
string url = "http://uo.neverlandsreborn.org:8000/botticus/status.ecl";
WebClient wc = new WebClient();
string data = wc.DownloadString(url);
You have to get the response stream and read the data out of that. Here's a function I wrote for one project that does just that:
private static string GetUrl(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.CreateDefault(new Uri(url));
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode != HttpStatusCode.OK)
throw new ServerException("Server returned an error code (" + ((int)response.StatusCode).ToString() +
") while trying to retrieve a new key: " + response.StatusDescription);
using (var sr = new StreamReader(response.GetResponseStream()))
{
return sr.ReadToEnd();
}
}
}