Location: PHPKode > scripts > PHPwebmail > phpwebmail/mime.php
<?php

// MIME functions written by other people (see comments)


/* 

by Bill Adams <hide@address.com>

Notes from Dan Potter:
Sure. I changed a few other things in here too though. One is that I let
you specify what the destination filename is (i.e., what is shows up as in
the attachment). This is useful since in a web submission you often can't
tell what the filename was supposed to be from the submission itself. I
also added my own version of chunk_split because our production version of
PHP doesn't have it. You can change that back or whatever though =).
Finally, I added an extra "\n" before the message text gets added into the
MIME output because otherwise the message text wasn't showing up.

note: someone mentioned a command-line utility called 'mutt' that 
can mail attachments.

If chunk_split does not work on your system, change the call to chunk_split
to my_chunk_split 

Note: if you don't have base64_encode on your sytem it will not work 

CHANGES by Jordan <hide@address.com>:
Sent Messages can be saved in an IMAP folder.

CHANGES by Bernard Piller:
I changed the handling of extra headers to make the function work better with
PHPwebmail. 

Mirko Holler <hide@address.com> added the following:

I would like to tell you about a change I made in the code. I have a private Linux Server which uses another host to relay mail to. I am only allowed to do so, if the right sender address is specified in the header of the mail.

When I used the code as it comes with the package, and send a mail, my local mail queue looks like:

                Mail Queue (1 request)
--Q-ID-- --Size-- -----Q-Time----- ------------Sender/Recipient------------
XAA14709      276 Fri Jan  3 23:54 wwwrun
                                   hide@address.com

As you can see, the sender name is wwwrun, the user of my webserver. In the mail client, the from address still would look like hide@address.com, as specified in phpwebmail.
When adding wwwrun as a trusted user to sendmail, wwwrun will be allowed to send mail using a different user name. To make phpwebmail do so, I changed in mime.php line 88 from

if(mail($this->addr_to,$this->subject,$message,$headers))

to

if(mail($this->addr_to,$this->subject,$message,$headers, "-f".$from))

Which will have the following result, when sending a mail: Here is the mail queue:

                Mail Queue (1 request)
--Q-ID-- --Size-- -----Q-Time----- ------------Sender/Recipient------------
XAA14709      276 Fri Jan  3 23:54 mirko <hide@address.com>
                                   hide@address.com

Now the sender name is correct and my relay server will accept my message.
Maybe this is an interesting point for other users, too?!
  
*/

// simple class that encapsulates mail() with addition of mime file attachment.
class CMailFile {
	var $subject;
	var $addr_to;
	var $text_body;
	var $text_encoded;
	var $mime_headers;
	var $mime_boundary = "--==================_846811060==_";
	var $smtp_headers;
	
	function CMailFile($subject,$to,$extra_headers,$msg,$the_file,$mimetype = "application/octet-stream", $mime_filename = false) {
		$this->subject = $subject;
		$this->addr_to = $to;
		$this->smtp_headers = $extra_headers;
		if ($the_file != "nope") {
		    $this->text_body = $this->write_body($msg);
		    $this->text_encoded = $this->attach_file($the_file,$mimetype,$mime_filename);
		    $this->mime_headers = $this->write_mimeheaders($the_file, $mime_filename);
	        } else $this->text_body = $msg;
	}

	function attach_file($the_file,$mimetype,$mime_filename) {
		$encoded = $this->encode_file($the_file);
		if ($mime_filename) $the_file = $mime_filename;
		$out = "--" . $this->mime_boundary . "\n";
		$out = $out . "Content-type: " . $mimetype . "; name=\"$the_file\";\n";		
		$out = $out . "Content-Transfer-Encoding: base64\n";
		$out = $out . "Content-disposition: attachment; filename=\"$the_file\"\n\n";
		$out = $out . $encoded . "\n";
		$out = $out . "--" . $this->mime_boundary . "--" . "\n";
		return $out; 
// added -- to notify email client attachment is done
	}

	function encode_file($sourcefile) {
		if (is_readable($sourcefile)) {
			$fd = fopen($sourcefile, "r");
			$contents = fread($fd, filesize($sourcefile));
			$encoded = chunk_split(base64_encode($contents));
			fclose($fd);	
		}
		return $encoded;
	}

	function sendfile() {
		global $imap_server;
		global $name;
		global $passwd;
		global $from;
		global $subject;
		global $to;
		global $sql_user, $sql_pw;

		$headers = $this->smtp_headers . $this->mime_headers;		
		$message = $this->text_body . $this->text_encoded;
		if(mail($this->addr_to,$this->subject,$message,$headers, "-f".$from))
		{
		      if ($db_link = mysql_connect($sql_host,$sql_user,$sql_pw)) {
				@mysql_select_db("phpwebmail");
				$sql_query = "SELECT sent, folder FROM prefs WHERE user='$name'";
				$result = mysql_query($sql_query);
			        // catch SQL errors
			        if (mysql_errno()) echo ("ERROR ".mysql_error());
				$row = mysql_fetch_row($result);
				$usersent = $row[0];
				$folder_pre = $row[1];
				if ($folder_pre && substr($folder_pre,-1)!="/") $folder_pre .= "/";
			       mysql_close($db_link);
			} // if db_link ends

			if ($usersent == "imap") {
				$streammbox = imap_open("{".$imap_server.":143}".$folder_pre."Sent",$name,$passwd);
				imap_append($streammbox,"{".$imap_server.":143}".$folder_pre."Sent",
				      "Date: " . date("D , d M Y H:i:s ") . (date("Z")/60) . "\r\n"
		                   ."Subject: " . $subject . "\r\n"
		                   ."To: " . $to . "\r\n"
				      .$headers."\r\n"
		                   .$message . "\r\n"
		                   );
				   
//	CHANGES BY MIRKO HOLLER (marks sent messages "seen")				

				   $check = imap_check($streammbox);
				   $checknr = $check->Nmsgs;
				   imap_setflag_full ($streammbox, $checknr, "\\Seen"); 
				   
				imap_close($streammbox);
			} // if usersent ends
	  	} // if mail ends
	}

	function write_body($msgtext) {
		$out = "--" . $this->mime_boundary . "\n";
		$out = $out . "Content-Type: text/plain; charset=\"us-ascii\"\n\n";
		$out = $out . $msgtext . "\n";
		return $out;
	}

	function write_mimeheaders($the_file, $mime_filename) {
		if ($mime_filename) $the_file = $mime_filename;
		$out = "MIME-version: 1.0\n";
		$out = $out . "Content-type: multipart/mixed; ";
		$out = $out . "boundary=\"$this->mime_boundary\"\n";
		$out = $out . "Content-transfer-encoding: 7BIT\n";
		$out = $out . "X-attachments: $the_file;\n\n";
		return $out;
	}

}

// usage - mimetype example "image/gif"
// $mailfile = new CMailFile($subject,$to,$extra_headers,$body,$the_file,$mimetype);
// $mailfile->sendfile();

// Splits a string by RFC2045 semantics (76 chars per line, end with \r\n).
// This is not in all PHP versions so I define one here manuall.
function my_chunk_split($str)
{
	$stmp = $str;
	$len = strlen($stmp);
	$out = "";
	while ($len > 0) {
		if ($len >= 76) {
			$out = $out . substr($stmp, 0, 76) . "\r\n";
			$stmp = substr($stmp, 76);
			$len = $len - 76;
		}
		else {
			$out = $out . $stmp . "\r\n";
			$stmp = ""; $len = 0;
		}
	}
	return $out;
}



/* mime and 8bit decoding and encoding functions for php */
/* by Chuck Hagenbuch <hide@address.com>        */

 function eightbit ($string) {
   if (is_string($string)) {
     for ($i = 0; $i < strlen($string); $i++) {
       if (ord($string[$i])>>7)
 return true;
     }
     return false;
   }
   return false;
 } // eightbit()


 function encode_mime_string ($text, $charset) {
   if (eightbit($text)) {
     if (((strlen($text) * 3) + strlen($charset) + 7) > 76) {
       $text = encode_mime_string(substr($text, 0, (23 -
 strlen($charset))), $charset) . "\r\n\t" .
 encode_mime_string(substr($text, (23 - strlen($charset))), $charset);
     } else {
       $text = "=?$charset?Q?" . strtr(trim(imap_8bit($text)), ' ', '_') . '?=';
     }
   }
   return $text;
 } // encode_mime_string()


 function encode_mime_address ($text, $charset, $defserver) {
   $addr_arr = imap_rfc822_parse_adrlist($text, $defserver);
   $text = '';
   if (is_array($addr_arr) && count($addr_arr) > 0) {
     while (list(,$addr) = each($addr_arr)) {
       if (empty($addr->personal)) $personal = '';
       else $personal = encode_mime_string($addr->personal, $charset);
       if (strlen($text) != 0) $text .= ', ';
       $text .= imap_rfc822_write_address($addr->mailbox, $addr->host, $personal);
     }
   }
   return $text;
 } // encode_mime_address()


 /* Function to decode a MIME-encoded string, returns the original string, if not MIME */
 function decode_mime_string ($string) {
   $pos = strpos($string, '=?');
   if (!is_int($pos)) {
     return $string;
   }
   
   $preceding = substr($string, 0, $pos); // save any preceding text
   
   $search = substr($string, $pos+2, 75); /* the mime header spec says this is the longest a single encoded word can be */
   $d1 = strpos($search, '?');
   if (!is_int($d1)) {
     return $string;
   }
   
   $charset = substr($string, $pos+2, $d1);
   $search = substr($search, $d1+1);
   
   $d2 = strpos($search, '?');
   if (!is_int($d2)) {
     return $string;
   }
   
   $encoding = substr($search, 0, $d2);
   $search = substr($search, $d2+1);
   
   $end = strpos($search, '?=');
   if (!is_int($end)) {
     return $string;
   }
   
   $encoded_text = substr($search, 0, $end);
   $rest = substr($string, (strlen($preceding . $charset . $encoding . $encoded_text)+6));
   
   switch ($encoding) {
   case 'Q':
   case 'q':
     $encoded_text = str_replace('_', '%20', $encoded_text);
     $encoded_text = str_replace('=', '%', $encoded_text);
     $decoded = urldecode($encoded_text);
     
     if (strtolower($charset) == 'windows-1251') {
       $decoded = convert_cyr_string($decoded, 'w', 'k');
     }
     break;
     
   case 'B':
   case 'b':
     $decoded = urldecode(base64_decode($encoded_text));
     
     if (strtolower($charset) == 'windows-1251') {
       $decoded = convert_cyr_string($decoded, 'w', 'k');
     }
     break;
     
   default:
     $decoded = '=?' . $charset . '?' . $encoding . '?' . $encoded_text . '?=';
     break;
   }
   
   return $preceding . $decoded . decode_mime_string($rest);
 } // decode_mime_string()

?>
Return current item: PHPwebmail