Possible to change message date through MAPI props? - c++

Is it possible to change any of the email message dates (sent, received, modified...) through MAPI properties? I'm looking at the IMessage interface and don't see anything related to that. Am I looking in the wrong place?
https://msdn.microsoft.com/en-us/library/office/cc842097.aspx
IMessage : IMAPIProp
IMessage::CreateAttach
IMessage::DeleteAttach
IMessage::GetAttachmentTable
IMessage::GetRecipientTable
IMessage::ModifyRecipients
IMessage::OpenAttach
IMessage::SetReadFlag
IMessage::SubmitMessage

Yes, all properties except for PR_CREATION_TIME and PR_LAST_MODIFICATION_TIME can be modified. You need to use IMessage::SetProps (that method is inherited from the IMAPIProp interface).

Related

How to create a stop-filter (instead of a pass-filter) when reading CAN messages? [C++, Linux]

I am using a SocketCAN to access the CAN bus.
I have successfully created pass-filters like this:
struct can_filter m_Filter;
// ... setting up m_Filters
setsockopt(m_CanSockId, SOL_CAN_RAW, CAN_RAW_FILTER, m_Filter,
sizeof(struct can_filter));
This instructs to let CAN messages pass when meeting the filter settings.
Now I want to create a stop-filter but I do not know how to do it.
For example: I wish to let all CAN messages pass except the ones with ID 0x18DAF101.
Does anybody know how to do it?
You have to set the bit CAN_INV_FILTER in your filter to invert the filter logic.
From the documentation behind the link you have provided:
The filter can be inverted in this semantic, when the CAN_INV_FILTER
bit is set in can_id element of the can_filter structure.

ws:outbound-gateway custom interceptor with message header

I am using ws:outbound-gateway to invoke soap service. I have added interceptor as well.
<int-ws:outbound-gateway id="wsOutboundGateway"
request-channel="requestChannel"
uri="{soapURI}"
message-sender="httpMessageSender"
message-factory="messageFactory"
interceptor="myInterceptor"
marshaller="jaxbMarshaller" unmarshaller="jaxbMarshaller">
<int-ws:uri-variable name="soapURI" expression="headers.soapURI"/>
</int-ws:outbound-gateway>
myInterceptor is a class which implements ClientInterceptor.
Query: I have the information in message header which needs to be intercepted. Is there any way to receive the message header in the interceptor.
Note : I am setting the header value in thread local and getting back in the interceptor now.
Any better solution, please suggest.
It depends of the premise and context.
Sorry, but you have to share more info. What is the header? What do you do with that? Maybe there is no need to intercept it in the ClientInterceptor, but would be better even before <int-ws:outbound-gateway>?
UPDATE
I have the info in message header where I have to pass it in the soap header.
Actually ClientInterceptor is fully for different purpose and its intention do not modify the message.
There is WebServiceMessageCallback abstraction for message modification before sending.
But having your requirements like pass SOAP header I can suggest you to take a look into out-of-the-box component like DefaultSoapHeaderMapper. Its populateStandardHeaders deal only with SoapAction and populateUserDefinedHeader populates only as soapHeader.addAttribute(). So, consider some extension of that class to insert custom tags into soapHeader. And already without any ThreadLocal hacks.

OTRS Webservice as Requestor Test

I'm new to OTRS (3.2) and also new to PERL but I have been given the task of setting up OTRS so that it will make a call to our remote webservice so a record can be created on our end when a ticket is set as "Closed".
I set up various dynamic fields so the customer service rep can fill in additional data that will be passed into the webservice call along with ticket details.
I couldn't get the webservice call to trigger when the ticket was "Closed" but I did get it to trigger when the "priority" was changed so I'm just using that now to test the webservice.
I'm just using the Test.pm and TestSimple.pm files that were included with OTRS.
When I look at the Debugger for the Webserice, I can see that the calls were being made:
$VAR1 = {
'TicketID' => '6'
};
My webservice currently just has one method "create" which just returns true for testing.
however I get the following from the Test.pm
"Got no TicketNumber (2014-09-02 09:20:42, error)"
and the following from the TestSimple.pm
"Error in SOAP call: 404 Not Found at /TARGET/SHARE/var/otrs/Kernel/GenericInterface/Transport/HTTP/SOAP.pm line 578 (2014-09-02 09:20:43, error)
I've spent countless hours on Google but couldn't find anything on this. All I could find is code for the Test.pm and TestSimple.pm but nothing really helpful to help me create a custom invoker for my needs and configure the webservice in OTRS to get it to work.
Does anyone have any sample invokers that I can look at to see how to set it up?
Basically I need to pass the ticket information along with my custom dynamic fields to my webservice. From there I can create the record on my end and do whatever processing.
I'm not sure how to setup the Invoker to pass the necessary ticket fields and dynamic fields and how to make it call a specific method in my remote webservice.
I guess getting the Test.pm and TestSimple.pm to work is the first step then I can modify those for my needs. I have not used PERL at all so any help is greatly appreciated.
I'm also struggling with similar set of requirements too. I've also never programmed in PERL, but I can tell you at least that the "Got no TicketNumber" in the Test.pm is right from the PrepareRequest method, there you can see this block of code:
# we need a TicketNumber
if ( !IsStringWithData( $Param{Data}->{TicketNumber} ) ) {
return $Self->{DebuggerObject}->Error( Summary => 'Got no TicketNumber' );
}
You should change all references to TicketNumber to TicketID, or remove the validation whatsoever (also there is mapping to ReturnedData variable).
Invoking specific methods on your WS interface is quite simple (but poorly documented). The Invoker name that you specify in the "OTRS as requester" section of web service configuration corresponds to the WS method that will be called. So if you have WS interface with a method called "create" just name the Invoker "create" too.
As far as the gathering of dynamic field goes, can't help you on that one yet, sorry.
Cheers

How to make the login part in QuickFIX

How can I make the login part in QuickFIX in c++?
I found tons of tutorials and articles on how to do this on c# or java, but nothing on c++.
I have a server (acceptor), and a client (initiator). The username and password of the client are stored in the settings file, and are hardcoded in the server program.
From what I've read in the client I set the username and password in fromAdmin() and read and check the in the server in the toAdmin(), but how do I do that?
Here's what I've tried so far:
cast the message to a FIX44::Logon& object using:
FIX44::Logon& logon_message = dynamic_cast<FIX44::Logon&>(message);
Set the Username and password to the logon object like this:
if(session_settings.has("Username"))
{
FIX::Username username = session_settings.getString("Username");
logon_message.set(username);
}
And send the message like this:
FIX::Message messageToSend = logon_message;
FIX::Session::sendToTarget(messageToSend);
But I get this error on the cast:
cannot dynamic_cast 'message' (of type 'class FIX::Message') to type 'struct FIX44::Logon&' (target is not pointer or reference to complete type)
What I've tried I got inspired from http://niki.code-karma.com/2011/01/quickfix-logon-support-for-username-password/comment-page-1/.
I'm still not clear on how to make the client and the server.
Can anyone help me?
Possible mistakes:
I think you have fromAdmin()/toAdmin() backward. toAdmin() is called on outgoing admin messages, fromAdmin() is called on incoming. For the Initiator, you must set the fields within the toAdmin() callback. Your Acceptor will check the user/pass in fromAdmin().
Are you trying to dynamic_cast without first checking to see if it was a Logon message? The toAdmin() callback handles all admin messages; the message could be a Heartbeat, Logon, Logout, etc. That might explain your cast error.
As to what the code should look like, my C++ is rusty, but the basic pattern is this:
void YourMessageCracker::toAdmin( FIX::Message& message, const FIX::SessionID& sessionID)
{
if (FIX::MsgType_Logon == message.getHeader().getField(FIX::FIELD::MsgType))
{
FIX44::Logon& logon_message = dynamic_cast<FIX44::Logon&>(message);
logon_message.setField(FIX::Username("my_username"));
logon_message.setField(FIX::Password("my_password"));
}
}
From there, I think you can see how you'd write a similar fromAdmin() where you'd get the fields instead of setting them.
The above uses hard-coded user/pass, but you probably want to pull it from the config file. I think your calls to session_settings.getString(str) are correct for that.
(Please forgive any coding errors. I'm much more fluent in the Java/C# versions of the QF engine, though the basic principles are the same.)
I see that your first web reference uses the FIELD_GET_REF macro. It may be better than message.getHeader().getField(), but I'm not familiar with it.

Questions about QuickFIX message cracking

VERY basic questions from a FIX newbie
Looking at the documentation at http://www.quickfixengine.org and reading posts here on stackoverflow I see lots of talk about message 'cracking'. I think I sort of get the idea, but feel like I'm still not totally clear.
Can some explain in general what exactly this is (why is it necessary? it sounds like a hack), why it only seems relates to received FIX messages, and is not used at all when using Python?
Thank you!
In practice, all you need to know is this:
Your fromApp() callback gets a Message object. That message is actually a NewOrderSingle or ExecutionReport or something. Rather than making you figure it out, QF lets you inherit from MessageCracker. To use it, call crack() in your fromApp(), as follows:
void fromApp( const FIX::Message& message, const FIX::SessionID& sessionID )
throw( FIX::FieldNotFound&, FIX::IncorrectDataFormat&, FIX::IncorrectTagValue&, FIX::UnsupportedMessageType& )
{
crack(message, sessionID);
}
What crack() does is this:
Converts your Message into the proper subclass (e.g. NewOrderSingle, ExecutionReport, etc)
Calls your user-defined onMessage(subtype) callback, if defined. If not defined, it throws an UnsupportedMessageType exception and your app will automatically send a BusinessMessageReject (35=j) to the counterparty.
So, do you want to handle NewOrderSingle messages? Great, just define an onMessage(NewOrderSingle) callback.
void onMessage( const FIX42::NewOrderSingle& message, const FIX::SessionID& )
{
// Do whatever you want with your NewOrderSingle message's content.
// Note that this message and the one passed to crack() are the same, content-wise.
}
Do you want to handle ExecutionReports? Define onMessage(ExecutionReport). And so on.
But what about those message types you don't want to handle? It would suck if you had to add handlers to reject all those other message types, but luckily, you don't have to. As I said earlier, if you don't define an onMessage(), QF will reject it for you. (If you want to swallow a particular message type and ignore it without rejection, then just define an onMessage() call with no body.)
Does that clear it up a bit? Perhaps now this page in the QF docs might read a little easier -- the bottom section talks about the MessageCracker.
Note: The MessageCracker does not handle session-level (aka "admin") messages. If you want to add custom handling for, say, Logon or Heartbeat messages, you must do it explicitly in fromAdmin() (see this question for more info).
I use quickfixj for Java. The cracking uses and interface to return the cracked message to the interface implementation. The implementor will over ride the interface's methods so that it can handle each message type individually.
Message cracker takes a plain message and returns the message as a specifically typed message. The advantage of this is that the dictionary will confine the fields of the message so that it is easier to look up each field.