1. 程式人生 > >PHP呼叫Python快速傳送高併發郵件

PHP呼叫Python快速傳送高併發郵件

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's address. -t "
[email protected]
,[email protected]". -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 發件人,'[email protected]' 或者修改發件人名 'CleverCode<[email protected]>'
     * @param string $toAddress 收件人,多個收件人逗號分隔,'[email protected],[email protected],[email protected]', 或者 'test1<[email protected]>,test2<[email protected]>,....'
     * @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 = '[email protected]';
        // 登入密碼
        $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<[email protected]>';
        
        // 接收者
        $toAddress = '[email protected]';
        
        // 標題
        $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 程式原始碼下載




相關推薦

PHP呼叫Python快速傳送併發郵件

1 簡介        在PHP中傳送郵件,通常都是封裝一個php的smtp郵件類來發送郵件。但是PHP底層的socket程式設計相對於python來說效率是非常低的。CleverCode同時寫過用python寫的爬蟲抓取網頁,和用php寫的爬蟲抓取網頁。發現雖然用了php

PHP利用Mysql鎖解決併發

前面寫過利用檔案鎖來處理高併發的問題的,現在我們說另外一個處理方式,利用Mysql的鎖來解決高併發的問題 先看沒有利用事務的時候併發的後果 建立庫存管理表 CREATE TABLE `storage` ( `id` int(11) unsigned NOT NULL AUTO_INCRE

PHP 利用檔案鎖處理併發

利用 flock()函式對檔案進行加鎖(排它鎖),實現併發按序進行。 flock(file,lock,block)有三個引數。 file : 已經開啟的檔案 lock : 鎖的型別 LOCK_SH : 共享鎖定(讀鎖) LOCK_EX : 獨佔鎖定(排它鎖,寫鎖

【Python3爬蟲】用Python實現傳送天氣預報郵件

此次的目標是爬取指定城市的天氣預報資訊,然後再用Python傳送郵件到指定的郵箱。   一、爬取天氣預報 1、首先是爬取天氣預報的資訊,用的網站是中國天氣網,網址是http://www.weather.com.cn/static/html/weather.shtml,任意選擇一個城市(比如武漢

python 如何解決併發下的庫存問題

        一個簡單的使用場景:一件商品的庫存只有5件,同時A使用者買了5個,B使用者買了5個,都提交資料,照成庫存不足的問題。        邏輯:根據一般電商商品的模型類,生成訂單一般包括訂單類(Order)和訂單詳情類(DetailOrder),這兩張表根據外來鍵o

Python SMTP 傳送純文字郵件

利用Python的smtp和email模組傳送郵件 最近,開始學習python,因為從未接觸過python,所以這幾天抽時間看了一下基礎知識,然後就看到了python郵件這一塊。 因為使用qq郵箱傳送,所以也碰到了一些問題。所以,在此對使用python,利用qq郵箱傳送郵件

PHP結合redis實現的併發下----搶購、秒殺功能

搶購、秒殺是如今很常見的一個應用場景,主要需要解決的問題有兩個:1 高併發對資料庫產生的壓力2 競爭狀態下如何解決庫存的正確減少("超賣"問題)對於第一個問題,已經很容易想到用鎖表來處理搶購,但是鎖表漏洞是  假設一個使用者出現問題程式就不能接著運行了 ,例如使用Redis

php 呼叫 python指令碼的方法

1. exec原型:string exec ( string command [, array &output [, int &return_var]] )描述:返回值儲存最後的輸出結果,而所有輸出結果將會儲存到$output陣列,$return_var用來儲存命令執行的狀態碼(用來檢測成功或

php呼叫Python介面的方法

最近因為公司用python做了一個根據cmpp2.0協議的簡訊介面,而我的任務就是用php的擴充套件去呼叫他,研究了很久,終於成功了,只有簡短的兩三行程式碼,這裡我就把程式碼放出來,請各大拿多給點意見

PHP和Redis實現在併發下的搶購及秒殺功能

搶購、秒殺是平常很常見的場景,面試的時候面試官也經常會問到,比如問你淘寶中的搶購秒殺是怎麼實現的等等。   搶購、秒

PHP+Redis連結串列解決併發下商品超賣問題

[TOC] [上一篇](https://www.cnblogs.com/itbsl/p/13418176.html)文章聊了一下使用**Redis事務**來解決高併發商品超賣問題,今天我們來聊一下使用**Redis連結串列**來解決高併發商品超賣問題。 ### 實現原理 使用redis連結串列來做,因為p

PHP呼叫mail()函式傳送郵件所需sendmail的基本配置和html格式的郵件資訊

首先從http://glob.com.au/sendmail上下載sendmail壓縮包;並將其解壓到D:盤中(一般最好不要解壓到C:盤,且目錄不要太長)。 設定一下PHP.ini檔案: [mail function] ; For Win32 only. ; http://

Python操作Excel, 開發和呼叫介面,傳送郵件

筆記: 上週回顧: 模組: 匯入模組的順序 lyl.py # def hhh(): pass name = 'lyl' a.py import lyl import sys from lyl import hhh

Python Flask 快速構建性能大型web網站項目實戰

空間 實現 處理 mac os 環境搭建 課程 3.1 4.6 統計 Python Flask 快速構建高性能大型web網站項目實戰視頻【下載地址:https://pan.baidu.com/s/1cUggNbUvptYz5vvwBhsdrg 】 作為最最流行的Python

模擬併發請求服務端(python gevent)

專案背景:對web後端進行高併發的請求,簡單測試服務框架的效能 解決思路:利用python的多執行緒,但python的多執行緒有點“雞肋”, 個人選擇使用簡潔輕便gevent。 解決方案:採用gevent非同步 + requests 進行高併發請求 import time import

Android實現快速傳送電子郵件

最近有朋友有需求是通過apk傳送郵件,我心想這怎麼可以實現?然後就研究了一番,最後得出結論是可行的! 確實可以自己的手機上定義主題和內容或者附件,然後傳送給對應的郵箱!詳細步驟傾聽我一一道來 我們以A郵箱傳送郵件給B郵箱為例: 1 開啟A郵箱的POP3服務 每個郵箱都有POP3服

Magento Transactional Emails常規設定 magento email:快速實現傳送自定義郵件

郵件是幾乎所有電商系統都要用到的功能,在magento中實現簡單的郵件傳送並不複雜,不過要想用特定郵件模板,就需要對magento郵件系統做一些深入瞭解,本文就分析一下如何傳送自定義郵件。之前已經發了一篇介紹magento基本郵件設定的文章 Magento Transactional Emails

PHP模擬併發

PHP模擬高併發 什麼是高併發? 簡單模擬高併發 什麼是高併發? 高併發(High Concurrency)是網際網路分散式系統架構設計中必須考慮的因素之一,它通常是指,通過設計保證系統能夠同時並行處理很多請求。 高併發相關常用的一些

Python可帶附件的郵件傳送

#coding=utf-8import smtplib from email.mime.multipart import MIMEMultipart  from email.mime.application import MIMEApplication  from emai

呼叫Mailgun API傳送電子郵件一例

Mailgun提供了免費的郵件傳送服務,適合拿來做通知提醒一類的服務。免費版預設支援每天傳送多達300封郵件,最多可以發10,000封。 註冊方法:訪問 https://www.mailgun.com/email-api , 點Sign Up Free 輸入基本資訊,包括要接收郵