PHP调用Python快速发送高并发邮件

来源:互联网 发布:js dom 编辑:程序博客网 时间:2024/06/05 15:22

1 简介

       在PHP中发送邮件,通常都是封装一个php的smtp邮件类来发送邮件。但是PHP底层的socket编程相对于python来说效率是非常低的。CleverCode同时写过用python写的爬虫抓取网页,和用php写的爬虫抓取网页。发现虽然用了php的curl抓取网页,但是涉及到超时,多线程同时抓取等等。不得不说python在网络编程的效率要比PHP好的多。

     PHP在发送邮件时候,自己写的smtp类,发送的效率和速度都比较低。特别是并发发送大量带有附件报表的邮件的时候。php的效率很低。建议可以使用php调用python的方式来发送邮件。


2 程序

2.1 python程序

      php的程序和python的文件必须是相同的编码。如都是gbk编号,或者同时utf-8编码,否则容易出现乱码。python发送邮件主要使用了email模块。这里python文件和php文件都是gbk编码,发送的邮件标题内容与正文内容也是gbk编码。

#!/usr/bin/python# -*- coding:gbk -*- """   邮件发送类"""# mail.py## Copyright (c) 2014 by http://blog.csdn.net/CleverCode## modification history:# --------------------# 2014/8/15, by CleverCode, Createimport threadingimport timeimport randomfrom email.MIMEText import MIMETextfrom email.MIMEMultipart import MIMEMultipartfrom email.MIMEBase import MIMEBasefrom email import Utils, Encodersimport mimetypesimport sysimport smtplibimport socketimport getoptimport osclass SendMail:    def __init__(self,smtpServer,username,password):        """        smtpServer:smtp服务器,                username:登录名,        password:登录密码        """        self.smtpServer = smtpServer                self.username = username        self.password = password        def genMsgInfo(self,fromAddress,toAddress,subject,content,fileList,\            subtype = 'plain',charset = 'gb2312'):        """        组合消息发送包        fromAddress:发件人,        toAddress:收件人,        subject:标题,        content:正文,        fileList:附件,        subtype:plain或者html        charset:编码        """        msg = MIMEMultipart()        msg['From'] = fromAddress        msg['To'] = toAddress          msg['Date'] = Utils.formatdate(localtime=1)        msg['Message-ID'] = Utils.make_msgid()                #标题        if subject:            msg['Subject'] = subject                #内容                if content:            body = MIMEText(content,subtype,charset)            msg.attach(body)                #附件        if fileList:            listArr = fileList.split(',')            for item in listArr:                                #文件是否存在                if os.path.isfile(item) == False:                    continue                                    att = MIMEText(open(item).read(), 'base64', 'gb2312')                att["Content-Type"] = 'application/octet-stream'                #这里的filename邮件中显示什么名字                filename = os.path.basename(item)                 att["Content-Disposition"] = 'attachment; filename=' + filename                msg.attach(att)                return msg.as_string()                                                                      def send(self,fromAddress,toAddress,subject = None,content = None,fileList = None,\            subtype = 'plain',charset = 'gb2312'):        """        邮件发送函数        fromAddress:发件人,        toAddress:收件人,        subject:标题        content:正文        fileList:附件列表        subtype:plain或者html        charset:编码        """        try:            server = smtplib.SMTP(self.smtpServer)                        #登录            try:                server.login(self.username,self.password)            except smtplib.SMTPException,e:                return "ERROR:Authentication failed:",e                                        #发送邮件            server.sendmail(fromAddress,toAddress.split(',') \                ,self.genMsgInfo(fromAddress,toAddress,subject,content,fileList,subtype,charset))                        #退出            server.quit()        except (socket.gaierror,socket.error,socket.herror,smtplib.SMTPException),e:            return "ERROR:Your mail send failed!",e                   return 'OK'def usage():    """    使用帮助    """    print """Useage:%s [-h] -s <smtpServer> -u <username> -p <password> -f <fromAddress> -t <toAddress>  [-S <subject> -c        <content> -F <fileList>]        Mandatory arguments to long options are mandatory for short options too.            -s, --smtpServer=  smpt.xxx.com.            -u, --username=   Login SMTP server username.            -p, --password=   Login SMTP server password.            -f, --fromAddress=   Sets the name of the "from" person (i.e., the envelope sender of the mail).            -t, --toAddress=   Addressee's address. -t "test@test.com,test1@test.com".                      -S, --subject=  Mail subject.            -c, --content=   Mail message.-c "content, ......."            -F, --fileList=   Attachment file name.                        -h, --help   Help documen.           """ %sys.argv[0]        def start():    """        """    try:        options,args = getopt.getopt(sys.argv[1:],"hs:u:p:f:t:S:c:F:","--help --smtpServer= --username= --password= --fromAddress= --toAddress= --subject= --content= --fileList=",)    except getopt.GetoptError:        usage()        sys.exit(2)        return        smtpServer = None    username = None    password = None                   fromAddress = None        toAddress = None        subject = None    content = None    fileList = None        #获取参数       for name,value in options:        if name in ("-h","--help"):            usage()            return                if name in ("-s","--smtpServer"):            smtpServer = value                if name in ("-u","--username"):            username = value                if name in ("-p","--password"):            password = value                if name in ("-f","--fromAddress"):            fromAddress = value                if name in ("-t","--toAddress"):            toAddress = value                if name in ("-S","--subject"):            subject = value                if name in ("-c","--content"):            content = value                if name in ("-F","--fileList"):            fileList = value        if smtpServer == None or username == None or password == None:        print 'smtpServer or username or password can not be empty!'        sys.exit(3)               mail = SendMail(smtpServer,username,password)        ret = mail.send(fromAddress,toAddress,subject,content,fileList)    if ret != 'OK':        print ret        sys.exit(4)        print 'OK'        return 'OK'         if __name__ == '__main__':        start()             

2.2 python程序使用帮助

输入以下命令,可以输出这个程序的使用帮助
# python mail.py --help


2.3 php程序

这个程序主要是php拼接命令字符串,调用python程序。注意:用程序发送邮件,需要到邮件服务商,开通stmp服务功能。如qq就需要开通smtp功能后,才能用程序发送邮件。开通如下图。


php调用程序如下:
<?php/** * SendMail.php *  * 发送邮件类 * * Copyright (c) 2015 by http://blog.csdn.net/CleverCode * * modification history: * -------------------- * 2015/5/18, by CleverCode, Create * */class SendMail{    /**     * 发送邮件方法     *     * @param string $fromAddress 发件人,'clevercode@qq.com' 或者修改发件人名 'CleverCode<clevercode@qq.com>'     * @param string $toAddress 收件人,多个收件人逗号分隔,'test1@qq.com,test2@qq.com,test3@qq.com....', 或者 'test1<test1@qq.com>,test2<test2@qq.com>,....'     * @param string $subject 标题     * @param string $content 正文     * @param string $fileList 附件,附件必须是绝对路径,多个附件逗号分隔。'/data/test1.txt,/data/test2.tar.gz,...'     * @return string 成功返回'OK',失败返回错误信息     */    public static function send($fromAddress, $toAddress, $subject = NULL, $content = NULL, $fileList = NULL){        if (strlen($fromAddress) < 1 || strlen($toAddress) < 1) {            return '$fromAddress or $toAddress can not be empty!';        }        // smtp服务器        $smtpServer = 'smtp.qq.com';        // 登录用户        $username = 'clevercode@qq.com';        // 登录密码        $password = '123456';                // 拼接命令字符串,实际是调用了/home/CleverCode/mail.py        $cmd = "LANG=C && /usr/bin/python /home/CleverCode/mail.py";        $cmd .= " -s '$smtpServer'";        $cmd .= " -u '$username'";        $cmd .= " -p '$password'";                $cmd .= " -f '$fromAddress'";        $cmd .= " -t '$toAddress'";                if (isset($subject) && $subject != NULL) {            $cmd .= " -S '$subject'";        }                if (isset($content) && $content != NULL) {            $cmd .= " -c '$content'";        }                if (isset($fileList) && $fileList != NULL) {            $cmd .= " -F '$fileList'";        }                // 执行命令        exec($cmd, $out, $status);        if ($status == 0) {            return 'OK';        } else {            return "Error,Send Mail,$fromAddress,$toAddress,$subject,$content,$fileList ";        }        return 'OK';    }}



2.3 使用样例

压缩excel成附件,发送邮件。
<?php/** * test.php * * 压缩excel成附件,发送邮件 * * Copyright (c) 2015 http://blog.csdn.net/CleverCode * * modification history: * -------------------- * 2015/5/14, by CleverCode, Create * */include_once ('SendMail.php');/* * 客户端类 * 让客户端和业务逻辑尽可能的分离,降低页面逻辑和业务逻辑算法的耦合, * 使业务逻辑的算法更具有可移植性 */class Client{    public function main(){                // 发送者        $fromAddress = 'CleverCode<clevercode@qq.com>';                // 接收者        $toAddress = 'all@qq.com';                // 标题        $subject = '这里是标题!';                // 正文        $content = "您好:\r\n";        $content .= "   这里是正文\r\n ";                // excel路径        $filePath = dirname(__FILE__) . '/excel';        $sdate = date('Y-m-d');        $PreName = 'CleverCode_' . $sdate;                // 文件名        $fileName = $filePath . '/' . $PreName . '.xls';                // 压缩excel文件        $cmd = "cd $filePath && zip $PreName.zip $PreName.xls";        exec($cmd, $out, $status);        $fileList = $filePath . '/' . $PreName . '.zip';                // 发送邮件(附件为压缩后的文件)        $ret = SendMail::send($fromAddress, $toAddress, $subject, $content, $fileList);        if ($ret != 'OK') {            return $ret;        }                return 'OK';    }}/** * 程序入口 */function start(){    $client = new Client();    $client->main();}start();?>

2.4 程序源码下载

http://download.csdn.net/detail/clevercode/8711809




版权声明:

1)原创作品,出自"CleverCode的博客",转载时请务必注明以下原创地址,否则追究版权法律责任。

2)原创地址:http://blog.csdn.net/clevercode/article/details/45815453(转载务必注明该地址)。

3)欢迎大家关注我博客更多的精彩内容:http://blog.csdn.net/CleverCode。





1 0