Experiences on EWSMA and Exchange Online Office 365 - exchange-server

Does anyone have experiences using Exchange Managed Webservices and Exchange Online (Office 365)
Are there Breaking Changes between a normal Exchange and the online? May I take the normal api for this ?
Any hints?

first of all it's important to know that O365 is currently running Exchange Server 2010 Service Pack 1 what has to be specified when using Exchange Managed API.
The exchange autodiscover is done by a centralized exchange cluster, so you have to enable the redirection here.
var service = new ExchangeService(ExchangeVersion.Exchange2010_SP1)
{
Credentials = new WebCredentials("MyO365UserId", "Password")
};
service.AutodiscoverUrl("foo#bar.onmicrosoft.com", delegate { return true; });
var allContactsFromO365 = service
.FindItems(WellKnownFolderName.Contacts, new ItemView(99));
foreach (var contact in allContactsFromO365
.Where(item => item as Contact != null)
.OfType<Contact>())
{
Console.WriteLine(contact.DisplayName);
}
Hope that helps a little bit.
So as you can see it's regular managed API code..
have fun

Related

Microsoft Bot Framework (Node.js- SDK4) + Microsoft Graph API

Is it possible that the Microsoft Bot Framework Node.js - SDK4 automatically identify a logged in user from a Microsoft account (like a user that is logged in Sharepoint) so that I can use Microsoft Graph services directly on the bot without needing to ask user login and password?
I'm asking that because I have a bot running on a sharepoint page, and in theory, the user already will be logged in on a microsoft account when he starts talking to the bot.
Check this code.
{ ResponseIds.Greeting, (context, data) => {
var greetings = JsonConvert.DeserializeObject<Greetings>
(MainStrings.GREETING);
Random r = new Random( );
int index = r.Next( greetings.messages.Count );
return greetings.messages[index].message.Replace("
{username}",context.Activity.From.Name);
}
Else I have seen an authentication dialog that probably does a similar operation

Securing traffic from Microsoft Teams to a bot?

How to secure the traffic from Microsoft Teams to a bot, so that bot could be answering on company specific questions / discussions and would not need to be exposed as anonymous WebAPI?
Bot integration to Teams UIs is easy from bot framework side, but right now there's no documentation for how to isolate bot only for specific enterprise.
Business case - We want to build enterprise specific bot, which could answer questions only specific to that particular enterprise where the questions are coming from. Technically this could be done with app-only access to SharePoint or Microsoft Graph, but we cannot expose this kind of WebAPI anonymously for Internet.
Any design patterns for this?
This is now possible, and I've actually even implemented it for Hubot in CoffeeScript and Node.JS. What I've described below is what it would look like in JavaScript/Node.JS.
Define an environment variable that, when set, filters for a particular tenant ID, OFFICE_365_TENANT_FILTER. (Doing it this way is a handy way of turning this feature on in production but not necessarily during development.)
For Microsoft Teams, the Office 365 tenant ID can be found here: session.message.sourceEvent.tenant.id.
The most elegant way to do it is to check for the tenant ID as middleware, and just drop further processing of the message if the filter is set and it doesn't match:
// [...]
var connector = new builder.ChatConnector({
appId: process.env.MICROSOFT_APP_ID,
appPassword: process.env.MICROSOFT_APP_PASSWORD
});
var bot = new builder.UniversalBot(connector);
// Middleware to check for OFFICE_365_TENANT_FILTER and only continue processing if it matches.
// If OFFICE_365_TENANT_FILTER is not specified, do nothing.
bot.use({
botbuilder: function(session, next) {
var targetTenant = typeof(process.env.OFFICE_365_TENANT_FILTER) !== "undefined" ? process.env.OFFICE_365_TENANT_FILTER : null;
var currentMsgTenant = typeof(session.message.sourceEvent.tenant) !== "undefined" ? session.message.sourceEvent.tenant.id : null;
if (targetTenant !== null) {
if (targetTenant == currentMsgTenant) {
next();
}
else {
console.log("MS Teams: Attempted access from a different Office 365 tenant (" + currentMsgTenant + "): message rejected");
}
}
else {
next();
}
}
});
// [...]
Here's how to do this in C#, the SDK exposes the TenantFilter that allows you to add this action filter to the controller class as shown below.
using Microsoft.Bot.Connector.Teams;
namespace Microsoft.Teams.Samples.HelloWorld.Web.Controllers
{
[BotAuthentication, TenantFilter]
public class MessagesController : ApiController
{
[HttpPost]
public async Task<HttpResponseMessage> Post([FromBody] Activity activity)
The tenant filter will take a comma separated list of tenantIds that will need to be placed in the web.config
<configuration>
<appSettings>
<!--other settings-->
<add key="AllowedTenants" value="*TenantId1,TenantId2,...*"/>
Find your Office 365 tenant ID shows how you can do it through PowerShell.
It is not currently possible to know the tenant-id of the user chatting with the bot right away, unless the bot authenticates the user first. Please take a look at AuthBot. It illustrates how to send a sign-in link to a user and authenticate the user against AAD.
Although not exactly what you are looking for, you can create custom bots which will be scoped to individual Teams.
The security key/HMAC auth will prevent others from accessing the API. With the drawback that you will have to configure the bot with a separate security token for every Team where you want to use it.

Acessing Microsoft CRM Online using Office 365 authentication

yesterday I created a new installation of Microsoft CRM Online.
Now I'm trying to access the webservice using the sdk provided from Microsoft.
When i try to connect to Microsoft CRM Online I get this error:
An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail.
I read in some posts that it can be the hours difference between my machine and the CRM Online Server, but I've tried running this code unsuccessfully using all the hours.
CrmConnection crmConnection = CrmConnection.Parse("Url=https://desenvolvimento.crm2.dynamics.com/XRMServices/2011/Organization.svc; Username=jones.rives#desenvolvimento.onmicrosoft.com; Password=XXX;");
OrganizationService service = new OrganizationService(crmConnection);
Entity account = new Entity("account");
account["name"] = "Test Account";
account.Id = Guid.NewGuid();
Guid accountId = service.Create(account);
Is it different to connect to CRM Online using 365 credentials? I really can't find the problem, and I've tried many solutions, but none worked.
Thanks in advise.
You don't need to put the endpoint inside the connection string when you use the simplified connection, just the organization url.
Assuming your url is correct (meaning you can login using a browser), try with:
CrmConnection crmConnection = CrmConnection.Parse("Url=https://desenvolvimento.crm2.dynamics.com; Username=jones.rives#desenvolvimento.onmicrosoft.com; Password=XXX;");
OrganizationService service = new OrganizationService(crmConnection);
Entity account = new Entity("account");
account["name"] = "Test Account";
Guid accountId = service.Create(account);

Fails Conecting Outlook Add-In to Exchange 2013 WS

I am trying to establish a connection with Exchange 2013 to retrieve a list of Contacts (from Global Contacts) given a certain criteria. This code works from a test console application, but when I place it in an Outlook Add-In, then it fails to even execute the method that contains the connection code, without throwing any exception. This is an extract of the code:
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
service.UseDefaultCredentials = true;
service.AutodiscoverUrl(emailAccount, RedirectionUrlValidationCallback);
NameResolutionCollection coll = service.ResolveName(searchStr, ResolveNameSearchLocation.DirectoryThenContacts, true);
Anybody has any idea why is this happening? Or if there is another way to search for Global Contacts in Exchange 2013 from an Add-In?

Using EWS API to search through different users mailboxes

We are developing a module with the main goal being to track and collect information about damage inspections (insurance market). Each case has a code (e.g. L000525). Each case could be managed by several people. All the emails related to a specific case include the case code in the subject.
What we want to do is to collect and show the incoming and sent emails related to each specific case.
The idea is that any user can open a "Case management" window, select an specific case, and then get all the related information (including the emails of course).
We have to find the emails into the the mailboxes of around 20 users. So the questions are:
Which is the better way to do this? Will it consume a lot of time and resources?
We are new in the Exchange world so we are thinking Exchange impersonation, but we are not sure at all. The module is developed in Silverlight 3, WCF, SQL Server + Exchange 2007.
If the credentials used to connect to EWS have rights to access a user's mailbox then you should be able to do something like this:
var service = new ExchangeService();
service.Credentials = new WebCredentials("user_with_access#example.com", "password");
service.AutodiscoverUrl("a_valid_user#example.com");
var userMailbox = new Mailbox("target_user#example.com");
var folderId = new FolderId(WellKnownFolderName.Inbox, userMailbox);
var itemView = new ItemView(20); // page size
var userItems = service.FindItems(folderId, itemView);
foreach (var item in userItems)
{
// do something with item (nb: it might not be a message)
}
That's it. Wow, my first SO answer!
A full working example of what #smcintosh has done above is here: Office365 API - Admin accessing another users/room's calendar events. It is a full java class that should compile and run and accesses a room resource calendar. Good luck!

Resources