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. 【转】win7 任务计划 任务映像已损坏或篡改(异常来自HRESULT:0x80041321)

    请这样操作:1. 以管理员身份运行命令提示符并执行命令chcp 437schtasks /query /v | find /i "ERROR: Task cannot be loaded:& ...

  2. EntityFramework走马观花之CRUD(下)

    我在Entity Framework系列文章的CRUD上篇中介绍了EF的数据查询,中篇谈到了EF的数据更新,下篇则聊聊EF实现CRUD的内部原理. 跟踪实体对象状态 在CRUD上篇和中篇谈到,为了实现 ...

  3. POJ3182 The Grove[射线法+分层图最短路]

    The Grove Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 904   Accepted: 444 Descripti ...

  4. 【BZOJ3630】[JLOI2014]镜面通道 几何+最小割

    [BZOJ3630][JLOI2014]镜面通道 Description 在一个二维平面上,有一个镜面通道,由镜面AC,BD组成,AC,BD长度相等,且都平行于x轴,B位于(0,0).通道中有n个外表 ...

  5. 【BZOJ4200】[Noi2015]小园丁与老司机 DP+最小流

    [BZOJ2839][Noi2015]小园丁与老司机 Description 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面.田野上有 nn 棵许愿树,编号 1,2,3,…,n1,2, ...

  6. EasyNVR NVR网页无插件直播在兼容宇视NVR RTSP流媒体时PLAY过程对Scale的兼容

    前一段在维护EasyNVR客户的过程中遇到一个问题,在接入宇视NVR的时候,就是明明在vlc中能非常正常播放的视频流,却用EasyRTSPClient RTSP客户端拉流的协议交互过程中,PLAY命令 ...

  7. EasyNVR RTSP转RTMP-HLS流媒体服务器前端构建之:bootstrap弹窗功能的实现

    在web前端的网页设计中,为了展示出简洁的网页风格和美观的效果,往往就会使用弹窗效果 在EasyNVR前端页面录像检索功能时,必然会播放录像,如果单独为播放录像文件排一个界面,用户在使用上会更加繁琐, ...

  8. Swift 学习笔记(扩展和泛型)

    在开始介绍Swift中的扩展之前,我们先来回忆一下OC中的扩展. 在OC中如果我们想对一个类进行功能的扩充,我们会怎么做呢. 对于面向对象编程的话,首先会想到继承,但是继承有两个问题. 第一个问题:继 ...

  9. view上下抖动特效

    shake.xml <?xml version="1.0" encoding="utf-8"?> <translate xmlns:andro ...

  10. android MVP模式思考

    在软件开发设计中,有多种软件设计模式,如web开发中经典的MVC, 将后台分为三层:Model层,View层和Controller层,其中,Model主要是数据处理,如数据库,文件,或网络数据等:Vi ...