package GT::Mail::Editor::HTML; use vars qw/$ERROR_MESSAGE/; use strict; use bases 'GT::Mail::Editor' => ''; $ERROR_MESSAGE = 'GT::Mail::Editor'; sub display { # ---------------------------------------------------------------- my ( $self, $tags ) = @_; my $page = $self->{html_tpl_name}; if ( $self->{fields}{page} and $self->{fields}{page} =~ /^(?:editor|email)_/ ) { $page = $self->{fields}{page}; } my $ret = $self->print_page( $page, $tags ); $self->{displayed} = 1; return $ret; } sub message_from_input { # ---------------------------------------------------------------- my ( $self ) = @_; $self->set_headers; # If we have a part ID, this isn't a new text part my ( $part, $id ); $part = $self->{part}; $part->set( 'content-type' => 'text/html; charset="'.( $self->{fields}{charset} || 'US-ASCII' ).'"' ); if ( exists( $self->{fields}{msg} ) ) { my $msg = $self->{fields}{msg}; $self->urls_to_inlines( $self->{part}, \$msg ); $part->body_data( $msg ); } } sub munge_message { # ---------------------------------------------------------------- my ( $self ) = @_; my $root_part = $self->{message}->root_part; # Simple case if the message is not multipart if ( !$root_part->is_multipart ) { $self->munge_non_multipart( $root_part ); } # We have a multipart. First thing we do is look for an alternative part # to use. elsif ( my ( $alt ) = $self->{message}->find_multipart( 'alternative' ) ) { $self->munge_alternative( $alt ); } else { $self->munge_other; } $self->fix_alt_parts; $self->fix_related_parts; $self->delete_empty_multiparts; my ( $alt_part ) = $self->{message}->find_multipart( 'alternative' ); my @skip = $alt_part->parts; $self->find_attachments( @skip ); $self->{alt_part} = $alt_part; $self->{part} = $skip[1]; } sub html_part { # ---------------------------------------------------------------- my $self = shift; return $self->{alt_part}->parts->[1]; } sub text_part { # ---------------------------------------------------------------- my $self = shift; return $self->{alt_part}->parts->[0]; } sub munge_non_multipart { # ---------------------------------------------------------------- my ( $self, $root_part ) = @_; # We need to munge the message into a multipart my $new_alt = $self->alt_part( html => $root_part, charset => $root_part->mime_attr( 'content-type.charset' ), headers_part => $root_part ); $root_part->set( 'content-type' => 'multipart/mixed' ); $root_part->parts( $new_alt ); } sub munge_alternative { # ---------------------------------------------------------------- my ( $self, $alt_part ) = @_; my $root_part = $self->{message}->root_part; # Make anything we can not view an attachment $self->{message}->move_parts_last( $root_part, grep { $_->content_type ne 'text/plain' and $_->content_type ne 'text/html' } $alt_part->parts ); # Anything left is either text or html my ( $html_part, $text_part ); for ( $alt_part->parts ) { if ( $_->content_type eq 'text/html' ) { $html_part = $_; } else { $text_part = $_; } } # If we do not have an editble part we need to make an empty html one if ( !defined( $text_part ) and !defined( $html_part ) ) { $html_part = $self->{message}->new_part( 'content-type' => 'text/html; charset="'.( $self->{fields}{charset} || 'US-ASCII' ).'"', -body_data => '
' ); } my $new_alt = $self->alt_part( html => $html_part, text => $text_part, charset => $self->{fields}{charset} ); if ( $alt_part == $root_part ) { $root_part->set( 'content-type' => 'multipart/mixed' ); $self->{message}->delete_parts( $root_part->parts ); $root_part->parts( $new_alt ); } else { $self->{message}->replace_part( $alt_part, $new_alt ); } } sub munge_other { # ---------------------------------------------------------------- my ( $self ) = @_; # Else we need to search through the parts to find the displayable parts my ( $html_part, $text_part ); for my $part ( $self->{message}->all_parts ) { if ( !$html_part and $part->content_type eq 'text/html' and $part->mime_attr( 'content-disposition' ) ne 'attachment' ) { $html_part = $part; } elsif ( !$text_part and $part->content_type eq 'text/plain' and $part->mime_attr( 'content-disposition' ) ne 'attachment' ) { $text_part = $part; } last if $html_part and $text_part; } # If we do not have an editble part we need to make an empty html one if ( !defined( $text_part ) and !defined( $html_part ) ) { $html_part = $self->{message}->new_part( 'content-type' => 'text/html; charset="'.( $self->{fields}{charset} || 'US-ASCII' ).'"', -body_data => '' ); my $new_alt = $self->alt_part( html => $html_part, text => $text_part, charset => $self->{fields}{charset} ); $self->{message}->add_parts_start( $self->{message}->root_part, $new_alt ); my $parent = $self->{message}->parent_part( $new_alt ); if ( $parent and $parent->content_type eq 'multipart/related' ) { $parent->set( 'content-type' => 'multipart/mixed' ); } } else { my $new_alt = $self->alt_part( html => $html_part, text => $text_part, charset => $self->{fields}{charset} ); my $parent_part = $self->{message}->parent_part( $html_part ); if ( !$parent_part ) { $parent_part = $self->{message}->parent_part( $text_part ) } if ( $parent_part and $parent_part->content_type eq 'multipart/related' ) { if ( !$html_part ) { $parent_part->set( 'content-type' => 'multipart/mixed' ); $self->{message}->add_parts_start( $parent_part, $new_alt ); if ( $text_part ) { $self->{message}->delete_part( $text_part ); } } else { $self->{message}->replace_part( $parent_part->parts->[0], $new_alt ); } } else { if ( $text_part ) { $self->{message}->delete_part( $text_part ); } if ( $html_part ) { $self->{message}->delete_part( $html_part ); } $self->{message}->add_parts_start( $self->{message}->root_part, $new_alt ); } } } sub alt_part { # ---------------------------------------------------------------- my ( $self, %opts ) = @_; my ( $text, $html, $header_from, $charset ) = @opts{qw/text html headers_part charset/}; my $text_type = 'text/plain; charset="'.( $self->{fields}{charset} || 'US-ASCII' ).'"'; my $html_type = 'text/html; charset="'.( $self->{fields}{charset} || 'US-ASCII' ).'"'; if ( defined( $text ) ) { $text = $self->new_part_from( $text, $text_type ); } elsif ( defined( $html ) ) { $text = $self->{message}->new_part( 'content-type' => $text_type, -body_data => $self->html_to_text( ref( $html ) ? $html->body_data : $html ) ); } else { $self->fatal( BADARGS => "Either text or html must be defined" ); } if ( defined( $html ) ) { $html = $self->new_part_from( $html, $html_type ); } elsif ( defined( $text ) ) { $html = $self->{message}->new_part( 'content-type' => $html_type, -body_data => $self->text_to_html( $text->body_data ) ); } # logic error, one must be defined else { $self->fatal( BADARGS => "Either text or html must be defined" ); } my @header = (); if ( $header_from ) { @header = map { $_ => [$header_from->get( $_ )] } $header_from->get; } return $self->{message}->new_part( @header, 'content-type' => 'multipart/alternative', -parts => [$text, $html] ); } sub new_part_from { # ---------------------------------------------------------------- my ( $self, $from, $type ) = @_; if ( !ref( $from ) ) { return $self->{message}->new_part( 'content-type' => $type, -body_data => $from ); } elsif ( ref( $from ) ) { return $self->{message}->new_part( 'content-type' => $type, -body_data => $from->body_data ); } } 1;