Link to home
Start Free TrialLog in
Avatar of Benny00
Benny00

asked on

Attach a non-specific file type to an e-mail

I am allowing the user to upload a file that will be attached to a form.  I want to allow this file to be any type.  How would I achieve this?  I was thinking of using MIME::Lite or MIME::Entity.

Please be specific in the exact coding of this.  I am still pretty new at Perl.  Thanks.
Avatar of Alien Life-Form
Alien Life-Form

Greetings.

If we're talking file upload through a  web form, you do not need to attach it via MIME. CGI.pm supplies a perfectly usable file upload field that can be used for this purpose.

You generate it like this:

print $query->start_multipart_form(...);

print $query->filefield(-name=>'uploaded_file',
                           -default=>'starting value',
                            -size=>50,
                            -maxlength=>80);
       
....

After that, the name of the field can be used like a file handle:

$filename = $query->param('uploaded_file');

while (<$filename>) {
  print;
}

You can desume type information thusly:

$filename = $query->param('uploaded_file');
$type = $query->uploadInfo($filename)->{'Content-Type'};


If, after the fact, you want to mail the uploaded file, yoou can indeed use MIME::Lite:

### Create a new multipart message:
$msg = MIME::Lite->new(
       From    =>'me@myhost.com',
       To      =>'you@yourhost.com',
       Cc      =>'some@other.com, some@more.com',
       Subject =>'A message with 2 parts...',
       Type    =>'multipart/mixed'

msg->attach(Type     =>'TEXT',  
            Data     =>"Here's the GIF file you wanted"
);  
msg->attach(Type     =>'image/gif',
            Path     =>'aaa000123.gif',
            Filename =>'logo.gif'
);

(Note: $fileame, as supplied by CGI.pm, has an - undocumented - method, $filename->tmpFileName(), that will give you the pathname of the temporary file that CGI itself  uses internally, and this can be handy in this predicamente)

You will use as type the info you gleaned from the upload form (or application/octet-stream in default). To actually send the message, you can get it in printable form as:

$str=$msg->as_string();

and then print it to a stream that you obtained with (say) Mail::Send.

Or, you can use the supplied $msg->send() that uses some heuristics to figure out how to send a message - you will have to trust the said heuristics, though.
Speaking from experience, you'll find out that uploading large files this way is quite inefficient. CGI.pm gives you a chance to limit the max size of the upload, by setting the $CGI::POST_MAX variable. (This still does not circumvent the inefficiency, though).


Cheers,
  alf

ASKER CERTIFIED SOLUTION
Avatar of maneshr
maneshr

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Benny00

ASKER

Ok...I am getting a file to send...I'm trying a MS Word File...Word won't open this file after it has been attached which leads me to believe something is getting goofed up in the transfer...Any ideas?

this is my code:



$msg = build MIME::Lite
             From => 'test@ac.com',
            To => 'benjamin.t.novak@c.com',
            Subject => 'Test',
            Type => 'multipart/mixed';
            
       attach $msg
             Type => 'TEXT',
             Data => "Testing testing testing";
            
       attach $msg
             Path => "/tmp/".$save_name,
            Filename => "$save_name",
            Type => "BINARY",
            Encoding => "base64";
                  
       $msg->send;
the file that you are sending is encoded using Mime's base 64 encoding.
to get the actual file you will first have to decode the file using base 64 decoding.

Avatar of Benny00

ASKER

I have found the problem...Unfortunately I do not know the answer...

The file is not being written correctly in the temp directory.  It ends up being a little small.  This is the code that writes out the file info...

Any ideas???

# spilt it so we can get the filename and extension
     @parts = split /(\\)|(\/)/,$filename;
     # get the last item from the array
       $save_name = @parts[$#parts];

     # open the file (make sure the web server account has write permissions on the directory)
      
     open(OUTFILE,">/tmp/".$save_name) or die("cannt copy image over ! ... $save_name".$!);
     # only set binmode if you are sure a binary file is coming over
     binmode OUTFILE;
     # use the filehandle $filename read it in and write it out to our OUTFILE
     while ($bytesread = read($filename,$buffer,1024))
     {
          print OUTFILE $buffer;
     }
Avatar of Benny00

ASKER

I'm a moron...All I had to do was close the file to make it work.