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. HTML5开发移动web应用——SAP UI5篇(8)

    本次对之前学习的SAP UI5框架知识进行简单小结.以及重点部分知识的梳理. 1.在UI5使用过程中,命名空间的概念非常重要. 2.一般的sap组件引用格式例如以下: sap.ui.define([ ...

  2. HDFS源码分析数据块复制之PendingReplicationBlocks

    PendingReplicationBlocks实现了所有正在复制的数据块的记账工作.它实现以下三个主要功能: 1.记录此时正在复制的块: 2.一种对复制请求进行跟踪的粗粒度计时器: 3.一个定期识别 ...

  3. zeroMQ研究(转)

    偶尔一个机会,了解了下zeroMQ消息队列. 1  ZeroMQ概述 ZeroMQ是一种基于消息队列的多线程网络库,其对套接字类型.连接处理.帧.甚至路由的底层细节进行抽象,提供跨越多种传输协议的套接 ...

  4. zoj 2068 - Chopsticks

    题目:非常多人在一起吃饭.有两组单支的筷子,定义badness为一对筷子长度差的平方,求最小的badness和. 分析:dp,最大公共子序列类似物. 这里利用数学关系找到一个结论: a < b ...

  5. 【EDAS问题】轻量级EDAS部署hsf服务出现找不到类的解决方案

    本地运行轻量级EDAS调用服务的时候报错如下: 2018-01-08 13:16:58.029 WARN [http-bio-8090-exec-8:t.hsf] [RPC Protocol call ...

  6. python 基础 6.0 异常的常用形式

    一. 异常   异常既是一个时间,该事件会在程序执行过程中发生,影响了程序的正常执行.一般情况下,在python无法正常处理程序时就会发生一个异常.异常是python对象,表示一个错误.当python ...

  7. php标准库DirectoryIterator类的操作说明

    <?php $dir = new DirectoryIterator(dirname(__FILE__)); foreach ($dir as $fileInfo) { if ($fileInf ...

  8. 如何使用doctrine:migrations:migrate

    doctrine:migrations:migrate: 可以生成数据库表 当新建完实体之后需要执行 doctrine:migrations:diff 更新差异到db 然后就ok了,这时候你的app/ ...

  9. python3用pdfminer3k在线读取pdf文件

    import importlib import sys import random from urllib.request import urlopen from urllib.request imp ...

  10. Cocoapods的安装以及使用

    在网上看博客,看了好多次,都没有学会cocoapods,今天上午浪费了一上午的时间,终于算是学会了.其实也是很简单的. iOS 新版 CocoaPods 安装流程 1.换掉现有Ruby默认源(由于好多 ...