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编码。

  1. #!/usr/bin/python
  2. # -*- coding:gbk -*-
  3. """
  4. 邮件发送类
  5. """
  6. # mail.py
  7. #
  8. # Copyright (c) 2014 by http://blog.csdn.net/CleverCode
  9. #
  10. # modification history:
  11. # --------------------
  12. # 2014/8/15, by CleverCode, Create
  13. import threading
  14. import time
  15. import random
  16. from email.MIMEText import MIMEText
  17. from email.MIMEMultipart import MIMEMultipart
  18. from email.MIMEBase import MIMEBase
  19. from email import Utils, Encoders
  20. import mimetypes
  21. import sys
  22. import smtplib
  23. import socket
  24. import getopt
  25. import os
  26. class SendMail:
  27. def __init__(self,smtpServer,username,password):
  28. """
  29. smtpServer:smtp服务器,
  30. username:登录名,
  31. password:登录密码
  32. """
  33. self.smtpServer = smtpServer
  34. self.username = username
  35. self.password = password
  36. def genMsgInfo(self,fromAddress,toAddress,subject,content,fileList,\
  37. subtype = 'plain',charset = 'gb2312'):
  38. """
  39. 组合消息发送包
  40. fromAddress:发件人,
  41. toAddress:收件人,
  42. subject:标题,
  43. content:正文,
  44. fileList:附件,
  45. subtype:plain或者html
  46. charset:编码
  47. """
  48. msg = MIMEMultipart()
  49. msg['From'] = fromAddress
  50. msg['To'] = toAddress
  51. msg['Date'] = Utils.formatdate(localtime=1)
  52. msg['Message-ID'] = Utils.make_msgid()
  53. #标题
  54. if subject:
  55. msg['Subject'] = subject
  56. #内容
  57. if content:
  58. body = MIMEText(content,subtype,charset)
  59. msg.attach(body)
  60. #附件
  61. if fileList:
  62. listArr = fileList.split(',')
  63. for item in listArr:
  64. #文件是否存在
  65. if os.path.isfile(item) == False:
  66. continue
  67. att = MIMEText(open(item).read(), 'base64', 'gb2312')
  68. att["Content-Type"] = 'application/octet-stream'
  69. #这里的filename邮件中显示什么名字
  70. filename = os.path.basename(item)
  71. att["Content-Disposition"] = 'attachment; filename=' + filename
  72. msg.attach(att)
  73. return msg.as_string()
  74. def send(self,fromAddress,toAddress,subject = None,content = None,fileList = None,\
  75. subtype = 'plain',charset = 'gb2312'):
  76. """
  77. 邮件发送函数
  78. fromAddress:发件人,
  79. toAddress:收件人,
  80. subject:标题
  81. content:正文
  82. fileList:附件列表
  83. subtype:plain或者html
  84. charset:编码
  85. """
  86. try:
  87. server = smtplib.SMTP(self.smtpServer)
  88. #登录
  89. try:
  90. server.login(self.username,self.password)
  91. except smtplib.SMTPException,e:
  92. return "ERROR:Authentication failed:",e
  93. #发送邮件
  94. server.sendmail(fromAddress,toAddress.split(',') \
  95. ,self.genMsgInfo(fromAddress,toAddress,subject,content,fileList,subtype,charset))
  96. #退出
  97. server.quit()
  98. except (socket.gaierror,socket.error,socket.herror,smtplib.SMTPException),e:
  99. return "ERROR:Your mail send failed!",e
  100. return 'OK'
  101. def usage():
  102. """
  103. 使用帮助
  104. """
  105. print """Useage:%s [-h] -s <smtpServer> -u <username> -p <password> -f <fromAddress> -t <toAddress>  [-S <subject> -c
  106. <content> -F <fileList>]
  107. Mandatory arguments to long options are mandatory for short options too.
  108. -s, --smtpServer=  smpt.xxx.com.
  109. -u, --username=   Login SMTP server username.
  110. -p, --password=   Login SMTP server password.
  111. -f, --fromAddress=   Sets the name of the "from" person (i.e., the envelope sender of the mail).
  112. -t, --toAddress=   Addressee's address. -t "test@test.com,test1@test.com".
  113. -S, --subject=  Mail subject.
  114. -c, --content=   Mail message.-c "content, ......."
  115. -F, --fileList=   Attachment file name.
  116. -h, --help   Help documen.
  117. """ %sys.argv[0]
  118. def start():
  119. """
  120. """
  121. try:
  122. options,args = getopt.getopt(sys.argv[1:],"hs:u:p:f:t:S:c:F:","--help --smtpServer= --username= --password= --fromAddress= --toAddress= --subject= --content= --fileList=",)
  123. except getopt.GetoptError:
  124. usage()
  125. sys.exit(2)
  126. return
  127. smtpServer = None
  128. username = None
  129. password = None
  130. fromAddress = None
  131. toAddress = None
  132. subject = None
  133. content = None
  134. fileList = None
  135. #获取参数
  136. for name,value in options:
  137. if name in ("-h","--help"):
  138. usage()
  139. return
  140. if name in ("-s","--smtpServer"):
  141. smtpServer = value
  142. if name in ("-u","--username"):
  143. username = value
  144. if name in ("-p","--password"):
  145. password = value
  146. if name in ("-f","--fromAddress"):
  147. fromAddress = value
  148. if name in ("-t","--toAddress"):
  149. toAddress = value
  150. if name in ("-S","--subject"):
  151. subject = value
  152. if name in ("-c","--content"):
  153. content = value
  154. if name in ("-F","--fileList"):
  155. fileList = value
  156. if smtpServer == None or username == None or password == None:
  157. print 'smtpServer or username or password can not be empty!'
  158. sys.exit(3)
  159. mail = SendMail(smtpServer,username,password)
  160. ret = mail.send(fromAddress,toAddress,subject,content,fileList)
  161. if ret != 'OK':
  162. print ret
  163. sys.exit(4)
  164. print 'OK'
  165. return 'OK'
  166. if __name__ == '__main__':
  167. start()

2.2 python程序使用帮助

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

2.3 php程序

这个程序主要是php拼接命令字符串,调用python程序。注意:用程序发送邮件,需要到邮件服务商,开通stmp服务功能。如qq就需要开通smtp功能后,才能用程序发送邮件。开通如下图。
 
php调用程序如下:
  1. <?php
  2. /**
  3. * SendMail.php
  4. *
  5. * 发送邮件类
  6. *
  7. * Copyright (c) 2015 by http://blog.csdn.net/CleverCode
  8. *
  9. * modification history:
  10. * --------------------
  11. * 2015/5/18, by CleverCode, Create
  12. *
  13. */
  14. class SendMail{
  15. /**
  16. * 发送邮件方法
  17. *
  18. * @param string $fromAddress 发件人,'clevercode@qq.com' 或者修改发件人名 'CleverCode<clevercode@qq.com>'
  19. * @param string $toAddress 收件人,多个收件人逗号分隔,'test1@qq.com,test2@qq.com,test3@qq.com....', 或者 'test1<test1@qq.com>,test2<test2@qq.com>,....'
  20. * @param string $subject 标题
  21. * @param string $content 正文
  22. * @param string $fileList 附件,附件必须是绝对路径,多个附件逗号分隔。'/data/test1.txt,/data/test2.tar.gz,...'
  23. * @return string 成功返回'OK',失败返回错误信息
  24. */
  25. public static function send($fromAddress, $toAddress, $subject = NULL, $content = NULL, $fileList = NULL){
  26. if (strlen($fromAddress) < 1 || strlen($toAddress) < 1) {
  27. return '$fromAddress or $toAddress can not be empty!';
  28. }
  29. // smtp服务器
  30. $smtpServer = 'smtp.qq.com';
  31. // 登录用户
  32. $username = 'clevercode@qq.com';
  33. // 登录密码
  34. $password = '123456';
  35. // 拼接命令字符串,实际是调用了/home/CleverCode/mail.py
  36. $cmd = "LANG=C && /usr/bin/python /home/CleverCode/mail.py";
  37. $cmd .= " -s '$smtpServer'";
  38. $cmd .= " -u '$username'";
  39. $cmd .= " -p '$password'";
  40. $cmd .= " -f '$fromAddress'";
  41. $cmd .= " -t '$toAddress'";
  42. if (isset($subject) && $subject != NULL) {
  43. $cmd .= " -S '$subject'";
  44. }
  45. if (isset($content) && $content != NULL) {
  46. $cmd .= " -c '$content'";
  47. }
  48. if (isset($fileList) && $fileList != NULL) {
  49. $cmd .= " -F '$fileList'";
  50. }
  51. // 执行命令
  52. exec($cmd, $out, $status);
  53. if ($status == 0) {
  54. return 'OK';
  55. } else {
  56. return "Error,Send Mail,$fromAddress,$toAddress,$subject,$content,$fileList ";
  57. }
  58. return 'OK';
  59. }
  60. }
 

2.3 使用样例

压缩excel成附件,发送邮件。
  1. <?php
  2. /**
  3. * test.php
  4. *
  5. * 压缩excel成附件,发送邮件
  6. *
  7. * Copyright (c) 2015 http://blog.csdn.net/CleverCode
  8. *
  9. * modification history:
  10. * --------------------
  11. * 2015/5/14, by CleverCode, Create
  12. *
  13. */
  14. include_once ('SendMail.php');
  15. /*
  16. * 客户端类
  17. * 让客户端和业务逻辑尽可能的分离,降低页面逻辑和业务逻辑算法的耦合,
  18. * 使业务逻辑的算法更具有可移植性
  19. */
  20. class Client{
  21. public function main(){
  22. // 发送者
  23. $fromAddress = 'CleverCode<clevercode@qq.com>';
  24. // 接收者
  25. $toAddress = 'all@qq.com';
  26. // 标题
  27. $subject = '这里是标题!';
  28. // 正文
  29. $content = "您好:\r\n";
  30. $content .= "   这里是正文\r\n ";
  31. // excel路径
  32. $filePath = dirname(__FILE__) . '/excel';
  33. $sdate = date('Y-m-d');
  34. $PreName = 'CleverCode_' . $sdate;
  35. // 文件名
  36. $fileName = $filePath . '/' . $PreName . '.xls';
  37. // 压缩excel文件
  38. $cmd = "cd $filePath && zip $PreName.zip $PreName.xls";
  39. exec($cmd, $out, $status);
  40. $fileList = $filePath . '/' . $PreName . '.zip';
  41. // 发送邮件(附件为压缩后的文件)
  42. $ret = SendMail::send($fromAddress, $toAddress, $subject, $content, $fileList);
  43. if ($ret != 'OK') {
  44. return $ret;
  45. }
  46. return 'OK';
  47. }
  48. }
  49. /**
  50. * 程序入口
  51. */
  52. function start(){
  53. $client = new Client();
  54. $client->main();
  55. }
  56. start();
  57. ?>
 

2.4 程序源码下载

PHP调用Python快速发送高并发邮件的更多相关文章

  1. python导出zabbix数据并发邮件脚本

    Zabbix没有报表导出的功能,于是通过编写脚本导出zabbix数据并发邮件.效果如下: 下面是脚本,可根据自己的具体情况修改: #!/usr/bin/python #coding:utf-8 imp ...

  2. Python Tornado搭建高并发Restful API接口服务

    Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快能实现高并发.得利于其 非阻塞的方式和对epoll的运用,Torn ...

  3. python 快速发送大量邮件

    因为公司需求,需要发送千万封级别邮件. # coding:utf-8 import csv import smtplib from email.mime.text import MIMEText im ...

  4. 用Python控制摄像头拍照并发邮件

    概述前言 工具 思路 安装及导入包 设置参数 实现拍照 构造邮件内容 发送邮件 判断网络连接 开机自启 后记 o1 前言为什么会有写这个程序的想法呢? 最初的想法是写一个可以用电脑前置摄像头拍照的程序 ...

  5. Python 实现发送、抄送邮件功能

    发送邮件 问题 在web.py中,如何发送邮件? 解法 在web.py中使用web.sendmail()发送邮件. web.sendmail('cookbook@webpy.org', 'user@e ...

  6. Mac怎么快速创建便签和发送附件的邮件

    1.如何快速创建便签        在Mac的任意界面选中文字:shift+command+y 就能创建便签2.如何快速发送附件的邮件(网页界面)        在Safari网页界面 command ...

  7. Python3+smtplib+poplib+imaplib实现发送和收取邮件(以qq邮箱为例)

    一.说明 1.1 程序说明 (1)smtp是邮件发送协议:pop和imap都是邮件接收协议,两者的区别通常的说法是imap的操作会同步到邮箱服务器而pop不会,表现上我也不是很清楚 (2)本程序实现使 ...

  8. [记录]Python高并发编程

    ========== ==多进程== ========== 要让Python程序实现多进程(multiprocessing),我们先了解操作系统的相关知识. Unix/Linux操作系统提供了一个fo ...

  9. java调用html模板发送html内容的邮件

    在项目需要发送邮件,普通内容的邮件觉得太单调.太丑,没逼格,所以说直接把用到的邮件内容做成一个html模板,发送之前将对应参数替换掉,发送html内容的高逼格邮件. 首先需要引用jar包,这就不多说了 ...

随机推荐

  1. 推荐TED演讲:20岁光阴不再来(Why 30 is not the new 20)

    缘起 早上起来在电脑上看到"自强不息"群(群号)中骆宏给大家分享的视频."20岁光阴不再来",利用短暂的时间浏览了一下.就像把这个TED视频分享给很多其它的朋友 ...

  2. linux 跟踪工具

    strace工具,进程诊断.排错.跟踪系统调用和信号量 每行输出都是一个系统调用,包括函数和返回值. strace是Linux环境下的一款程序调试工具,用来监察一个应用程序所使用的系统调用及它所接收的 ...

  3. Hive报错:Failed with exception Unable to rename

    之前也安装过hive,操作过无数,也没发现什么错误,今天因为之前安装的hadoop不能用了,不知道为什么,老是提示node 0,所以重新安装了hadoop和hive.安装完测试hive创建表也没发现什 ...

  4. 华为P20无敌拍摄能力开放 如何即刻获得?

    在全球专业相机测评机构DXOmark发布的相机评测排行中,华为P20.P20 Pro成功登顶“全球拍照最好智能手机”.P20 Pro综合得分高达109分,P20综合得分102分.“华为并非简单地将第三 ...

  5. 在PHP中,通过filesize函数可以取得文件的大小,文件大小是以字节数表示的。如果要转换文件大小的单位,可以自己定义函数来实现。

    <?php function getsize($size, $format) { $p = 0; if ($format == 'kb') { $p = 1; } elseif ($format ...

  6. linux下安装go

    在centOS下,安装go的环境,如下: 下载压缩包,wget https://storage.googleapis.com/golang/go1.8.linux-amd64.tar.gz 解压该文件 ...

  7. 平滑处理 - cvSmooth() 函数实现

    前言 平滑是图像处理中很重要的操作,其主要用途是降噪.Open CV 提供了 5 种不同的平滑方法:简单模糊,简单无缩放变换的模糊,中值模糊,高斯模糊和双边滤波,它们都通过函数 cvSmooth 实现 ...

  8. FAT12中,如何定位大于一个扇区(512B)的文件内容

    [0]README 0.1)本文旨在于 演示在FAT12中, 如何取定位大于 512B 的文件内容,和查看它: 0.2)如何制作FAT12文件系统,以及如何向文件中添加temp.txt文件,参见: { ...

  9. 九度OJ 1068:球的半径和体积 (基础题)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5385 解决:1949 题目描述: 输入球的中心点和球上某一点的坐标,计算球的半径和体积 输入: 球的中心点和球上某一点的坐标,以如下形式输 ...

  10. JavaScript library of crypto standards. 看源码

    crypto-js - npm https://www.npmjs.com/package/crypto-js crypto-js/docs/QuickStartGuide.wiki <wiki ...