Sending mail through PHP forms either directly or through CGI or PERL mail scripts can be tricky in getting through most if not all mail servers on the receiving end… This is due to the increased anti-spamming filters and algorithms running on the mail servers that look for various criteria in the header of each e-mail they receive… The MIME data within the e-mail’s header needs to be designed properly for the type of format within the e-mail, as well as the server it is coming from.

Below is a series of PHP code that embeds MIME data into the header of the outgoing e-mail from your HTML form.

****************
To send messages
****************

To send a message:

sendMIME(
$senderEmail, //in valid email format - see Email list format (qv)
$replyTo, //a normal email address or " if none
$recipientEmailList, //in Email list format (qv)
$ccEmailList, //in Email list format (qv) or " if none
$bccEmailList, //in Email list format (qv) or " if none - NOT SUPPORTED in PHP < 4.3
$priority, //integer 1 (highest) - 5 (lowest) or 0 (default) [not supported by some email clients]
$subject, //a normal subject
$mailBody, //a plain text message body
$mailHTML, //a HTML message body or " if none
//with this script, the HTML body cannot use attached files as message contents
$filesToSend, //in Attachment list format (qv) or " if none
$filesToEmbed, //in Attachment list format (qv) or " if none
$additional_headers, //in valid message header format - separated by line breaks ("..n") - or " if none
$wrapText //true = wrap body text if required, false = do not wrap body text (default = true)
);

The function can accept one further parameter after wrapText – Debug – set to true to display the output

instead of sending the email (uses tags).

If the body text is already wrapped (for example, if you are using my html2text library to create it), you

should set $wrapText to false – otherwise set it to true (or leave it because it is optional).

If this script automatically uses html2text (see above), it will automaically set $wrapText to false.

Email list format:
You will need to check that all email addresses are valid
Emails can be written in any valid email list format
Usually, each email address is written as
email@address.com
or
“Person’s name”
To create a list, email addresses can be separated by commas:
email@address.com, “Person’s name” , anotherEmail@address.com
You can use the prepareEmails function to prepare the email addresses from name/email lists:
For one email address:

$emailList = prepareEmails( Array( $recipientName, $recipientEmail ) );

Or for multiple addresses (this format will also work for a single address if required):

$emailList = prepareEmails( Array(
Array( $recipientName, $recipientEmail ),
Array( $recipientName2, $recipientEmail2 ),
Array( $recipientName3, $recipientEmail3 )
) );

Attachment list format:
If using PHP version 4.1.0 or higher, you should use _FILES instead of HTTP_POST_FILES
For no attachments:


$filesToSend = ";
For single file upload (it is important to do this as shown):
$filesToSend = $HTTP_POST_FILES['fileAttachment'];
For a single static file:
$filesToSend = ‘/var/files/filename.txt';

For multiple file upload (it is important to do this as shown) – this format will also work with a single file if required:

$filesToSend = Array( $HTTP_POST_FILES['fileAttachment'], $HTTP_POST_FILES['fileAttachment2'], etc. );

For multiple static files – this format will also work with a single file if required:

$filesToSend = Array( ‘/var/files/filename.txt', ‘../www/someFile.exe', ‘myFile.php', etc. );

To read the HTML body from a static file, use:

fread( fopen( $filePath, ‘rb' ), filesize( $filePath ) )

To read the HTML body from an uploaded file, use:

fread( fopen( $HTTP_POST_FILES['fileAttachment']['tmp_name'], ‘rb' ), filesize( $HTTP_POST_FILES['fileAttachment']['tmp_name'] ) )

To embed images or files in the HTML body you will need to include those files in the $filesToEmbed input.
These files will not appear as attachments unless they are also included in the $filesToSend input.
The HTML must be modified slightly to use the embedded file, by using ” as the data source.
The number starts at 1, and files will be used in the order that they are put into the $filesToEmbed input.
Eg.

..”>.. data=””>..>..”>
[NOTE: as this syntax is in fact invalid HTML, it should never accidentally appear in any HTML email]
_______________________________________________________________*/


function sendMIME( $senderEmail = ", $replyTo = ", $recipientEmail = ", $ccEmailList = ", $bccEmailList = ", $priority = 0, $subject = ‘No Subject', $usrMailBody = ", $mailHTML = ", $fileNamesAndPaths = ", $embedNamesAndPaths = ", $extraHeaders = ", $doWrap = true, $debug = false ) {

function prepareEmails( $EMaddr ) {
//with each email name/address pair, prepare it in email format
if( !is_array( $EMaddr[0] ) ) { $EMaddr = Array( $EMaddr ); }
$EMstr = "; foreach( $EMaddr as $key => $emComb ) {
$EMstr .= ( $EMstr ? ‘, ‘ : " ).( $emComb[0] ? ( ‘"‘.addslashes(preg_replace( "/[..n..r.."]/", ", $emComb[0] )).'" ‘ ) : " ).'<'.addslashes(preg_replace( "/[..n..r<>]/", ", $emComb[1] )).">";
}
return $EMstr;
}

//prepare basic headers
$extraHeaders = "From: ".$senderEmail."..n".
( $replyTo ? ( "Reply-To: ".preg_replace( "/[..n..r]/", ", $replyTo )."..n" ) : " ).
( $ccEmailList ? ( "Cc: ".$ccEmailList."..n" ) : " ).
( $bccEmailList ? ( "Bcc: ".$bccEmailList."..n" ) : " ).
( $priority ? ( "X-Priority: ".preg_replace( "/[..n..r]/", ", $priority )."..n" ) : " ).
‘X-Mailer: makeMIME v2.1 in PHP by MTWJ'.
( $extraHeaders ? ( "..n".$extraHeaders ) : " );

//use UNIX linebreaking (works on all platforms and resolves problems with some platforms)
$usrMailBody = preg_replace( "/..r..n?/", "..n", $usrMailBody );
$mailHTML = preg_replace( "/..r..n?/", "..n", $mailHTML );

if( !$fileNamesAndPaths && !$mailHTML ) {

//no attachments or HTML - all that we need to do is wrap the body text
$mailBody = $doWrap ? wordwrap( $usrMailBody ) : $usrMailBody;

} else {

//I forbid the use of HTML-only emails
if( !$usrMailBody && $mailHTML ) { $usrMailBody = ( $doWrap = !function_exists( ‘html2text' ) ) ? strip_tags( $mailHTML ) : html2text( $mailHTML ); }

//prepare MIME boundaries that do not appear in the message body(s) (or base64 encoded attachments - hence the use of _)
$MIMEboundary = ‘MTWJ_mixed_Bound_0?; $MIMEAboundary = ‘MTWJ_alt_Bound_0?; $MIMERboundary = ‘MTWJ_rel_Bound_0?; $MIMEcid = ‘MTWJ_cnid_0?; $randChars = Array('A','B');
while( substr_count( $mailBody , $MIMEboundary ) || substr_count( $mailBody , $MIMEAboundary ) || substr_count( $mailBody , $MIMERboundary ) || substr_count( $mailBody , $MIMEcid ) || substr_count( $mailHTML , $MIMEboundary ) || substr_count( $mailHTML , $MIMEAboundary ) || substr_count( $mailHTML , $MIMERboundary ) || substr_count( $mailHTML , $MIMEcid ) ) { }

//prepare the MIME declaration headers - the multipart/mixed boundary means that I can add attachments
$extraHeaders .= "..nMime-Version: 1.0..nContent-Type: multipart/mixed; boundary=.."$MIMEboundary.."";

//prepare the multipart/alternative header [allowing HTML / text alternatives] and the plain body
$mailBody = "..nThis is a MIME email - please upgrade to a MIME compatible email client..n".
"..n-$MIMEboundary..nContent-Type: multipart/alternative; boundary=.."$MIMEAboundary.."..n".
"..n-$MIMEAboundary..nContent-Type: text/plain; charset=.."us-ascii.."..n".
"Content-Transfer-Encoding: 7bit..n..n".( $doWrap ? wordwrap( $usrMailBody ) : $usrMailBody )."..n";

//prepare the HTML body and embedded files
if( $mailHTML ) {

//if they only provide one embed, put it in an array as if they provided more than one
if( !is_array( $embedNamesAndPaths ) || ( is_string( $embedNamesAndPaths['name'] ) && is_string( $embedNamesAndPaths['tmp_name'] ) ) ) {
$embedNamesAndPaths = Array( $embedNamesAndPaths );
}

//use correct Content-ID for embeds
for( $x = 0; $embedNamesAndPaths[$x]; $x++ ) {
$mailHTML = str_replace( "@makeMIMEembed', $mailHTML );
}

//put in the modified HTML body with multipart/related header, allowing embedded files
$mailBody .= "..n-$MIMEAboundary..nContent-Type: multipart/related; boundary=.."$MIMERboundary.."..n".
"..n-$MIMERboundary..nContent-Type: text/html; charset=.."us-ascii.."..n".
"Content-Transfer-Encoding: 7bit..n..n".$mailHTML."..n";

//for each embed, get the file type for MIMEtyping and encode the file
$x = 0; foreach( $embedNamesAndPaths as $key => $fullPath ) { if( $fullPath ) {
//if it was an upload, use its tmp_name, else use the path
if( is_array( $fullPath ) ) { $fullPath = $fullPath['tmp_name']; }
$mailBody .= "..n-$MIMERboundary..nContent-Type: ".solveMimeType( $fullPath )."..n".
"Content-ID: <..nContent-Transfer-Encoding">".$MIMEcid.'_'.( ++$x )."@makeMIMEembed>..nContent-Transfer-Encoding: base64..n..n".
chunk_split(base64_encode(fread(fopen($fullPath,'rb'),filesize($fullPath))))."..n";
} }

$mailBody .= "..n-$MIMERboundary-..n"; //end of HTML and embedded files

}

$mailBody .= "..n-$MIMEAboundary-..n"; //end of text and HTML alternatives

//if they only provide one attachment, put it in an array as if they provided more than one
if( !is_array( $fileNamesAndPaths ) || ( is_string( $fileNamesAndPaths['name'] ) && is_string( $fileNamesAndPaths['tmp_name'] ) ) ) {
$fileNamesAndPaths = Array( $fileNamesAndPaths );
}

//for each attachment, get the file name for sending to the recipient and encode the file
foreach( $fileNamesAndPaths as $key => $fullPath ) { if( $fullPath ) {
//if it was an upload, use its tmp_name and name, else use the name with and without the path
if( is_array( $fullPath ) ) { $justFileName = $fullPath['name']; $fullPath = $fullPath['tmp_name'];
} else { $justFileName = preg_replace( "/.*..//", ", str_replace( "....", ‘/', $fullPath ) ); }
$mailBody .= "..n-$MIMEboundary..nContent-Type: ".solveMimeType( $fullPath )."; name=.."".$justFileName.".."..n".
"Content-Transfer-Encoding: base64..nContent-Disposition: attachment; name=.."".$justFileName.".."..n..n".
chunk_split(base64_encode(fread(fopen($fullPath,'rb'),filesize($fullPath))))."..n";
} }

$mailBody .= "..n-$MIMEboundary-..n"; //end of MIME email

}

//send the email
if( $debug ) { return print "

".htmlspecialchars("To: ".$recipientEmail."..nSubject: $subject..n$extraHeaders..n..n$mailBody")."

";

} else { return mail($recipientEmail,$subject,$mailBody,$extraHeaders); }

}

function solveMimeType($fileName) {
if( is_array( $fileName ) ) { return $fileName['type'] ? $fileName['type'] : ( function_exists( ‘mime_content_type' ) ? mime_content_type( $fileName['tmp_name'] ) : ( function_exists( ‘ext2mime' ) ? ext2mime( $fileName['name'] ) : ‘application/octet-stream' ) ); }
else { return function_exists( ‘mime_content_type' ) ? mime_content_type( $fileName ) : ( function_exists( ‘ext2mime' ) ? ext2mime( $fileName ) : ‘application/octet-stream' ); }
}