How to change email subject in C# using Exchange Web Services - c#

I have a piece of code where I am connecting via Exchange Web Services, and I have the message ID. I need to change the subject of this email to the string passed into my method for successful processing later in my workflow. However, I am a bit confused as to how to use the exchange web services classes, my code is below:
public bool SetEmailCorrectSubject(string msgID, string subject)
{
bool bSuccess = true;
if (String.IsNullOrEmpty(msgID))
{
return false;
}
try
{
ItemIdType messageId = new ItemIdType();
messageId.Id = msgID;
ItemChangeDescriptionType desc = new ItemChangeDescriptionType();
// Not sure how to set this up
ItemChangeType itemChange = new ItemChangeType();
itemChange.Item = messageId;
UpdateItemType updateItem = new UpdateItemType();
}
catch (Exception e)
{
_logger.Error("error with resending email with title", e);
return false;
}
return bSuccess;
}
From what I understand, the UpdateItemType class is the way to go, but I'm not clear on how to tell it that I want to change the email subject to the subject parameter.
Any ideas? Is using UpdateItemType even the best way to do this?

Instead of EWS you should use the EWS Managed API as it's more simple to use:
EWS Managed API - Download: http://www.microsoft.com/download/en/details.aspx?id=13480
EWS Managed API - SDK: http://msdn.microsoft.com/en-us/library/dd633710(v=exchg.80).aspx
Apart from that, you don't use the ItemChangeType and UpdaetItemType to modify items. Use the Item.Bind() method to bind to the item, change the subject and update it:
var service = new ExchangeService(ExchangeVersion.Exchange2010_SP1)
{
UseDefaultCredentials = true,
Url = new Uri("https://casserver/ews/exchange.asmx")
};
Item item = Item.Bind(service, new Itemid(msgid));
item.Subject = "test";
item.Update(ConflictResolutionMode.AutoResolve);
Btw, are you sure you have the ItemId? Or do you have an RFC 822 Message-Id? Those two are different.

Related

Botframework DirectLineClient.Conversations.PostActivityAsync returns null

I'm trying to send an activity through DirectLineClient library to my bot :
var directLineClient = new DirectLineClient($"{secret}");
directLineClient.BaseUri = new Uri($"https://directline.botframework.com/");
var conversation = await directLineClient.Conversations.StartConversationAsync().ConfigureAwait(false);
var activity = new Microsoft.Bot.Connector.DirectLine.Activity();
activity.From = new Microsoft.Bot.Connector.DirectLine.ChannelAccount();
activity.From.Name = "Morgan";
activity.Text = message;
activity.Type = "message";
var resourceResponse = await directLineClient.Conversations.PostActivityAsync(conversation.ConversationId, activity).ConfigureAwait(false);
await ReadBotMessagesAsync(directLineClient, conversation.ConversationId);
resourceResponse is always null.
Edit after Nicolas R answer
I added a method to wait for a response from the bot :
private static async Task ReadBotMessagesAsync(DirectLineClient client, string conversationId)
{
string watermark = null;
while (true)
{
var activitySet = await client.Conversations.GetActivitiesAsync(conversationId, watermark);
watermark = activitySet?.Watermark;
foreach (Microsoft.Bot.Connector.DirectLine.Activity activity in activitySet.Activities)
{
Console.WriteLine(activity.Text);
if (activity.Attachments != null)
{
foreach (Microsoft.Bot.Connector.DirectLine.Attachment attachment in activity.Attachments)
{
Console.WriteLine(attachment.ContentType);
}
}
}
if (activitySet.Activities.Count > 0)
{
return;
}
await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
}
}
But I never get out of ReadBotMessagesAsync.
I precise that I can communicate with my bot through HTTP request (tested with Postman), and it should be sending a response message whenever a message is sent.
Edited after OP precision
Methods always returns null
Based on the documentation/samples, it looks like this PostActivityAsync return is never used so the value may not be relevant.
From the samples:
await client.Conversations.PostActivityAsync(conversation.ConversationId, userMessage);
See example here.
For those who want more details, because this answer is only limited to the comparison with the sample use, this package is sadly not open-source: https://github.com/Microsoft/BotBuilder/issues/2756
Remarks (for those who would be using the wrong packages)
I would not recommend to use this DirectLineClient Nuget package located here:
https://www.nuget.org/packages/DirectLineClient as it is not maintained since May 2016 and the Bot Framework has changed a lot since that time.
Moreover, it is using DirectLine API 1.0, which is not the best practice at the time. See documentation here:
Important
This article introduces key concepts in Direct Line API 1.1 and
provides information about relevant developer resources. If you are
creating a new connection between your client application and bot, use
Direct Line API 3.0 instead.

CheckID does not have associated TTL

I'm trying to utilize Consul .NET API to register and fire health checks via TTL. First I'm registering my service with following code:
var address = node.Address;
var id = ServiceId(address);
var registration = new AgentServiceRegistration
{
ID = id,
Name = node.ClusterName,
Address = node.Address.Host,
Port = node.Address.Port.Value,
Check = new AgentServiceCheck
{
TTL = settings.AliveInterval, // 10sec
DeregisterCriticalServiceAfter = settings.AliveTimeout, // 60sec
}
};
// first, try to deregister service, if it has been registered previously
await consul.Agent.ServiceDeregister(registration.ID);
await consul.Agent.ServiceRegister(registration);
Right afterwards, I'm trying to fire a TTL via:
await consul.Agent.PassTTL("service:" + ServiceId(addr), string.Empty);
However, what I end up with is an exception thrown during PassTTL: Consul.ConsulRequestException: Unexpected response, status code InternalServerError: CheckID "service:{service-id}" does not have associated TTL
And the related log from consul agent itself:
[ERR] http: Request PUT /v1/agent/check/pass/service:{service-id}, error: CheckID "service:{service-id}" does not have associated TTL from=127.0.0.1:25419
I'd like to know what I'm doing wrong here.
I'm using consul agent -dev (version: 1.0.1) and Nuget package Consul (version: 0.7.2.3).
Turns out AgentServiceRegistration.Check property is pretty useless. I've achieved the expected result with CheckRegister method.
Here's the code
var registration = new AgentServiceRegistration
{
ID = "serviceId",
Name = node.ClusterName,
Address = node.Address.Host,
Port = node.Address.Port.Value
};
// first, try to deregister service, if it has been registered previously
await consul.Agent.ServiceDeregister(registration.ID);
await consul.Agent.ServiceRegister(registration);
await consul.Agent.CheckRegister(new AgentCheckRegistration()
{
ID = "checkId",
Name = "Check Name",
Status = HealthStatus.Passing,
TTL = settings.AliveInterval,
ServiceID = "serviceId",
DeregisterCriticalServiceAfter = settings.AliveTimeout, // 60sec
})
Now you can pass TTL via
await consul.Agent.PassTTL("checkId", string.Empty);
Just be sure to deregister your check afterwards
It looks like my example was missing a crucial detail here: a ServiceId(address) method was constructing a service ID in form of protocol://service#host:port/ which resulted in Consul complaining about lack of TTL. Changing it to service#host:port seems to fix the error.
I guess in this case a consul error message was very misleading.
Check if id format is:
"service:{service id}:{number}"
In your case, you must pass:
"service:" + ServiceId(addr) + ":1"
as your check id.

Try connect to AD via Ldap

I want to implement a function which connects to AD via Ldap.
My code:
public bool TryConnect(string server, string userName, string password)
{
try
{
var credentials = new NetworkCredential(#"test\administrator123", #"P2ssw0rd");
var ldapidentifier = new LdapDirectoryIdentifier("Test");
using (var ldapconn = new LdapConnection(ldapidentifier, credentials))
{
ldapconn.AuthType = AuthType.Basic;
var request = new SearchRequest("dc=test, dc=local", "(objectClass=user)", System.DirectoryServices.Protocols.SearchScope.Subtree, null);
var response = (SearchResponse)ldapconn.SendRequest(request);
}
}
catch (Exception)
{
return false;
}
return true;
}
This is working, but I don't like it !
Is there some cleaner way how to test connection without try/catch and without some dummy search request?
Instead of performing a search, you could call the Bind() method to test basic connectivity like so:
ldapconn.Bind();
However I don't know a way to test this without try/catch.

Linq To Twitter clearing IOAuthCredentials credentials

I have a piece of functionality that creates a voice message and if authenticated through Twitter, will post a message to their Twitter account. I want the ability for the user to turn off the message posting to Twitter if they desire, so I was curious if there was a way to clear the credentials. I followed an example from the LinqToTwitter documentation:
IOAuthCredentials credentials = new SessionStateCredentials();
if (credentials.ConsumerKey == null || credentials.ConsumerSecret == null)
{
credentials.ConsumerKey = ConfigurationManager.AppSettings["twitterConsumerKey"];
credentials.ConsumerSecret = ConfigurationManager.AppSettings["twitterConsumerSecret"];
}
auth = new WebAuthorizer
{
Credentials = credentials,
PerformRedirect = authUrl => Response.Redirect(authUrl)
};
if (!Page.IsPostBack && Request.QueryString["oauth_token"] != null)
{
auth.CompleteAuthorization(Request.Url);
}
if (auth.IsAuthorized)
{
twitterCtx = new TwitterContext(auth);
Session["TwitterContext"] = twitterCtx;
twLoginButton.Text = "Logout of Twitter";
}
I've tried the following code and variations:
credentials = null;
or
SessionStateCredentials credentials = Dispose();
But it shows errors for each of these. I was hoping someone could guide me in clearing out
IOAuthCredentials credentials = new SessionStateCredentials();
which is what I think needs to happen. Any advice would be appreciated.
The SessionStateCredentials type has properties that use Session state as their backing store. Here are a few options, with pros and cons of each:
Set the properties to null. e.g.
credentials.ConsumerKey = null;
credentials.ConsumerSecret = null;
// etc ...
This is a little ugly, though you could write a method to encapsulate the statements.
Clear out the individual Session state items. e.g.
Session.Remove("ConsumerKey");
Session.Remove("ConsumerSecret");
// etc ...
This is more explicit. However, it breaks the existing encapsulation and forces you to obtain a reference to the current session.
Derive a new class from SessionStateCredentials with a Clear method that performs the steps from one of the previous methods. This might be the cleanest option.
Here's a link to the SessionStateCredentials class so you can see the internal implementation:
http://linqtotwitter.codeplex.com/SourceControl/latest#LinqToTwitter/OAuth/SessionStateCredentials.cs

How to invalidate a C# WCF session if login is incorrect

I am writing a remote service for an application using WCF, in which login information is kept in a database. The service requires session establishment through a login or account creation call. There is no ASP involved.
Now, when a client starts a session by calling an exposed IsInitiating method, I check the account data provided against the information on the database and, if it is not correct, I want to invalidate that session and force the client to start again with a call to an IsInitiating method.
Looking at some other questions, I have found pros and cons for two ways to invalidate a session. One does so the hard way, by throwing a FaultException; the other with softer manners, storing accepted session IDs.
Now, the first one, although achieving what I desire, is way too aggressive, given that incorrect logins are part of the normal flow of the application. The second one, on the other hand, allows the client to continue calling non-initiating methods, eventhough they will be rejected, while also incurring in a considerable code overhead on the service due to the added thread safety requirements.
So, the question: Is there a third path which allows the service to invalidate the session initialization and communicate it to the client, so it is forced to make a new IsInitiating call?
A reduced version of the code I have:
[DataContractAttribute]
public class AccountLoginFault
{
public AccountLoginFault (string message)
{
this.Message = message;
}
[DataMemberAttribute]
public string Message { get; set; }
}
[ServiceContract (SessionMode = SessionMode.Required)]
public interface IAccountService
{
[OperationContract (
IsInitiating = true)]
[FaultContractAttribute (
typeof (AccountLoginFault),
ProtectionLevel = ProtectionLevel.EncryptAndSign)]
bool Login (AccountData account, out string message);
}
[ServiceBehavior (
ConcurrencyMode = ConcurrencyMode.Single,
InstanceContextMode = InstanceContextMode.PerSession)]
public class AccountService : IAccountService
{
public bool Login (AccountData account, out string message)
{
UserManager userdb = ChessServerDB.UserManager;
bool result = false;
message = String.Empty;
UserData userData = userdb.GetUserData (account.Name);
if (userData.Name.Equals (account.Name)
&& userData.Password.Equals (account.Password))
{
// Option one
// Get lock
// this.AcceptedSessions.Add (session.ID);
// Release lock
result = true;
} else
{
result = false;
// Option two
// Do something with session context to mark it as not properly initialized.
// message = "Incorrect account name or password. Account provided was " + account.Name;
// Option three
throw new FaultException<AccountLoginFault> (
new AccountLoginFault (
"Incorrect account name or password. Account provided was " + account.Name));
}
return result;
}
}
Throwing an exception is by far the easiest option because WCF enforces that the session cannot be re-used. From what I gather, what you would like the third party component to accomplish comes quite close to this functionality. But, instead of forcing the client to call IsInitialized again, you would force the client to create a new connection. This looks like a very small difference to me.
An alternative would be to have a private variable bool _authorised and check this variable at every method call.
Do something like this:
public ConnectResponseDTO Connect(ConnectRequestDTO request) {
...
if(LoginFailed)
OperationContext.Current.OperationCompleted += FaultSession;
}
private void FaultSession(object sender, EventArgs e) {
var context = (OperationContext) sender;
context.Channel.Abort();
}
This will fault the channel and the client will havce to reesatablish the session.

Categories