in reply to Re^4: MIME voodoo.
in thread MIME voodoo.

if you switch the two mimes around it doesn't work

Note my last comment for the example. There's a bug, as $_->content_type returns not just text/plain, but text/plain; charset=.... So you should replace

$ct{$_->content_type} = $_ for @parts;
with
for (@parts) { (my $c = $_->content_type) =~ s/;.+//; $ct{$c} = $_; }

but this solution thought would work for most messages isn't perfect either, as it is possible to have several text/plain parts with different charsets.

Replies are listed 'Best First'.
Re^6: MIME voodoo.
by vxp (Pilgrim) on Jul 16, 2009 at 20:10 UTC

    Ah! I see now - you're getting rid of the semicolon and everything that follows, so you're only left with text/plain or text/html. I see. :)

    Any ideas why it only returns the plain text portion, and no html?

    sub get_text_parts { my @parts = shift->parts; my %ct; # $ct{$_->content_type} = $_ for @parts; for (@parts) { (my $c = $_->content_type) =~ s/;.+//; # print "\nDEBUG: $c\n"; $ct{$c} = $_; } return $ct{'text/plain'} if exists $ct{'text/plain'}; return $ct{'text/html'} if exists $ct{'text/html'}; return $parts[0] if $which =~ /text/; return $parts[1] if $which =~ /html/; }

    outputs:

    $ ./grab.pl mime4 html line1 line2 line3 $ ./grab.pl mime4 text line1 line2 line3 $

    I really appreciate you taking the time to help out, thanks a lot :)

      return $ct{'text/plain'} if exists $ct{'text/plain'}; return $ct{'text/html'} if exists $ct{'text/html'}; return $parts[0] if $which =~ /text/; return $parts[1] if $which =~ /html/;
      should be
      my $ct = $which eq 'html' ? 'text/html' : 'text/plain'; return $ct{$ct} if exists $ct{$ct}; # Fall back to plain text or HTML return $ct{'text/plain'} if exists $ct{'text/plain'}; return $ct{'text/html'} if exists $ct{'text/html'}; # Fall back to whatever's first return $parts[0];

      By the way,

      $ct{$_->content_type} = $_ for @parts;

      should be changed to

      $ct{$_->content_type} ||= $_ for @parts;

      to get the *first* part with the right content type, not the last.

        Now it works as I intended! Much thanks to all
      Any ideas why it only returns the plain text portion, and no html?

      Sure ;) Look at this, here are four returns and first always works:

      #this one returns you text/plain part return $ct{'text/plain'} if exists $ct{'text/plain'}; # and these are not executed it there's text/plain part return $ct{'text/html'} if exists $ct{'text/html'}; # these are not executed at all an they are not correct! # parts[0] may contain text/html and parts[1] text/plain return $parts[0] if $which =~ /text/; return $parts[1] if $which =~ /html/