首頁  >  文章  >  後端開發  >  關於php如何呼叫Python快速發送高並發郵件的範例程式碼

關於php如何呼叫Python快速發送高並發郵件的範例程式碼

黄舟
黄舟原創
2017-07-17 15:33:591843瀏覽

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, Create

import threading
import time
import random
from email.MIMEText import MIMEText
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email import Utils, Encoders
import mimetypes
import sys
import smtplib
import socket
import getopt
import os

class 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&#39;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 &#39;smtpServer or username or password can not be empty!&#39;
        sys.exit(3)
           
    mail = SendMail(smtpServer,username,password)
    
    ret = mail.send(fromAddress,toAddress,subject,content,fileList)
    if ret != &#39;OK&#39;:
        print ret
        sys.exit(4)
    
    print &#39;OK&#39;
    
    return &#39;OK&#39;    
     
if name == &#39;main&#39;:
    
    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 发件人,&#39;clevercode@qq.com&#39; 或者修改发件人名 &#39;CleverCode<clevercode@qq.com>&#39;
     * @param string $toAddress 收件人,多个收件人逗号分隔,&#39;test1@qq.com,test2@qq.com,test3@qq.com....&#39;, 或者 &#39;test1<test1@qq.com>,test2<test2@qq.com>,....&#39;
     * @param string $subject 标题
     * @param string $content 正文
     * @param string $fileList 附件,附件必须是绝对路径,多个附件逗号分隔。&#39;/data/test1.txt,/data/test2.tar.gz,...&#39;
     * @return string 成功返回&#39;OK&#39;,失败返回错误信息
     */
    public static function send($fromAddress, $toAddress, $subject = NULL, $content = NULL, $fileList = NULL){
        if (strlen($fromAddress) < 1 || strlen($toAddress) < 1) {
            return &#39;$fromAddress or $toAddress can not be empty!&#39;;
        }
        // smtp服务器
        $smtpServer = &#39;smtp.qq.com&#39;;
        // 登录用户
        $username = &#39;clevercode@qq.com&#39;;
        // 登录密码
        $password = &#39;123456&#39;;
        
        // 拼接命令字符串,实际是调用了/home/CleverCode/mail.py
        $cmd = "LANG=C && /usr/bin/python /home/CleverCode/mail.py";
        $cmd .= " -s &#39;$smtpServer&#39;";
        $cmd .= " -u &#39;$username&#39;";
        $cmd .= " -p &#39;$password&#39;";
        
        $cmd .= " -f &#39;$fromAddress&#39;";
        $cmd .= " -t &#39;$toAddress&#39;";
        
        if (isset($subject) && $subject != NULL) {
            $cmd .= " -S &#39;$subject&#39;";
        }
        
        if (isset($content) && $content != NULL) {
            $cmd .= " -c &#39;$content&#39;";
        }
        
        if (isset($fileList) && $fileList != NULL) {
            $cmd .= " -F &#39;$fileList&#39;";
        }
        
        // 执行命令
        exec($cmd, $out, $status);
        if ($status == 0) {
            return &#39;OK&#39;;
        } else {
            return "Error,Send Mail,$fromAddress,$toAddress,$subject,$content,$fileList ";
        }
        return &#39;OK&#39;;
    }
}

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 (&#39;SendMail.php&#39;);

/*
 * 客户端类
 * 让客户端和业务逻辑尽可能的分离,降低页面逻辑和业务逻辑算法的耦合,
 * 使业务逻辑的算法更具有可移植性
 */
class Client{

    public function main(){
        
        // 发送者
        $fromAddress = &#39;CleverCode<clevercode@qq.com>&#39;;
        
        // 接收者
        $toAddress = &#39;all@qq.com&#39;;
        
        // 标题
        $subject = &#39;这里是标题!&#39;;
        
        // 正文
        $content = "您好:\r\n";
        $content .= "   这里是正文\r\n ";
        
        // excel路径
        $filePath = dirname(FILE) . &#39;/excel&#39;;
        $sdate = date(&#39;Y-m-d&#39;);
        $PreName = &#39;CleverCode_&#39; . $sdate;
        
        // 文件名
        $fileName = $filePath . &#39;/&#39; . $PreName . &#39;.xls&#39;;
        
        // 压缩excel文件
        $cmd = "cd $filePath && zip $PreName.zip $PreName.xls";
        exec($cmd, $out, $status);
        $fileList = $filePath . &#39;/&#39; . $PreName . &#39;.zip&#39;;
        
        // 发送邮件(附件为压缩后的文件)
        $ret = SendMail::send($fromAddress, $toAddress, $subject, $content, $fileList);
        if ($ret != &#39;OK&#39;) {
            return $ret;
        }
        
        return &#39;OK&#39;;
    }
}

/**
 * 程序入口
 */
function start(){
    $client = new Client();
    $client->main();
}

start();

?>

以上是關於php如何呼叫Python快速發送高並發郵件的範例程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn