PHP Mail() Attachment Problems

PHP mail() attachment problems

$to = "myemail@mydomain.com";
$from = "Website <website@mydomain.com>";
$subject = "Test Attachment Email";

$separator = md5(time());

// carriage return type (we use a PHP end of line constant)
$eol = PHP_EOL;

// attachment name
$filename = "document.pdf";

//$pdfdoc is PDF generated by FPDF
$attachment = chunk_split(base64_encode($pdfdoc));

// main header
$headers = "From: ".$from.$eol;
$headers .= "MIME-Version: 1.0".$eol;
$headers .= "Content-Type: multipart/mixed; boundary=\"".$separator."\"";

// no more headers after this, we start the body! //

$body = "--".$separator.$eol;
$body .= "Content-Transfer-Encoding: 7bit".$eol.$eol;
$body .= "This is a MIME encoded message.".$eol;

// message
$body .= "--".$separator.$eol;
$body .= "Content-Type: text/html; charset=\"iso-8859-1\"".$eol;
$body .= "Content-Transfer-Encoding: 8bit".$eol.$eol;
$body .= $message.$eol;

// attachment
$body .= "--".$separator.$eol;
$body .= "Content-Type: application/octet-stream; name=\"".$filename."\"".$eol;
$body .= "Content-Transfer-Encoding: base64".$eol;
$body .= "Content-Disposition: attachment".$eol.$eol;
$body .= $attachment.$eol;
$body .= "--".$separator."--";

// send message
if (mail($to, $subject, $body, $headers)) {
echo "mail send ... OK";
} else {
echo "mail send ... ERROR";
}

What I've done:

  • Separated the body from the headers
  • removed extra EOLs put before separators

PHP Mail attachment not opening or error file

You are missing the attachment part in the email body.
Try this:

if (isset($_POST["send"])) {  
$subject = "Applicant";
$name = $_POST['contact_name'];
$position = $_POST['position'];

$tmpName = $_FILES['attachment']['tmp_name'];
$fileType = $_FILES['attachment']['type'];
$fileName = $_FILES['attachment']['name'];

$message = "Name: ".$name."\r\n"."Position: ".$position;

# Open a file
# encode the data for safe transit
# and insert \r\n after every 76 chars.
$encoded_content = chunk_split(base64_encode(file_get_contents($tmpName)));

# Get a random 32 bit number using time() as seed.
$random_hash = md5(date('r', time()));

# Define the main headers.
$headers = "From: no-reply@example.com\r\n";
$headers .= "Reply-To: no-reply@example.com\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: multipart/mixed; boundary=\"PHP-mixed-".$random_hash."\"\r\n";
$headers .= "X-Priority: 3\r\n";
$headers .= "X-MSMail-Priority: Normal\r\n";
$headers .= "X-Mailer: PHP/" . phpversion();

# Plain text section
$body = "--PHP-mixed-" . $random_hash . "\r\n";
$body .= "Content-Type: text/plain; charset=\"UTF-8\"\r\n";
$body .= "Content-Transfer-Encoding: 8bit\r\n\r\n";
$body .= $message;
$body .= "\r\n\r\n";
$body .= "\r\n--PHP-mixed-" . $random_hash . "\r\n\r\n";

# Define the attachment section
$body .= "--PHP-mixed-" . $random_hash . "\r\n";
$body .= "Content-Type: " . $fileType . "; name=\"" . $fileName . "\"\r\n";
$body .= "Content-Transfer-Encoding: base64\r\n";
$body .= "Content-Disposition: attachment; filename=\"" . $fileName . "\"\r\n\r\n";
$body .= $encoded_content;
$body .= "\r\n--PHP-mixed-" . $random_hash . "\r\n\r\n";

# Send email now
$retval = mail('sample@gmail.com', $subject, $body, $headers);

if( $retval == true ) {
echo "<div style='border-style: solid; border: thick double #00386c; margin-bottom: 10px;'><h1 style='text-align: center; color: #00386c; padding: 10px;'>Your resume was sent! Thank you.</h1></div>";
} else{
echo "error";exit;
}
}

PHP mail sends attachments successfully, but the message is empty

Resolved by adding $body .= $message.$eol; before the PDF-attachment.

PHP mail PDF attachment gets file corrupted

It's been a while, but finally got this problem solved. The issue is on PHP_EOL which in my case is returning \n, while some systems the email should have \r\n as line break.
To fix this issue just place the new $eol:

$eol = "\r\n";

php mail attachment - error - how to debug

This one works....

        $text     = "Hello Mr. Xyz," . $crnl . "Some stupid text as an example."                . $crnl;
$content = chunk_split(base64_encode($file));

$headers = "MIME-Version: 1.0" . $crnl;
$headers .= "From: " . $mail_from . $crnl;

$headers .= "Content-Type: multipart/mixed; boundary=\"" . $boundary1 . "\"" . $nl . $crnl;
$headers .= "Content-Type: text/plain" . $nl;
$headers .= "--" . $boundary1 . $crnl;
$headers .= 'Content-Length: '.strlen($text) . $crnl;
$headers .= "Content-Transfer-Encoding: 8-bit" . $nl . $crnl;
$headers .= $text;
$headers .= "--" . $boundary1 . $crnl;

$headers .= "Content-Type: application/excel; charset=\"ISO8859-1\"; name=\"xyz.csv\"" . $nl . $crnl;
$headers .= "--" . $boundary1 . $crnl;
$headers .= "Content-Disposition: attachment; filename=\"xyz.csv\"" . $crnl;
$headers .= 'Content-Length: ' . strlen($content) . $crnl;
$headers .= "Content-Transfer-Encoding: base64" . $nl . $crnl;
$headers .= $content;
$headers .= "--" . $boundary1 . "--"

...with a small bug. I have an extra attment, but that's for now ok. We other thing is a longer play with "\n", "\r\n" and a mixture of both on the right places (lines).

Issues with PHP email attachment

Answer

You propably should use an email library as was mentioned in one of the comments, but if you must use mail(), your code should look something like this:

//standard mail headers
$header = "From: $from\r\n";
$header .= "Reply-To: $replyto\r\n";
$header .= "MIME-Version: 1.0\r\n";
$header .= "Content-Type: multipart/mixed; boundary=\"$uid\"\r\n\r\n";

Stop right there! The double line-break (\r\n\r\n) marks the end of the headers. I don't know if mail() allows you to send the body like this. Perhaps it does, but the rest of your message should go inside the message body.

You're also missing a close-delimiter. See the MIME syntax section below.

$body  = "This is a multi-part message in MIME format.\r\n";

// text part
$body .= "--$uid\r\n"; // dash-boundary
$body .= "Content-type: text/html; charset=iso-8859-1\r\n";
$body .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
$body .= $message;

// file attachment
if (isset ($FILES['attachment'])) {
$file_name = $_FILES['attachment']['name'];
$temp_name = $_FILES['attachment']['tmp_name'];
$file_type = $_FILES['attachment']['type'];
$body .= "\r\n--$uid\r\n"; // delimiter
$body .= "Content-Type: $file_type; name=\"$file_name\"\r\n";
$body .= "Content-Transfer-Encoding: base64\r\n";
$body .= "Content-Disposition: attachment filename=\"$file_name\"\r\n\r\n";
$body .= $content;
}
$body .= "\r\n--$uid--\r\n"; // close-delimiter

//send the mail
if (mail($to, $subject, $body, $header)) {
/* ... */

Additional notes

$from = $_POST['email'];
$to = 'email@email.com,'.$_POST['email'];

$header = "From: ".$from."\r\n";
$header .= "Reply-To: ".$replyto."\r\n";

if (mail($to, $subject, "", $header)) {

The code above allows the user to send spam or other unwanted email to arbitrary addresses, both through the $to variable and through the $from variable (by inserting line-breaks and a Bcc: header or similar). You should remove $_POST['email'] from $to, and strip out line-breaks from $from. I don't know about your Reply-To: header; $replyto is undefined.



// if thre is an attachment
$_FILES['attachment']['name'];

This code does nothing (except perhaps generate a notice if there is no attachment).



$extension = substr($base, strlen($base)-4, strlen($base));

This can be simplified as:

$extension = substr($base, -4);

MIME Syntax

This is an excerpt of what the structure of a multi-part message body looks like according to RFC 2046. (BNF syntax, somewhat simplified.)


multipart-body := [preamble CRLF]
dash-boundary CRLF
body-part *encapsulation
close-delimiter
[CRLF epilogue]

dash-boundary := "--" boundary

body-part := MIME-part-headers [CRLF *OCTET]

encapsulation := delimiter
CRLF body-part

delimiter := CRLF dash-boundary

close-delimiter := delimiter "--"

References

  • RFC 5322 Internet Message Format
  • RFC 2045 (MIME) Part One: Format of Internet Message Bodies
  • RFC 2046 (MIME) Part Two: Media Types


Related Topics



Leave a reply



Submit