Drupal 6: Uploading a file via the Forms API and attaching it to an email

In this tutorial I'll show how I used the Forms API to add a file upload field and attach the uploaded file in an email. I have experience using the PEAR libraries Mail and Mail_MIME to handle MIME/HTML emails and file attachments, so I decided to use them.

If you are unfamiliar with PEAR, here are a few quick tips:

# install pear via YUM (this will vary across operating system)
$ sudo yum install php-pear

# upgrade all PEAR packages
$ sudo yum upgrade-all

# check for Mail and Mail_MIME libraries
$ pear list | grep -i mail
Mail             1.1.14  stable
Mail_Mime        1.5.2   stable

# install a PEAR library
$ sudo pear install Mail

Now we can create our form callback function. NOTE: I'm keeping this form as simple as possible to focus on the file attachment functionality.

<?php
function _MYMODULE_form() {
  // create an empty form array
  $form = array();

  // set the form encoding type
  $form['#attributes']['enctype'] = "multipart/form-data";

  // add a file upload file
  $form['upload'] = array(
    '#type' => 'file',
    '#title' => t('Attach a file'),
  );

  // add a submit button
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Submit',
  );

}
?>

The above will create a basic form object with a file upload file and a submit button. The form can be included using the drupalgetform function. Example:

<?php
$html = drupal_get_form('_MYMODULE_form');
?>

Next I added a validation function to validate the file upload.

<?php
function _MYMODULE_form_validate($form, &$form_state) {

  // define upload field name
  // NOTE: this should match the name of your form file field
  $fieldName = 'upload';

  // If a file was uploaded, process it.
  if (isset($_FILES['files']) && is_uploaded_file($_FILES['files']['tmp_name'][$fieldName])) {

    // attempt to save the uploaded file
    $file = file_save_upload($fieldName);

    // set error if file was not uploaded
    if (!$file) {
      form_set_error($fieldName, 'Error uploading file.');
      return;
    }

    // set files to form_state, to process when form is submitted
    $form_state['values']['file'] = $file;

  }
  else {
    // set error
    form_set_error($fieldName, 'Error uploading file.');
    return;
  }

}
?>

The above validation form will check to see if a file has been uploaded and set a form error as necessary. The last line of the function sets information about the successfully uploaded file to the $form_state array, which will then be passed to the submit handler function.

Next I created a form submit handler function which will create a Mail_Mime object, attach the file, send the email, and set a drupal message for the user to see.

<?php
function _MYMODULE_form_submit($form, &$form_state) {

  // create the email subject
  $subject = 'File attachment form submitted';

  // create the text version of the email body
  $body_text = "Dear Eric,\n\nblah blah blah.\nblah blah blah.\n\nRegards,\nEric";

  // create an html version of the email
  $body_html = str_replace("\n", "<br>", $body_text);

  // define who receives the email
  $to = "YOUREMAILADDRESS";

  // include pear libraries
  require_once('Mail.php');
  require_once('Mail/mime.php');

  // create new mail mime object
  $mime = new Mail_mime("\n");

  // add attachment
  if ($form_state['values']['file']) {
    $mime->addAttachment(
      $form_state['values']['file']->filepath,
      $form_state['values']['file']->filemime,
      $form_state['values']['file']->filename
    );
  }

  // set text message
  $mime->setTXTBody($body_text);

  // set html message
  $mime->setHTMLBody($body_html);

  // get message body
  $body = $mime->get();

  // define headers
  $hdrs = array(
    'From' => variable_get('site_mail','YOUREMAILADDRESS'),
    'Subject' => $subject,
  );

  // process headers
  $hdrs = $mime->headers($hdrs);

  // create mail object
  $mail =& Mail::factory('mail');

  // send email
  $mail->send($to, $hdrs, $body);

  // set message to user
  drupal_set_message('The file attachment form has been submitted.');

}
?>

If everything worked correctly, the form will be validated, submitted, and an email with the file attachment will be sent.