Can I use shortcodes in mail body

The shortcode generation should output a string, so that should in theory be possible if you know and trust the shortcode’s output.

But many shortcodes are generated with the front-end in mind and within the loop context, so the mail context might not always work though, if they depend on conditional checks like is_single().

There is the shortcode_exists() function to make sure the shortcode exists.

It’s also possible to use the shortcode’s callback directly, instead of having to run the complicated parsing of do_shortcode().

You might also add some validations regarding the shortcode’s output, before mailing it. Like do you want allow sending an empty string?

You should also hook your mailing code, after the shortcode has been added within the init action.

Note that WordPress uses the wp_mail() wrapper that plugins can hook into.