I am developing a custom transport agent for Exchange 2013. I am getting null in e.MailItem.Message.CalendarPart though I am sending a meeting request.
if (e.MailItem.Message.CalendarPart != null)
{
LocationProcessorStrategy.AddLocationInBody(e.MailItem.Message);
}
else
{
e.MailItem.Message.Subject += " [There is no calendar part - added by agent.]";
}
e.MailItem.Message.MapiMessageClass is giving me the value "IPM.Schedule.Meeting.Request" but CalendarPart is null.
That generally means that at the Messaging stage you trying to intercept the message there is no ICal Body part to parse. iCal is usually create post categorisation depending on the recipient type https://technet.microsoft.com/en-us/library/bb232174(v=exchg.150).aspx . So either push your Agent to run after categorisation has occurred or use the TNEFReader/TNEFWriter to parse the TNEFStream for the message. Note you may need two solution if you want process bother internal and external Calendar Invites because of the formats used.
Related
I am currently trying to handle the exception, when a subscription request can't be validated in time, using the Graph SDK. Unfortunately i am not really sure how to achieve this. The exception thrown when a subscription isn't validated in time is:
Microsoft.Graph.ServiceException: Code: InvalidRequest
Message: Subscription validation request failed. Must respond with 200 OK to
this request.
The HttpStatusCode in the ServiceException is "BadRequest" but just this isn't enough to distinguish the error from other common errors since i want to handle them differently. The ServiceException also contains an Error property with a string property called "Code", which contains "InvalidRequest" in my case. The GraphErrorCode enum in the Graph SDK contained this code so i used it with the "IsMatch" method in the ServiceException:
catch (ServiceException serviceException)
{
var invRequest = GraphErrorCode.InvalidRequest.ToString();
if(serviceException.StatusCode == HttpStatusCode.BadRequest)
{
if (serviceException.IsMatch(invRequest))
{
// do something
}
}
}
"InvalidRequest" is defined in the graph documentation as:
The request is malformed or incorrect.
Considering this i still think my ErrorHandling isn't enough to just catch this specific error.
What i want to know is:
Is using the "GraphErrorCode" enum even correct.
Is there a way to handle this specific error without just comparing the exception message ("Subscription validation request failed. Must respond with 200 OK to this request") with a hard coded string.
You're referencing an outdated library (by over 2 years). The correct SDK for this is the Microsoft Graph .NET Client Library. It includes an far more recent error code enumeration.
As for processing the error, the code is typically enough for handling exceptions. The message content is useful for debugging since it often includes more granular information (what exactly failed, which properties were invalid, etc.). My general rule of thumb is to use the code for handling errors but log both code and message properties for debugging.
The import piece to understand is that different endpoints may surface the same error code for different reasons. A BadRequest may mean something different when issuing a GET against a user resource than it does when issuing a POST to /events. Your handler should take into account both the action and the error.
Here is an example error returned when sending an invalid request (/v1.0/me/a):
{
"error": {
"code": "BadRequest",
"message": "Unsupported segment type. ODataQuery: users/48d31887-5fad-4d73-a9f5-3c356e68a038/a",
"innerError": {
"request-id": "fd4c8b27-26af-4b07-a5be-5efb139d1eb7",
"date": "2018-05-22T14:39:02"
}
}
}
If all I handled was the BadRequest, my handler would likely sufficient. I can handle the error and keep the user moving forward. In my log however I store both BadRequest and Unsupported segment type. ODataQuery: users/48d31887-5fad-4d73-a9f5-3c356e68a038/a so that I can properly file a bug in the code.
Another option might be to do some additional parsing. Lets say that /a doesn't always return an error. Maybe /a works fine for AAD accounts but not for MSA users (FTR, /a is entirely fictitious). If this were the case, I might also want to parse the message and see if the BadRequest included "Unsupported segment type" and handle it a bit differently than a BadRequest that didn't include that message.
For now I have tried to filter the messages based on Message Attribute Name="Class". As you can see in the below code
//Specify attribute list
List<string> AttributesList = new List<string>();
AttributesList.Add("Class");
receiveMessageRequest.MessageAttributeNames = AttributesList;
receiveMessageRequest.QueueUrl = urlSQS;
receiveMessageRequest.MaxNumberOfMessages = 10;
ReceiveMessageResponse receiveMessageResponse = objClient.ReceiveMessage(receiveMessageRequest);
But the messages are not been filtered based on the provided MessageAttributeName = "class".
receiveMessageRequest.MessageAttributeNames = AttributesList;
This tells SQS which message attributes you want it to return with the message if the are present on the message. It is not a message filter. If the attributes aren't present, nothing happens.
But your confusion seems understandable -- it's not actually obvious why the API even has this functionality, though it may be a holdover from when SQS supported only smaller messages than it does today, or it may be so that you can avoid spending any time parsing information from the response that you will end up discarding. I almost always just ask for All.
Please note this regarding messaging services on AWS
SQS : No filtering support ( while picking up messages)
SNS : Supports attributes-based filtering: subscriber can set a subscription attribute (a subscription filter policy) which is applied on incoming messages and only relevant messages can be sent to the subscriber.
EventBridge: Amazon EventBridge supports declarative filtering using event patterns. With event pattern content filtering you can write complex rules that only trigger under very specific conditions. For instance, you might want a rule that will trigger only when a field of the event is within a specific numeric range, if the event comes from a specific IP address, or only if a specific field does not exist in the event JSON.
Please refer my article for a detailed difference between main messaging frameworks on AWS.
https://www.linkedin.com/pulse/mastering-art-decoupling-application-architecture-aws-amit-meena/
It depends on how the message in question gets onto the queue. If you are pushing the message via SNS then yes you can filtered messages; https://docs.aws.amazon.com/sns/latest/dg/message-filtering.html
Any other filtering mechanism doesn't exist right now.
Hope that helps!
As per the AWS SDK method, we can use following code to do the filter.
ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest("QUEUE URL" );
receiveMessageRequest.setMaxNumberOfMessages(Integer.valueOf(1));
private static AmazonSQS sqs;
List<Message> messages = sqs.receiveMessage(receiveMessageRequest.withMessageAttributeNames("Attribute Name")).getMessages();
If you want all the message then use given code
ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest("QUEUE URL" );
receiveMessageRequest.setMaxNumberOfMessages(Integer.valueOf(1));
private static AmazonSQS sqs;
List<Message> messages = sqs.receiveMessage(receiveMessageRequest.withMessageAttributeNames("All")).getMessages();
I am bit new to the whole MQ world so I am not sure about the specific technicalities.
I am struggling to send a message on a Websphere Mq with additional data; the additional data will then be used by another system for processing.
I am using the following code to do add additional properties to the mq; is this the correct way to do it?
Code in C#
IMessage sendMsg;
IMessageProducer producer;
// Create a message ---someMessage will be a xml file
sendMsg = new IMessage(someMessage);
int fileSize= size("document.pdf");
//add addtional message properties
sendMsg.SetStringProperty("MessageSize",fileSize);
// Send the message
producer.Send(sendMsg);
Also, how do i query the mq so that I get all these properties along with the actual message?
Can anyone please help; this has got me going round in circles....
Yes using SetStringProperty,SetBooleanProperty, etc,you should be able to set the properties. For getting back the property values you should use msg.GetStringProperty,msg.GetBooleanProperty etc after the message is received.In your case it has to be something like msg.GetStringProperty(MessageSize).
FYI. The MQ Knowledge Center is full of information.
Here is the page on Message. Scroll down to the 'Property methods' sections. It has all the methods to retrieve properties from a message.
I'm developing a graphic user interface where the user can send a message to mutuple user using Twilio API in c#
I'm trying to bind a list view to the status of each number being sent and I also want to know the status of the message every time the user click on refresh list view
public void sendSMS(string ssid, string token , string fromNumber, List<string>TOnumbersList ,string msgBody )
{
TwilioClient.Init(ssid, token);
foreach (var toNumber in TOnumbersList)
{
var message = MessageResource.Create(
to: new PhoneNumber(toNumber),
from: new PhoneNumber(fromNumber),
body: msgBody,
provideFeedback: true,
statusCallback: new Uri("http://requestb.in/1jnk4451"));
ListViewItem items = new ListViewItem(message.To);//This show the number being sent to ( delivered number)
items.SubItems.Add(message.Status.ToString()); //Refresh the status WHERE number = message.To
items.SubItems.Add(message.ErrorCode.ToString());//Show error code in case
items.SubItems.Add(message.ErrorMessage); // In case error message show them
listView1.Items.AddRange(new ListViewItem[] { items });
}
}
Twilio API is doing the perfect job updating the status so everytime I go click the link I can see the status. as explained in this documentation Track Delivery Status of Messages in C#
But is It possible to bind a list view so it can be updated everytime the user click on refresh list view ?
Or what is the best way to dynamically show the message status from the URI http://requestb.in/1jnk4451? Maybe embedding a webpage would be better ?
Thank you
Twilio developer evangelist here.
Rather than using the RequestBin URL, if you provide a URL to your own application then you can write an endpoint that receives the status updates of the messages. That way you can store the status yourself and update the list view without having to loop through all the messages.
[Edit] In more detail:
When you send an SMS message with Twilio using the REST API you can set a statusCallback URL to receive updates about the message as it processes through from Twilio to the network and the device.
Twilio will make HTTP requests to this URL as the message goes through each state, the possible states being queued, failed, sent, delivered, or undelivered. Twilio sends a number of parameters as part of this request, some are general ones about the message and some are about the actual status.
To receive these requests you need to set up a web server. I'm not a C# developer I'm afraid, however we have a guide on how to set up a C# and ASP.NET MVC environment that can receive webhooks that should be able to help you there.
Let me know if this helps a bit more!
I am sending an MQ message and getting a messageID and correlationID back in return as expected, and I can capture the response from specific message that I send using the messageID returned by the MQ server.
I put my application into a load testing tool and I saw that in some cases the messageID returned by the queue manager was the same as a previous message, and in these cases the app failed to read the next message with the same messageID.
I'm not the owner of the queue manager and the response from the admin was "created your own message id".
Can I do that? Does the messageID need to have a specific format?
This is my code :
message = strInputMsg;
queueMessage = new MQMessage();
queueMessage.WriteString(message);
queueMessage.Format = MQC.MQFMT_STRING;
queueMessage.Expiry = timeOutExpiry;
queueMessage.ReplyToQueueName = QueueNameExpiry;
queuePutMessageOptions = new MQPutMessageOptions();
queuePutMessageOptions.Options = MQC.MQRO_COPY_MSG_ID_TO_CORREL_ID;
queue.Put(queueMessage, queuePutMessageOptions);
bytReturn = queueMessage.MessageId;
So can I set the MessageID property to my own message ID value before I send the message, like the below?
queueMessage.MessageId = myOwnMessageId
Yes, it's possible that the code sets the message ID explicitly but your code appears to not reuse the MQMD structure which is how that normally happens. It is more likely based on your description and code provided that the load testing tool is replaying the same messages multiple times and preserving the Message ID while doing so.
If MQ is allowed to set the Message ID it guarantees this to be unique within the queue manager for IDs that it generates. It does not guarantee a GUID across many queue managers but does attempt to ensure no collisions by including 12 characters of the QMgr name in the Message ID. So although we have no information as to which load testing tool is being used and if it employs message replay, that possibility seems much more likely than that MQ has a bug that duplicates message IDs during execution of the .Net MQMessage() class constructor.
Please see:
MQMessage.NET class which says "Creates an MQMessage object with default message descriptor information..." Of course, the default MQMD causes the QMgr to generate the Message ID.
MQMD - MsgId (MQBYTE24) which explains in a note at the bottom how MsgID is made to be unique and in the body how it can be controlled by the application putting the messages.