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. linux crontab 定时任务解析

    -----------crontab定时任务---------------------- 检查crontab工具是否安装 crontab -l 检查crontab服务是否启动 service cron ...

  2. 【TensorFlow-windows】(七) CNN之VGG-net的测试

    主要内容: 1.CNN之VGG-net的测试 2.该实现中的函数总结 平台: 1.windows 10 64位 2.Anaconda3-4.2.0-Windows-x86_64.exe (当时TF还不 ...

  3. JAVA学习第五十二课 — IO流(六)File对象

    File类 用来给文件或者目录封装成对象 方便对文件与目录的属性信息进行操作 File对象能够作为參数传递给流的构造函数 一.构造函数和分隔符 public static void FileDemo( ...

  4. 在安装ubuntu时,卡在启动画面

    在我安装ubuntu时发生的情况,记录下来希望能帮助到需要帮助的朋友. 我先后尝试16.04与14.05两个版本的Ubuntu系统,方法均为:https://www.ubuntu.com/downlo ...

  5. BeeFramework 系列二 UISignal篇下

    本文转载至 http://www.apkbus.com/android-126129-1-1.html     qihoo2 该用户从未签到 156 主题 156 帖子 1826 积分 Android ...

  6. C#中的new和override(转)

    在衍生类中的方法上使用new和override关键字有何意义,可以通过一系列问题来找到答案.先看一段代码: 1 class Program 2 { 3 static void Main(string[ ...

  7. css 字体的unicode码

    微软雅黑: YaHei宋体: SimSun黑体: SimHei ;

  8. Grunt 学习笔记【1】----基础知识

    题记:虽然现在大家都在推Webpack,无奈业务需要,因此研究下Grunt. 说明:本文是基于Grunt 0.4.5版本. 一 说明 为何要用构建工具? 一句话:自动化.对于需要反复重复的任务,例如压 ...

  9. php总结2——php中的变量、数据类型及转换、运算符、流程控制中的分支结构

    2.1  php中的变量: 定义变量:$变量名称=值: 变量名称:$开头    $之后的第一位必须是字母    $第二位之后可以是字母.数字或者是下划线.习惯上变量名称有实际含义,第二个单词后首字母大 ...

  10. 超限学习机 (Extreme Learning Machine, ELM) 学习笔记 (一)

    1. ELM 是什么 ELM的个人理解: 单隐层的前馈人工神经网络,特别之处在于训练权值的算法: 在单隐层的前馈神经网络中,输入层到隐藏层的权值根据某种分布随机赋予,当我们有了输入层到隐藏层的权值之后 ...