百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

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

off999 2024-12-12 14:24 27 浏览 0 评论

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 "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。

相关推荐

手机秒变电脑摄像头(手机秒变电脑摄像头怎么设置)

可以的我用过,但是要你手机支持啊国产的山寨机很多都支持这个功能:支持这个功能的手机摄像头有两种工作状态:手机摄像状态和USB连接状态,在手机设置里把手机的摄像头改为USB连接状态,直接插到电脑上就可以...

苹果ipad充不上电是什么原因
  • 苹果ipad充不上电是什么原因
  • 苹果ipad充不上电是什么原因
  • 苹果ipad充不上电是什么原因
  • 苹果ipad充不上电是什么原因
bios没有advanced选项(bios没有advanced选项卡)

华硕主板可开机后点击ESC键或F12键选择AdvancedBIOSFeatures项:你说的只很少几项可以修改,可能是分别设置了CMOS密码和开机密码。而你进入COMS时输的的开机密码!要输入C...

路由器选购技巧(路由器选购技巧大全)

第一,WI-FI协议;我们在购买路由器的时候需要仔细注意分辨WI-FI协议是厂家的噱头还是真正实用的,对上网体验有帮助的功能。目前的Wi-Fi协议已经发展到第6代,既厂商宣传的Wi-Fi...

联想电脑摄像头驱动怎么安装
  • 联想电脑摄像头驱动怎么安装
  • 联想电脑摄像头驱动怎么安装
  • 联想电脑摄像头驱动怎么安装
  • 联想电脑摄像头驱动怎么安装
win7电脑没有声音怎么解决(win7电脑为什么没声音)

1.在我们的win7系统中,突然间没有声音,此时用鼠标右键点击电脑左边的开始菜单,选择“管理”按钮。2.在此页点击系统工具下面的设备管理器,然后展开声音、视频和游戏控制器此选项。3、在该选项当中,...

playstore(playstore app install english)

原文:PlayStore翻译:谷歌的电子市场,或者是指一些虚拟的电子商城。例句:Playstore,restaurant,oricecreamstandtogether.情景游戏...

office2010不激活可以用吗(window10中office不激活可以吗)

可以购买正版授权码激活或激活工具,不激活也可以一直用,但是每一次打开都会弹框。可以使用。因为Office2010不激活后,只会出现一个提醒框,并不影响软件的正常使用。但是未激活的Office2010不...

雨林木风在线重装系统(雨林木风系统安装教程win10)

一,一般雨林木风番茄花园之类的盗版系统重装系统后都是自动激活的,不需要再重新激活。二,如果偶尔系统提示没有激活的话,上系统之家等网站可以下载激活码,按提示激活即可。三,不建议安装雨林木风之类的盗版系统...

系统镜像文件放在哪里(系统镜像文件放在哪里好)

镜像文件路径在安装的U盘内有显示,如果没有显示,那是文件不对,或被解压了。镜像文件是一些压缩文件的统称。常见的有img格式的文件(例如,文本文件的格式是txt),它通常是用特定的软件,将本身自带启动文...

mtu设置多少最好(mtu设置多少最好 4g)

路由器MTU的设置应根据网络情况决定,各种网络环境建议使用的MTU值如下:1.1500—以太网信息包最大值,也是默认值,是没有PPPoE和虚拟专用网络的网络连接的典型设置。是大部分路由器,网络适配器和...

u盘最便宜多少钱一个(u盘最低价格)

一般情况下,一分钱,一分货;没有又便宜,货又好的事情。1、扩容盘。扩容盘是用PC技术,在量产时运用容量优先,输入了固定的容量,但它真实的容量只有标称容量的10倍左右。512M没人要的U盘扩容成4G,它...

小白三步装机教程(小白三步装机法)

下面给大家整理了一份小白装机的详细教程,有需要的朋友们快来看看吧!1、我们下载一个小白软件,然后选择了安装win7系统。2、在下载界面,下载速度取决于您的网络您只需要耐心等待即可。3、软件下载完成后会...

winpe下载官网下载iso(winpe.iso下载)

你好,以winpe装win7iso系统说明安装步骤:  1、根据教程制作好winpe启动盘,然后将下载的win7iso系统文件直接复制到U盘的GHO目录下;  2、在需要装系统的电脑上...

把系统装在u盘(把系统装在u盘里的缺点)

系统装进U盘有效的方法。1、下载并且安装好大白菜装机版,打开安装好的大白菜装机版,插入u盘等待软件成功读取到u盘之后,点击“一键制作启动u盘”进入下一步操作:2、弹出的信息提示窗口中,选择自己下载的的...

取消回复欢迎 发表评论: