关于奇矩互动奇矩互动招贤纳士奇矩互动优质虚拟主机Discuz!商业用户享有本站VIP服务LAMP环境配置手册(CentOS5.1)
 14 12
发新话题
打印

PHP学习专题--第18期:PHP邮件技术专题

本主题由 aming 于 2008-5-2 17:24 设置高亮

PHP学习专题--第18期:PHP邮件技术专题

随着网络技术的飞速发展,邮件技术已经成为现阶段信息交流的主要手段之一。PHP 实现邮件发送接收的方法有多种,本学习专题将全面介绍PHP发送邮件的方法,从而帮助读者掌握这门技术。

基础篇:

可扩展标识语言(Extensible Markup Language )明显是大多数开发人员将想要将其加入到他们的工具箱中的东西。XML是一种W3C的标准,它是开放的、语言中性的、API中性的、流式的、文本的、人类可读的, 并且是一种将结构化数据带到Web上的一种方法。

电子邮件函数库

mail: 寄出电子邮件。

mail
寄出电子邮件。
语法: boolean mail(string to, string subject, string message, string [additional_headers]);
返回值: 布尔值
函数种类: 网络系统
内容说明: 本函数寄出电子邮件到指定的邮件地址 to,subject 表示主题,message 为信件内容。额外的选项 additional_headers 可省略,表示其它的邮件文件头。
使用范例
复制内容到剪贴板
代码:
<?
$message="abcdefghijklmnopqrstuvwxyz";
mail("php@wilson.gs", "没有主题", $message, "from: someone@wahaha.org.tw\nreply-to: reply@wahaha.org.tw\nx-mailer: php/" . phpversion());

?>

TOP

PHP功能齐全的发送邮件类

下面这个类的功能则很强大,不但能发html格式的邮件,还可以发附件
复制内容到剪贴板
代码:
<?php
class Email {
        // ---设置全局变量
        var $mailTo = ""; // 收件人
        var $mailCC = ""; // 抄送
        var $mailBCC = ""; // 秘密抄送
        var $mailFrom = ""; // 发件人
        var $mailSubject = ""; // 主题
        var $mailText = ""; // 文本格式的信件主体
        var $mailHTML = ""; // html格式的信件主体
        var $mailAttachments = ""; // 附件
        /**
         * 函数setTo($inAddress) :用于处理邮件的地址 参数 $inAddress
         * 为包涵一个或多个字串,email地址变量,使用逗号来分割多个邮件地址
         * 默认返回值为true
         */
        function setTo($inAddress) {
                // --用explode()函数根据”,”对邮件地址进行分割
                $addressArray = explode(",", $inAddress);
                // --通过循环对邮件地址的合法性进行检查
                for($i = 0;$i < count($addressArray);$i++) {
                        if ($this -> checkEmail($addressArray[$i]) == false) return false;
                }
                // --所有合法的email地址存入数组中
                $this -> mailTo = implode($addressArray, ",");
                return true;
        }
        /**
         * 函数 setCC($inAddress) 设置抄送人邮件地址
         * 参数 $inAddress 为包涵一个或多个邮件地址的字串,email地址变量,
         * 使用逗号来分割多个邮件地址 默认返回值为true
         */
        function setCC($inAddress) {
                // --用explode()函数根据”,”对邮件地址进行分割
                $addressArray = explode(",", $inAddress);
                // --通过循环对邮件地址的合法性进行检查
                for($i = 0;$i < count($addressArray);$i++) {
                        if ($this -> checkEmail($addressArray[$i]) == false) return false;
                }
                // --所有合法的email地址存入数组中
                $this -> mailCC = implode($addressArray, ",");
                return true;
        }
        /**
         * 函数setBCC($inAddress) 设置秘密抄送地址 参数 $inAddress 为包涵一个或多
         * 个邮件地址的字串,email地址变量,使用逗号来分割多个邮件地址 默认返回值为
         * true
         */
        function setBCC($inAddress) {
                // --用explode()函数根据”,”对邮件地址进行分割
                $addressArray = explode(",", $inAddress);
                // --通过循环对邮件地址的合法性进行检查
                for($i = 0;$i < count($addressArray);$i++) {
                        if ($this -> checkEmail($addressArray[$i]) == false)
                                return false;
                }
                // --所有合法的email地址存入数组中
                $this -> mailBCC = implode($addressArray, ",");
                return true;
        }
        /**
         * 函数setFrom($inAddress):设置发件人地址 参数 $inAddress 为包涵邮件
         * 地址的字串默认返回值为true
         */
        function setFrom($inAddress) {
                if ($this -> checkEmail($inAddress)) {
                        $this -> mailFrom = $inAddress;
                        return true;
                }
                return false;
        }
        /**
         * 函数 setSubject($inSubject) 用于设置邮件主题参数$inSubject为字串,
         * 默认返回的是true
         */
        function setSubject($inSubject) {
                if (strlen(trim($inSubject)) > 0) {
                        $this -> mailSubject = ereg_replace("n", "", $inSubject);
                        return true;
                }
                return false;
        }
        /**
         * 函数setText($inText) 设置文本格式的邮件主体参数 $inText 为文本内容默
         * 认返回值为true
         */
        function setText($inText) {
                if (strlen(trim($inText)) > 0) {
                        $this -> mailText = $inText;
                        return true;
                }
                return false;
        }
        /**
         * 函数setHTML($inHTML) 设置html格式的邮件主体参数$inHTML为html格式,
         * 默认返回值为true
         */
        function setHTML($inHTML) {
                if (strlen(trim($inHTML)) > 0) {
                        $this -> mailHTML = $inHTML;
                        return true;
                }
                return false;
        }
        /**
         * 函数 setAttachments($inAttachments) 设置邮件的附件 参数$inAttachments
         * 为一个包涵目录的字串,也可以包涵多个文件用逗号进行分割 默认返回值为true
         */
        function setAttachments($inAttachments) {
                if (strlen(trim($inAttachments)) > 0) {
                        $this -> mailAttachments = $inAttachments;
                        return true;
                }
                return false;
        }
        /**
         * 函数 checkEmail($inAddress) :这个函数我们前面已经调用过了,主要就是
         * 用于检查email地址的合法性
         */
        function checkEmail($inAddress) {
                return (ereg("^[^@ ]+@([a-zA-Z0-9-]+.)+([a-zA-Z0-9-]{2}|net|com|gov|mil|org|edu|int)$", $inAddress));
        }
        /**
         * 函数loadTemplate($inFileLocation,$inHash,$inFormat) 读取临时文件并且
         * 替换无用的信息参数$inFileLocation用于定位文件的目录
         * $inHash 由于存储临时的值 $inFormat 由于放置邮件主体
         */
        function loadTemplate($inFileLocation, $inHash, $inFormat) {
                /**
                 * 比如邮件内有如下内容: Dear ~!UserName~,
                 * Your address is ~!UserAddress~
                 */
                // --其中”~!”为起始标志”~”为结束标志
                $templateDelim = "~";
                $templateNameStart = "!";
                // --找出这些地方并把他们替换掉
                $templateLineOut = ""; //--打开临时文件
                if ($templateFile = fopen($inFileLocation, "r")) {
                        while (!feof($templateFile)) {
                                $templateLine = fgets($templateFile, 1000);
                                $templateLineArray = explode($templateDelim, $templateLine);
                                for($i = 0; $i < count($templateLineArray);$i++) {
                                        // --寻找起始位置
                                        if (strcspn($templateLineArray[$i], $templateNameStart) == 0) {
                                                // --替换相应的值
                                                $hashName = substr($templateLineArray[$i], 1);
                                                // --替换相应的值
                                                $templateLineArray[$i] = ereg_replace($hashName, (string)$inHash[$hashName], $hashName);
                                        }
                                }
                                // --输出字符数组并叠加
                                $templateLineOut .= implode($templateLineArray, "");
                        } //--关闭文件fclose($templateFile);
                        // --设置主体格式(文本或html)
                        if (strtoupper($inFormat) == "TEXT")
                                return($this -> setText($templateLineOut));
                        else if (strtoupper($inFormat) == "HTML")
                                return($this -> setHTML($templateLineOut));
                }
                return false;
        }
        /**
         * 函数 getRandomBoundary($offset) 返回一个随机的边界值
         * 参数 $offset 为整数 – 用于多管道的调用 返回一个md5()编码的字串
         */
        function getRandomBoundary($offset = 0) {
                // --随机数生成
                srand(time() + $offset);
                // --返回 md5 编码的32位 字符长度的字串
                return ("----" . (md5(rand())));
        }
        /**
         * 函数: getContentType($inFileName)用于判断附件的类型
         */
        function getContentType($inFileName) {
                // --去除路径
                $inFileName = basename($inFileName);
                // --去除没有扩展名的文件
                if (strrchr($inFileName, ".") == false) {
                        return "application/octet-stream";
                }
                // --提区扩展名并进行判断
                $extension = strrchr($inFileName, ".");
                switch ($extension) {
                        case ".gif": return "image/gif";
                        case ".gz": return "application/x-gzip";
                        case ".htm": return "text/html";
                        case ".html": return "text/html";
                        case ".jpg": return "image/jpeg";
                        case ".tar": return "application/x-tar";
                        case ".txt": return "text/plain";
                        case ".zip": return "application/zip";
                        default: return "application/octet-stream";
                }
                return "application/octet-stream";
        }
        /**
         * 函数formatTextHeader把文本内容加上text的文件头
         */
        function formatTextHeader() {
                $outTextHeader = "";
                $outTextHeader .= "Content-Type: text/plain;
charset=us-asciin";
                $outTextHeader .= "Content-Transfer-Encoding: 7bitnn";
                $outTextHeader .= $this -> mailText . "n";
                return $outTextHeader;
        }
        /**
         * 函数formatHTMLHeader()把邮件主体内容加上html的文件头
         */
        function formatHTMLHeader() {
                $outHTMLHeader = "";
                $outHTMLHeader .= "Content-Type: text/html;
charset=us-asciin";
                $outHTMLHeader .= "Content-Transfer-Encoding: 7bitnn";
                $outHTMLHeader .= $this -> mailHTML . "n";
                return $outHTMLHeader;
        }
        /**
         * 函数 formatAttachmentHeader($inFileLocation) 把邮件中的附件标识出来
         */
        function formatAttachmentHeader($inFileLocation) {
                $outAttachmentHeader = "";
                // --用上面的函数getContentType($inFileLocation)得出附件类型
                $contentType = $this -> getContentType($inFileLocation);
                // --如果附件是文本型则用标准的7位编码
                if (ereg("text", $contentType)) {
                        $outAttachmentHeader .= "Content-Type: " . $contentType . ";n";
                        $outAttachmentHeader .= ' name="' . basename($inFileLocation) . '"' . "n";
                        $outAttachmentHeader .= "Content-Transfer-Encoding: 7bitn";
                        $outAttachmentHeader .= "Content-Disposition: attachment;n";
                        $outAttachmentHeader .= ' filename="' . basename($inFileLocation) . '"' . "nn";
                        $textFile = fopen($inFileLocation, "r");
                        while (!feof($textFile)) {
                                $outAttachmentHeader .= fgets($textFile, 1000);
                        }
                        // --关闭文件 fclose($textFile);
                        $outAttachmentHeader .= "n";
                }
                // --非文本格式则用64位进行编码
                else {
                        $outAttachmentHeader .= "Content-Type: " . $contentType . ";n";
                        $outAttachmentHeader .= ' name="' . basename($inFileLocation) . '"' . "n";
                        $outAttachmentHeader .= "Content-Transfer-Encoding: base64n";
                        $outAttachmentHeader .= "Content-Disposition: attachment;n";
                        $outAttachmentHeader .= ' filename="' . basename($inFileLocation) . '"' . "nn";
                        // --调用外部命令uuencode进行编码
                        exec("uuencode -m $inFileLocation nothing_out", $returnArray);
                        for ($i = 1; $i < (count($returnArray)); $i++) {
                                $outAttachmentHeader .= $returnArray[$i] . "n";
                        }
                }
                return $outAttachmentHeader;
        }
        /**
         * 函数 send()用于发送邮件,发送成功返回值为true
         */
        function send() {
                // --设置邮件头为空
                $mailHeader = "";
                // --添加抄送人
                if ($this -> mailCC != "")
                        $mailHeader .= "CC: " . $this -> mailCC . "n";
                // --添加秘密抄送人
                if ($this -> mailBCC != "")
                        $mailHeader .= "BCC: " . $this -> mailBCC . "n";
                // --添加发件人
                if ($this -> mailFrom != "")
                        $mailHeader .= "FROM: " . $this -> mailFrom . "n";
                // ---------------------------邮件格式------------------------------
                // --文本格式
                if ($this -> mailText != "" && $this -> mailHTML == "" && $this -> mailAttachments == "") {
                        return mail($this -> mailTo, $this -> mailSubject, $this -> mailText, $mailHeader);
                }
                // --html或text格式
                else if ($this -> mailText != "" && $this -> mailHTML != "" && $this -> mailAttachments == "") {
                        $bodyBoundary = $this -> getRandomBoundary();
                        $textHeader = $this -> formatTextHeader();
                        $htmlHeader = $this -> formatHTMLHeader();
                        // --设置 MIME-版本
                        $mailHeader .= "MIME-Version: 1.0n";
                        $mailHeader .= "Content-Type: multipart/alternative;n";
                        $mailHeader .= ' boundary="' . $bodyBoundary . '"';
                        $mailHeader .= "nnn";
                        // --添加邮件主体和边界
                        $mailHeader .= "--" . $bodyBoundary . "n";
                        $mailHeader .= $textHeader;
                        $mailHeader .= "--" . $bodyBoundary . "n";
                        // --添加html标签
                        $mailHeader .= $htmlHeader;
                        $mailHeader .= "n--" . $bodyBoundary . "--";
                        // --发送邮件
                        return mail($this -> mailTo, $this -> mailSubject, "", $mailHeader);
                }
                // --文本加html加附件
                else if ($this -> mailText != "" && $this -> mailHTML != "" && $this -> mailAttachments != "") {
                        $attachmentBoundary = $this -> getRandomBoundary();
                        $mailHeader .= "Content-Type: multipart/mixed;n";
                        $mailHeader .= ' boundary="' . $attachmentBoundary . '"' . "nn";
                        $mailHeader .= "This is a multi-part message in MIME format.n";
                        $mailHeader .= "--" . $attachmentBoundary . "n";
                        $bodyBoundary = $this -> getRandomBoundary(1);
                        $textHeader = $this -> formatTextHeader();
                        $htmlHeader = $this -> formatHTMLHeader();
                        $mailHeader .= "MIME-Version: 1.0n";
                        $mailHeader .= "Content-Type: multipart/alternative;n";
                        $mailHeader .= ' boundary="' . $bodyBoundary . '"';
                        $mailHeader .= "nnn";
                        $mailHeader .= "--" . $bodyBoundary . "n";
                        $mailHeader .= $textHeader;
                        $mailHeader .= "--" . $bodyBoundary . "n";
                        $mailHeader .= $htmlHeader;
                        $mailHeader .= "n--" . $bodyBoundary . "--";
                        // --获取附件值
                        $attachmentArray = explode(",", $this -> mailAttachments);
                        // --根据附件的个数进行循环
                        for($i = 0;$i < count($attachmentArray);$i++) {
                                // --分割 $mailHeader .= "n--".$attachmentBoundary. "n";
                                // --附件信息
                                $mailHeader .= $this -> formatAttachmentHeader($attachmentArray[$i]);
                        }
                        $mailHeader .= "--" . $attachmentBoundary . "--";
                        return mail($this -> mailTo, $this -> mailSubject, "", $mailHeader);
                }
                return false;
        }
}

?>
使用方法:
复制内容到剪贴板
代码:

<?php
Include “email . class”

$mail -> setTo("a@a.com"); //收件人
$mail -> setCC("b@b.com,c@c.com"); //抄送
$mail -> setCC("d@b.com,e@c.com"); //秘密抄送
$mail -> setFrom(“f@f . com”); //发件人
$mail -> setSubject(“主题”) ; //主题
$mail -> setText(“文本格式”) ; //发送文本格式也可以是变量
$mail -> setHTML(“html格式”) ; //发送html格式也可以是变量
$mail -> setAttachments(“c:a . jpg”) ; //添加附件,需表明路径
$mail -> send(); //发送邮件

?>

TOP

IMAP 电子邮件系统函数库

imap 的全名是 internet message access protocol,即网际网络信息存取协议,为美国史丹福大学 (stanford university) 在 1986 年开始研发的多重邮箱电子邮件系统。php 所提供的功能是 imap 4 的系统,这是根据 rfc 1730 所实作的。更多有关 imap 的信息可以参考 imap 的官方网站 http://www.imap.org
欲使用 imap 的电子邮件功能,要先到 ftp://ftp.cac.washington.edu/imap 下载 imap 的客户端程序。在编译完成之后将 c-client/c-client.a 复制到 /usr/local/lib 之中,并将 c-client/rfc822.h、mail.h 及 linkage.h 三个文件复制到 /usr/local/include 之下。之后编译 php 程序时要加入 --with-imap 的选项。


imap_append : 附加字符串到指定的邮箱中。
imap_base64 : 解 base64 编码。
imap_body : 读信的内文。
imap_check : 返回邮箱信息。
imap_close : 关闭 imap 链接。
imap_createmailbox : 建立新的信箱。
imap_delete : 标记欲删除邮件。
imap_deletemailbox : 删除既有信箱。
imap_expunge : 删除已标记的邮件。
imap_fetchbody : 从信件内文取出指定部分。
imap_fetchstructure : 获取某信件的结构信息。
imap_header : 获取某信件的标头信息。
imap_headers : 获取全部信件的标头信息。
imap_listmailbox : 获取邮箱列示。
imap_listsubscribed : 获取订阅邮箱列示。
imap_mail_copy : 复制指定信件到它处邮箱。
imap_mail_move : 移动指定信件到它处邮箱。
imap_num_msg : 取得信件数。
imap_num_recent : 取得新进信件数。
imap_open : 打开 imap 链接。
imap_ping : 检查 imap 是否连接。
imap_renamemailbox : 更改邮箱名字。
imap_reopen : 重开 imap 链接。
imap_subscribe : 订阅邮箱。
imap_undelete : 取消删除邮件标记。
imap_unsubscribe : 取消订阅邮箱。
imap_qprint : 将 qp 编码转成八位。
imap_8bit : 将八位转成 qp 编码。
imap_binary : 将八位转成 base64 编码。
imap_scanmailbox : 寻找信件有无特定字符串。
imap_mailboxmsginfo : 取得目前邮箱的信息。
imap_rfc822_write_address : 电子邮件位址标准化。
imap_rfc822_parse_adrlist : 解析电子邮件位址。
imap_setflag_full : 配置信件标志。
imap_clearflag_full : 清除信件标志。
imap_sort : 将信件标头排序。
imap_fetchheader : 取得原始标头。
imap_uid : 取得信件 uid。
imap_getmailboxes : 取得全部信件详细信息。
imap_getsubscribed : 列出所有订阅邮箱。
imap_msgno : 列出 uid 的连续信件。
imap_search : 搜寻指定标准的信件。
imap_last_error : 最后的错误信息。
imap_errors : 所有的错误信息。
imap_alerts : 所有的警告信息。
imap_status : 目前的状态信息。

imap_append
附加字符串到指定的邮箱中。
语法: int imap_append(int imap_stream, string mbox, string message, string [flags]);
返回值: 整数
函数种类: 网络系统
内容说明: 本函数可在指定的电子邮箱中增加附加的字符串。参数 imap_stream 为 imap 的代号。参数 mbox 为电子邮箱的位址。参数 message 为欲附加的信息。参数 flag 为可省略的标志,表示电子邮箱的标志值。治募注意的是要与 cyrus imap 服务器沟通时,应使用 \r\n 作为行结束字符 (end-of-line, eol)。若有错误则返回 false 值。

imap_base64
解 base64 编码。
语法: string imap_base64(string text);
返回值: 字符串
函数种类: 网络系统
内容说明: 本函数可将用 base64 编码字符串解码。返回值是解码后的字符串。
参考 imap_binary() base64_encode() base64_decode()
imap_body
读信的内文。
语法: string imap_body(int imap_stream, int msg_number, int [flags]);
返回值: 字符串
函数种类: 网络系统
内容说明
本函数可读取信件的内文 (body) 部份。参数 imap_stream 为 imap 的代号。参数 msg_number 为信件的序号。参数 flags 可省略,有下列的值
ft_uid : 信件序号为 uid。
ft_peek : 若无配置 \seen 标志则不要设本标志。
ft_internal : 返回字符串使用系统格式,不要刻意转成 crlf 行结束标准。
使用范例
本例利用 imap 协议读取 myid@localhost 的第一封信件。
<?php
$mbox = imap_open("{localhost:143}inbox","myid","mypw");
$message = imap_body($mbox, 1);
imap_close($mbox);
echo $message;
?>
imap_check
返回邮箱信息。
语法: object imap_check(int imap_stream);
返回值: 类
函数种类: 网络系统
内容说明: 本函数可取得目前电子邮箱的信息。返回值为类类型,包含下面的属性
date最新邮件的日期driver使用的界面mailbox电子邮箱网址nmsgs总邮件数目recent新进邮件数目
类属性代表意义说明
参考 imap_mailboxmsginfo()
imap_close
关闭 imap 链接。
语法: int imap_close(int imap_stream, int [flags]);
返回值: 整数
函数种类: 网络系统
内容说明: 本函数用来关闭 imap 的资料流,亦即结束链接。可省略的参数 flags 的值若为 cl_expunge 则在关闭链接前会将电子邮件信箱清空。
imap_createmailbox
建立新的信箱。
语法: int imap_createmailbox(int imap_stream, string mbox);
返回值: 整数
函数种类: 网络系统
内容说明
本函数用来建立新的信箱。成功则返回 true 值。

[ 本帖最后由 aming 于 2008-5-2 17:13 编辑 ]

TOP

imap_delete
标记欲删除邮件。
语法: int imap_delete(int imap_stream, int msg_number);
返回值: 整数
函数种类: 网络系统
内容说明
本函数仅用来标记欲删除之邮件。实际删除的指令 imap_expunge()
imap_deletemailbox
删除既有信箱。
语法: int imap_deletemailbox(int imap_stream, string mbox);
返回值: 整数
函数种类: 网络系统
内容说明: 本函数用来删除既有的信箱。成功则返回 true 值。
imap_expunge
删除已标记的邮件。
语法: int imap_expunge(int imap_stream);
返回值: 整数
函数种类: 网络系统
内容说明: 本函数用来删除已加入删除标记的邮件。欲标记邮件须使用 imap_delete() 函数。
imap_fetchbody
从信件内文取出指定部分。
语法: string imap_fetchbody(int imap_stream, int msg_number, string part_number, flags [flags]);
返回值: 字符串
函数种类: 网络系统
内容说明: 本函数可读取信件的内文 (body) 部份。参数 imap_stream 为 imap 的代号。参数 msg_number 为信件的序号。参数 part_number 为指定的部分。参数 flags 可省略,有下列的值
ft_uid : 信件序号为 uid。
ft_peek : 若无配置 \seen 标志则不要设本标志。
ft_internal : 返回字符串使用系统格式,不要刻意转成 crlf 行结束标准。
imap_fetchstructure
获取某信件的结构信息。
语法: array imap_fetchstructure(int imap_stream, int msg_number);
返回值: 数组
函数种类: 网络系统
内容说明
本函数可读取指定信件的相关信息。参数 imap_stream 为 imap 的代号。参数 msg_number 为信件的序号。返回的信息为数组的方式,各元素的内容见下表
type整数 (integer)encoding整数 (integer)ifsubtype布尔 (boolean)subtype字符串 (string)ifdescription布尔 (boolean)description字符串 (string)ifid布尔 (boolean)id字符串 (string)lines整数 (integer)bytes整数 (integer)ifparameters布尔 (boolean)
元素名称类型

其中 type 元素的值代表的意义如下 0文字 text1复合 multipart2信息 message3程序 application4声音 audio5图形 image6影像 video7其它 other
代表意义

而 encoding 值代表的意义如下 0七位 (7 bit)1八位 (8 bit)2二进位 (binary)3base64 编码4qp 编码 (quotedprintable)5其它
代表意义


imap_header
获取某信件的标头信息。
语法: object imap_header(int imap_stream, int msg_number, int [fromlength], int [subjectlength], int [defaulthost]);
返回值: 类
函数种类: 网络系统
内容说明: 本函数可读取指定信件的标头信息。 msg_number 为信件的序号。返回类有下列的属性:answered、bcc、bccaddress、cc、ccaddress、date、date、deleted、 fetchfrom、fetchsubject、flagged、followup_to、from、fromaddress、in_reply_to、 maildate、message_id、msgno、newsgroups、recent、references、remail、reply_to、 reply_toaddress、return_path、return_pathaddress、sender、senderaddress、 size、subject、subject、to、toaddress、udate、unseen。
imap_headers
获取全部信件的标头信息。
语法: array imap_headers(int imap_stream);
返回值: 数组
函数种类: 网络系统
内容说明: 本函数可读取全部信件的标头信息。参数 imap_stream 为 imap 的代号。返回的数组一个元素为某一封信的标头。
使用范例
<?php
$mb = imap_open("{my.imap.com.tw}inbox", "wilson", "mypasswd");
$allheaders = imap_headers($mb);
imap_close($mb);
echo "<pre>\n";
for ($i=0; $i < count($allheaders); $i++) {
echo $allheaders[$i]."<p><hr><p>\n";
}
echo "</pre>\n";
?>
imap_listmailbox
获取邮箱列示。
语法: array imap_listmailbox(int stream_id, string ref, string pattern);
返回值: 数组
函数种类: 网络系统
内容说明: 本函数可获得邮箱列示。参数 imap_stream 为 imap 的代号。参数 ref 通常为 imap 服务器名称,参考下例。参数 pattern 可用万用字符 * 代表全部的路径,aayawa@yahoo.com 并指出 (27-apr-1999) 若本参数以 "" (空字符) 代入,不会返回资料。
使用范例
本例为 alank@shermanloan.com 于 02-jun-1999 所提出的。
<?php
$account = "myid";
$password= "mypasswd";
$mailbox = imap_open("{mail.xyz.com:143}inbox", $account, $password);
if ($mailbox) {
$mailboxes = imap_listmailbox($mailbox, "{mail.xyz.com:143}", "*");
for ($index = 0; $index < count($mailboxes); $index++) {
print($mailboxes[$index] . "\n");
}
imap_close($mailbox);
} else {
print("无法?/font>}启 $account 的信箱.\n");
}
?>
imap_listsubscribed
获取订阅邮箱列示。
语法: array imap_listsubscribed(int stream_id, string ref, string pattern);
返回值: 数组
函数种类: 网络系统
内容说明: 本函数可获得订阅邮箱 (subscribed) 列示。参数 imap_stream 为 imap 的代号。参数 ref 通常为 imap 服务器名称。参数 pattern 可用万用字符 * 代表全部的路径。
参考 imap_listmailbox() imap_subscribe() imap_unsubscribe()
imap_mail_copy
复制指定信件到它处邮箱。
语法: int imap_mail_copy(int imap_stream, string msglist, string mbox, int [flags]);
返回值: 整数
函数种类: 网络系统
内容说明: 本函数复制指定的信件到指定的邮箱 (mailbox) 之中。参数 imap_stream 为 imap 的代号。参数 msglist 可以是信件号序,也可以是范围。参数 mbox 为复制的目的邮箱。参数 flags 可省略,有二种选择 cp_uid,cp_move。
imap_mail_move
移动指定信件到它处邮箱。
语法: int imap_mail_move(int imap_stream, string msglist, string mbox);
返回值: 整数
函数种类: 网络系统
内容说明: 本函数移动指定的信件到指定的邮箱 (mailbox) 之中。参数 imap_stream 为 imap 的代号。参数 msglist 可以是信件号序,也可以是范围。参数 mbox 为移动的目的邮箱。
imap_num_msg
取得信件数。
语法: int imap_num_msg(int imap_stream);
返回值: 整数
函数种类: 网络系统
内容说明: 本函数可取得邮箱 (mailbox) 的信件数。参数 imap_stream 为 imap 的代号。
imap_num_recent
取得新进信件数。
语法: int imap_num_recent(int imap_stream);
返回值: 整数
函数种类: 网络系统
内容说明
本函数可取得邮箱 (mailbox) 的新进未读信件数。参数 imap_stream 为 imap 的代号。
imap_open
打开 imap 链接。
语法: int imap_open(string mailbox, string username, string password, int [flags]);
返回值: 整数
函数种类: 网络系统
内容说明: 本函数可打开客户端与服务器之间的 imap 链接,并可链接至 pop3 或 nntp 服务器。参数 mailbox 为服务器端的位置。参数 username 为用户帐号。参数 password 为用户的密码。参数 flags 可省略,有下列的值:
op_readonly : 打开链接使用只读状态。
op_anonymous : 匿名读取 nntp 服务器,不使用 .newsrc 文件。
op_halfopen : 只与 imap 或 nntp 服务器链接,不打开邮箱。
cl_expunge : 关闭链接时自动清除邮箱中的信件。
使用范例
下例分别为打开 imap、pop3、nntp 的部份参考范例
复制内容到剪贴板
代码:
<?php
$mbox = imap_open("{localhost:143}inbox","user_id","password");
?/font>}启与 imap 服务器链接,imap 的埠 (port) 通?/font>`为 143。
$mbox = imap_open("{localhost/pop3:110}inbox","user_id","password");
\\ ?/font>}启与 pop3 服务器链接,pop3 的埠值为 110。
$nntp = imap_open("{localhost/nntp:119}comp.test","","");
\\ ?/font>}启与 nntp 服务器链接,nntp 的埠为 119。
?>

TOP

imap_ping
检查 imap 是否连接。
语法: int imap_ping(int imap_stream);
返回值: 整数
函数种类: 网络系统
内容说明: 本函用来检查与 imap 服务器的连接状态。参数 imap_stream 为 imap 的代号。若仍然保持与 imap 服务器连接则返回 true 值。

imap_renamemailbox
更改邮箱名字。
语法: int imap_renamemailbox(int imap_stream, string old_mbox, string new_mbox);
返回值: 整数
函数种类: 网络系统
内容说明: 本函用来更改邮箱 (mailbox) 的名字。参数 imap_stream 为 imap 的代号。参数 old_mbox 及 new_mbox 分别为原邮箱名字及欲更换成的新邮箱名字。更换成功则返回 true 值。

imap_reopen
重开 imap 链接。
语法: int imap_reopen(string imap_stream, string mailbox, string [flags]);
返回值: 整数
函数种类: 网络系统
内容说明: 本函数可重新打开客户端与服务器之间的 imap 链接。本函数通常与 imap_ping() 函数合用。参数 mailbox 为服务器端的位置。参数 flags 可省略,有下列的值:
op_readonly : 打开链接使用只读状态。
op_anonymous : 匿名读取 nntp 服务器,不使用 .newsrc 文件。
op_halfopen : 只与 imap 或 nntp 服务器链接,不打开邮箱。
cl_expunge : 关闭链接时自动清除邮箱中的信件。
使用范例
复制内容到剪贴板
代码:
<?php
$userid = "nulluser";
$passwd = "passwd38";
$mb = imap_open("(imap.null.org)inbox", $userid, $passwd);
if (!imap_ping($mb)) {
imap_reopen($mb, $userid, $passwd);
}
imap_close($mb);
?>
imap_subscribe
订阅邮箱。
语法: int imap_subscribe(int imap_stream, string mbox);
返回值: 整数
函数种类: 网络系统
内容说明: 本函数可订阅新邮箱 (mailbox)。

imap_undelete
取消删除邮件标记。
语法: int imap_undelete(int imap_stream, int msg_number);
返回值: 整数
函数种类: 网络系统
内容说明
本函数将标记欲删除邮件取消。标记欲删除邮件需使用 imap_delete()。参数 msg_number 代表邮件的流水序号。

imap_unsubscribe
取消订阅邮箱。
语法: int imap_unsubscribe(int imap_stream, string mbox);
返回值: 整数
函数种类: 网络系统
内容说明: 本函数可取消订阅新邮箱 (mailbox)。

imap_qprint
将 qp 编码转成八位。
语法: string imap_qprint(string string);
返回值: 字符串
函数种类: 网络系统
内容说明
本函数可将 qp (quoted-printable) 编码字符串转成八位字符串。
参考 quoted_printable_decode() imap_8bit()

imap_8bit
将八位转成 qp 编码。
语法: string imap_8bit(string string);
返回值: 字符串
函数种类: 网络系统
内容说明: 本函数可将八位字符串转成 qp (quoted-printable) 编码字符串。
参考 quoted_printable_decode() imap_qprint()

imap_binary
将八位转成 base64 编码。
语法: string imap_binary(string string);
返回值: 字符串
函数种类: 网络系统
内容说明: 本函数将字符串转成 mime base64 编码。此编码方式可以让中文字或者图片也能在网络上顺利传输。更多的 base64 编码信息可以参考 rfc2045 文件之 6.8 节或是 base64_encode()。
参考 imap_base64() base64_decode() chunk_split()

imap_scanmailbox
寻找信件有无特定字符串。
语法: array imap_scanmailbox(int imap_stream, string ref, string pattern, string content);
返回值: 数组
函数种类: 网络系统
内容说明: 本函用来检查与 imap 服务器信件中有无特定的字符串。参数 imap_stream 为 imap 的代号。参数 ref 通常为 imap 服务器名称,如 "{mail.wahaha.com:143}"。参数 pattern 为解析比对字符串的规则。参数 content 则为欲寻找的字符串内容。


取得目前邮箱的信息。
语法: object imap_mailboxmsginfo(int imap_stream);
返回值: 类
函数种类: 网络系统
内容说明: 本函用来取得目前使用中邮箱 (mailbox) 的相关信息。参数 imap_stream 为 imap 的代号。返回类包括下列的属性 date最新邮件的日期driver使用的界面mailbox电子邮箱网址nmsgs总邮件数目recent新进邮件数目unread未读邮件数目size邮箱大小 类属性 代表意义说明
参考:imap_check

imap_rfc822_write_address
电子邮件位址标准化。
语法: string imap_rfc822_write_address(string mailbox, string host, string personal);
返回值: 字符串
函数种类: 网络系统
内容说明: 本函数将电子邮件位址成为 rfc822 的标准格式。

imap_rfc822_parse_adrlist
解析电子邮件位址。
语法: object imap_rfc822_parse_adrlist(string address, string default_host);
返回值: 类
函数种类: 网络系统
内容说明: 本函数可解析电子邮件位址。返回的类包括下列属性 mailbox用户名称host服务器名称personal个人名字adl所在来源绕路 属性名 说明


imap_setflag_full
配置信件标志。
语法: int imap_setflag_full(int imap_stream, string sequence, string flag, int [options]);
返回值: 整数
函数种类: 网络系统
内容说明: 本函数可指定连续信件而配置标志。参数 imap_stream 为 imap 的代号。参数 sequence 为特定的部分序号。参数 flag 为欲配置的标志值,包括 seen、answered、flagged、deleted、draft 及 recent。参数 options 可省略,可为 st_uid。

imap_clearflag_full
清除信件标志。
语法: imap_clearflag_full(int imap_stream, string sequence, string flag, int [options]);
返回值: 无
函数种类: 网络系统
内容说明: 本函数可指定连续信件而清除标志。参数 imap_stream 为 imap 的代号。参数 sequence 为特定的部分序号。参数 flag 为欲配置的标志值,包括 seen、answered、flagged、deleted、draft 及 recent。参数 options 可省略,可为 st_uid。

imap_sort
将信件标头排序。
语法: array imap_sort(int imap_stream, int criteria, int reverse, int [options]);
返回值: 数组
函数种类: 网络系统
内容说明
本函数将信件标头排序。参数 imap_stream 为 imap 的代号。参数 criteria 的意义见下表,并只能是下表的其中一项 mailbox用户名称host服务器名称personal个人名字adl所在来源绕路 属性名 说明


参数 reverse 值为 0 时表由小到大排序,若值为 1 表由大到小排序。参数 options 可省略,有下列的值: se_uid 与 se_noprefetch。

imap_fetchheader
取得原始标头。
语法: string imap_fetchheader(int imap_stream, int msg_no, int [options]);
返回值: 字符串
函数种类: 网络系统
内容说明: 本函数将信件标头排序。参数 imap_stream 为 imap 的代号。参数 msg_no 为信件序号。参数 options 可省略,其值有下列数种
ft_uid : 信件序号为 uid。
ft_internal : 返回字符串使用系统格式,不要刻意转成 crlf 行结束标准。
ft_prefetchtext : 去掉额外的 rtt。

imap_uid
取得信件 uid。
语法: string imap_uid(string mailbox, int msgno);
返回值: 字符串
函数种类: 网络系统
内容说明: 本函数可取得指定信件的 uid。参数 mailbox 为邮箱名。参数 msgno 为信件序号。

imap_getmailboxes
取得全部信件详细信息。
语法: object imap_getmailboxes(int imap_stream, string ref, string pattern);
返回值: 类
函数种类: 网络系统
内容说明: 本函用来检查 imap 服务器信件的详细信息。参数 imap_stream 为 imap 的代号。参数 ref 通常为 imap 服务器名称,如 "{mail.wahaha.com:143}"。参数 pattern 为解析比对字符串的规则。

imap_getsubscribed
列出所有订阅邮箱。
语法: array imap_getsubscribed(int imap_stream, string ref, string pattern);
返回值: 数组
函数种类: 网络系统
内容说明: 本函用来列示出所有订阅 imap 服务器信箱 (mailbox)。参数 imap_stream 为 imap 的代号。参数 ref 通常为 imap 服务器名称,如 "{mail.wahaha.com:143}"。参数 pattern 为解析比对字符串的规则。

imap_msgno
列出 uid 的连续信件。
语法: int imap_msgno(int imap_stream, int uid);
返回值: 整数
函数种类: 网络系统
内容说明: 本函用来列示指定 uid 的连续信件。参数 imap_stream 为 imap 的代号。参数 uid 为用户代号。
搜寻指定标准的信件。
语法: array imap_search(int imap_stream, string criteria, int flags);
返回值: 数组
函数种类: 网络系统
内容说明: 本函用来搜寻合乎指定条件的信件。参数 imap_stream 为 imap 的代号。参数 criteria 为指定的条件,各字段以空格 (space) 分开,条件见下表。参数 flags 为 se_uid。 all返回所有合乎标准的信件answered信件有配置 \\answered 标志者bcc "字符串"bcc 栏中有指定 "字符串" 的信件before "日期"指定 "日期" 以前的信件body "字符串"内文字段中有指定 "字符串" 的信件cc "字符串"cc 栏中有指定 "字符串" 的信件deleted合乎已删除的信件flagged信件有配置 \\flagged 标志者from "字符串"from 栏中有指定 "字符串" 的信件keyword "字符串"关键字为指定 "字符串" 者new新的信件old旧的信件on "日期"指定 "日期" 的信件recent信件有配置 \\recent 标志者seen信件有配置 \\seen 标志者since "日期"指定 "日期" 之后的信件subject "字符串"subject 栏中有指定 "字符串" 的信件text "字符串"text 栏中有指定 "字符串" 的信件to "字符串"to 栏中有指定 "字符串" 的信件unanswered未回应的信件undeleted未删除的信件unflagged未配置标志的信件unkeyword "字符串"未配置关键 "字符串" 的信件unseen未读取的信件 条件 说明


imap_last_error
最后的错误信息。
语法: string imap_last_error(void);
返回值: 字符串
函数种类: 网络系统
内容说明: 本函数用来显示最后出现的 imap 错误字符串。本函数不需要使用任何参数。

imap_errors
所有的错误信息。
语法: array imap_errors(void);
返回值: 数组
函数种类: 网络系统
内容说明: 本函数用来显示所有出现的 imap 错误字符串。本函数不需要使用任何参数。

imap_alerts
所有的警告信息。
语法: array imap_alerts(void);
返回值: 数组
函数种类: 网络系统
内容说明: 本函数用来显示所有出现的 imap 警告字符串。本函数不需要使用任何参数。

imap_status
目前的状态信息。
语法: object imap_status(int imap_stream, string mailbox, int options);
返回值: 类
函数种类: 网络系统
内容说明: 本函数用来显示目前 imap 的状态信息。参数 imap_stream 为 imap 的代号。参数 mailbox 为指定的邮箱。参数 options 有下面的选择:sa_messages、sa_recent、sa_unseen、sa_uidnext、sa_uidvalidity 与 sa_all。

TOP

PHP中用Socket发送电子邮件

在作者所申请的几个PHP 主页空间中,能够提供mail功能的实在不多,总是调用完mail()函数之后就毫
无下文了。但是电子邮件在网上生活中的作用越来越大作用我不想再说了,但是如果主页空间不支持mail()发送那么怎么办呢?我也想过通过socket来实现邮件  

发送,但无奈对用php 进行socket编程不熟悉,再加上发送邮件要用到SMTP协议,又要读不少的英文了,所
以一直也没有去研究过。终于有一天我发现了一篇文章,关于用socket编程发送邮件。我如获至宝般将其拷
贝下来,并且将其改造成了一个php 可用的类,供大家使用。原来的文章只是一个简单的例子,而且还有一
些错误,在我经过多次的实验、改造终于将其改成了一个直接使用socket,向指定的邮箱发送邮件的类,如
果大家和前面关于发送MIME的文章结合起来,就可以实现在不支持mail()函数的网站上发送邮件了。因为发
送邮件的过程需要时间,可能与mail()的处理机制还不完全一样,所以速度要慢一些,但是可以解决需要发
送邮件功能的燃眉之急,同时你也可以学习用php 进行socket编程。下面就将这个类的实现原理介绍给大家,
同时向大家讲解一些关于SMTP的基本知识。

Socket编程介绍
  向大家申明,本人不是一个TCP/IP编程专家,故在此只是讲出了我的一点理解和体会。

  使用fsockopen函数打开一个Internet连接,函数语法格式:

int fsockopen(string hostname, int port, int [errno], string [errstr], int [timeout]);

  参数的意思我想不用讲了,这里由于要使用SMTP协议,所以端口号为25。在打开连接成功后,会返回一
个socket句柄,使用它就可以象使用文件句柄一样的。可使用的操作有fputs(),fgets(),feof(),fclose()
等。

  很简单地介绍就到这里吧。

SMTP的基础
  基于TCP/IP的因特网协议一般的命令格式都是通过请求/ 应答方式实现的,采用的都是文本信息,所以
处理起来要容易一些。SMTP是简单邮件传输协议的简称,它可以实现客户端向服务器发送邮件的功能。所以
下面所讲的命令是指客户端向服务器发出请求指令,而响应则是指服务器返回给客户端的信息。

  SMTP分为命令头和信息体两部分。命令头主要完成客户端与服务器的连接,验证等。整个过程由多条命
令组成。每个命令发到服务器后,由服务器给出响应信息,一般为3 位数字的响应码和响应文本。不同的服
务器返回的响应码是遵守协议的,但是响应正文本则不必。每个命令及响应的最后都有一个回车符,这样使
用fputs()和fgets()就可以进行命令与响应的处理了。SMTP的命令及响应信息都是单行的。信息体蚴怯始?
的正文部分,最后的结束行应以单独的"."作为结束行。

  客户端一些常用的SMTP指令为:

HELO hostname: 与服务器打招呼并告知客户端使用的机器名字,可以随便填写
MAIL FROM: sender_id : 告诉服务器发信人的地址
RCPT TO: receiver_id : 告诉服务器收信人的地址
DATA : 下面开始传输信件内容,且最后要以只含有.的特殊行结束
RESET: 取消刚才的指令,从新开始
VERIFY userid: 校验帐号是否存在(此指令为可选指令,服务器可能不支持)
QUIT : 退出连接,结束
  服务器返回的响应信息为(格式为:响应码+空格+解释):

220 服务就绪(在socket连接成功时,会返回此信息)
221 正在处理
250 请求邮件动作正确,完成(HELO,MAIL FROM,RCPT TO,QUIT指令执行成功会返回此信息)
354 开始发送数据,结束以 .(DATA指令执行成功会返回此信息,客户端应发送信息)
500 语法错误,命令不能识别
550 命令不能执行,邮箱无效
552 中断处理:用户超出文件空间
  下面给出一个简单的命令头(这是在打开socket之后做的),是我向stmp.263.net发邮件的测试结果:

HELO limodou
250 smtp.263.net
MAIL FROM: chatme@263.net
250 Ok
RCPT TO: chatme@263.net
250 Ok
DATA
354 End data with .
To: chatme@263.net
From: chatme@263.net
Subject: test
From: chatme@263.net
test
.
QUIT
250 Ok: queued as C46411C5097E0

  这就是一些SMTP的简单知识。相关内容可以查阅RFC。

RFC 821定义了收/发电子邮件的相关指令。
RFC 822则制定了邮件?容的格式。
RFC 2045-2048制定了多媒体邮件?容的格式,
RFC 1113, 1422-1424则是讨论如何增进电子邮件的保密性。

send_mail类的实现
  现在开始介绍我所编写的发送邮件类。有了上面的预备知识了,下面就是实现了。

类的成员变量

var $lastmessage; //记录最后返回的响应信息
var $lastact; //最后的动作,字符串形式
var $welcome; //用在HELO后面,欢迎用户
var $debug; //是否显示调试信息
var $smtp; //smtp服务器
var $port; //smtp端口号
var $fp; //socket句柄

  其中,$lastmessage和$lastact用于记录最后一次响应信息及执行的命令,当出错时,用户可以使用它
们。为了测试需要,我还定义了$debug变量,当其值为true时,会在运行过程中显示一些执行信息,否则无
任何输出。$fp用于保存打开后的socket句柄。

类的构造


--------------------------------------------------------------------------------
function send_mail($smtp, $welcome="", $debug=false)
{
if(empty($smtp)) die("SMTP cannt be NULL!");
$this->smtp=$smtp;
if(empty($welcome))
{
$this->welcome=gethostbyaddr("localhost");
}
else
$this->welcome=$welcome;
$this->debug=$debug;
$this->lastmessage="";
$this->lastact="";
$this->port="25";
}
--------------------------------------------------------------------------------
  这个构造函数主要完成一些初始值的判定及设置。$welcome用于HELO指令中,告诉服务器用户的名字。
HELO指令要求为机器名,但是不用也可以。如果用户没有给出$welcome,则自动查找本地的机器名。

显示调试信息

--------------------------------------------------------------------------------
1 function show_debug($message, $inout)
2 {
3 if ($this->debug)
4 {
5 if($inout=="in") //响应信息
6 {
7 $m='<< ';
8 }
9 else
10 $m='>> ';
11 if(!ereg("\n$", $message))
12 $message .= "<br>";
13 $message=nl2br($message);
14 echo "<font color=#999999>${m}${message}</font>";
15 }
16 }
--------------------------------------------------------------------------------
  这个函数用来显示调试信息。可以在$inout中指定是上传的指令还是返回的响应,如果为上传指令,则
使用"out";如果为返回的响应则使用"in"。

第3行,判断是否要输出调试信息。
第5行,判断是否为响应信息,如果是,则在第7行将信息的前面加上"<< "来区别信息;否则在第10行加上
    ">> "来区别上传指令。
第11-12行,判断信息串最后是否为换行符,如不是则加上HTML换行标记。第13行将所以的换行符转成HTML
的换行标记。
第14行,输出整条信息,同时将信息颜色置为灰色以示区别。

执行一个命令


--------------------------------------------------------------------------------
1 function do_command($command, $code)
2 {
3 $this->lastact=$command;
4 $this->show_debug($this->lastact, "out");
5 fputs ( $this->fp, $this->lastact );
6 $this->lastmessage = fgets ( $this->fp, 512 );
7 $this->show_debug($this->lastmessage, "in");
8 if(!ereg("^$code", $this->lastmessage))
9 {
10 return false;
11 }
12 else
13 return true;
14 }
--------------------------------------------------------------------------------
  在编写socket处理部分发现,一些命令的处理很相似,如HELO,MAIL FROM,RCPT TO,QUIT,DATA命令,
都要求根据是否显示调试信息将相关内容显示出来,同时对于返回的响应码,如果是期望的,则应继续处理,
如果不是期望的,则应中断出理。所以为了清晰与简化,专门对这些命令的处理编写了一个通用处理函数。
函数的参数中$code为期望的响应码,如果响应码与之相同则表示处理成功,否则出错。

第3行,记录最后执行命令。
第4行,将上传命令显示出来。
第5行,则使用fputs真正向服务器传换指令。
第6行,从服务器接收响应信息将放在最后响应消息变量中。
第7行,将响应信息显示出来。
第8行,判断响应信息是否期待的,如果是则第13行返回成功(true),否则在第10行返回失败(false)。

  这样,这个函数一方面完成指令及信息的发送显示功能,别一方面对返回的响应判断是否成功。

邮件发送处理

  下面是真正的秘密了,可要看仔细了。

--------------------------------------------------------------------------------
1 function send( $to,$from,$subject,$message)
2 {
3
4 //连接服务器
5 $this->lastact="connect";
6
7 $this->show_debug("Connect to SMTP server : ".$this->smtp, "out");
8 $this->fp = fsockopen ( $this->smtp, $this->port );
9 if ( $this->fp )
10 {
11
12 set_socket_blocking( $this->fp, true );
13 $this->lastmessage=fgets($this->fp,512);
14 $this->show_debug($this->lastmessage, "in");
15
16 if (! ereg ( "^220", $this->lastmessage ) )
17 {
18 return false;
19 }
20 else
21 {
22 $this->lastact="HELO " . $this->welcome . "\n";
23 if(!$this->do_command($this->lastact, "250"))
24 {
25 fclose($this->fp);
26 return false;
27 }
28
29 $this->lastact="MAIL FROM: $from" . "\n";
30 if(!$this->do_command($this->lastact, "250"))
31 {
32 fclose($this->fp);
33 return false;
34 }
35
36 $this->lastact="RCPT TO: $to" . "\n";
37 if(!$this->do_command($this->lastact, "250"))
38 {
39 fclose($this->fp);
40 return false;
41 }
42
43 //发送正文
44 $this->lastact="DATA\n";
45 if(!$this->do_command($this->lastact, "354"))
46 {
47 fclose($this->fp);
48 return false;
49 }
50
51 //处理Subject头
52 $head="Subject: $subject\n";
53 if(!empty($subject) && !ereg($head, $message))
54 {
55 $message = $head.$message;
56 }
57
58 //处理From头
59 $head="From: $from\n";
60 if(!empty($from) && !ereg($head, $message))
61 {
62 $message = $head.$message;
63 }
64
65 //处理To头
66 $head="To: $to\n";
67 if(!empty($to) && !ereg($head, $message))
68 {
69 $message = $head.$message;
70 }
71
72 //加上结束串
73 if(!ereg("\n\.\n", $message))
74 $message .= "\n.\n";
75 $this->show_debug($message, "out");
76 fputs($this->fp, $message);
77
78 $this->lastact="QUIT\n";
79 if(!$this->do_command($this->lastact, "250"))
80 {
81 fclose($this->fp);
82 return false;
83 }
84 }
85 return true;
86 }
87 else
88 {
89 $this->show_debug("Connect failed!", "in");
90 return false;
91 }
92 }
--------------------------------------------------------------------------------
  有些意思很清楚的我就不说了。

  这个函数一共有四个参数,分别是$to表示收信人,$from表示发信人,$subject表求邮件主题和$message
表示邮件体。如果处理成功则返回true,失败则返回false。

第8行,连接邮件服务器,如果成功响应码应为220。
第12行,设置阻塞模式,表示信息必须返回才能继续。详细说明看手册吧。
第16行,判断响应码是否为220,如果是,则继续处理,否则出错返回。
第22-27行,处理HELO指令,期望响应码为250。
第29-34行,处理MAIL FROM指令,期望响应码为250。
第36-41行,处理RCPT TO指令,期望响应码为250。
第44-49行,处理DATA指令,期望响应码为354。
第51-76行,生成邮件体,并发送。
第52-56行,如果$subject不为空,则查找邮件体中是否有主题部分,如果没有,则加上主题部分。
第59-63行,如果$from不为空,则查找邮件体中是否有发信人部分,如果没有,则加上发信人部分。
第66-70行,如果$to不为空,则查找邮件体中是否有收信人部分,如果没有,则加上收信人部分。
第73-74行,查找邮件体是否有了结束行,如果没有则加上邮件体的结束行(以"."作为单独的一行的特殊行)。
第76行,发送邮件体。
第78-83行,执行QUIT结否与服务器的连接,期望响应码为250。
第85行,返回处理成功标志(true)。
第81-91行,与服务器连接失败的处理。

  以上为整个send_mail类的实现,应该不是很难的。下面给出一个实例。

邮件发送实例
  先给出一个最简单的实例:
--------------------------------------------------------------------------------
<?
1 include "sendmail.class.php3";
2 $email="Hello, this is a test letter!";
3 $sendmail=new send_mail("smtp.263.net", "limodou", true); //显示调示信息
4 if($sendmail->send("chatme@263.net", "chatme@263.net", "test", $email))
5 {
6 echo "发送成功!<br>";
7 }
8 else
9 {
10 echo "发送失败!<br>";
11 }
?>
--------------------------------------------------------------------------------
第1行,装入send_mail类。
第3行,创建一个类的实例,且设置显示调示信息,如果不想显示,可以
    $sendmail=new send_mail("smtp.263.net");。
第4行,发送邮件。


很简单,不是吗?下面再给合以前的发送MIME邮件的例子,给出一个发送HTML附件的例子。

--------------------------------------------------------------------------------
<?php

include "MIME.class.php3";
//注,在发送MIME邮件一文中,这个类文件名为MIME.class,在此处我改成这样的

$to = 'chatme@263.net'; //改为收信人的邮箱
$str = "Newsletter for ".date('M Y', time());

//信息被我改少了
$html_data = '<html><head><title>'. $str. '</title></head>
<body bgcolor="#ffffff">
Hello! This is a test!
</body>
</html>';

//生成MIME类实例
$mime = new MIME_mail("chatme@263.net", $to, $str);

//添加HTML附件
$mime->attach($html_data, "", HTML, BASE64);

//注释掉,采用我的发送邮件处理
//$mime->send_mail();

//生成邮件
$mime->gen_email();

//显示邮件信息
//echo $mime->email."<br>";

//包含sendmail文件
include "sendmail.class.php3";

//创建实例
$sendmail=new send_mail("smtp.263.net", "limodou", true);

//发送邮件
$sendmail->send("chatme@263.net", "chatme@263.net", $str, $mime->email);

?>

TOP

NT下基于邮件服务软件(IMAIL)的发送程序

如果你无法在服务器上安装IMAIL,那只能通过socket来发送邮件。但是如果你幸运的话,也可以用163/sina的

smtp服务。

例程如下(原程序由马毅兄提供):
<HTML>
<HEAD>
<TITLE>Mail Form anywhere </TITLE>
</HEAD>
<BODY>
<?
if($sendit)
{
$smtpserver="202.110.200.242" ;        //将此处设为IMAIL的IP
echo "<pre>" ;
$fp = fsockopen($smtpserver, 25, &$errno, &$errstr, 10) ; //连接smtp服务器,端口25
if(!$fp) die("wrong open smtp SERVER") ;
$hostreplay=fgets($fp,128);
//if (!strstr($hostreplay,"220")) die(" can n't receive the 220 answer ") ;
$smailname=strstr(ltrim($hostreplay),"220 ") ;
$smailname=substr($smailname,0,strpos($smailname,".")) ;
//echo "\nsmailnamesmailname\n" ;
fputs($fp,"$smailname \n") ;
$hostreplay=fgets($fp,128);
//if (!strstr($hostreplay,"250")) die(" can n't receive the 250 answer ") ;

fputs($fp,"MAIL FROM: \n") ;
$hostreplay=fgets($fp,128) ;
if (!strstr($hostreplay,"250")) {
fputs($fp,"MAIL FROM: root\n") ;
$hostreplay=fgets($fp,128) ;
if (!strstr($hostreplay,"250")) {
fputs($fp,"MAIL FROM: root@263.net\n") ;
echo($hostreplay=fgets($fp,128)) ;
if (!strstr($hostreplay,"250")) {
fputs($fp,"MAIL FROM: $from_address\n") ;
$hostreplay=fgets($fp,128) ;
if (!strstr($hostreplay,"250")) die(" can n't receive the 250 answer ") ;
};
};
};
fputs($fp,"RCPT TO: $to_address\n") ;
$hostreplay=fgets($fp,128);
if (!strstr($hostreplay,"250")) {
fputs($fp,"RCPT TO: $mailname\n") ;
$hostreplay=fgets($fp,128) ;
if (!strstr($hostreplay,"250")) echo(" can n't receive the 354 answer") ;
};
fputs($fp,"DATA\n") ;
$hostreplay=fgets($fp,128) ;
if (!strstr($hostreplay,"354")) die(" can n't receive the 250 answer ") ;
$tosend="From: $from_address\n";
$tosend.="To: $to_address\n";
$tosend.="Subject:".str_replace("\N"," ",$subject)."\n你好,这是yukuang发给您的一封测试信!!

\n.\n";
fputs($fp,$tosend) ;
$hostreplay=fgets($fp,128) ;
if (!strstr($hostreplay,"250")) die(" can n't receive the 250 answer ") ;
fputs($fp,"QUIT\n") ;
fclose($fp) ;
echo "发送成功";
exit();
//if($ck_name!='root') die("</pre><hr>bye bye ");

};

?>

<br>
<FORM METHOD="OST" ACTION=" <? echo $PHP_SELF; ?>" >
<table width="73%" border="1" align="center">
<tr>
<td colspan="5">
<div align="center">cn-bbs web meil </div>
</td>
</tr>
<tr>
<td width="9%">from<br>
</td>
<td width="36%">
<input type="text" name="from_address" size="30" maxlength="40"
value="">
</td>
<td width="6%">to </td>
<td colspan="2" width="49%">
<input type="text" name="to_address" size="40" maxlength="40"
value="">
</td>
</tr>
<tr>
<td width="9%">subject</td>
<td colspan="4">
<input type="text" name="subject" size="80" maxlength="200" value=" ">
</td>
</tr>
<tr>
<td rowspan="5" width="9%">c<br>
o<br>
n<br>
t<br>
e<br>
n<br>
t</td>
<td colspan="4" rowspan="5">
<div align="center">
<textarea name="message" cols="80" rows="16"> </textarea>
</div>
</td>
</tr>
<tr> </tr>
<tr> </tr>
<tr> </tr>
<tr> </tr>
<tr>
<td colspan="5" height="2">
<div align="center">
<select name="smtpserver">
<option value="smtp.21cn.com" selected>21cn.net</option>
<option value="smtp.163.net">163.com</option>
<option value="smtp.263.net">263.com</option>
<option value="server0026.freedom2surf.net">server0026.freedom2surf.net</option>
<option value="www.cnbbs.f2s.com" >www.cnbbs.f2s.com</option>
</select>
<input type=submit value ="ok . send" name="sendit">
<input type=reset value ="Reset " name="reset">
<input type="button" name="back" value="cancle" onclick=history.back()>
</div>
</td>
</tr>
</table>
<br>
</FORM>
</BODY>
</html>

TOP

应用篇:

可扩展标识语言(Extensible Markup Language )明显是大多数开发人员将想要将其加入到他们的工具箱中的东西。XML是一种W3C的标准,它是开放的、语言中性的、API中性的、流式的、文本的、人类可读的, 并且是一种将结构化数据带到Web上的一种方法。

如何用PHP发电子邮件(一)

一个发送E-MAIL的脚本也许是你能够在Web 站点上找到的最普通的脚本之一了,虽然它很简单,一个邮件脚本有时会令程序员非常沮丧.PHP中有一个叫做mail()的函数,它只需要知道接收方的地址和信件主体就可以发送邮件,但是要让mail()按你的意思运行你还需要解决一些棘手的问题.

要使mail()能够运行,你必须有一个SMTP服务器以便PHP能够连接上去.不管这个服务器对邮件程序多么重要,大多数人对它如何运转没有一星半点的概念.在本教程中,我们将揭示SMTP的秘密并解决一些使用PHP发送邮件的常见问题.而本文中的另一些主题将包括循环遍历一个地址列表的方法以及同时以文本和HTML格式向接收者发送一个邮件的方法.

SMTP是简单邮件传输协议(Simple Mail Transfer Protocol)的缩写,而一个SMTP服务器是一台运行这种协议并发出邮件的计算机.运行这种协议实际上指的是运行诸如Sendmail和Qmail的程序--如果你使用的是一台非Windows计算机的话.在Windows平台上,作为Windows NT Service Pack一部分或是内建于Windows 2000内部的SMTP服务程序就是典型的这种程序.

我并不是说SMTP软件包就只有那些,但是它们是最普通的.如果你的Web站点使用了互联网服务提供者的主机软件包(Internet Service Provider's virtual hosting package)的一部分,那么SMTP服务程序就应该已经在这台计算机上安装了.如果你是一台位于ISP或是室内的计算机的系统管理员,那么你很有可能已经在这台计算机上安装了某种SMTP软件,用来处理从Web服务器发送邮件的过程.

但是,如果你是一个个人用户并只有一个开发用的Web服务程序运行在你的个人电脑上,你可能没有在自己的机器上运行SMTP软件.下面是一个非常简单但是准确的拇指定律:如果你是一个Windows用户而从没有看见SMTP服务器这样的字眼,那么你就没有运行这个程序.如果你确实没有,那么你有两种选择:安装,配置,和维护一个SMTP服务程序(如果你不知道那是怎么一回事的话就不推荐你使用这种方法)或是使用一个现存的SMTP服务器.

"如果一个服务器现在没有运行的话,我又怎么使用它呢?"你可能要问.如果你的计算机是通过拨号连接(或是DSL或电缆)连到互联网的话,你可以使用你ISP的外发邮件服务器.例如,如果你开发用的 计算机是一个Windows98的系统并使用56kbps modem通过EarthLink连接到互联网,那么你就可以使用mail.earthlink.net作为你的SMTP服务器.不论你对你的外发邮件服务器使用什么样的邮件客户端(Eudora, Outlook, Netscape Mail等等),它们都将和你的PHP代码使用你的SMTP服务器的过程一样.技巧就是使PHP知道一点点事实.

在php.ini管理配置文件里,有几个条目需要被设置以便mail()函数能够正常运行.在改变它们以前,搞清楚它们都是做什么用的.你可以使用phpinfo()函数通过创建一个文件来显示系统当前的配置情况,这个文件包括:
复制内容到剪贴板
代码:
<? phpinfo() ?>
保存这个文件,将它放置到你的Web服务程序的文件根目录,然后通过你的浏览器访问它.你应该可以看到一个被优美的格式化了的信息,显示你的配置情况.你要查看的条目如下:

SMTP
sendmail_from
sendmail_path
如果你没有使用windows,那么sendmail_path指令就是你唯一要担心的东西.如果你正在使用Windows,你就需要看看最后两个指令.

如果你使用的是Linux或是一个Unix变种,sendmail_path看起来应该象这样:

sendmail_path = /usr/sbin/sendmail

或者如果你使用Qmail:

sendmail_path = /var/qmail/bin/sendmail

在这条指令里,你还可以设置配置参数来指明队列缓冲选项或是显示的设置Return-Path头,如下所示:

sendmail_path = /usr/sbin/sendmail -t -fyou@yourdomain.com

作为一个非Windows用户,这就是你要做的一切了.如果你使用的是Windows,你有更多的事情要做.你还需要看一看SMTP和sendmail_from的值.不要被sendmail_from指令名字中的sendmail弄迷糊了.虽然你没有在Windows上使用名叫Sendmail的程序,但那只是指令的名字.不要被它吓到了.

在你的phpinfo()显示的结果里,看看SMTP和sendmail_from的缺省值--它们要么是空白,要么包含了胡乱的值.你应该把它们改成有意义的值.

如果你决心在这台电脑上运行一个SMTP服务程序,你在php.ini文件中的条目就应该如下:

SMTP = localhost

但是,如果你要使用你ISP(在这个例子中是EarthLink)的外发邮件服务器,那么php.ini中的邮件看起来应该如下:

SMTP = mail.earthlink.net

你也可以使用IP地址而不是域名,因为计算机不区分这两种条目.

第二条配置指令是sendmail_from,它应该被设置成From头中的电子邮件地址.它可以在脚本里被修改但是通常作为缺省值使用.下面就是这个配置指令的示例youraddress@yourdomain.com指的是你自己的邮件地址.

sendmail_from = youraddress@yourdomain.com

在做了这些配置上的改动以后,重启Web服务程序然后使用phpinfo()函数来验证这些修改.在这些工作完成以后,你就可以用PHP来发送电子邮件了.

mail()函数是非常简单的:只有五个参数,而其中的两个是可选的.这些参数是:

接收方地址
主题
信件内容
其它文件信息头(可选)
SMTP服务程序的其它配置选项(可选)

附加的头参数控制了诸如CC, BCC, Reply-To之类的邮件功能,或者其它遵循SMTP协议的功能.在这个例子中,我只使用From 和 Reply-To信息头.

如果你想给我发邮件但你使用的是一个非Windows系统, 程序代码就应该如下:
复制内容到剪贴板
代码:
<?
$to = "julie@thickbook.com";
$subject = "ZDNet Developer article";
$msg = "I completely understand SMTP servers now!";
$headers = "From: me@mycompany.com\nReply-To: someoneelse@mycompany.com";
$config = "-fwebmaster@mycompany.com";
mail("$to", "$subject", "$msg", "$headers", "$config");
echo "finished!";
?>
如果你使用的是一个基于Windows的SMTP服务,那么你有可能不需要使用第五个参数,而且在附加的头信息参数中(也就是第四个参数),你需要将它们分开写--使用\r\n而不是\n.所以,同样的一个邮件通过基于Windows的SMTP服务发送的代码如下:
复制内容到剪贴板
代码:
<?
$to = "julie@thickbook.com";
$subject = "ZDNet Developer article";
$msg = "I completely understand SMTP servers now!";
$headers = "From: me@mycompany.com\r\nReply-To: someoneelse@mycompany.com";
mail("$to", "$subject", "$msg", "$headers");
echo "finished!";
?>
脚本中的echo语句使你的Web浏览器在脚本运行完成的时候向你显示一条信息.如果不写echo语句,你就会得到一个"空文件"的对话框,因为没有任何输出能够发送到浏览器端.

只要能够连接到指定的SMTP服务器mail()函数就会返回真值.但是这并不意味着邮件成功的到达了接收方那里.mail()函数不会等待或报告SMTP服务器发来的成功/错误代码.

mail()函数有可能返回假值,然后给你警告"无法连接,在第x行"或是"未知的错误,在第x行."如果这两条信息中的任何一条出现了,你就应该检查php.ini中的SMTP值.引起这些消息有两种可能:SMTP服务器瘫痪了,或者PHP无法连接到它.无论是这两种情况中的哪一种,你的邮件都无法被发送出去.

这个脚本对这些参数使用硬编码的值.使用一个简单的HTML表单,你就可以在这些参数中插入一些值并拥有一个良好的反馈表单.

一旦你知道了如何给一个人发送邮件,你可能按奈不住要把同一个邮件发送给许多接收者--就象新闻信件一样.所有这些牵涉到一个漂亮轻巧的循环来遍历一个接收者的列表并将邮件发送给他们.mail函数的形式还是相同的.

TOP

如何用PHP发电子邮件(二)

mail()函数是非常简单的:只有五个参数,而其中的两个是可选的.这些参数是:

接收方地址
主题
信件内容
其它文件信息头(可选)
SMTP服务程序的其它配置选项(可选)

附加的头参数控制了诸如CC, BCC, Reply-To之类的邮件功能,或者其它遵循SMTP协议的功能.在这个例子中,我只使用From 和 Reply-To信息头.

如果你想给我发邮件但你使用的是一个非Windows系统, 程序代码就应该如下:
复制内容到剪贴板
代码:
<?
$to = "julie@thickbook.com";
$subject = "ZDNet Developer article";
$msg = "I completely understand SMTP servers now!";
$headers = "From: me@mycompany.com\nReply-To: someoneelse@mycompany.com";
$config = "-fwebmaster@mycompany.com";
mail("$to", "$subject", "$msg", "$headers", "$config");
echo "finished!";
?>
如果你使用的是一个基于Windows的SMTP服务,那么你有可能不需要使用第五个参数,而且在附加的头信息参数中(也就是第四个参数),你需要将它们分开写--使用\r\n而不是\n.所以,同样的一个邮件通过基于Windows的SMTP服务发送的代码如下:
复制内容到剪贴板
代码:
<?
$to = "julie@thickbook.com";
$subject = "ZDNet Developer article";
$msg = "I completely understand SMTP servers now!";
$headers = "From: me@mycompany.com\r\nReply-To: someoneelse@mycompany.com";
mail("$to", "$subject", "$msg", "$headers");
echo "finished!";
?>
脚本中的echo语句使你的Web浏览器在脚本运行完成的时候向你显示一条信息.如果不写echo语句,你就会得到一个"空文件"的对话框,因为没有任何输出能够发送到浏览器端.

只要能够连接到指定的SMTP服务器mail()函数就会返回真值.但是这并不意味着邮件成功的到达了接收方那里.mail()函数不会等待或报告SMTP服务器发来的成功/错误代码.

mail()函数有可能返回假值,然后给你警告"无法连接,在第x行"或是"未知的错误,在第x行."如果这两条信息中的任何一条出现了,你就应该检查php.ini中的SMTP值.引起这些消息有两种可能:SMTP服务器瘫痪了,或者PHP无法连接到它.无论是这两种情况中的哪一种,你的邮件都无法被发送出去.

这个脚本对这些参数使用硬编码的值.使用一个简单的HTML表单,你就可以在这些参数中插入一些值并拥有一个良好的反馈表单.

一旦你知道了如何给一个人发送邮件,你可能按奈不住要把同一个邮件发送给许多接收者--就象新闻信件一样.所有这些牵涉到一个漂亮轻巧的循环来遍历一个接收者的列表并将邮件发送给他们.mail函数的形式还是相同的:

mail([接收方], [主题], [邮件主体], [头信息]);

你只需要简单的用列表中的下一个名字来替换[接收方].假设你已经有了一个电子邮件地址的数组:

$addresses = array("me@mycompany.com", "you@yourcompany.com", "someone@otherplace.com");

你所需要做的就是循环遍历这个数组,取得新地址而后发送这个邮件.

如果你在数据库中拥有一个电子邮件地址的列表,同样的原则也是适用的:循环遍历它们.

你已经懂得要领了.显然,同样的概念对你特定的数据库类型和表结构来说也是适用的,虽然代码会需要做一些改动.

人们在循环遍历一个地址列表的时候似乎都忽视了一点:如果你有多于50个地址要处理,你的脚本在完成以前很可能超时,因为PHP对每一个脚本的运行有一个缺省为30秒的时间限制.你可以修改这个时间限制但是这样做的时候要小心.要把这种修改限定在特定的脚本上,比方说遍历一个地址列表发送邮件的脚本.否则,你可能亲手将服务器的线程超载,然后你的计算机将崩溃,从此万劫不复.

要在脚本中设置时间限制,你可以