Last updated 12 February 2012. Created on 2 December 2007.
Edited by Ayesh, WorldFallz, bryan kennedy, AjK. Log in to edit this page.

Inspired by http://drupal.org/node/197092 I decided to write a short snippet to demo how to take a simple form field, validate it and send the field to an email address on submission.

Like the above post, this snippet just asks for an email address with a submit button. Validation just checks the email address syntax.

This is really meant as a "starting point", it's up to you, the reader, to add bells and whistles as required.

To use this snippet, create a new block. Cut'n'paste the code below and set the blocks input filter to "PHP". Then place the block somewhere to use it.

Drupal 5 version


$send_form_to = 'jdow@example.com'; // Change this!

function my_sign_up_form() {
  $form['email'] = array(
    '#type' => 'textfield',
    '#title' => '',
    '#size' => '20',
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Subscribe',
  );
  return $form;
}

function my_sign_up_form_validate($form_id, $form) {
  if (!valid_email_address($form['email'])) {
    form_set_error('email', 'Your email address appears malformed');
  }
} 

function my_sign_up_form_submit($form_id, $form) {
  $message = 'New signup email address: '. $form['email']; // Body of your email here.
  drupal_mail('my_sign_up_form', $send_form_to, 'New signup', $message, variable_get('site_mail', 'an@example.com'));
  drupal_set_message('Thank you for signing up to our email alerts'); // Your thank you message here
} 

return drupal_get_form('my_sign_up_form');

btw, the above is a basic starting point and does not include any filtering so you are advised to see the handbook section on writing secure code

Drupal 6 Version

This form will send an email to the user-submitted e-mail address instead of a preset e-mail address as above example. So make sure you change the TO address to another email address if you want to get the same functionality as above example.

/**
* Create a custom php block
* Place the block in the rh column.
*/

/**
* Create a form with a single text field and submit button.
*/
function my_form() {

  $form['email'] = array(
    '#type' => 'textfield',
    '#title' => '',
    '#size' => '20',
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Subscribe',
  );
  return $form;
}

/**
* Validate the form.
*/
function my_form_validate($form, &$form_state) {
  $valid_email = $form_state['values']['email'];
  if (!valid_email_address($valid_email)) {
  form_set_error('email', 'Your email address -- ' . $valid_email . ' -- appears malformed');
  }
}

/**
* Create the hook_mail function
* Required in Drupal 6
*/
function my_form_mail($key, &$message, $params) {
 
  $headers = array(
    'MIME-Version' => '1.0',
    'Content-Type' => 'text/html; charset=UTF-8; format=flowed',
    'Content-Transfer-Encoding' => '8Bit',
    'X-Mailer' => 'Drupal'
  );
 
  foreach ($headers as $key => $value) {
    $message['headers'][$key] = $value;
  }
 
  $message['subject'] = $params['subject'];
  $message['body'] = $params['body'];
}

/**
* Create the form submit function
*/
function my_form_submit($form, &$form_state) {

    $valid_email = $form_state['values']['email'];
    $from = 'test@example.com';
    $body = 'New Email Sent = ' . $valid_email;
  
    $params = array(
    'body' => $body,
    'subject' => 'This is a subject',
    );
  
    //NB First argument of the drupal_mail function must match the first part of the hook_mail function.
    //Therefore the first argument is  'my_form' and the the mail hook is 'my_form_mail'
    //For more info see:
    //http://api.drupal.org/api/function/drupal_mail/6     
    //http://api.drupal.org/api/function/hook_mail/6
   
    if (drupal_mail('my_form', 'some_mail_key', $valid_email, language_default(), $params, $from, TRUE))
    {
        drupal_set_message('An email has been sent to ' . $valid_email);      
    } else {
        drupal_set_message('There was an error sending your email');
    }
}

/**
* Return the form.
*/
return drupal_get_form('my_form');

Drupal 7 version

function my_form() {
  $form['email'] = array(
    '#type' => 'textfield',
    '#title' => '',
    '#size' => '20',
    '#attributes' =>array('placeholder' => t('E-mail address'))
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Subscribe'),
  );
  return $form;
}

function my_form_validate($form, &$form_state) {
  $valid_email = $form_state['values']['email'];
  if (!valid_email_address($valid_email)) {
  form_set_error('email', 'Sorry. Your email address,' . $valid_email . ', is not valid. Please submit a valid E-mail address.');
  }
}

function my_form_mail($key, &$message, $params) {

  $headers = array(
    'MIME-Version' => '1.0',
    'Content-Type' => 'text/html; charset=UTF-8;',
    'Content-Transfer-Encoding' => '8Bit',
    'X-Mailer' => 'Drupal'
  );

  foreach ($headers as $key => $value) {
    $message['headers'][$key] = $value;
  }

  $message['subject'] = $params['subject'];
  $message['body'] = $params['body'];
}


function my_form_submit($form, &$form_state) {
    $valid_email = $form_state['values']['email'];
    $from = 'noreply@example.com';
    $body[] = 'Email: '.$valid_email.'<br />URL: '.request_uri();
    $to = 'example@example.com'; // Set this email address - emails will be sent to this email address! 
    $params = array(
    'body' => $body,
    'subject' => 'Website Information Request',
    );
 
    if (drupal_mail('my_form', 'some_mail_key', $to, language_default(), $params, $from, TRUE))
    {
        drupal_set_message('Thanks, we will be in contact with more information soon.');     
    } else {
        drupal_set_message('There was an error subscribing you. Please try again later');
    }
}
return drupal_render(drupal_get_form('my_form')); 

Thanks to Neptun for form rendering stuff.
Thanks to AlexanderPop for array tip.

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.

Comments

OpenSourcer’s picture

Thanks for above. It was really helpful ;-)

AshokanKid’s picture

Thanks for this. Much appreciated.
The form sends the email BACK to the submitter though.
How about having the form send (collect) the email to an internal (site) address?
Much more useful to collect contact info & then set up an auto-responder to reply.
Guess I am not sure why you would want a visitor to be able to send themselves an eMail?

To clarify; This is PERFECT for what I need and want. Simple, no fuss or muss. Single form field for email address (harvest from user) and a button. SWEET., BUT, I want the form to send the email TO me at a (hidden form specified) internal site email address with the USER (form entered) address as the FROM or SENDER so that my internal auto-responder will reply to them and then I also capture their email address. Cool?

AlexanderPop’s picture

I think you forgot to put
drupal_mail('my_form', 'some_mail_key', $valid_email, language_default(), $params, $from, TRUE);
somewhere above "//NB First argument of the..." comments

alienzed’s picture

how would one accomplish this in drupal 7? pasting the code from Drupal 6 just prints out the word "Array"

mr-huge’s picture

I successfully managed the code for Drupal 6 to get it work in Drupal 7 almost without changes. The code is lower.

rossmerriam’s picture

I was having trouble figuring this out for the longest time but your note about the first argument cleared things up for me.

cigotete’s picture

the snippet is tagged like Insecure code.., why is insecure?

Flowster’s picture

Same question here.

mr-huge’s picture

I successfully managed the code for Drupal 6 to get it work in Drupal 7 almost without changes.

I only made $body an array $body[]:

    $body[] = 'New Email Sent';
    $body[] = '123123131232';

There was a error in mail system which implodes body with something, and if it's not an array body stays empty.

I use this form in a created custom module.

Neptun’s picture

To work in block you must change
return drupal_get_form('my_form');
to
return drupal_render(drupal_get_form('my_form'));

calculus’s picture

Why is this code insecure? The only user-submitted content is e-mail, but there is a validation. Only problem is spam protection.

weespoon’s picture

Nice Work based on liren.zhu's post: http://drupal.org/node/159678#comment-2278210
I have extended this example to include a file attachment.

function my_form() {
  $form['email'] = array(
    '#type' => 'textfield',
    '#title' => '',
    '#size' => '20',
    '#attributes' =>array('placeholder' => t('E-mail address'))
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Subscribe'),
  );
  return $form;
}

function my_form_validate($form, &$form_state) {
  $valid_email = $form_state['values']['email'];
  if (!valid_email_address($valid_email)) {
  form_set_error('email', 'Sorry. Your email address,' . $valid_email . ', is not valid. Please submit a valid E-mail address.');
  }
}

function my_form_mail($key, &$message, $params) {

  $hash = md5("randomstring");
  drupal_set_message('Boundary: ' . $hash );
  
  $headers = array(
    'MIME-Version' => '1.0',
    "Content-Type" => "multipart/mixed; boundary=\"".$hash."\"",
    'Content-Transfer-Encoding' => '8Bit',
    'X-Mailer' => 'Drupal'
  );

  foreach ($headers as $key => $value) {
    $message['headers'][$key] = $value;
  }
 
  $message['subject'] = $params['subject'];
  
  $file_mime = 'text/plain';
  $file_name = 'test.txt';
  $file_data = chunk_split(base64_encode("Test Attachment, text."));
  //$file_data = chunk_split(base64_encode(file_get_contents($attachment['filepath'])));

  $multipart = "--".$hash."\n" . 
    "Content-Type: text/plain; charset=ISO-8859-1\n\n"; 
  
  foreach($params['body'] as $bod) {
    $multipart .= $bod . "\n";
  }
  
  $multipart .= "\n--".$hash."\n"
    ."Content-Type: ".$file_mime."; name=".$file_name."\n"
    ."Content-Disposition: attachment; filename=".$file_name."\n"
    ."Content-Transfer-Encoding: base64\n\n"
    .$file_data."\n";
  $multipart .= "--".$hash."--";
  
  $message['body'] = array($multipart);
  drupal_set_message('Body: ' . $multipart );
}


function my_form_submit($form, &$form_state) {
    $valid_email = $form_state['values']['email'];
    $from = 'noreply@example.com';
    $body[] = 'Email: '.$valid_email.'<br />URL: '.request_uri();
    $to =  $valid_email; // Set this email address - emails will be sent to this email address! 
    $params = array(
      'body' => $body,
      'subject' => 'Website Information Request',
    );

    if (drupal_mail('my_form', 'some_mail_key', $to, language_default(), $params, $from, TRUE))
    {
        drupal_set_message('Thanks, we will be in contact with more information soon.');     
    } else {
        drupal_set_message('There was an error subscribing you. Please try again later');
    }
}
return drupal_render(drupal_get_form('my_form')); 
Wartus’s picture

Good example.

2 small issues:

Content-Type should be "text/plain", otherwise stuff like page breaks (\n) don't work.
also, when using text/plain, "<br />" should be replaced with \n

cheers!

lsabug’s picture

return drupal_render(drupal_get_form('my_form'));

produces error message :

Strict warning: Only variables should be passed by reference in eval() (line 58 of F:\xampp\htdocs\domain.com\modules\php\php.module(80) : eval()'d code).

The form itself does show up in a block but when the submit button is clicked the above error message is produced and there is no email sent.

Using 7.17

darylpqb’s picture

Hi All,

This comment may seem late, but I'll try asking anyway. From @Wartus comment, how do I go about adding markup to my email aside from basic php line breaks e.g. /r/n? Thanks!

Daryl

whiplashomega’s picture

Any chance of adding a Drupal 8 example anytime soon?

avinash_thombre’s picture

To make sure that the email is sent using above code, we have to install and configure the mail systems- MIME mail system, HTML mail and Default mail system. If MIME mail is configure in the headers as "'MIME-Version' => '1.0',", then configure the default mail system to MIME then mail will get sent. Otherwise it may show Warning: implode() Invalid arguments passed in form_error().