use strict; use warnings; use 5.010; use MIME::Lite; use HTML::TreeBuilder; # or what you like most use File::Basename; use File::Type; # ... sub makemsg { my (%id, %saw); (my $tree=HTML::TreeBuilder->new)->parse_file(shift); for my $img ($tree->look_down(_tag => 'img')) { defined(my $imgname=$img->attr('src')) or warn "[$0] Warning: img tag with no src attribute!" and next; unless($id{$imgname}) { # not necessary, but I prefer it like that! (my $id=basename $imgname) =~ s/_*[^\w]+/_/g; $id++ while exists $saw{$id}; $saw{$id}++; $id{$imgname}=$id; } $img->attr(src => "cid:$id{$imgname}"); } my $msg=MIME::Lite->new( To =>'someone@example.org', Subject =>'HTML with in-line images!', Type =>'multipart/related'); $msg->attach( Type => 'text/html', Data => $tree->as_HTML); $tree->delete; # However ugly, it's necessary! my $ft=File::Type->new; for (keys %id) { $msg->attach( Type => $ft->checktype_filename($_) // 'image/xyz', Id => $id{$_}, Path => $_); } $msg; }