PHP调用Python快速发送高并发邮件
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编码。
- #!/usr/bin/python
- # -*- coding:gbk -*-
- """
- 邮件发送类
- """
- # mail.py
- #
- # Copyright (c) 2014 by http://blog.csdn.net/CleverCode
- #
- # modification history:
- # --------------------
- # 2014/8/15, by CleverCode, Create
- import threading
- import time
- import random
- from email.MIMEText import MIMEText
- from email.MIMEMultipart import MIMEMultipart
- from email.MIMEBase import MIMEBase
- from email import Utils, Encoders
- import mimetypes
- import sys
- import smtplib
- import socket
- import getopt
- import os
- class SendMail:
- def __init__(self,smtpServer,username,password):
- """
- smtpServer:smtp服务器,
- username:登录名,
- password:登录密码
- """
- self.smtpServer = smtpServer
- self.username = username
- self.password = password
- def genMsgInfo(self,fromAddress,toAddress,subject,content,fileList,\
- subtype = 'plain',charset = 'gb2312'):
- """
- 组合消息发送包
- fromAddress:发件人,
- toAddress:收件人,
- subject:标题,
- content:正文,
- fileList:附件,
- subtype:plain或者html
- charset:编码
- """
- msg = MIMEMultipart()
- msg['From'] = fromAddress
- msg['To'] = toAddress
- msg['Date'] = Utils.formatdate(localtime=1)
- msg['Message-ID'] = Utils.make_msgid()
- #标题
- if subject:
- msg['Subject'] = subject
- #内容
- if content:
- body = MIMEText(content,subtype,charset)
- msg.attach(body)
- #附件
- if fileList:
- listArr = fileList.split(',')
- for item in listArr:
- #文件是否存在
- if os.path.isfile(item) == False:
- continue
- att = MIMEText(open(item).read(), 'base64', 'gb2312')
- att["Content-Type"] = 'application/octet-stream'
- #这里的filename邮件中显示什么名字
- filename = os.path.basename(item)
- att["Content-Disposition"] = 'attachment; filename=' + filename
- msg.attach(att)
- return msg.as_string()
- def send(self,fromAddress,toAddress,subject = None,content = None,fileList = None,\
- subtype = 'plain',charset = 'gb2312'):
- """
- 邮件发送函数
- fromAddress:发件人,
- toAddress:收件人,
- subject:标题
- content:正文
- fileList:附件列表
- subtype:plain或者html
- charset:编码
- """
- try:
- server = smtplib.SMTP(self.smtpServer)
- #登录
- try:
- server.login(self.username,self.password)
- except smtplib.SMTPException,e:
- return "ERROR:Authentication failed:",e
- #发送邮件
- server.sendmail(fromAddress,toAddress.split(',') \
- ,self.genMsgInfo(fromAddress,toAddress,subject,content,fileList,subtype,charset))
- #退出
- server.quit()
- except (socket.gaierror,socket.error,socket.herror,smtplib.SMTPException),e:
- return "ERROR:Your mail send failed!",e
- return 'OK'
- def usage():
- """
- 使用帮助
- """
- print """Useage:%s [-h] -s <smtpServer> -u <username> -p <password> -f <fromAddress> -t <toAddress> [-S <subject> -c
- <content> -F <fileList>]
- Mandatory arguments to long options are mandatory for short options too.
- -s, --smtpServer= smpt.xxx.com.
- -u, --username= Login SMTP server username.
- -p, --password= Login SMTP server password.
- -f, --fromAddress= Sets the name of the "from" person (i.e., the envelope sender of the mail).
- -t, --toAddress= Addressee's address. -t "test@test.com,test1@test.com".
- -S, --subject= Mail subject.
- -c, --content= Mail message.-c "content, ......."
- -F, --fileList= Attachment file name.
- -h, --help Help documen.
- """ %sys.argv[0]
- def start():
- """
- """
- try:
- options,args = getopt.getopt(sys.argv[1:],"hs:u:p:f:t:S:c:F:","--help --smtpServer= --username= --password= --fromAddress= --toAddress= --subject= --content= --fileList=",)
- except getopt.GetoptError:
- usage()
- sys.exit(2)
- return
- smtpServer = None
- username = None
- password = None
- fromAddress = None
- toAddress = None
- subject = None
- content = None
- fileList = None
- #获取参数
- for name,value in options:
- if name in ("-h","--help"):
- usage()
- return
- if name in ("-s","--smtpServer"):
- smtpServer = value
- if name in ("-u","--username"):
- username = value
- if name in ("-p","--password"):
- password = value
- if name in ("-f","--fromAddress"):
- fromAddress = value
- if name in ("-t","--toAddress"):
- toAddress = value
- if name in ("-S","--subject"):
- subject = value
- if name in ("-c","--content"):
- content = value
- if name in ("-F","--fileList"):
- fileList = value
- if smtpServer == None or username == None or password == None:
- print 'smtpServer or username or password can not be empty!'
- sys.exit(3)
- mail = SendMail(smtpServer,username,password)
- ret = mail.send(fromAddress,toAddress,subject,content,fileList)
- if ret != 'OK':
- print ret
- sys.exit(4)
- print 'OK'
- return 'OK'
- if __name__ == '__main__':
- start()
2.2 python程序使用帮助
2.3 php程序
- <?php
- /**
- * SendMail.php
- *
- * 发送邮件类
- *
- * Copyright (c) 2015 by http://blog.csdn.net/CleverCode
- *
- * modification history:
- * --------------------
- * 2015/5/18, by CleverCode, Create
- *
- */
- class SendMail{
- /**
- * 发送邮件方法
- *
- * @param string $fromAddress 发件人,'clevercode@qq.com' 或者修改发件人名 'CleverCode<clevercode@qq.com>'
- * @param string $toAddress 收件人,多个收件人逗号分隔,'test1@qq.com,test2@qq.com,test3@qq.com....', 或者 'test1<test1@qq.com>,test2<test2@qq.com>,....'
- * @param string $subject 标题
- * @param string $content 正文
- * @param string $fileList 附件,附件必须是绝对路径,多个附件逗号分隔。'/data/test1.txt,/data/test2.tar.gz,...'
- * @return string 成功返回'OK',失败返回错误信息
- */
- public static function send($fromAddress, $toAddress, $subject = NULL, $content = NULL, $fileList = NULL){
- if (strlen($fromAddress) < 1 || strlen($toAddress) < 1) {
- return '$fromAddress or $toAddress can not be empty!';
- }
- // smtp服务器
- $smtpServer = 'smtp.qq.com';
- // 登录用户
- $username = 'clevercode@qq.com';
- // 登录密码
- $password = '123456';
- // 拼接命令字符串,实际是调用了/home/CleverCode/mail.py
- $cmd = "LANG=C && /usr/bin/python /home/CleverCode/mail.py";
- $cmd .= " -s '$smtpServer'";
- $cmd .= " -u '$username'";
- $cmd .= " -p '$password'";
- $cmd .= " -f '$fromAddress'";
- $cmd .= " -t '$toAddress'";
- if (isset($subject) && $subject != NULL) {
- $cmd .= " -S '$subject'";
- }
- if (isset($content) && $content != NULL) {
- $cmd .= " -c '$content'";
- }
- if (isset($fileList) && $fileList != NULL) {
- $cmd .= " -F '$fileList'";
- }
- // 执行命令
- exec($cmd, $out, $status);
- if ($status == 0) {
- return 'OK';
- } else {
- return "Error,Send Mail,$fromAddress,$toAddress,$subject,$content,$fileList ";
- }
- return 'OK';
- }
- }
2.3 使用样例
- <?php
- /**
- * test.php
- *
- * 压缩excel成附件,发送邮件
- *
- * Copyright (c) 2015 http://blog.csdn.net/CleverCode
- *
- * modification history:
- * --------------------
- * 2015/5/14, by CleverCode, Create
- *
- */
- include_once ('SendMail.php');
- /*
- * 客户端类
- * 让客户端和业务逻辑尽可能的分离,降低页面逻辑和业务逻辑算法的耦合,
- * 使业务逻辑的算法更具有可移植性
- */
- class Client{
- public function main(){
- // 发送者
- $fromAddress = 'CleverCode<clevercode@qq.com>';
- // 接收者
- $toAddress = 'all@qq.com';
- // 标题
- $subject = '这里是标题!';
- // 正文
- $content = "您好:\r\n";
- $content .= " 这里是正文\r\n ";
- // excel路径
- $filePath = dirname(__FILE__) . '/excel';
- $sdate = date('Y-m-d');
- $PreName = 'CleverCode_' . $sdate;
- // 文件名
- $fileName = $filePath . '/' . $PreName . '.xls';
- // 压缩excel文件
- $cmd = "cd $filePath && zip $PreName.zip $PreName.xls";
- exec($cmd, $out, $status);
- $fileList = $filePath . '/' . $PreName . '.zip';
- // 发送邮件(附件为压缩后的文件)
- $ret = SendMail::send($fromAddress, $toAddress, $subject, $content, $fileList);
- if ($ret != 'OK') {
- return $ret;
- }
- return 'OK';
- }
- }
- /**
- * 程序入口
- */
- function start(){
- $client = new Client();
- $client->main();
- }
- start();
- ?>
2.4 程序源码下载
PHP调用Python快速发送高并发邮件的更多相关文章
- python导出zabbix数据并发邮件脚本
Zabbix没有报表导出的功能,于是通过编写脚本导出zabbix数据并发邮件.效果如下: 下面是脚本,可根据自己的具体情况修改: #!/usr/bin/python #coding:utf-8 imp ...
- Python Tornado搭建高并发Restful API接口服务
Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快能实现高并发.得利于其 非阻塞的方式和对epoll的运用,Torn ...
- python 快速发送大量邮件
因为公司需求,需要发送千万封级别邮件. # coding:utf-8 import csv import smtplib from email.mime.text import MIMEText im ...
- 用Python控制摄像头拍照并发邮件
概述前言 工具 思路 安装及导入包 设置参数 实现拍照 构造邮件内容 发送邮件 判断网络连接 开机自启 后记 o1 前言为什么会有写这个程序的想法呢? 最初的想法是写一个可以用电脑前置摄像头拍照的程序 ...
- Python 实现发送、抄送邮件功能
发送邮件 问题 在web.py中,如何发送邮件? 解法 在web.py中使用web.sendmail()发送邮件. web.sendmail('cookbook@webpy.org', 'user@e ...
- Mac怎么快速创建便签和发送附件的邮件
1.如何快速创建便签 在Mac的任意界面选中文字:shift+command+y 就能创建便签2.如何快速发送附件的邮件(网页界面) 在Safari网页界面 command ...
- Python3+smtplib+poplib+imaplib实现发送和收取邮件(以qq邮箱为例)
一.说明 1.1 程序说明 (1)smtp是邮件发送协议:pop和imap都是邮件接收协议,两者的区别通常的说法是imap的操作会同步到邮箱服务器而pop不会,表现上我也不是很清楚 (2)本程序实现使 ...
- [记录]Python高并发编程
========== ==多进程== ========== 要让Python程序实现多进程(multiprocessing),我们先了解操作系统的相关知识. Unix/Linux操作系统提供了一个fo ...
- java调用html模板发送html内容的邮件
在项目需要发送邮件,普通内容的邮件觉得太单调.太丑,没逼格,所以说直接把用到的邮件内容做成一个html模板,发送之前将对应参数替换掉,发送html内容的高逼格邮件. 首先需要引用jar包,这就不多说了 ...
随机推荐
- 美景听听Ai语音导游,助力华为荣耀PLAY手机发布
6月6日,荣耀PLAY科技酷玩新品发布会在北京大学生体育馆如期举办,美景听听Ai语音讲解助力新EUMI系统智慧旅行成新卖点,震撼登场! 随着生活水平的不断提升,出门旅行已经成了许多亲们释放压力.调节自 ...
- Linux下实现RAID
一.实验目的 1.掌握Linux系统下软RAID的实现方法: 2.掌握RAID5的配置过程: 3. 通过实验熟悉RAID.5的特点. 二.实验内容及步骤 1.在VMware中创建一台Linux. 2. ...
- mfc 小程序---在系统菜单中添加菜单项
1建立一个对话框工程:在dlg类里定义一个菜单指针m_pMenu,在对话框OnInitDialog函数里添加代码: m_pMenu=GetSystemMenu(FALSE);//获取系统菜单的指针 m ...
- EasyPlayerPro RTMP播放器助力远程娃娃机直播抓娃娃技术方案
远程娃娃机 目前市面上娃娃机的方案有很多种.核心的技术流程就是实现远程直播加上对娃娃机手臂的远程操作.其中最主要的技术还是视频直播方案,需要低延时,视频秒开等流媒体技术. 最简单的直播方案 视频直播方 ...
- 九度OJ 1027:欧拉回路 (欧拉回路)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2989 解决:1501 题目描述: 欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路.现给定一个图,问是 ...
- 早一天把生意做到de
const isMobilePhoneNum = (params) => { const areaCode = params.areaCode || 'cn' const str = param ...
- iOSapp内跳转到设置界面
从app内跳转到设置界面的代码如下: NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; if ([[UIAp ...
- SDUT OJ I样(0-1背包问题 【模板】)
I样 Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 这是个什么问题呢?DP,贪心,数据结构,图论,数论还是计算几何?管他呢,反正 ...
- Keepalived实现心跳检测实现自动重启
项目中服务器如果发生宕机:1.故障转移 2.心跳检测 3.负载均衡 4.自动重启 心跳检测: 心跳检测脚本: 写入nginx_check.sh脚本 vi /etc/keepalived/nginx_ ...
- 算法(Algorithms)第4版 练习 1.3.25 1.3.24
代码实现: //1.3.24 /** * remove the node following the node x * (and does nothing if the argument or the ...