Hi,

for all of you who search for a custom contact form with the ability to attach files, here is my solution.
Hope you enjoy it and don't be shy, let me know your opinion and give me some feedback so I can improve this form.

<?php

$form['name'] = array(
	'#type' => 'textfield',
	'#title' => t('your name'),
	'#default_value' => $object['name'],
	'#size' => 30,
	'#maxlength' => 128,
	'#required' => TRUE,
);

$form['eMail'] = array(
	'#type' => 'textfield',
	'#title' => t('your email-adress'),
	'#default_value' => $object['eMail'],
	'#size' => 30,
	'#maxlength' => 128,
	'#required' => TRUE,
);

$form['subject'] = array(
	'#type' => 'textfield',
	'#title' => t('subject'),
	'#default_value' => $object['subject'],
	'#size' => 30,
	'#maxlength' => 128,
	'#required' => TRUE,
);

$form['message'] = array(
	'#type' => 'textarea',
	'#title' => t('your message'),
	'#default_value' => $object['message'],
	'#size' => 30,
	'#maxlength' => 128,
	'#rows'	=> 7,
	'#required' => TRUE,
);
	
$form['file1'] = array(
	'#type' => 'file',
  	'#title' => t('attach your files here'),
);	
$form['file2'] = array(
	'#type' => 'file',
);
$form['file3'] = array(
	'#type' => 'file',
);	
	
$form['submit'] = array(
	'#type' => 'submit',
	'#value' => t('send email'),
);

$form['#attributes']['enctype'] = 'multipart/form-data';

$output = drupal_get_form('contactform', $form);
return $output;

// validation function for the contact form
function contactform_validate($form_id, $form_values) {
	// first we validate if there is a email injection
	$finds = array("/bcc:/i",
			"/Content-Type:/i",
			"/Mime-Type:/i",
			"/MIME-Version:/i",
			"/multipart\/mixed/i",
			"/boundary=/i",
			"/subject:/i",
			"/cc:/i",
			"/to:/i");
	foreach($form_values as $value)
  		foreach($finds as $find)
	    		if(preg_match($find,$value))
	    			form_set_error('', '<h2 class="red center">Stop spamming</h2>');

	// then we validate the email-adress	  
	if (!valid_email_address($form_values['eMail']) && !empty($form_values['eMail']))
		form_set_error('', t('Please check the spelling of your email-adress.'));
}


// submit function for the contact form
function contactform_submit($form_id, $form_values) {
	  
	$from 		= $form_values['name'].' <'.$form_values['eMail'].'>';
	$recipient	= 'Michael Smolla <smolla@creazion.de>';
	$subject	= $form_values['subject'];
	$body 		= wordwrap($form_values['message']);
	$reply		= 'Thank you for your message.';
	$goto		= '<front>';

	if (!flood_is_allowed('contact', variable_get('contact_hourly_threshold', 3))) {
		$output = t("You cannot send more than %number messages per hour. Please try again later.", array('%number' => variable_get('contact_hourly_threshold', 3)));
		drupal_set_message('<h3 class="red center">'.$output.'</h3>');
		drupal_goto($goto);
	}else{	
		$attachment	 = FALSE;
		$trenner	 = md5(uniqid(time()));
		$headers	.= "MIME-Version: 1.0\n";
		$headers 	.= "From: $from\nReply-to: $from\nReturn-path: $from\nErrors-to: $from\nX-Mailer: Drupal\n";			
		$headers 	.= "Content-Type: multipart/mixed;\n\tboundary=$trenner\n";
		$message 	.= "\n--$trenner\n";
		$message 	.= "Content-Type: text/plain; charset=UTF-8;"."\n\n"; // sets the mime type
		$message 	.= $body."\n";
		$message 	.= "\n\n";
		for($i=1;$i<=3;$i++){
			$file = file_check_upload('file'.$i);
			if($file->filename){
				$file->filepath = str_replace("\\","\\\\",$file->filepath);
				$message	.= "--$trenner"."\n";
				$message	.= "Content-Type:$file->filemime;\n\tname=$file->filename\n";
				$message	.= "Content-Transfer-Encoding: base64\n";
				$message	.= "Content-Disposition: attachment;\n\tfilename=$file->filename\n\n";
				$filedata	= fread(fopen($file->filepath, "rb"), $file->filesize);
				$message	.= chunk_split(base64_encode($filedata));
				$message	.= "\n\n";
				$attachment	= TRUE;
			}
		}
		$message .= "--$trenner--";

		// send Mail
		if($attachment) // use the php mail function if we have attachments
			mail($recipient, $subject, $message, $headers);
		else
			user_mail($recipient, $subject, $body, "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from");

		// Reply
		user_mail($from, $subject, wordwrap($reply), "From: $recipient\nReply-to: $recipient\nX-Mailer: Drupal\nReturn-path: $recipient\nErrors-to: $recipient");
	
		// Log the operation:
		flood_register_event('contact');
		watchdog('mail', t('%name-from use contact form', array('%name-from' => theme('placeholder', $form_values['name'] ." <$from>"),)));

		drupal_set_message('Your message has been sent to us');
		drupal_goto($goto);
		}

	}
?>

*******************************

a solution from www.creazion.de

Comments

laura s’s picture

Any interest in patching this into the webform module?

Laura
_____ ____ ___ __ _ _
design, snap, blog

_____ ____ ___ __ _ _
Laura Scott :: design » blog » tweet

Muslim guy’s picture

Looking for this - attaching files (pdf, txt, doc, jpg, gif) to webform

quicksketch’s picture

I'm now implementing this into webform after finally finding where my file uploads were going. You can expect to see this in webform cvs in the next week. Thanks for this excellent example!

Nathan Haug
creative graphic design        w: quicksketch.org
& software development       e: nate@quicksketch.org

tormu’s picture

Is it supposed to be working already?
I just updated the Webform module, the CVS version, but I'm not seeing a way to add an attachment field into my forms..

quicksketch’s picture

The file component sat in the issue queue for a while as an attachment to a message. It still doesn't actually attach the file to an email, though it is a possibility in the future.

Nathan Haug
creative graphic design        w: quicksketch.org
& software development       e: nate@quicksketch.org

headless_pnub’s picture

Whenever i try and use this page it brings up the Red Hat Enterprise Linux Test Page. Does anyone now why or how to stop this.

Thanks, Pnub

wdrupal’s picture

Where does this code go? In a node?
That wasn't working for me.

michellex’s picture

Great job Creazion!

I've been tinkering with your code for a week now trying to get it to display and send contents of a select menu.
I've got it to display, and it'll send a number, but not the text. If the second option is selected, it'll send a 2, for instance.
Here's the snippet:

 $account = array(
'--'.t('Select').'--',
t('Model'),
t('Photographer'),
t('Crew'),
); 

$form['assign'] = array(
	'#type' => 'select',
	'#title' => t('select your account type'),
	'#default_value' => $object['assign'],
	'#options' => $account,
); 
 

How do I get this to work?
--
www.steelveils.com

sanguis’s picture

On another thread Creazion gave instructions for using this, here http://drupal.org/node/67341#comment-129222
I think it is less the obvious. I also would be interested in helping to turn it in to a mod that one could just download. the problem w/ that is I am a drupal noob and would not know where to start any one got any suggestions as to, where to start?
JOsh

Sanguis Development

grippat’s picture

I'm trying to do the exact same thing as you michellex. Plugging your code into the original gives me the array values as well.

saltwater’s picture

Is there a way to log the whole message itself to the database for a backup copy?

I can see that the fact that the form was sent is logged, but how would one go about emailing the form to the database?

I'm running 4.7.5 so far, if that helps.

-Curious in Maine

saltwater’s picture

hoorah!

apparently i have been looking in all the wrong places.

what i've actually been looking for is the webform module.

dig it - will save you some time trying to hack this one to get more options to create an online job application.

cheerios!

-=cc

www.saltwatermedia.net

creazion_dev’s picture

If you want to log the whole mail, you must replace the following line:

<?php
    watchdog('mail', t('%name-from use contact form', array('%name-from' => theme('placeholder', $form_values['name'] ." <$from>"),)));
?>

with this line:

<?php
    watchdog('mail', t('%name-from used the contact form and send the message: <br /><em>%message</em>', array('%name-from' => theme('placeholder', $form_values['name'] ." <$from>"), '%message' => $body)));
?>

---------------------------------------------
www.creazion.de

saltwater’s picture

thanks creazion!

have you ever had any issues with an email address not receiving automated emails from certain servers?

-curious in nyc

www.saltwatermedia.net

enxox’s picture

Does it work with 5.x?
I've tried to use it, but i receive a 500 error.
My error log says
[error] [client xx.xx.xx.xx] mod_security: Access denied with code 500. Pattern match "((select|grant|delete|insert|drop|alter|replace|truncate|update|create|rename|describe)[[:space:]]+[A-Z|a-z|0-9|\\\\*| |\\\\,]+[[:space:]]+(from|into|table|database|index|view)[[:space:]]+[A-Z|a-z|0-9|\\\\*| |\\\\,]|UNION SELECT.*\\\\'.*\\\\'.*,[0-9].*INTO.*FROM)" at POST_PAYLOAD [id "300013"] [rev "1"] [msg "Generic SQL injection protection"] [severity "CRITICAL"] [hostname "xxxx.domainxxx.com"] [uri "/node/91/edit"]

How to solve it?

Thanks

Mephistox’s picture

I'm getting the error:

warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, 'contactform' was given in /home/.inch/msena/toxic-penguin.com/home/includes/form.inc on line 218.

:(

I'm using drupal 5.1.... could that be the problem?

enxox’s picture

do you have converted it for 5.x? The code is for 4.7, I really need it for my 5.1, but I'm not able to convert it.
If you did't convert it, the problem is that API's in 5.x works different (drupal_get_form, for example)

NancyDru’s picture

enxox’s picture

webform module still doesn't send attachments, but only stores it on a site folder...

buttonmax’s picture

I'm getting the same error as Mephistox and am also using the latest version of drupal 5.1. This would be an excellent tool if we could get it to work! Creazion, please help!!

creazion_dev’s picture

Hi enxox,

I updated the code. Now it should work with Drupal 5.

<?php

print drupal_get_form('contactform', $form);

function contactform($form){
  $form['name'] = array(
      '#type' => 'textfield',
      '#title' => t('your name'),
      '#default_value' => $object['name'],
      '#size' => 30,
      '#maxlength' => 128,
      '#required' => TRUE,
  );

  $form['eMail'] = array(
      '#type' => 'textfield',
      '#title' => t('your email-adress'),
      '#default_value' => $object['eMail'],
      '#size' => 30,
      '#maxlength' => 128,
      '#required' => TRUE,
  );

  $form['subject'] = array(
      '#type' => 'textfield',
      '#title' => t('subject'),
      '#default_value' => $object['subject'],
      '#size' => 30,
      '#maxlength' => 128,
      '#required' => TRUE,
  );

  $form['message'] = array(
      '#type' => 'textarea',
      '#title' => t('your message'),
      '#default_value' => $object['message'],
      '#size' => 30,
      '#maxlength' => 128,
      '#rows'    => 7,
      '#required' => TRUE,
  );

  $form['file1'] = array(
      '#type' => 'file',
        '#title' => t('attach your files here'),
  );
  $form['file2'] = array(
      '#type' => 'file',
  );
  $form['file3'] = array(
      '#type' => 'file',
  );

  $form['submit'] = array(
      '#type' => 'submit',
      '#value' => t('send email'),
  );

  $form['#attributes'] = array(
    'enctype' => 'multipart/form-data',
    'id' => 'contactform',
  );

  return $form;
  
}

// validation function for the contact form
function contactform_validate($form_id, $form_values) {
    // first we validate if there is a email injection
    $finds = array("/bcc:/i",
            "/Content-Type:/i",
            "/Mime-Type:/i",
            "/MIME-Version:/i",
            "/multipart\/mixed/i",
            "/boundary=/i",
            "/subject:/i",
            "/cc:/i",
            "/to:/i");
    foreach($form_values as $value)
          foreach($finds as $find)
                if(preg_match($find,$value))
                    form_set_error('', '<h2 class="red center">Stop spamming</h2>');

    // then we validate the email-adress
    if (!valid_email_address($form_values['eMail']) && !empty($form_values['eMail']))
        form_set_error('', t('Please check the spelling of your email-adress.'));
}


// submit function for the contact form
function contactform_submit($form_id, $form_values) {

  $headers   = array();
  $mailkey   = 'contact-with-attachment';
  $from      = $form_values['name'].' <'.$form_values['eMail'].'>';
  $recipient = 'Michael Smolla <smolla@creazion.de>';
  $subject   = $form_values['subject'];
  $body      = wordwrap($form_values['message']);
  $reply     = 'Thank you for your message.';
  $goto      = '<front>';

  if (!flood_is_allowed('contact', variable_get('contact_hourly_threshold', 3))) {
      $output = t("You cannot send more than %number messages per hour. Please try again later.", array('%number' => variable_get('contact_hourly_threshold', 3)));
      drupal_set_message('<h3 class="red center">'.$output.'</h3>');
      drupal_goto($goto);
  }else{
    if(file_check_upload('file1')){
      $trenner  = md5(uniqid(time()));
      $headers  = array('Content-Type' => "multipart/mixed; boundary=$trenner");
      $message  = "\n--$trenner\n";
      $message .= "Content-Type: text/plain; charset=UTF-8; format=flowed;"."\n\n"; // sets the mime type
      $message .= $body."\n";
      $message .= "\n\n";
      for($i=1;$i<=3;$i++){
        $file = file_check_upload('file'.$i);
        if($file->filename){
          $file->filepath = str_replace("\\","\\\\",$file->filepath);
          $message   .= "--$trenner"."\n";
          $message  .= "Content-Type:$file->filemime;\n\tname=$file->filename\n";
          $message  .= "Content-Transfer-Encoding: base64\n";
          $message  .= "Content-Disposition: attachment;\n\tfilename=$file->filename\n\n";
          $filedata  = fread(fopen($file->filepath, "rb"), $file->filesize);
          $message  .= chunk_split(base64_encode($filedata));
          $message  .= "\n\n";
        }
      }
      $message .= "--$trenner--";
    }else{
      $message = $body;
    }

    // send mail
    drupal_mail($mailkey, $recipient, $subject, $message, $from, $headers);

    // Reply
    drupal_mail($mailkey, $from, $subject, wordwrap($reply), $recipient);

    // Log the operation:
    flood_register_event('contact');
    watchdog('mail', t('%name-from use contact form', array('%name-from' => theme('placeholder', $form_values['name'] ." <$from>"),)));

    drupal_set_message('Your message has been sent to us.');
    drupal_goto($goto);
  }
}
?>

If I've a little more time I'll put the code into a module for better use.

---------------------------------------------
www.creazion.de

enxox’s picture

Very very much!
I'm sure that this module will be widely appreciated.

enxox’s picture

There is some problem in the code, i receive an error

mod_security: Access denied with code 403. Pattern match "(chr|fwrite|fopen|system|echr|passthru|popen|proc_open|shell_exec|exec|proc_nice|proc_terminate|proc_get_status|proc_close|pfsockopen|leak|apache_child_terminate|posix_kill|posix_mkfifo|posix_setpgid|posix_setsid|posix_setuid|phpinfo)\\\\(.*\\\\)\\\\;" at POST_PAYLOAD [id "300009"] [rev "1"] [msg "Generic PHP exploit pattern denied"] [severity "CRITICAL"] [uri "/node/add/page"]

creazion_dev’s picture

Hi enxox,

it seems to be a problem with the apache module 'mod_security'. At time, I can't reproduce the error.
I think it would be better to put the code in a module.

These links might be helpful:

---------------------------------------------
www.creazion.de

enxox’s picture

The solution proposed in http://drupal.org/node/110219 works for me.

I've no time to try a better solution for now....

cammangels’s picture

You just saved me about 20 hours worth of work.

To me, that makes you a god.

Cam Mangels
Webmaster, City of Garden Grove, CA
All Done in Drupal:
www.garden-grove.org
www.internationalwest.com
www.ggcf.com

creazion_dev’s picture

For all of you who want to use this form as a module here it is:

http://www.creazion.de/drupal/module/mailattach.tar.gz

---------------------------------------------
www.creazion.de

NancyDru’s picture

Do you plan to contribute this to the downloads area?

Nancy W.
now running 5 sites on Drupal so far
Drupal Cookbook (for New Drupallers)
Adding Hidden Design or How To notes in Your Database

creazion_dev’s picture

Hi nancy,

I'll contribute the module in the next two weeks.

---------------------------------------------
www.happyfaces-kinderschminken.de - www.3p-consulting.com

coupet’s picture

I think adding the option for admin to limit the filesize would be great.

----
Darly

enxox’s picture

I don't know if its the best way...but it works!

  if (!flood_is_allowed('contact', variable_get('contact_hourly_threshold', 17))) {
      $output = t("You cannot send more than %number messages per hour. Please try again later.", array('%number' => variable_get('contact_hourly_threshold', 17)));
      drupal_set_message('<h3 class="red center">'.$output.'</h3>');
      drupal_goto($goto);
  }else{
    if(file_check_upload('file1')){
      $trenner  = md5(uniqid(time()));
      $headers  = array('Content-Type' => "multipart/mixed; boundary=$trenner");
      $message  = "\n--$trenner\n";
      $message .= "Content-Type: text/plain; charset=UTF-8; format=flowed;"."\n\n"; // sets the mime type
      $message .= $body."\n";
      $message .= "\n\n";
      for($i=1;$i<=3;$i++){
        $file = file_check_upload('file'.$i);

 // file size control

 if($file->filesize > 105500)
                {
    drupal_set_message('Attachment is too large.');
    drupal_goto($goto);
                }
else
        if($file->filename){
          $file->filepath = str_replace("\\","\\\\",$file->filepath);
          $message   .= "--$trenner"."\n";
          $message  .= "Content-Type:$file->filemime;\n\tname=$file->filename\n";
          $message  .= "Content-Transfer-Encoding: base64\n";
          $message  .= "Content-Disposition: attachment;\n\tfilename=$file->filename\n\n";
          $filedata  = fread(fopen($file->filepath, "rb"), $file->filesize);
          $message  .= chunk_split(base64_encode($filedata));
          $message  .= "\n\n";
        }
      }
      $message .= "--$trenner--";
    }else{
      $message = $body;
    }

coupet’s picture


/**
 * Implementation of hook_menu().
 */
function contact_form_menu() {
  $items = array();

    $items[] = array(
      'path'		=> 'admin/settings/contact_form',
      'title'		=> t('Contact Form settings'),
      'description'	=> t('Change defaults.'),
      'callback'	=> 'drupal_get_form',
      'callback arguments' => array('contact_form_settings'),
      'access'		=> user_access('administer contact forms'),
    );
  }

/**
 * Admin settings ().
 */
function contact_form_settings() {
  $form = array();
  $form['contact_form_max_image_size'] = array(
    '#type'			=> 'textfield',
    '#title'		=> t('Maximum filesize'),
    '#default_value'	=> variable_get('contact_form_max_image_size', 100000),
    '#description'	=> t('The maximum filesize for Attachments'),
    '#required'		=> FALSE, 
    '#weight'		=> 0
  );
  return system_settings_form($form);
}

 // file size control logic
 if($file->filename){
   if($file->filesize > contact_form_max_image_size){
     drupal_set_message('Attachment is too large.');
     drupal_goto($goto);
   }
 // process file
 .....
 }

----
Darly

creazion_dev’s picture

Now a project exists which you can find here http://drupal.org/project/mailattach

Please make a feature request and I will include your suggestions.

---------------------------------------------
last projects: www.happyfaces-kinderschminken.de - www.3p-consulting.com

newdru’s picture

1) have an actual downloadable module on the project page :-)...

I guess your waiting for feature requests before you post the actual module?

thanks

yched’s picture

1) be patient :-) Tarballs for dev releases often take a few hours to be generated.
Meanwhile, the code is available using the 'View CVS messages' link on the project page

newdru’s picture

I'll wait for them to post..

Also, good to know that you can access the code in the cvs link. thanks for that tip

mixacom’s picture

Grear Thanx!!! It's great.

ermaeco’s picture

Great module. Just what I needed. Thanks a lot! :)

kat6b’s picture

I'm trying to follow the thread here. I've downloaded the module, but there are no instructions for configuration. After enabling it, how does this actually get attached to the contact form?

krynsky’s picture

Hello, I've installed the module, enabled it, provided proper access controls, have been able to edit the settings, yet I do not see any options for attachments on my contact form. Since there isn't any readme or installation docs with the module am I missing something?

Thanks,

Mark

Arieh’s picture

This module doesn't add "Attach File" field to usual Contact Form. It creates additional special page. The link to this page appears on the menu section under your username.

There are 2 parts of menu, usually on the left side of your drupal based website. The upper menu is for all visitors. Under it, there is one more menu, that appears after you logged in. Just below your username in this menu will appear link "Contact with attachment" or just "Contact".

You can disable this menu item, if you want, and build a new menu item for the upper menu section, sounding like "Send Files" or "Contact with attachment" or whatever. In any case, after enabling the module and configuring permissions etc the URL to the Mail Attach page will be: http://yourdomain.com/mailattach

I hope this helps.

Arieh

andrew9109’s picture

Got your code, made it work after realised I copied the wrong version, but it doens't appear to email the file to the destination address I told it to and nor does it display the message?

Any chance of some help?

Nutty’s picture

I'm having a problem.

A logged in user can use the mailattach module just fine. If an anonymous visitor attempts to bring up the domain/mailattach URL however, they immediately get, "You need to provide a valid e-mail address to contact other users. Please update your user information and try again."

Is this by design or have I F'd something up?

Thanks.

wshi2007’s picture

Hi,

Can somebody please explain whether there is any way to edit,update, delete the webform submitted data?

I am really stuck up with this, and dont know whether there is any other module which can do this.
I have fields like resume (file upload) and E-mail,... in my form, so i used webform module, got the proper look and feel. But now i dont know how do i get the submitted fields back and edit or delete them.

Are there any patches to be added to webform module,which can be helpful for editting webform submitted data??

Any help regarding this would be really appreciated.
and sorry if i posted this forum in wrong place.

Thankyou,

NecroHill’s picture

Drupal 6.x has amended Contact module and this solution doesn't work :((
Is any chance to convert that for Drupal 6.x?

whoey’s picture

I'd also like to see a Drupal 6 version unless there is a better solution?

mboc’s picture

Suscribing to the mail attach problem in Drupal 6!!

Thanks!

epulula’s picture

Hello,

How can I costum CONTACT form in Drupal 6?

I want to have more fields. Is that possible? How?

naveenpl’s picture

Hai Michael Smolla,

I was wondering exactly what does this line of code do, in the code you have given.
if($file->filename){
$file->filepath = str_replace("\\","\\\\",$file->filepath);

Thanks,
Naveen P.L.

mitndc’s picture

tnx creazion,

I'm using drupal 6.x i used your code to create the contact form page.
the page was create, how ever an error is accuring if you want to send a message and attached file through that form.

the error is saying:

Fatal error: Cannot use string offset as an array in C:\wamp\www\includes\form.inc on line 986