PHP Email Topic PHP SMTP class
<?
/***********************************
PHP MIMESMTP ver 1.0 Powered by Boss_ch, Unigenius soft ware co. Ltd
All rights reserved, Copyright 2000 ;
This class uses PHP to send MIME-type emails through smtp sock operation, and can send
HTML format text and attachments, encoded in base64
This version is for individuals. Unlike the multi-common version, each time it is sent to a person, it is re-encoded. In the eyes of the user on the receiving end, it is just sent to him.
For multi-person sending, it is sent only once, and sent to different people's mailboxes through multiple RCPTTO commands.
illustrate:
Please set $hostname as the default smtp server with permissions or specify it when new
Change $charset to your default character set
If there is an image in the Html text, please use the absolute path reference "httP://host/path/";
And connect to the Internet to ensure that the program can read the data information of the picture
If the Html body is submitted through the form, please use StripSlashes ($html_body) to preprocess the content of the text first
Please do not use references like <link> as a stylesheet file used in Html, just put the stylesheet definition directly
In the <style></style> tag
Please keep this copyright information when reprinting. Bugs Report: [email]boss_ch@[/email]
*************************************/
if(!isset($__smtp_class__)){
$__smtp_class__=1;
class smtp
{
var $hostname="";
var $port=25;
var $connection=0;
var $debug=1;
var $timeout=30;
var $err_str;
var $err_no;
var $autocode=true;
var $charset="??????";
var $subject="";
var $body="";
var $attach="";
var $temp_text_body;
var $temp_html_body;
var $temp_body_images;
var $bound_begin="=====powered_by_boss_chen_";
var $bound_end="_046484063883_=====";
Function smtp($server="",$port=25,$time_out=20)
{$this->hostname=$server;
$this->port=$port;
$this->timeout=$time_out;
return true;
}
Function outdebug($message)
{
echo htmlspecialchars($message)."<br>\n";
}
function command($command,$return_lenth=1,$return_code='2')
{
if ($this->connection==0)
{
$this->err_str="Not connected to any server, please check the network connection";
return false;
}
if ($this->debug)
$this->outdebug(">>> $command");
if (!fputs($this->connection,"$command \r\n"))
{
$this->err_str="Cannot send command".$command;
return false;
}
else
{
$resp=fgets($this->connection,256);
if($this->debug)
$this->outdebug("$resp");
if (substr($resp,0,$return_lenth)!=$return_code)
{
$this->err_str=$command." The command server returns invalid: ".$resp;
return false;
}
else
return true;
}
}
Function open()
{
if($this->hostname=="")
{$this->err_str="Invalid hostname!!";
return false;
}
if ($this->debug) echo "$this->hostname,$this->port,&$err_no, &$err_str, $this->timeout<BR>";
if (!$this->connection=fsockopen($this->hostname,$this->port,&$err_no, &$err_str, $this->timeout))
{
$this->err_str="Connect to SMTP server failed, error message: ".$err_str." Error number: ".$err_no;
return false;
}
else
{
$resp=fgets($this->connection,256);
if($this->debug)
$this->outdebug("$resp");
if (substr($resp,0,1)!="2")
{$this->err_str="The server returns invalid information: ".$resp." Please check whether the SMTP server is correct";
return false;
}
return true;
}
}
Function Close()
{
if($this->connection!=0)
{
fclose($this->connection);
$this->connection=0;
}
}
Function Buildhead($from_name,$to_name,$from_mail,$to_mail,$subject)
{
if (empty($from_name))
$from_name=$from_mail;
if (empty($to_name)) $to_name=$to_mail;
$this->subject="From: =?$this->charset?B?".base64_encode($from_name)."?=<$from_mail>\r\n";
$this->subject.="To: =?$this->charset?B?".base64_encode($to_name)."?=<$to_mail>\r\n";
$subject=ereg_replace("\n","",$subject);
$this->subject.="Subject: =?$this->charset?B?".base64_encode($subject)."?=\r\n";
if ($this->debug) echo nl2br(htmlspecialchars($this->subject));
return true;
}
Function parse_html_body($html_body=null)
{
$passed="";
$image_count=0;
$this->temp_body_images=array();
while (eregi("\<*img([^\>]+)src[[:space:]]*=[[:space:]]*([^ ]+)",$html_body,$reg))
{
$pos=@strpos($html_body,$reg[0]);
$passed.=substr($html_body,0,$pos);
$html_body=substr($html_body,$pos+strlen($reg[0]));
$image_tag=$reg[2];
$image_att=$reg[1];
$tag_len=strlen($image_tag);
if ($image_tag[0]=="'" or $image_tag[0]=='"')
$image_tag=substr($image_tag,1);
if (substr($image_tag,strlen($imgage_tag)-1,1)=="'" or substr($image_tag,strlen($imgage_tag)-1,1)=='"')
$image_tag=substr($image_tag,0,strlen($imgage_tag)-1);
//echo $image_tag."<br>";
$cid=md5(uniqid(rand()));
$cid=substr($cid,0,15)."@";
$passed.="<img ".$image_att."src=\"cid:".$cid."\"";
$end_pos=@strpos($html_body,'>');
$passed.=substr($html_body,0,$end_pos);
$html_body=substr($html_body,$end_pos);
// Read out the image data and save it to a data;
$img_file_con=fopen($image_tag,"r");
unset($image_data);
while ($tem_buffer=AddSlashes(fread($img_file_con,16777216)))
$image_data.=$tem_buffer;
fclose($img_file_con);
$image_exe_name=substr($image_tag,strrpos($image_tag,'.')+1,3);
switch (strtolower($image_exe_name))
{
case "jpg":
case "jpeg":
$content_type="image/jpeg";
break;
case "gif":
$content_type="image/gif";
break;
case "png":
$content_type="image/x-png";
break;
case "tif":
$content_type="image/tif";
break;
default:
$content_type="image/";
break;
}
$this->temp_body_images[$image_count][name]=basename($image_tag);
$this->temp_body_images[$image_count][type]=$content_type;
$this->temp_body_images[$image_count][cid]=$cid;
$this->temp_body_images[$image_count][data]=$image_data;
$image_count++;
}
$this->temp_html_body=$passed.$html_body;
return true;
}
function build_content($bound_level=0,$text_body,$html_body,$hava_att=false)
{
if ($html_body)
{
if (eregi("\<*img[[:space:]]+src[[:space:]]*=[[:space:]]*([^ ]+)",$html_body,$reg))
{
$bound_level++;
if ($text_body)
{
$this->body.="Content-Type: multipart/related;
type=\"multipart/alternative\";
\tboundary=\"";
$this->body.=$this->bound_begin.$bound_level.$this->bound_end."\"\r\n\r\n";
}
else
{
$this->body.="Content-Type: multipart/related;
\tboundary=\"";
$this->body.=$this->bound_begin.$bound_level.$this->bound_end."\"\r\n\r\n";
}// For whether text text and html text, there must be different MIME headers
if (!$hava_att) $this->body.="This is a multi-part message in MIME format.\r\n\r\n";
// Text identifier. If it is an encoded with an attachment, this sentence is not needed in the text
$this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."\r\n";
$this->parse_html_body($html_body);
if ($text_body)
{
$this->body.="Content-Type: multipart/alternative;
\tboundary=\"";
$bound_level++;
$this->body.=$this->bound_begin.$bound_level.$this->bound_end."\"\r\n\r\n";
$this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."\r\n";
$this->body.="Content-Type: text/plain;\r\n";
$this->body.="\tcharset=\"$this->charset\"\r\n";
$this->body.="Content-Transfer-Encoding: base64\r\n";
$this->body.="\r\n".chunk_split(base64_encode(StripSlashes($text_body)))."\r\n";
$this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."\r\n";
$this->body.="Content-Type: text/html;\r\n";
$this->body.="\tcharset=\"$this->charset\"\r\n";
$this->body.="Content-Transfer-Encoding: base64\r\n";
$this->body.="\r\n".chunk_split(base64_encode(StripSlashes($this->temp_html_body)))."\r\n";
$this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."--\r\n\r\n";
$bound_level--;
}
else
{
$this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."\r\n";
$this->body.="Content-Type: text/html;\r\n";
$this->body.="\tcharset=\"$this->charset\"\r\n";
$this->body.="Content-Transfer-Encoding: base64\r\n";
$this->body.="\r\n".chunk_split(base64_encode(StripSlashes($this->temp_html_body)))."\r\n";
}//The text code, with or without text parts, is compiled into different formats.
for ($i=0;$i<count($this->temp_body_images);$i++)
{
$this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."\r\n";
$this->body.="Content-Type:".$this->temp_body_images[$i][type].";
name=\"";
$this->body.=$this->temp_body_images[$i][name]."\"\r\n";
$this->body.="Content-Transfer-Encoding: base64\r\n";
$this->body.="Content-ID: <".$this->temp_body_images[$i][cid].">\r\n";
$this->body.="\r\n".chunk_split(base64_encode(StripSlashes($this->temp_body_images[$i][data])))."\r\n";
}
$this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."--\r\n\r\n";
$bound_level--;
}
else // With or without pictures, the above is the processing with pictures, the following is the processing without pictures
{
$this->temp_html_body=$html_body;
if ($text_body)
{
$bound_level++;
$this->body.="Content-Type: multipart/alternative;
\tboundary=\"";
$this->body.=$this->bound_begin.$bound_level.$this->bound_end."\"\r\n\r\n";
if (!$hava_att) $this->body.="\r\nThis is a multi-part message in MIME format.\r\n\r\n";
$this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."\r\n";
$this->body.="Content-Type: text/plain;\r\n";
$this->body.="\tcharset=\"$this->charset\"\r\n";
$this->body.="Content-Transfer-Encoding: base64\r\n";
$this->body.="\r\n".chunk_split(base64_encode(StripSlashes($text_body)))."\r\n";
$this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."\r\n";
$this->body.="Content-Type: text/html;\r\n";
$this->body.="\tcharset=\"$this->charset\"\r\n";
$this->body.="Content-Transfer-Encoding: base64\r\n";
$this->body.="\r\n".chunk_split(base64_encode(StripSlashes($this->temp_html_body)))."\r\n";
$this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."--\r\n\r\n";
$bound_level--;
}
else
{
$this->body.="Content-Type: text/html;\r\n";
$this->body.="\tcharset=\"$this->charset\"\r\n";
$this->body.="Content-Transfer-Encoding: base64\r\n";
$this->body.="\r\n".chunk_split(base64_encode(StripSlashes($this->temp_html_body)))."\r\n";
}//The text code, with or without text parts, is compiled into different formats.
}// end else
}
else // If there is no html text, only text
{
$this->body.="Content-Type: text/plain;
\tcharset=\"$this->charset\"\r\n";
$this->body.="Content-Transfer-Encoding: base64\r\n";
$this->body.="\r\n".chunk_split(base64_encode(StripSlashes($text_body)))."\r\n";
}
}// end function default
Function Buildbody($text_body=null,$html_body=null,$att=null)
{
$this->body="MIME-Version: 1.0\r\n";
if (null==$att or (@count($att)==0)) //If there is no attachment, check the type of the text;
{
$encode_level=0;
$this->build_content($encode_level,$text_body,$html_body);
}// If there is no attachment,
// ********************************************************
else //If there is an attachment,
{
$bound_level=0;
$this->body.="Content-Type: multipart/mixed;
\tboundary=\"";
$bound_level++;
$this->body.=$this->bound_begin.$bound_level.$this->bound_end."\"\r\n\r\n";
$this->body.="This is a multi-part message in MIME format.\r\n\r\n";
$this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."\r\n";
$this->build_content($bound_level,$text_body,$html_body,true);// Include the main part
$num=count($att);
for ($i=0;$i<$num;$i++)
{
$file_name=$att[$i][name];
$file_source=$att[$i][source];
$file_type=$att[$i][type];
$file_size=$att[$i][size];
if (file_exists($file_source))
{
$file_data=addslashes(fread($fp=fopen($file_source,"r"), filesize($file_source)));
$file_data=chunk_split(base64_encode(StripSlashes($file_data)));
$this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."\r\n";
$this->body.="Content-Type: $file_type;\r\n\tname=\"$file_name\"\r\nContent-Transfer-Encoding: base64\r\n";
$this->body.="Content-Disposition: attachment;\r\n\tfilename=\"$file_name\"\r\n\r\n";
$this->body.=$file_data."\r\n";
}
}//end for
$this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."--\r\n\r\n";
}// end else
if ($this->debug) echo nl2br(htmlspecialchars($this->body));
return true;
}
function send($from_name,$to_name,$from_mail,$to_mail,$subject,$text_body=false,$html_body=false,$att=false)
{
if (empty($from_mail) or empty($to_mail))
{
$this->err_str="No correct email address is specified: sender: ".$from_mail." Recipient: ".$to_mail;
return false;
}
if (gettype($to_mail)!="array")
$to_mail=split(",",$to_mail);//If it is not an array, convert it into an array, even if there is only one sending object;
if (gettype($to_name)!="array")
$to_name=split(",",$to_name);//If it is not an array, convert it into an array, even if there is only one sending object;
$this->Buildbody($text_body,$html_body,$att);
// The content of all letters is the same and can be edited only once, but different heads are required for different recipients.
if (!$this->open()) return false;
if (!$this->command("HELO $this->hostname",3,"250")) return false;
// Create a link with the server
if (!$this->open()) return false;
if (!$this->command("HELO $this->hostname",3,"250")) return false;
for ($i=0;$i<count($to_mail);$i++)
{
$this->Buildhead($from_name,$to_name[$i],$from_mail,$to_mail[$i],$subject);
if (!$this->command("RSET",3,"250")) return false;
if (!$this->command("MAIL FROM:".$from_mail,3,"250")) return false;
if (!$this->command("RCPT TO:".$to_mail[$i],3,"250")) return false;
if (!$this->command("DATA",3,"354")) return false;
// Prepare to send emails
if ($this->debug) $this->outdebug("sending subject;");
if (!fputs($this->connection,$this->subject)) {$this->err_str="Error sending the email header!";return false;}
if ($this->debug) $this->outdebug("sending body;");
if (!fputs($this->connection,$this->body)) {$this->err_str="Error sending the body!";return false;}
if (!fputs($this->connection,".\r\n")) {$this->err_str="Error sending the text!"; return false;}//The text is sent and exited;
$resp=fgets($this->connection,256);
if($this->debug)
$this->outdebug("$resp");
if (substr($resp,0,1)!="2")
{
$this->err_str="After sending, the server did not respond!!";
return false;
}
// Send email
}
if (!$this->command("QUIT",3,"221")) return false;
$this->close();
return true;
}
}//end class define
}//end if(!isset($__smtp_class__))
?>
How to use PHP SMTP class
<?
include("");
$mail = new smtp("localhost");
$mail->debug = 0;
$sender_name = "root";
$sender_mail = "root@localhost";
$to_name = "mm";
$to_mail = "[email]mm@[/email]";
$subject = "i miss u";
$content = "i miss u much.";
$att[0]["name"] = "";
$att[0]["source"] = "/path/to/your/";
$att[0]["type"] = "image/jpeg";
$att[0]["size"] = "10kb";
$extra_subject = "To:".$to_mail." Topic:".$subject;
if (!$mail->send($sender_name,$to_name,$sender_mail,$to_mail,$extra_subject,$content,false,$att))
$err = 1;
?>
Return the MIME type function guessMIMEType()
function guessMIMEType($filename) {
//GUESS MIME TYPE
$filename = basename($filename);
if(strrchr($filename,".") == false) {
return("application/octet-stream");
}
$ext = strrchr($filename,".");
switch($ext) {
case ".gif":
return "image/gif";
break;
case ".gz":
return "application/x-gzip";
case ".htm":
case ".html":
return "text/html";
break;
case ".jpg":
return "image/jpeg";
break;
case ".tar":
return "application/x-tar";
break;
case ".txt":
return "text/plain";
break;
case ".zip":
return "application/zip";
break;
default:
return "application/octet-stream";
break;
}
}
Function IsValidEmail() for detecting email address
function IsValidEmail($Email) {
if(!ereg("^[[:alnum:]\_\.]+@([[:alnum:]\_]+\.)+[[:alnum:]][[:alnum:]][[:alnum:]]?$",$Email, $regs)){
$IsValidEmail = false;
}
else
{
$IsValidEmail = true;
}
return $IsValidEmail;
}
A MIME MAIL class, please pay attention to how to construct an email body.
<?
class mime_mail
{
var $parts;
var $to;
var $from;
var $headers;
var $subject;
var $body;
/*
* void mime_mail()
* class constructor
*/
function mime_mail()
{
$this->parts = array();
$this->to = "";
$this->from = "";
$this->subject = "";
$this->body = "";
$this->headers = "";
}
/*
* void add_attachment(string message, [string name], [string ctype])
* Add an attachment to the mail object
*/
function add_attachment($message, $name = "", $ctype = "application/octet-stream")
{
$this->parts[] = array (
"ctype" => $ctype,
"message" => $message,
"encode" => $encode,
"name" => $name
);
}
/*
* void build_message(array part=
* Build message parts of an multipart mail
*/
function build_message($part)
{
$message = $part["message"];
$message = chunk_split(base64_encode($message));
$encoding = "base64";
return "Content-Type: ".$part["ctype"].
($part["name"]?";\n\tname=\"".$part["name"]."\"" : "").
"\nContent-Transfer-Encoding: $encoding".
"\nContent-Disposition: attachment".
($part["name"]?";\n\tfilename=\"".$part["name"]."\"" : "").
"\n\n$message\n";
}
/*
* void build_multipart()
* Build a multipart mail
*/
function build_multipart()
{
$boundary = "b".md5(uniqid(time()));
$multipart = "Content-Type: multipart/mixed;\n\tboundary=\"$boundary\"\n\nThis is a MIME encoded message.\n\n--$boundary";
for($i = sizeof($this->parts)-1; $i >= 0; $i--)
{
$multipart .= "\n".$this->build_message($this->parts[$i])."--$boundary";
}
return $multipart.= "--\n";
}
/*
* void send()
* Send the mail (last class-function to be called)
*/
function send()
{
$addtionheaders = "";
if (!empty($this->from))
$addtionheaders .= "From: ".$this->from."\n";
if (!empty($this->headers))
$addtionheaders .= $this->headers."\n";
if (!empty($this->body))
$this->add_attachment($this->body, "", "text/plain");
$addtionheaders .= "MIME-Version: 1.0\n".$this->build_multipart();
$fp = fopen("","w");
fputs($fp,$addtionheaders);
fclose($fp);
mail($this->to, $this->subject, "", $addtionheaders);
}
}; // end of class
/*
* Example usage
*
$attachment = fread(fopen("", "r"), filesize(""));
$mail = new mime_mail();
$mail->from = "[email]foo@[/email]";
$mail->headers = "Errors-To: [email]foo@[/email]";
$mail->to = "[email]bar@[/email]";
$mail->subject = "Testing...";
$mail->body = "This is just a test.";
$mail->add_attachment("$attachment", "", "image/jpeg");
$mail->send();
*/
?>
myimap class, read email
<?php
//////////////////////////////////////////////
//Origin by (5/21/2000)
//Modified By Belltree <[email]belltree@[/email]> (11/01/2000)
///////////////////////////////////////////////
class myimap
{
var $username="";
var $userpwd="";
var $hostname="";
var $port=0;
var $connection=0; //Is it connected
var $state="DISCONNECTED"; //Connection status
var $greeting="";
var $must_update=0;
var $inStream=0;
var $num_msg_parts = 0;
var $attach;
var $num_of_attach = 0;
function open()
{
if ($this->port==110)
$this->inStream=imap_open("{".$this->hostname."/pop3:110}inbox",$this->username,$this->userpwd);
else
$this->inStream=imap_open("{".$this->hostname.":143}INBOX",$this->username,$this->userpwd);
if ($this->inStream)
{
//echo "User: The mailbox connection of $this->username is successful.<br>";
return $inStream;
}
else
{
echo "User: The mailbox connection for $this->username failed.<br>";
return 0;
}
}
Function close()
{
if(imap_close($this->inStream))
{
//echo "<hr> has been disconnected from server $this->hostname.";
return 1;
}
else
{
//echo "<hr>Failed to disconnect from server $this->hostname.";
return 0;
}
}
function DeleteMail($msg_no){
if (@imap_delete($this->inStream,$msg_no))
return true;
else
return false;
}
function ExpungeMail(){
if (@imap_expunge($this->inStream))
return true;
else
return false;
}
function CheckMailbox($page_size,$page)
{
$mboxinfo=@imap_mailboxmsginfo($this->inStream);
//$mboxinfo=imap_check($this->inStream);
if ($mboxinfo)
if ($mboxinfo->Nmsgs>0)
{
//echo "Your email:".$mboxinfo->Mailbox."<br>";
echo $this->username."@'s inbox has a total number of emails: ".$mboxinfo->Nmsgs."<br>\n";
echo "Number of unread emails:".$mboxinfo->Unread."";
echo "New email count:".$mboxinfo->Recent." ";
echo "Total space occupied:".$mboxinfo->Size."Byte<br>\n";
$last_page = ceil($mboxinfo->Nmsgs/$page_size);
$cur_page = $page +1;
$num_page = $last_page;
echo "Lesson".$cur_page." pages, totaling ".$last_page." pages.\n";
}
else
{
echo "There is no email in your mailbox.<br><hr>\n";
}
else
{
echo '<font color="#ff0000">Error: Unable to get information for your inbox. </font>';
return 0;
}
echo "<table border=1 width=100% cellpadding=2 cellpacing=0 bordercolorlight=#000080 bordercolordark=#ffffff style=\"font:9pt Tahoma,Stick\">\n";
echo "<tr bgcolor=#ffffd8><td width=24>Status</td><td width=24> </td><td>Sender</td><td>Theme</td><td>Time</td><td>Size</td></tr>\n";
$sortby="SORTDATE";
$sort_reverse=1;
$sorted = imap_sort($this->inStream, $sortby, $sort_reverse, SE_UID);
for ($i=0;$i<$mboxinfo->Nmsgs;$i++)
{
if (($i>=$page*$page_size) and ($i<$page*$page_size+$page_size)){
$msg_no = @imap_msgno($this->inStream, $sorted[$i]);
$msgHeader = @imap_header($this->inStream, $msg_no);
//date
if (isset($msgHeader->date))
{
$date = $msgHeader->date;
if (ord($date) > 64)
$date = substr($date, 5);
$datepart = split(" ",$date);
$date = $datepart[0]." ".$datepart[1]." ".$datepart[2]." ".$datepart[3];
/*
while (strstr(' ', $date))
{
$date = str_replace(' ', ' ', $date);
}
*/
}
if (isset($msgHeader->from[0]))
{
$from = $msgHeader->from[0];
if (isset($from->personal))
{
$frm = trim($this->decode_mime_string($from->personal));
if (isset($from->mailbox) && isset($from->host))
{
$frm_add = $from->mailbox . '@' . $from->host;
}
}
else
if (isset($from->mailbox) && isset($from->host))
{
$frm = $from->mailbox . '@' . $from->host;
}
else
if (isset($msgHeader->fromaddress))
$frm = trim($h->fromaddress);
}
else
if (isset($msgHeader->fromaddress))
$frm = trim($msgHeader->fromaddress);
if (isset($msgHeader->toaddress))
$to = trim($msgHeader->toaddress);
else
$to = "Unknown";
if (isset($msgHeader->subject))
$sub = trim($this->decode_mime_string($msgHeader->subject));
if ($sub == "")
$sub = "No topic";
if (isset($msgHeader->Size))
$msg_size = ($msgHeader->Size > 1024) ? sprintf("%.0f kb", $msgHeader->Size / 1024) : $msgHeader->Size;
//if (strlen($frm) > 50)
// $frm = substr($frm, 0, 50) . '...';
if (strlen($sub) > 50)
$sub = substr($sub, 0, 50) . '...';
if ($msgHeader->Unseen == "U")
$newmail = "Unread";
else
$newmail = "read";
echo "<tr>\n";
echo "<td align=center>$newmail</td><td align=\"center\"></td>\n";
echo '<td>'.$frm.'</td><td><a href="mail_read.php?msg='.$msg_no.'">'.$sub.'</a></td><td width=125>'.$date.'</td><td width=50>'.$msg_size.'</td>';
echo "</tr>\n";
}}
echo "</table>\n";
echo "<table border=0 width=100% cellspacing=4 cellpadding=4><tr>\n";
if ($page == 0)
echo "<td>Page 1</td>\n";
else
echo "<td><a href=\"mail_list.php?page=0\">Page 1</a></td>\n";
if (($prev_page = $page-1) < 0)
echo "<td>Previous page</td>\n";
else
echo "<td><a href=\"mail_list.php?page=$prev_page\">Previous page</a></td>\n";
if (($next_page = $page + 1) >= $last_page)
echo "<td>Last Page</td>\n";
else
echo "<td><a href=\"mail_list.php?page=$next_page\">Last page</a></td>\n";
$last_page --;
if ( $last_page < $next_page)
echo "<td>last page</td>\n";
else
echo "<td><a href=\"mail_list.php?page=$last_page\">Last Page</a></td>\n";
echo "</tr></table>\n";
}
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);
break;
case 'B':
case 'b':
$decoded = urldecode(base64_decode($encoded_text));
break;
default:
$decoded = '=?' . $charset . '?' . $encoding . '?' . $encoded_text . '?=';
break;
}
return $preceding . $decoded . $this->decode_mime_string($rest);
}
Function display_toaddress ($user, $server, $from)
{
return is_int(strpos($from, $this->get_barefrom($user, $server)));
}
Function get_barefrom($user, $server)
{
$barefrom = "$user@$real_server";
return $barefrom;
}
Function get_structure($msg_num)
{
$structure=imap_fetchstructure($this->inStream,$msg_num);
//echo gettype($structure);
return $structure;
}
Function proc_structure($msg_part, $part_no, $msg_num)
{
if ($msg_part->ifdisposition)
{
// See if it has a disposition, The only thing I know of that this, would be used for would be an attachment
// Lets check anyway
if ($msg_part->disposition == "attachment")
{
$att_name = "unknown";
for ($lcv = 0; $lcv < count($msg_part->parameters); $lcv++)
{
$param = $msg_part->parameters[$lcv];
if ($param->attribute == "name")
{
$att_name = $param->value;
break;
}
}
$att_name = $this->decode_mime_string($att_name);
$att_path = $this->username."\\".$att_name;
$this->attach[$this->num_of_attach]=$att_name; //Register attachment list
$this->num_of_attach ++; //Register number of attachments
/*
$att_path = $this->username."\\".$this->decode_mime_string($att_name);
if ($this->attach=="")
$this->attach = $att_name;
else
$this->attach .= ";".$att_name;
*/
if (!is_dir($this->username))
mkdir($this->username,0700);
$fp=fopen($att_path,"w");
switch ($msg_part->encoding)
{
case 3: // base64
fputs($fp,imap_base64(imap_fetchbody($this->inStream,$msg_num,$part_no)));
break;
case 4: // QP
fputs($fp,imap_qprint(imap_fetchbody($this->inStream,$msg_num,$part_no)));
break;
default:
fputs($fp,imap_fetchbody($this->inStream,$msg_num,$part_no));
break;
}
fclose($fp);
//if ($msg_part->type=="5"){
// echo "<p align=center><hr align=center>\n";
// echo "<img src=\"$att_path\" align=center></p>\n";
//}
} // END IF ATTACHMENT
else //NOT ifdisposition
{
// I guess it is used for something besides attachments????
}
}
else
{
// Not an attachment, lets see what this part is...
switch ($msg_part->type)
{
case 0:
$mime_type = "text";
break;
case 1:
$mime_type = "multipart";
// Hey, why not use this function to deal with all the parts
// of this multipart part
$this->num_msg_parts = count($msg_part->parts);
for ($i = 0; $i < $this->num_msg_parts; $i++)
{
if ($part_no != "")
{
$part_no = $part_no.".";
}
for ($i = 0; $i < count($msg_part->parts); $i++)
{
$this->proc_structure($msg_part->parts[$i], $part_no.($i + 1), $msg_num);
}
}
break;
case 2:
$mime_type = "message";
break;
case 3:
$mime_type = "application";
break;
case 4:
$mime_type = "audio";
break;
case 5:
$mime_type = "image";
break;
case 6:
$mime_type = "video";
break;
case 7:
$mime_type = "model";
break;
default:
$mime_type = "unknown";
// hmmm....
}
$full_mime_type = $mime_type."/".$msg_part->subtype;
$full_mime_type = strtolower($full_mime_type);
// Decide what you what to do with this part
// If you want to show it, figure out the encoding and echo away
switch ($msg_part->encoding)
{
case 0:
case 1:
if ($this->num_msg_parts == 0){
echo ereg_replace("\r\n","<br>\r\n",imap_body($this->inStream,$msg_num));
}
else{
if ($part_no!=""){
echo ereg_replace("\r\n","<br>\r\n",imap_fetchbody($this->inStream,$msg_num,$part_no));
}
}
break;
case 3: //BASE64
if ($full_mime_type=="text/plain"){
if ($this->num_msg_parts == 0){
$content=imap_base64(imap_body($this->inStream,$msg_num));
}
else{
$content = imap_base64(imap_fetchbody($this->inStream,$msg_num,$part_no));
$att_path = $this->username . "\\Text content.txt";
$fp = fopen($att_path,"w");
fputs($fp,$content);
fclose($fp);
$this->attach[$this->num_of_attach]="Text content.txt";
$this->num_of_attach++;
}
echo $content;
}
if ($full_mime_type=="text/html"){
$att_path = $this->username . "\\Hypertext content.htm";
$fp = fopen($att_path,"w");
fputs($fp,imap_base64(imap_fetchbody($this->inStream,$msg_num,$part_no)));
fclose($fp);
$this->attach[$this->num_of_attach]="Hypertext content.htm";
$this->num_of_attach++;
}
break;
case 4: //QPRINT
// use imap_qprint to decode
if ($this->num_msg_parts == 0){
echo ereg_replace("\n","<br>",imap_qprint(imap_body($this->inStream,$msg_num)));
}
else{
echo ereg_replace("\n","<br>",imap_qprint(imap_fetchbody($this->inStream,$msg_num,$part_no)));
}
if ($full_mime_type=="text/html"){
$att_path = $this->username . "\\qp hypertext content.htm";
$fp = fopen($att_path,"w");
fputs($fp,imap_base64(imap_fetchbody($this->inStream,$msg_num,$part_no)));
fclose($fp);
$this->attach[$this->num_of_attach]="qp hypertext content.htm";
$this->num_of_attach++;
}
break;
case 5:
// not sure if this needs decoding at all
echo ereg_replace("\n","<br>",imap_fetchbody($this->inStream,$msg_num));
break;
default:
//echo ereg_replace("\n","<br>",imap_fetchbody($this->inStream,$msg_num,$part_no));
break;
}
}
}
};
?>
Myimap extension class and examples of reading an email (mail_read.php)
<?
require("");
class myimap_ext extends myimap {
function get_mail_subject($msg_no){
$msgHeader = @imap_header($this->inStream, $msg_no);
if (isset($msgHeader->subject))
$sub = trim($this->decode_mime_string($msgHeader->subject));
if ($sub == "")
$sub = "No topic";
return "Fw:".$sub;
}
function print_attaches(){
for ($i=0;$i<count($this->attach);$i++){
echo "<a target=_blank href=\"".$this->username."\\".$this->attach[$i]."\">".$this->attach[$i]."<br/>";
}
}
function list_attaches(){
for ($i=0;$i<count($this->attach);$i++){
if ($i==0)
$attaches = $this->attach[$i];
else
$attaches .= ";".$this->attach[$i];
}
return $attaches;
}
}
$imap=new myimap_ext;
$imap->hostname="localhost";
$imap->port=143;
$imap->username="name";
$imap->userpwd="password";
$imap->open();
$mail_structure=$imap->get_structure($msg);
$imap->proc_structure($mail_structure,"",$msg);
if ($imap->num_of_attach > 0){
$imap->print_attaches();
}
@$imap->close();
?>
Example of myimap (mail_list.php)
<?
require("");
$imap=new myimap;
$imap->hostname="localhost";
$imap->port=143;
$imap->username="name";
$imap->userpwd="password";
$imap->open();
if ($page=="") $page=0;
$imap->CheckMailBox(10,$page);
@$imap->close();
?>
How to send attachments (redirect)
I often hear the question: "I have a contract from a website. How do I add an attachment to an email sent through a form?"
First of all, I want to say that there is no easy way to do this. You need to understand PHP well or
Other server-side scripting languages. Of course, you also need an account that truly supports PHP website. If this premise is met, you can use PHP to send an email with attachments after you have finished reading this chapter.
1. How the attachment works
If you've ever searched for "attachment" functions in PHP's manual, it might be that there's nothing (at least not yet at the time I've written this article). Later you have to spend a lot of time learning about this.
You might want to send someone an email with an attachment, which is placed in the recipient's mailbox with the email (for example, if you send him/her a PNG image file, his/her mailbox will contain a txt file (e.g., and a .png file (attachment) in his/her mailbox). But that's not how it works. When you add an attachment, your mail program converts the attachment to a plain text file and inserts this text block after what you wrote (the actual email). This, when you send everything out, there is only one plain text file in the recipient's mailbox - a file that contains both the attachment and the actual email content.
Here is an example of an email with an attachment (an HTML file). I've marked the important lines:
Return-Path: <[email]someone@[/email]>
Date: Mon, 22 May 2000 19:17:29 +0000
From: Someone <[email]someone@[/email]>
To: Person <[email]person@[/email]>
Message-id: <[email]83729KI93LI9214@[/email]>
Content-type: multipart/mixed; boundary="396d983d6b89a"
Subject: Here's the subject
--396d983d6b89a
Content-type: text/plain; charset=iso-8859-1
Content-transfer-encoding: 8bit
This is the body of the email.
--396d983d6b89a
Content-type: text/html; name=
Content-disposition: inline; filename=
Content-transfer-encoding: 8bit
<html>
<head>
<title>The attachment</title>
</head>
<body>
<h2>This is the attached HTML file</h2>
</body>
</html>
--396d983d6b89a--
The first 7 lines are the header of the email, and the one that is worth noting is the Content-type header. This header tells the mail program that the email is composed of more than one part. There is only one part of the email without attachments: the message itself. Electronics with attachments usually consist of at least two parts: message and attachment. In this way, a message with two attachments consists of three parts: the message, the first attachment and the second attachment.
The different parts of the email with attachments are separated by a dividing line. The dividing line is defined in the Content-type header. Each new part of the message begins with two hyphens (--) and dividing lines. There are also two hyphens after the last dividing line, indicating that there is no other part of the email.
After each dividing line, there are some lines that tell the mailer the type of content in this part of the content. For example, look at the two lines following the first dividing line in the example above - the line starting with Content-type: text/plain. The following sections of these lines are plain text for the ISO-8859-1 character set. The line following the second dividing line tells the mailer that the current part is an HTML file, whose name is "".
Content-disposition This tells the mailer to display attachments in embedded mode if possible. Now the new mail program will display the HTML content after the message. If Content-disposition is set to attachment, the mail program will not display the contents of the HTML file, but will display an icon (or something like that) connected to the file. To view the content of the attachment, the recipient must click this icon. Generally speaking, if the attachment is some text (including HTML), Content-disposition will be set to inline, because most mail programs can now directly display the content of the attachment (text) without using other browsers. If the attachment is not text (such as an image or other similar content), Content-disposition is set to attachment.
2. Use PHP to generate emails with attachments
Here is an example to tell you if you add a defined HTML file as an attachment to the email:
<?php
# Let's write the actual message first
$emailBody = "This is text that goes into the body of the email.";
# Then we want to be the HTML file as an attachment
$attachment = "<html>
<head>
<title>The attached file</title>
</head>
<body>
<h2>This is the attached HTML file</h2>
</body>
</html>";
# Create a dividing line in the email that separates different parts.
# Basically, the dividing line can be any string.
# But the important thing is to identify someone who writes the email
# This will write a string at will, so we use
# uniqid function to generate a random string.
$boundary = uniqid( "");
# Now we want to create the email header. Don't forget to insert
# Content-type header to indicate that this message contains one or more attachments.
$headers = "From: [email]someone@[/email]
Content-type: multipart/mixed; boundary=\"$boundary\"";
# OK, now we have everything in the email.
# The next thing is to modify the body of the email.
$emailBody = "--$boundary
Content-type: text/plain; charset=iso-8859-1
Content-transfer-encoding: 8bit
$emailBody
--$boundary
Content-type: text/html; name=
Content-disposition: inline; filename=
Content-transfer-encoding: 8bit
$attachment
--$boundary--";
# Now you can send the email
mail( "[email]person@[/email]", "The subject", $emailBody, $headers);
?>
3. Use the file uploaded by the user as an attachment
You may find the above example difficult to understand, but below... In the example below, things are even harder because we have to use a form to let users upload their file and use this file as an attachment to the email we are going to send. The trouble is that we cannot know the MIME type of the file in advance. In the previous example, we already knew that it was an HTML file, so it is very easy to set the Content-type header for this attachment. In the following example, the MIME type may be arbitrary, because the user may upload an HTML file, a PNG file, a vCard file, or something else. Let's take a look at the example:
<?php
# Now let's generate the form. When generating a form that can upload files,
# Don't forget to set the "enctype" property of the <form> tag to "multipart/form-data".
echo "<form action='$PHP_SELF' enctype='multipart/form-data' method='post'>\n";
echo "<input type='text' name='from'><br>\n";
echo "<input type='text' name='to'><br>\n";
echo "<input type='text' name='subject'><br>\n";
echo "<input type='file' name='attachment'><br>\n";
echo "<textarea name='body'></textarea><br>\n";
echo "<input type='submit' name='send' value='Send'>\n";
echo "</form>\n";
# If the user has pressed the "Send" button
if ($send) {
# Define the dividing line
$boundary = uniqid( "");
# Generate email header
$headers = "From: $from
Content-type: multipart/mixed; boundary=\"$boundary\"";
# Determine the MIME type of uploaded file
if ($attachment_type) $mimeType = $attachment_type;
# If the browser does not specify the MIME type of the file,
# We can set it to "application/unknown".
else $mimeType = "application/unknown";
# Determine the file name
$fileName = $attachment_name;
# Open the file
$fp = fopen($attachment, "r");
# Read the entire file into a variable
$read = fread($fp, filesize($attachment));
# OK, now the variable $read saves the text block containing the entire file content.
# Now we want to convert this text block into a format that the mail program can understand.
# We use base64 to encode it
$read = base64_encode($read);
# Now we have a long string encoded with the base64 method.
# The next thing is to cut this long string into small pieces of 76 characters per line
$read = chunk_split($read);
# Now we can create the body of the email
$body = "--$boundary
Content-type: text/plain; charset=iso-8859-1
Content-transfer-encoding: 8bit
$body
--$boundary
Content-type: $mimeType; name=$fileName
Content-disposition: attachment; filename=$fileName
Content-transfer-encoding: base64
$read
--$boundary--";
# Send email
mail($to, $subject, $body, $headers);
}
?>
That's all. If you don't understand the above example well, my suggestion is to send yourself a few emails with attachments and then take a closer look at the source code of the email.