The decryption of S/MIME messages is triggered in mailnews/mime/src/mimecms.cpp.
We have a streaming decoder, see how the decoder_context object is used.
nsCOMPtr<nsICMSDecoder> decoder_context = do_CreateInstance(NS_CMSDECODER_CONTRACTID, &rv);
You initialize it with a callback function that will be called with decrypted content.
Then you have to feed chunks of the encrypted input data into decoder_context->Update(encrypted_input), which will decrypt the chunks, and call content_callback(decrypted_content). When you're done with all input, call decoder_context->Finish(info_object). You can ignore the contents of the info_object for your purpose.
The implementation of content_callback can search for the needle, but doesn't need to do anything else with the haystack it's receiving. However, a single call to content_callback might contain only a subset of needle. So to be really certain, you'd have to search across boundaries of chunks. A possible solution is to grow a large buffer of all decrypted content, and delay the search until you have processed all input.
This will also help with S/MIME (CMS) messages that are signed-only (not encrypted), but uses the CMS opaque encoding, so a simple search through it doesn't work.