File uploaded and sent as attachment to email

Principle

The idead behind this perl script is to allow file transfert from someone without a suitable mail user agent, just a simple browser. File attachment for the dummies. From a web page with a form and a file field, the file is uploaded to the server that deals with it to make it a mime attachment.

Implementation

For this script, we will only use perl modules included in the standard distribution.

#!/usr/bin/perl
# All by HAbeTT
# Up2me

use CGI;
use MIME::Base64;

CGI helps us retrieve data from the html form and MIME::Base64 will be used to encode the attachment file. At first, we start to build the html output page.

print <<frag;
Content-type: text/html

<html>
<head>
</head>
<body>
frag

Then we retrieve the cgi data and output an error message if the form doesn't contain the expected fields and data.

$query = new CGI;
unless ($query->param('fichier')) {
  print "<font color=\"#ff0000\">Error, file not specified.<p>";
  print "</body></html>";
  exit(0);
}

Now we retrieve the name of the uploaded file and then the data it contains.

$file = $query->param('fichier');
$data = "";
while ($size = read($file,$daa,1024)) {
  $data.=$daa;
}

The data is now base64 encoded as mail protocols require and the file name is processed to exclude path information that we don't need :

$encodata = encode_base64($data);
$file =~ s/\\/\//g;
$file = substr($file, rindex($file, "/")+1);

In theory, a fixed boundary can be set to tear appart the different segments of the message, but we will include a random boundary generator to avoid any trouble wiht badly written mail user agents. The boundary must a 7 bits ascii string. Dashes (-) are recomended as this character cannot appear in base 64 encoded data.

$bound = int(rand(1000))."--".int(rand(1000))."--".int(rand(1000));

Now we open a pipe to sendmail (check it is located at the same place on your server). We use the t switch so that the From: and the To: are set only one time, inside the message (plus security bonus).

open (SENDMAIL, "|/usr/lib/sendmail -t");
print SENDMAIL <<End;
From: robot\@habett.org
To: habett\@habett.org
Subject: Transport of the $file file
X-Mailer: Up2Me by HAbeTT
MIME-Version: 1.0
Content-Type: multipart/mixed;
 boundary="$bound"

MIME format mail and base64 data

$bound
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit

$file is attached

$bound
Content-Type: text/plain; name="$file"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="$file"

$encodata

$bound

ok

End

To make things easier, we have defined the attachment to have a Content-Type: text/plain on 8 bits that should suit any data but should have been more precise. We could have included a deduction of the right Content-Type from the extension of the name of the uploaded file.

We just have to conclude the html control page.

print <<frag;

message sent with the file <b>$file</b> attached.
<p>
thanks
</body>
</html>
frag

exit(0);

up2me.zip

main menu