Advanced email in PHP

Decent article for a beginner. Kev is always clear.

I adapted the script in this article to email an attached tab-delimited file created on the fly from mysql data. It works great with one exception. When I open the file in Excel, all the space and tab characters have been replaced with the ASCII nul character.

Does anyone know the cause of this problem?

I see this is your first post. Welcome to the SitePoint forums! :smiley:

Are you sure you encoded the data with basecode 64? That might possibly be the problem. OTOH, if it doesn’t seem to have anything to do with it, post your code. Maybe someone will spot something in it.

Yes, I tried it both with and without base64 encoding. Neither fixed the bug. I found a workaround though. If I first open the file in notepad and then copy and paste it into Excel, the tab characters render as they should and place each data field in its own column. I’d still like to know why the tabs are replaced by nul characters if I open the file in Excel directly.

My code is attached.

bbergin - Your code attachment is still pending approval as I write this, but I thought of something else to try in the meantime. See if using htmlentities does anything for you.

great tut, i receive file as attachment, but no message!?? what could i possible be doing wrong?

Hiya, great tutorial!

I am having a problem with the sending of an attachment though, i am modifying the script slightly as most are i presume. What i am trying to do is send two e-mails out of the one form as well as sign a user up to a database from another tutorial, which doesn’t seem to be the problem. It is just one is sending an attachment and the other is not. The following code gets no errors but the attachement is not recieved, but content is complete:

<<<<-----------------------------CODE------------------------>>>>>>
<?php
else:
// Process signup submission
dbConnect(‘srecruit’);

 if ($_POST['newfname']=='' or $_POST['newlname']=='' 
 or $_POST['newemail']=='' or $_POST['newtel']=='') { 
   error('One or more required fields were left blank.\\\

'.
‘Please fill them in and try again.’);
}

 // Check for existing user with the new email 

$sql = “SELECT COUNT(*) FROM users WHERE email = ‘$_POST[newemail]’”;
$reg_result = mysql_query($sql);
if (!$reg_result) {
error('A database error occurred in processing your '.
'submission.\
If this error persists, please '.
‘contact you@example.com.’);
}
if (@mysql_result($reg_result,0,0)>0) {
error('A user already exists with your chosen userid.\
'.
‘Please try another.’);
}

  $sql = "INSERT INTO users SET 
         fname = '$_POST[newfname]', 
         lname = '$_POST[newlname]', 
         email = '$_POST[newemail]', 
         tel = '$_POST[newtel]'"; 

if (!mysql_query($sql))
error('A database error occurred in processing your '.
'submission.\
If this error persists, please '.
‘contact you@example.com.’);

   // Email the new password to the person. 

$message = "G’Day!

Your personal account for the Project Web Site
has been created! To log in, proceed to the
following address:

http://www.example.com/

Your personal login ID and password are as
follows:

E-mail: $_POST[newemail]

You aren’t stuck with this password! Your can
change it at any time after you have logged in.

If you have any problems, feel free to contact me at
<you@example.com>.

-Your Name
Your Site Webmaster
";

mail($_POST[‘newemail’],“Your Password for Your Website”,
$message, “From:Your Name <you@specialist-recruit.com>”);

// Read POST request params into global vars
$to = “kesterwynyard@pure-tech.co.uk”;
$from = “signup@specialist-recruit.com”;
$subject = “New Website User”;
$messageatt = “get out!”;

// Obtain file upload vars
$fileatt = $_FILES[‘fileatt’][‘tmp_name’];
$fileatt_type = $_FILES[‘fileatt’][‘type’];
$fileatt_name = $_FILES[‘fileatt’][‘name’];

$headers = “From: $from”;

if (is_uploaded_file($fileatt)) {
// Read the file to be attached (‘rb’ = read binary)
$file = fopen($fileatt,‘rb’);
$data = fread($file,filesize($fileatt));
fclose($file);

// Generate a boundary string
$semi_rand = md5(time());
$mime_boundary = “==Multipart_Boundary_x{$semi_rand}x”;

// Add the headers for a file attachment
$headers .= "
MIME-Version: 1.0
" .
“Content-Type: multipart/mixed;
" .
" boundary=\”{$mime_boundary}\“”;

// Add a multipart boundary above the plain message
$messageatt = "This is a multi-part message in MIME format.

" .
"–{$mime_boundary}
" .
"Content-Type: text/plain; charset=\“iso-8859-1\”
" .
"Content-Transfer-Encoding: 7bit

" .
$messageatt . "

";

// Base64 encode the file data
$data = chunk_split(base64_encode($data));

// Add file attachment to the message
$messageatt .= “–{$mime_boundary}
" .
“Content-Type: {$fileatt_type};
" .
" name=\”{$fileatt_name}\”
" .
//“Content-Disposition: attachment;
" .
//” filename=\“{$fileatt_name}\”
" .
"Content-Transfer-Encoding: base64

" .
$data . "

" .
"–{$mime_boundary}–
";
}

// Send the message
$ok = mail($to, $subject, $messageatt, $headers);
if ($ok) {
echo “<p>Mail sent! Yay PHP!</p>”;
} else {
echo “<p>Mail could not be sent. Sorry!</p>”;
}
?>
<<<<-----------------------------CODE------------------------>>>>>>

Just prior to posting this thread, i hadn’t actually uploaded the two pages untouched, so i have done so. On a submit of the untouched tutorial i get the following error:

Warning: filesize(): Stat failed for C:\WINDOWS\TEMP\php1EA3.tmp (errno=2 - No such file or directory) in \
as22ent\domains\s\specialist-recruit.com\user\htdocs\mail.php on line 23

Any ideas to if these problems are linked or any solution to the orginal?

Sorry about the length!
Any help is much appreciated!

Kester Wynyard

Is there a simple to handle errors? I get the “Mail could not be sent. Sorry!” error, but would like more information about what is causing the error. Maybe I just need to change the .ini settings?

Added code…assume email addresses are valid:


<?
if ($position == "Counselor") {
	$toMail == "email1@yoursite.com";
} else {
	$toMail == "email2@yoursite.com";
}
// Read POST request params into global vars
$to = $toMail;
$from = $_POST['from'];
$subject = "Resume Submittal";
$position = $_POST['position'];
$message = $_POST['message'];

// Obtain file upload vars
$fileatt = $_FILES['fileatt']['tmp_name'];
$fileatt_type = $_FILES['fileatt']['type'];
$fileatt_name = $_FILES['fileatt']['name'];

$headers = "From: $from";

if (is_uploaded_file($fileatt)) {
  // Read the file to be attached ('rb' = read binary)
  $file = fopen($fileatt,'rb');
  $data = fread($file,filesize($fileatt));
  fclose($file);

  // Generate a boundary string
  $semi_rand = md5(time());
  $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
  
  // Add the headers for a file attachment
  $headers .= "\
MIME-Version: 1.0\
" .
              "Content-Type: multipart/mixed;\
" .
              " boundary=\\"{$mime_boundary}\\"";

  // Add a multipart boundary above the plain message
  $message = "This is a multi-part message in MIME format.\
\
" .
             "--{$mime_boundary}\
" .
             "Content-Type: text/plain; charset=\\"iso-8859-1\\"\
" .
             "Content-Transfer-Encoding: 7bit\
\
" .
             $message . "\
\
";

  // Base64 encode the file data
  $data = chunk_split(base64_encode($data));

  // Add file attachment to the message
  $message .= "--{$mime_boundary}\
" .
              "Content-Type: {$fileatt_type};\
" .
              " name=\\"{$fileatt_name}\\"\
" .
              //"Content-Disposition: attachment;\
" .
              //" filename=\\"{$fileatt_name}\\"\
" .
              "Content-Transfer-Encoding: base64\
\
" .
              $data . "\
\
" .
              "--{$mime_boundary}--\
";
}

// Send the message
$ok = @mail($to, $subject, $position, $message, $headers);
if ($ok) {
  echo "<p>Mail sent! Yay PHP!</p>";
} else {
  echo "<p>Mail could not be sent. Sorry!</p>";
}
?>

This tutorials are good. But i am still confusing on how to setup the SMTP server.

No one :frowning:

This statement in your code:

$fd = fopen($sourcefile, "r");

needs to be this instead:

$fd = fopen($sourcefile, "rb");

Don’t know if that’s all you have to do though. Please compare your code with what I posted in this thread (post #11) to see if you can find other differences. Then you’ll probably have your problem solved.

@ vinyl J

Tried changing the ‘r’ to ‘rb’ but it looks like something else stoping it from showing me the file

I looked at your previous post and the script you supplied works :slight_smile:

I might just use this instead to save my self the headache :slight_smile:

You’re certainly welcome to use my script. :slight_smile:

You might be interested in a slightly modified version of the mail.php script that I made. It has some anti-spam measures that weren’t included with the script in that other post. Here is that modified script:

<html>
<head>
<title> Sending Email </title>
</head>
<body>
<?php
// Read POST request params into global vars
$to      = $_POST['to'];
$from    = $_POST['from'];
$subject = $_POST['subject'];
$message = stripslashes($_POST['message']);
$yourdomain = "yoursitename.com";
$YourWebsiteURL = "http://www.".$yourdomain."/";
$fromtest		= strpos($from, $yourdomain);

// If they call this page direct from the browser, send them away because they havent filled in
// the form! Also, test to see if some joker is using my domain as their email addy
if($from == "" || $fromtest == true) {
 header("location: $YourWebsiteURL");
 exit();
}

// Obtain file upload vars
$fileatt		= $_FILES['fileatt']['tmp_name'];
$fileatt_type	= $_FILES['fileatt']['type'];
$fileatt_name	= $_FILES['fileatt']['name'];
$fileatt2		= $_FILES['fileatt2']['tmp_name'];
$fileatt_type2	= $_FILES['fileatt2']['type'];
$fileatt_name2	= $_FILES['fileatt2']['name'];
$fileatt3		= $_FILES['fileatt3']['tmp_name'];
$fileatt_type3	= $_FILES['fileatt3']['type'];
$fileatt_name3	= $_FILES['fileatt3']['name'];

$headers = "From: $from";

if (is_uploaded_file($fileatt) || is_uploaded_file($fileatt2) || is_uploaded_file($fileatt3)) {
  // Read the file to be attached ('rb' = read binary)
  if (is_uploaded_file($fileatt)) {
  	$file = fopen($fileatt,'rb');
  	$data = fread($file,filesize($fileatt));
  	fclose($file);

  	// Base64 encode the file data
  	$data = chunk_split(base64_encode($data));
  }

  if (is_uploaded_file($fileatt2)) {
  	$file2 = fopen($fileatt2,'rb');
  	$data2 = fread($file2,filesize($fileatt2));
  	fclose($file2);

  	// Base64 encode the file data
  	$data2 = chunk_split(base64_encode($data2));
  }

  if (is_uploaded_file($fileatt3)) {
  	$file3 = fopen($fileatt3,'rb');
  	$data3 = fread($file3,filesize($fileatt3));
  	fclose($file3);

  	// Base64 encode the file data
  	$data3 = chunk_split(base64_encode($data3));
  }

  // Generate a boundary string
  $semi_rand = md5(time());
  $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
  
  // Add the headers for a file attachment
  $headers .= "\
MIME-Version: 1.0\
" .
              "Content-Type: multipart/mixed;\
" .
              " boundary=\\"{$mime_boundary}\\"";

  // Add a multipart boundary above the plain message
  $message = "This is a multi-part message in MIME format.\
\
" .
             "--{$mime_boundary}\
" .
             "Content-Type: text/plain;\
 charset=\\"iso-8859-1\\"\
" .
             "Content-Transfer-Encoding: 7bit\
\
" .
             $message . "\
\
" .
			 "--{$mime_boundary}\
";

  // Add file attachment(s) to the message
  if ($fileatt_name > "") {
  	$message .= "Content-Type: {$fileatt_type};\
" .
         	     " name=\\"{$fileatt_name}\\"\
" .
            	  "Content-Transfer-Encoding: base64\
" .
           	     "Content-Disposition: attachment;\
" .
           	     " filename=\\"{$fileatt_name}\\"\
\
" .
            	  $data . "\
" .
            	  "--{$mime_boundary}\
";
	}
	
	
  if ($fileatt_name2 > "") {
  	$message .=  "Content-Type: {$fileatt_type2};\
" .
         	     " name=\\"{$fileatt_name2}\\"\
" .
            	  "Content-Transfer-Encoding: base64\
" .
           	     "Content-Disposition: attachment;\
" .
           	     " filename=\\"{$fileatt_name2}\\"\
\
" .
            	  $data2 . "\
" .
            	  "--{$mime_boundary}\
";
	}
	
	
  if ($fileatt_name3 > "") {
  	$message .=  "Content-Type: {$fileatt_type3};\
" .
         	     " name=\\"{$fileatt_name3}\\"\
" .
            	  "Content-Transfer-Encoding: base64\
" .
           	     "Content-Disposition: attachment;\
" .
           	     " filename=\\"{$fileatt_name3}\\"\
\
" .
            	  $data3 . "\
" .
            	  "--{$mime_boundary}";
	}
	$message .=  "--\
\
";	
}

//Validate the email address used
if (eregi('^[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\\.([a-zA-Z]{2,4})$', $from)) {
	// Send the message
	$ok = @mail($to, $subject, $message, $headers);
	if ($ok) {
  echo "<p>Mail sent! Yay PHP!</p>";
	}
	else {
		echo "<p>Mail could not be sent. Sorry!</p>";
	}
else {
	echo "<p>Your email address is invalid. Mail could not be sent. Sorry!</p>";
}
?>
</body>
</html>

I took the last echo out and it works fine :slight_smile:

Thanks for the script! Don’t know why it’s playing up but does not matter.

Motions 2082. You were’nt ending the if(eregi(‘…’, $from)) before you did the else. You had this:

if(eregi('...', $from)){
  if($ok){
  } else {
  } else {
}

Should have been like this:

if(eregi('...', $from)){
  if($ok){
  } else {
  }
[color=red]}[/color] else {
}

Notice the red }?

Sorry about the mistake. :blush: I was trying to copy/paste code from my the script I use on my website, which itself is a little bit more complicated than the one here.

Without even reading this thread, I’ll give you the best advice you’re going to get here. Download Richard Heyes’ htmlMimeMail5, POP3, and mimeDecode classes and quit driving yourself bananas over this stuff. :slight_smile:

Version 1.3.1? Version 5 is as easy as falling off a ladder, dude. :wink:

You don’t need to understand how it works. The method names are self-explanatory. Read the article here:

Download the PHP 4 version here:

The file in that screenshot got renamed with the .tar extension twice somehow. It should be .tar.gz Rename it then try opening it in WinZip.