MIME-tools/Mail-tools incompatible? 
Author Message
 MIME-tools/Mail-tools incompatible?

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!

Mail-tools want header fields in a hash-ref, but MIME-tools doesn't
provide a way to create one. You could of course dump the
header_as_string and parse it before passing a suitable hash-ref to
Mail::Mailer, but that looks an exceedingly dirty solution to me. The
crutch I've come up with is to dump the complete MIME message (ERYQ
would probably say "MIME Entity", I suppose) to a tempfile, close() and
reopen the file, and pass a glob of the filehandle to
Mail::Mailer->open() (I refuse to open a pipe to sendmail when Net:SMTP
is so readily available!).

Now, I refuse to believe it has to be that hard (or that dirty for that
matter)! Why can't I pass a prefab MIME::Entity object to Mail::Mailer
and call Mail::Mailer->send()? Am I missing something blatantly obvious
here or do the two not want to cooperate at all?

It's conceivable that you can dig up something further down in the
subclasses (or is it "superclasses"? I never get these straight ;D) on
each side that will let you interchange data between the two, but so
far I haven't come up with anything. Anyway, it would make sense to be
able to create a MIME::Entity with MIME-tools and then just pass that
to Mail::Mailer for delivery. Either ERYQ and GBARR are not speaking to
eachother these days; or the how of it is buried too far down in the,
otherwise plentifull and excellent, documentation for the two packages.

Anyways, I'd appreciate it if someone could clarify. Even if it's just
to say that "Sorry, can't be done!".

On a similar note. Has anyone used MIME::Lite? Does it have any serious
problems? Is it still in alpha because the interface is subject to
change or is that indicative of remaining serious bugs? How is
performance?

--

Jobs in your "Board of Directors" folder.  | in comp.sys.mac.comm



Sun, 08 Apr 2001 03:00:00 GMT  
 MIME-tools/Mail-tools incompatible?

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!

> Mail-tools want header fields in a hash-ref, but MIME-tools doesn't
> provide a way to create one. You could of course dump the
> header_as_string and parse it before passing a suitable hash-ref to
> Mail::Mailer, but that looks an exceedingly dirty solution to me. The

I do it this way, it only takes about 4 lines of clear perl code, less
if you don't mind obfuscation. Where I think I win is using Byron's (Zenin)
Mail::Sendmail module, available form his home ftp server:-

        ftp://thrush.omix.com/pub/perl/modules/Mail-Sendmail-1.10.tar.gz

Just give it a header as a hash. Give it the body as a scalar and tell it
to send it. Works brilliantly. Copes with anything.

Quote:
> crutch I've come up with is to dump the complete MIME message (ERYQ
> would probably say "MIME Entity", I suppose) to a tempfile, close() and
> reopen the file, and pass a glob of the filehandle to
> Mail::Mailer->open() (I refuse to open a pipe to sendmail when Net:SMTP
> is so readily available!).

Yuk.

Quote:

> Now, I refuse to believe it has to be that hard (or that dirty for that
> matter)! Why can't I pass a prefab MIME::Entity object to Mail::Mailer
> and call Mail::Mailer->send()? Am I missing something blatantly obvious
> here or do the two not want to cooperate at all?

I looked at MAil::Mailer ages ago. :-( didn't like what I saw.
IMHO Mail::Tools modules are better.

Quote:

> It's conceivable that you can dig up something further down in the
> subclasses (or is it "superclasses"? I never get these straight ;D) on
> each side that will let you interchange data between the two, but so
> far I haven't come up with anything. Anyway, it would make sense to be
> able to create a MIME::Entity with MIME-tools and then just pass that
> to Mail::Mailer for delivery. Either ERYQ and GBARR are not speaking to
> eachother these days; or the how of it is buried too far down in the,
> otherwise plentifull and excellent, documentation for the two packages.

> Anyways, I'd appreciate it if someone could clarify. Even if it's just
> to say that "Sorry, can't be done!".

> On a similar note. Has anyone used MIME::Lite? Does it have any serious
> problems? Is it still in alpha because the interface is subject to
> change or is that indicative of remaining serious bugs? How is
> performance?

--
--
Ian J. Garlick


A lack of leadership is no substitute for inaction.



Sun, 08 Apr 2001 03:00:00 GMT  
 MIME-tools/Mail-tools incompatible?

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>

I took a look at the MIME RFC (RFC 2045), and I guess I'm not understanding
what the "character set" header ought to be, or maybe I'm just completely
confused.

Anyway, if you get this figured out (using your approach or mine), I'd love to
hear about it.

Thanks!

Chris
http://www.charman.com/
Remove the SPAM to reply:



Sun, 08 Apr 2001 03:00:00 GMT  
 MIME-tools/Mail-tools incompatible?

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 ....



Mon, 09 Apr 2001 03:00:00 GMT  
 MIME-tools/Mail-tools incompatible?


Quote:


>>Mail-tools want header fields in a hash-ref, but MIME-tools doesn't
>>provide a way to create one. You could of course dump the
>>header_as_string and parse it before passing a suitable hash-ref to
>>Mail::Mailer, but that looks an exceedingly dirty solution to me. The

>I do it this way, it only takes about 4 lines of clear perl code, less
>if you don't mind obfuscation.

Sure, you could go that way, but I don`t find that particularly more
clean then the approach that gos by way of a tempfile.

Quote:
>Where I think I win is using Byron's (Zenin) Mail::Sendmail module [...]
>Just give it a header as a hash. Give it the body as a scalar and tell it
>to send it. Works brilliantly. Copes with anything.

Mail::Mailer also accepts the header-as-hash. Alas, ERYQ spaketh thusly:

       Why all this "occurence" and "index" jazz?
           Isn't every field unique?
           Aaaaaaaaaahh....no.

           (This question is generic to all Mail::Header
           subclasses, but I'll field it here...)

           Looking at a typical mail message header, it is
           sooooooo tempting to just store the fields as a hash
           of strings, one string per hash entry.  Unfortunately,
           there's the little matter of the Received: field,
           which (unlike From:, To:, etc.) will often have
           multiple occurences; e.g.:

               Received: from gsfc.nasa.gov by eryq.ppr.mcs.net
                         with smtp (Linux Smail3.1.28.1 #5)
                         id m0tStZ7-00007X4C; Thu, 21 Dec 95 16:34 CST
               Received: from rhine.gsfc.nasa.gov
                         by gsfc.nasa.gov (5.65/Ultrix3.0-C)
                         id AA13596; Thu, 21 Dec 95 17:20:38 -05000

                         id RAA28069; Thu, 21 Dec 1995 17:27:54 -0500
               Date: Thu, 21 Dec 1995 17:27:54 -0500



               Subject: Stuff and things

           The Received: field is used for tracing message
           routes, and although it's not generally used for
           anything other than human debugging, I didn't want to
           inconvenience anyone who actually wanted to get at
           that information.

           I also didn't want to make this a special case; after
           all, who knows what other fields could have multiple
           occurences in the future?  So, clearly, multiple
           entries had to somehow be stored multiple times... and
           the different occurences had to be retrievable.

Which basically boils down to: the header can`t be represented as a hash.

Quote:
>I looked at MAil::Mailer ages ago. :-( didn't like what I saw.
>IMHO Mail::Tools modules are better.

Eh, Mail::Mailer is part of the Mail-tools distribution. Am I missing
something here?

The problem doesn`t lie with creating or sending the MIME message. The
problem is finding some decent way to feed the MIME message created by
MIME::Entity into Mail::Mailer for delivery. This could be done by
modifying either module; MIME::Entity so it can return the header as a
hash; _or_ Mail::Mailer so it accepts a MIME::Entity object as input
instead of/addition to a hash. I could even have lived with a solution
where Mail::Tools accepted an IO::Handle as input. A glob ref is neither
here nor there (IMO, of course).



Mon, 09 Apr 2001 03:00:00 GMT  
 MIME-tools/Mail-tools incompatible?


Quote:


>>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.

Ugh! No, please don`t do that! This is a bad case of reinventing the wheel.
Using MIME::Entity to create the MIME email message works just great. The
problem is in coercing that message into a format that is suitable for
input to Mail::Mailer. That problem is simply that Mail::Mailer wants
the header fed to it as a hash reference, but MIME::Entity emits objects.

If all you are going to do is to pipe it to sendmail, you won`t even hit
this problem. Even if you don`t want to use sendmail directly (I wouldn`t!)
the solution I came up with works; it`s just not vey pretty.

The big advantage (apart from "prettyness" and cleanlyness of
implementation) to using Mail::Mailer is that you can set it to use "smtp"
for delivery. In practice this means that it uses the Net:SMTP module to
send the message rather then opening a pipe to sendmail or /[Mm]ail(x)?/.
This improves portability and, quite likely, performance. I also suspect
you`ll find it improves reliability and stability quite a bit.

Quote:
>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...

Oh I`ll bet!
Dealing with MIME by hand (so to speak) is not reccomended. It`s a big
bloated confusing standard (IMO) which is best left to "professionals"
(i.e. MIME::*) to deal with. That email message format is almost as
complex as MIME doesn`t exactly improve the situation.

Quote:
>I took a look at the MIME RFC (RFC 2045), and I guess I'm not understanding
>what the "character set" header ought to be, or maybe I'm just completely
>confused.

You`re confused! :-)
The carset is likely irelevant here. It`s the encoding or the labeling of the
encoding that is the most likely culprit.

Quote:
>Anyway, if you get this figured out (using your approach or mine), I'd love
>to hear about it.

Here is what I`m currently using:

#!perl -w

# Switch on all the best compiler protections.
use strict;

# Really only needed for POSIX "compliant" temporary file names
use POSIX;

# Do all the gritty work of MIME Encoding for us.
use MIME::Entity;

# Need to use Mail::Internet for sending because while it can accept
# a filehandle glob ref, Mail::Mailer can not.
use Mail::Internet;

# Mailserver to use. Optional if you specified a default in $ENV{SMTPHOSTS},
# or 'mailhost' or 'localhost' are answering on SMTP.
my $Mailserver = 'smtp.isp.dom';

# Create a new MIME::Entity object.
my $msg = new MIME::Entity;

# Build the top level with recipients etc.
$msg->build(
            Type    => "multipart/mixed",


            Subject => 'Whatever',
           );

# Attach a specified text file.
# You could also feed a $scalar in a "Data" parameter instead of feeding
# a file using "Path". "Encoding can be set to "-SUGGEST" to have the
# module guess at a good encoding to use. Works best (only?) with text.
$msg->attach(
             Path        => '/tmp/message.txt',
             Type        => 'text/plain',
             Encoding    => 'quoted-printable',
             Disposition => 'inline',
            );

# Attach a Perl program as an attachment in Base64.
$msg->attach(
             Path        => '/tmp/program.pl',
             Type        => 'text/plain',
             Encoding    => 'base64',
             Filename    => 'program.pl',
             Disposition => 'attachment',
            );

# A GIF image in Base64. Also attachment (as opposed to "inline").
$msg->attach(
             Path        => '/tmp/image.gif',
             Type        => 'image/gif',
             Encoding    => 'base64',
             Filename    => 'image.gif',
             Disposition => 'attachment',
            );

# Get a filename to use for a tempfile from POSIX.
my $tmpfile = POSIX::tmpnam;

# Open a tempfile, dump the message with header to it, and close filehandle.
open  FH, ">$tmpfile" or die "open(>$tmpfile) returned: $!\n";
print FH $msg->as_string;
close FH;

# Reopen the same tempfile.
open FH, $tmpfile or die "open($tmpfile) returned: $!\n";

# Create a new Mail::Internet object and tell it to initialize itself
# with header and body from the filehandle we pass it as a glob ref.
my $mail = Mail::Internet->new(\*FH);

# Tell the Mail::Internet object to send it`s message to $Mailserver
# for delivery.
$mail->smtpsend(Host => $Mailserver);

# Close the filehandle and unlink (delete) the temporary file.
close FH;
unlink $tmpfile or warn "unlink($tmpfile) returned: $!\n";

__END__

This works like a charm, except for: 1) it`s not as clean
implementation wise, as I would have wished 2) it has performance
problems in that all the file i/o is expensive.



Mon, 09 Apr 2001 03:00:00 GMT  
 MIME-tools/Mail-tools incompatible?

Quote:





[snipped]
> The big advantage (apart from "prettyness" and cleanlyness of
> implementation) to using Mail::Mailer is that you can set it to use "smtp"
> for delivery. In practice this means that it uses the Net:SMTP module to
> send the message rather then opening a pipe to sendmail or /[Mm]ail(x)?/.
> This improves portability and, quite likely, performance. I also suspect
> you`ll find it improves reliability and stability quite a bit.

I would dispute that last line, the part about stability, so would many others
here about from what I have read. Where sendmail is available, use it, it's
much better at queing email than you will ever be.

--
--
Ian J. Garlick


Just because you're paranoid doesn't mean they AREN'T after you.



Tue, 10 Apr 2001 03:00:00 GMT  
 MIME-tools/Mail-tools incompatible?
I've just checked my version of MIME::Entity and found that it is
derived from Mail::Internet.  If I'm not mistaken this means that you
couls use any of Mail::Internet's functions right?
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!

> Mail-tools want header fields in a hash-ref, but MIME-tools doesn't
> provide a way to create one. You could of course dump the
> header_as_string and parse it before passing a suitable hash-ref to
> Mail::Mailer, but that looks an exceedingly dirty solution to me. The
> crutch I've come up with is to dump the complete MIME message (ERYQ
> would probably say "MIME Entity", I suppose) to a tempfile, close() and
> reopen the file, and pass a glob of the filehandle to
> Mail::Mailer->open() (I refuse to open a pipe to sendmail when Net:SMTP
> is so readily available!).

> Now, I refuse to believe it has to be that hard (or that dirty for that
> matter)! Why can't I pass a prefab MIME::Entity object to Mail::Mailer
> and call Mail::Mailer->send()? Am I missing something blatantly obvious
> here or do the two not want to cooperate at all?

> It's conceivable that you can dig up something further down in the
> subclasses (or is it "superclasses"? I never get these straight ;D) on
> each side that will let you interchange data between the two, but so
> far I haven't come up with anything. Anyway, it would make sense to be
> able to create a MIME::Entity with MIME-tools and then just pass that
> to Mail::Mailer for delivery. Either ERYQ and GBARR are not speaking to
> eachother these days; or the how of it is buried too far down in the,
> otherwise plentifull and excellent, documentation for the two packages.

> Anyways, I'd appreciate it if someone could clarify. Even if it's just
> to say that "Sorry, can't be done!".

> On a similar note. Has anyone used MIME::Lite? Does it have any serious
> problems? Is it still in alpha because the interface is subject to
> change or is that indicative of remaining serious bugs? How is
> performance?

> --

> Jobs in your "Board of Directors" folder.  | in comp.sys.mac.comm



Wed, 11 Apr 2001 03:00:00 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. Mime-Tools Parsing multiple mails (newbie)

2. MIME-tools and MailTools modules confusion

3. Problem with MIME::Lite and MIME-tools

4. MIME-Tools - MIME::Entity - extra newline problem

5. MIME::Tools - Getting All MIME Header Info for a Message

6. MIME::Tools decoding of a MIME::Entity

7. problems with MIME::Lite and MIME-tools

8. Problem with MIME::Lite and MIME-tools

9. Mail Tools, Mail::header scalar array help

10. MIME-tools help

11. MIME-tools 4.116 uploaded to CPAN [vital bug fix]

12. MIME-tools 4.112 available on CPAN

 

 
Powered by phpBB® Forum Software