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. python升级或者其他原因把yum搞坏了

    第一个命令查询出来,原本是安装的啥版本 rpm -qa | grep python- | grep 2.6 然后执行下一个命令,就可以安装原本的python版本了,注意链接要换成你对应的那个版本 rp ...

  2. delphi 解析Json格式(转自:http://blog.csdn.net/jayqiang/article/details/7066824)

    SuperObject 是开源的 Delphi 的 JSON 工具包,可生成 JSON 数据以及进行 JSON 解析. unit Unit6; interface uses Windows, Mess ...

  3. Socket的UDP协议在erlang中的实现

    现在我们看看UDP协议(User Datagram Protocol,用户数据报协议).使用UDP,互联网上的机器之间可以互相发送小段的数据,叫做数据报.UDP数据报是不可靠的,这意味着如果客户端发送 ...

  4. WebRTC for android ios开发官方指南

    The WebRTC native code package can be found at: https://chromium.googlesource.com/external/webrtc ht ...

  5. 多媒体开发之---如何确定slice_header slice_type 的位置

    引用网友的问答:我找到0x000001 NAL的开头了,请问如何确定slice head的位置,继而得出slice_type呢?Nal unit后紧跟的就是slice head吗?标准里的循环让人看得 ...

  6. sigar 监控服务器硬件信息

    转载 http://www.cnblogs.com/jifeng/archive/2012/05/16/2503519.html 通过使用第三方开源jar包sigar.jar我们可以获得本地的信息 1 ...

  7. vue-cli3.0升级失败,vue-cli卸载不掉,vue-cli升级不了3.0

    https://juejin.im/post/5bf7d67c51882518805acb1a vue-cli3.0 使用图形化界面创建和管理项目

  8. 3597: [Scoi2014]方伯伯运椰子[分数规划]

    3597: [Scoi2014]方伯伯运椰子 Time Limit: 30 Sec  Memory Limit: 64 MB Submit: 404  Solved: 249 [Submit][Sta ...

  9. 九度OJ 1176:树查找 (完全二叉树)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5209 解决:2193 题目描述: 有一棵树,输出某一深度的所有节点,有则输出这些节点,无则输出EMPTY.该树是完全二叉树. 输入: 输入 ...

  10. viewport详解

    本文主要讲解viewpor相关知识. 参考资料&内容来源 博客园:https://www.cnblogs.com/zaoa/p/8630393.html 博客园:http://www.cnbl ...