use strict; use warnings; use 5.010; use MIME::Lite; use Email::MIME; my $msg = MIME::Lite->new( From => 'src@example.com', To => 'dst@example.com', Subject => 'message', Type => 'multipart/alternative', ); $msg->attach( Type => 'text/plain', Data => 'this is text content', ); $msg->attach( Type => 'text/html', Data => 'this is html content', ); my $msg_str = $msg->as_string; print $msg_str; # note the output here -- that's a complete message my $parsed = Email::MIME->new($msg_str); say "*" x 50; if ($parsed->content_type =~ m{^multipart/alternative}) { say get_text_parts($parsed)->body; } sub get_text_parts { my @parts = shift->parts; my %ct; $ct{$_->content_type} = $_ for @parts; return $ct{'text/plain'} if exists $ct{'text/plain'}; return $ct{'text/html'} if exists $ct{'text/html'}; return $parts[0]; }