Quote:
>>Hi all.
>>I just spent a day trying to figure out how to contctruct a multipart
>>MIME message with MIME-tools (MIME::Entity) and then send it using
>>Mail-tools (Mail::Mailer, preferably, or Mail::Internet). So far I've
>>come up with, drum roll, nothing! Nada! Zilch!
> I've been attempting something similar, though not using MIME::Entity or
> Mail:: - my feeble attempt was to use MIME::Base64 to encode the file I'm
> trying to send, then piping the output directly to sendmail.
> I got it sorta working - I'm getting attachments, but they're basically
> complete garbage when my email client gets done with them. Bizarre file names,
> and weird contents... I'll end up with an attachment called "scriptname.dat"
> (two attachements, actually, with the same name) that contain the first line
> or so of the file I'm sending... I was trying with an HTML file, and when I
> look at my results, I see something like:
> <html>
> <t>
> Anyway, if you get this figured out (using your approach or mine), I'd love to
> hear about it.
> Thanks!
> Chris
Ok this is obviously more difficult than I thought. I do remember having a
little fun with this but it is by no means the hardest thing I have had to do.
Basically do all of the pre-processing of the meassage first.
Get a list/array of files together or a list/array of text/* messages, these
these are going to be used to build an 'entity'.
What needs to be done nest depends on whether you are just sending files or
if you want to send a message as the first part (of a multipart), as I
found you had to init the entity slightly differently for each.
If you want an intro as it where you need to include the data when you
build your entity, otherwise you have to incude the encoding and type stuff
in the hash you send to the buils method.
I put into a module to make it easier to use, I'll just post the relevant
bits, go easy on it as I wrote it a while ago. (Although improvements would
be greatly accepted :-) )
So here goes.
package Attach;
use MIME::Entity;
use MIME::Parser;
use File::Basename;
use Carp;
# Create a new Mime Entity
sub new {
# create a new instance of a mime object
my $self = shift;
my $dir = $params{Dir} || undef;
my $msg = $params{Message} || undef;
my $size = $params{Limit} || 0;
=pod
I use a tie hash to load the list of mime types (basically because
I had written it and I didn't need to do anything else to get it to
work but it's probably just as easy to load the mime types in from
the stansrd apache mime-type file.
my %TypeFor;
# Lookup table:
if ($params{MTypePath}) {
(tie my %typ, "FlatFile", $params{MTypePath}) ||
warn "Warning: possible error in mime types";
my ($mime_type,$val,$sub);
foreach $mime_type (keys %typ) {
$val = $typ{$mime_type};
# ($val,$sub) = split ';', $val;
foreach (split ',',$val) {
$TypeFor{$_} = "$mime_type";
}
}
untie %typ;
}
=cut
my $entity = {
USER => $params{Sender},
TYPE => {%TypeFor},
DIR => $dir,
ENT => undef,
FILES => [],
};
my $obj = bless $entity, $self;
if ($params{Header}) {
warn "Info A:prt1";
my $msg = $params{Header}."\n\n".$params{Body};
unless (-d $dir) {
mkdir $dir,0755 or
(warn "Can't create directory $dir: $!" and return undef);
}
my $parser = new MIME::Parser;
$parser->output_to_core($size);
$parser->output_dir($dir) if $dir;
$obj->{ENT} = $parser->parse_data($msg);
}
elsif (!$msg) {
warn "Info A:prt2";
my $path = $dir ? $dir.'/' : '';
$obj->{ENT} = build MIME::Entity
From => $params{Sender},
'X-Mailer' => "WebMail [version 0.8]",
Path => $path,
Type => $obj->_TFOR($path),
Encoding => '-SUGGEST';
$obj->sign($params{Sig}) if $params{Sig};
}
else {
warn "Info A:prt3";
$obj->{ENT} = build MIME::Entity
From => $params{Sender},
'X-Mailer' => "WebMail [version 0.8]",
Data => $msg;
$obj->sign($params{Sig}) if $params{Sig};
}
return $obj;
Quote:
}
sub sign {
my $self = shift;
my $sig = shift;
$self->{ENT}->attach(Data => $sig);
Quote:
}
sub _ATTACH {
# INTERNAL SUBROUTINE DO NOT USE
# attache and encode files to message
my $self = shift;
return undef;
}
my $path = $self->{DIR} ? $self->{DIR}.'/' : '';
$path .= $file;
return undef unless ( -e $path );
$self->{ENT}->attach(
Path => $path,
Type => $self->_TFOR($path),
Encoding => '-SUGGEST');
}
else {
$self->_ATTACH($_);
}
}
Quote:
}
sub _TFOR {
# get the mime type for this file
my $self = shift;
my $path = shift;
my ($mime_type,$ext);
($ext) = $path =~ /.*\.(.+)\Z/i;
$mime_type = $self->{TYPE}{$ext}
if (exists $self->{TYPE}{$ext});
($ext and $mime_type) or
(-T $path ? 'text/plain' : 'application/octet-stream');
Quote:
}
sub hdr {
# get/set a mime header. will return as an array or scalar
my $self = shift;
$self->{ENT}->head->add(shift,shift,0);
}
}
else {
return $self->{ENT}->stringify_header unless wantarray;
foreach (split "\n",$self->{ENT}->stringify_header) {
}
}
Quote:
}
sub body{
# get/set a mime body. will return as an array or scalar
my $self = shift;
;
Quote:
}
sub files {
# return the original file names of each attachement
my $self = shift;
# return $self->{FILES};
Quote:
}
sub add {
# append a file to message
my $self = shift;
return $self->{FILES};
Quote:
}
Sorry it's long and probably ugly, but I understand it.
To use it just do something like this...
# create a new mime entity
my $ent = new Attach Sender => $sender,
Dir => $wkg_dir,
Message => $msg,
MTypePath => $self->{STP}{mime},
# add some more headers to the mime entity
$ent->hdr(To => $sendto,Subject => $subject);
$ent->hdr(Cc => $ccto) if $ccto;
$ent->sign($sig) if $sig;
# get the mime headers and put them in a hash
my %hdr = $ent->hdr;
# get the body from the entity
my $msg = $ent->body;
All that remains is to build a header and combine it with the body with
a blank line in between the 2, and then send it with your favourite
mail delivery agent (I would suggest sendmail for it's queing ability and
other attributes)
I do it this way because I can then pass the headers and body separately to
Zenins Sendmail.pm module. (But that's another story :-) )
Ok I know it's probably OTT for what Terje and Chris want, but they should
be able to work out what they need from it.
Also I really should look at converting this to an OOP module as I suspect
I am doing a lot of the work that the MIME::Entity module already does
and inheritance may solve this. However I am a firm believer of the addage
'if it ain't broke don't fix it' (best said in good Lancashire accent)
Quote:
> Remove the SPAM to reply:
NO. I hate this. Learn to use filters.
--
--
Ian J. Garlick
FLASH! Intelligence of mankind decreasing. Details at ... uh, when
the little hand is on the ....