python发邮件
#coding: utf-8
#来自转载 地址忘记了
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.header import Header
#设置smtplib所需的参数
#下面的发件人,收件人是用于邮件传输的。
smtpserver = 'smtp.163.com'
username = 'XXX@163.com'
password='XXX'
sender='XXX@163.com'
#receiver='XXX@126.com'
#收件人为多个收件人
receiver=['XXX@126.com','XXX@126.com']
subject = 'Python email test'
#通过Header对象编码的文本,包含utf-8编码信息和Base64编码信息。以下中文名测试ok
#subject = '中文标题'
#subject=Header(subject, 'utf-8').encode()
#构造邮件对象MIMEMultipart对象
#下面的主题,发件人,收件人,日期是显示在邮件页面上的。
msg = MIMEMultipart('mixed')
msg['Subject'] = subject
msg['From'] = 'XXX@163.com <XXX@163.com>'
#msg['To'] = 'XXX@126.com'
#收件人为多个收件人,通过join将列表转换为以;为间隔的字符串
msg['To'] = ";".join(receiver)
#msg['Date']='2012-3-16'
#构造文字内容
text = "Hi!\nHow are you?\nHere is the link you wanted:\nhttp://www.baidu.com"
text_plain = MIMEText(text,'plain', 'utf-8')
msg.attach(text_plain)
#构造图片链接
sendimagefile=open(r'D:\pythontest\testimage.png','rb').read()
image = MIMEImage(sendimagefile)
image.add_header('Content-ID','<image1>')
image["Content-Disposition"] = 'attachment; filename="testimage.png"'
msg.attach(image)
#构造html
#发送正文中的图片:由于包含未被许可的信息,网易邮箱定义为垃圾邮件,报554 DT:SPM :<p><img src="cid:image1"></p>
html = """
<html>
<head></head>
<body>
<p>Hi!<br>
How are you?<br>
Here is the <a href="http://www.baidu.com">link</a> you wanted.<br>
</p>
</body>
</html>
"""
text_html = MIMEText(html,'html', 'utf-8')
text_html["Content-Disposition"] = 'attachment; filename="texthtml.html"'
msg.attach(text_html)
#构造附件
sendfile=open(r'D:\pythontest\1111.txt','rb').read()
text_att = MIMEText(sendfile, 'base64', 'utf-8')
text_att["Content-Type"] = 'application/octet-stream'
#以下附件可以重命名成aaa.txt
#text_att["Content-Disposition"] = 'attachment; filename="aaa.txt"'
#另一种实现方式
text_att.add_header('Content-Disposition', 'attachment', filename='aaa.txt')
#以下中文测试不ok
#text_att["Content-Disposition"] = u'attachment; filename="中文附件.txt"'.decode('utf-8')
msg.attach(text_att)
#发送邮件
smtp = smtplib.SMTP()
smtp.connect('smtp.163.com')
#我们用set_debuglevel(1)就可以打印出和SMTP服务器交互的所有信息。
#smtp.set_debuglevel(1)
smtp.login(username, password)
smtp.sendmail(sender, receiver, msg.as_string())
smtp.quit()
import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.image import MIMEImage from email.header import Header from datetime import datetime,timedelta # import gzip # import string import json import save_jpg #自定义图片统计模块 class send(): def __init__(self,content): self.content = content def send_email(self): error = self.content save_jpg.save_jpg() date = datetime.now().strftime('%Y-%m-%d ') yesterday = (datetime.now() + timedelta(-1)).strftime('%Y-%m-%d') #设置smtplib所需的参数 #下面的发件人,收件人是用于邮件传输的。 smtpserver = 'smtp.163.com' #需要在邮箱里设置 接受 username = 'wenqiang_leo@163.com' password='SFQXXLZHAHORDTSE' #授权码 # password=base64.b64encode('wenjiang'.encode()).decode() sender='wenqiang_leo@163.com' #发送邮箱 with open(r'receiver.json','r',encoding='utf8') as df: receiver = json.load(df) receiver = receiver['receiver'] # receiver=['1642151528@qq.com'] #接收邮箱 subject = '百度统计数据获取报警日志-%s'%date #构造邮件对象MIMEMultipart对象 msg = MIMEMultipart('mixed') msg['Subject'] = subject #主题 msg['From'] = 'wenqiang_leo@163.com <wenqiang_leo@163.com>' # msg['To'] = '1642151528@qq.com' # 收件人为多个收件人,通过join将列表转换为以;为间隔的字符串 msg['To'] = ";".join(receiver) msg['Date'] = date msgAlternative = MIMEMultipart('alternative') msg.attach(msgAlternative) #构造文字内容 text = """ <p>百度统计数据获取错误报警:\n%s</p> <p><a href="http://www.qq.com"></a></p> <p>近30天数据统计:</p> <p><img src="cid:image1"></p> """%error # text_plain = MIMEText(text,'plain', 'utf-8') #'plain'文本内容 html_plain = MIMEText(text,'html', 'utf-8') #'HTML'html类型内容 msgAlternative.attach(html_plain) # #构造图片链接 sendimagefile=open(r'image/baidu_data.jpg','rb').read() image = MIMEImage(sendimagefile) image.add_header('Content-ID','<image1>') image["Content-Disposition"] = 'attachment; filename="testimage.png"' msg.attach(image) #发送邮件 smtp = smtplib.SMTP() smtp.connect('smtp.163.com') #如果报错 则忽略证书 #smtp = smtplib.SMTP_SSL(r'smtp.163.com', 465) #smtp.ehlo(r'smtp.163.com') #我们用set_debuglevel(1)就可以打印出和SMTP服务器交互的所有信息。 # smtp.set_debuglevel(1) smtp.login(username, password) smtp.sendmail(sender, receiver, msg.as_string()) smtp.quit()
MIME 类型
语法
通用结构
type/subtype
MIME的组成结构非常简单;由类型与子类型两个字符串中间用'/'
分隔而组成。不允许空格存在。type 表示可以被分多个子类的独立类别。subtype 表示细分后的每个类型。
MIME类型对大小写不敏感,但是传统写法都是小写。
独立类型
text/plain text/html image/jpeg image/png audio/mpeg audio/ogg audio/* video/mp4 application/* application/json application/javascript application/ecmascript application/octet-stream …
独立类型表明了对文件的分类,可以是如下之一:
类型 | 描述 | 典型示例 |
---|---|---|
text |
表明文件是普通文本,理论上是人类可读 | text/plain , text/html , text/css, text/javascript |
image |
表明是某种图像。不包括视频,但是动态图(比如动态gif)也使用image类型 | image/gif , image/png , image/jpeg , image/bmp , image/webp , image/x-icon , image/vnd.microsoft.icon |
audio |
表明是某种音频文件 | audio/midi , audio/mpeg, audio/webm, audio/ogg, audio/wav |
video |
表明是某种视频文件 | video/webm , video/ogg |
application |
表明是某种二进制数据 |
|
对于text文件类型若没有特定的subtype,就使用 text/plain
。类似的,二进制文件没有特定或已知的 subtype,即使用 application/octet-stream
。
Multipart 类型
multipart/form-data multipart/byteranges
Multipart 类型表示细分领域的文件类型的种类,经常对应不同的 MIME 类型。这是复合文件的一种表现方式。multipart/form-data
可用于联系 HTML Forms 和 POST
方法,此外 multipart/byteranges
使用状态码206
Partial Content
来发送整个文件的子集,而HTTP对不能处理的复合文件使用特殊的方式:将信息直接传送给浏览器(这时可能会建立一个“另存为”窗口,但是却不知道如何去显示内联文件。)
重要的MIME类型
application/octet-stream
这是应用程序文件的默认值。意思是 未知的应用程序文件 ,浏览器一般不会自动执行或询问执行。浏览器会像对待 设置了HTTP头Content-Disposition
值为 attachment
的文件一样来对待这类文件。
text/plain
文本文件默认值。即使它意味着未知的文本文件,但浏览器认为是可以直接展示的。
text/plain
并不是意味着某种文本数据。如果浏览器想要一个文本文件的明确类型,浏览器并不会考虑他们是否匹配。比如说,如果通过一个表明是下载CSS文件的<link>
链接下载了一个 text/plain
文件。如果提供的信息是text/plain,浏览器并不会认出这是有效的CSS文件。CSS类型需要使用text/css。
text/css
在网页中要被解析为CSS的任何CSS文件必须指定MIME为text/css
。通常,服务器不识别以.css为后缀的文件的MIME类型,而是将其以MIME为text/plain
或 application/octet-stream
来发送给浏览器:在这种情况下,大多数浏览器不识别其为CSS文件,直接忽略掉。特别要注意为CSS文件提供正确的MIME类型。
text/html
所有的HTML内容都应该使用这种类型。XHTML的其他MIME类型(如application/xml+html
)现在基本不再使用(HTML5统一了这些格式)。
Note: You still need to use application/xml
or application/xhtml+xml
if you intend to make use of XML’s strict parsing rules, use <![CDATA[…]]>
or elements from non‑HTML, non‑SVG or non‑MathML XML namespaces, as text/html
’s parsing semantics are subtly incompatible with those of application/xml
.
JavaScript types
据 MIME 嗅探标准,下面是有效的 JavaScript MIME 类型
application/javascript
application/ecmascript
application/x-ecmascript
application/x-javascript
text/ecmascript
text/javascript
text/javascript1.0
text/javascript1.1
text/javascript1.2
text/javascript1.3
text/javascript1.4
text/javascript1.5
text/jscript
text/livescript
text/x-ecmascript
text/x-javascript
所有的 text
JavaScript 类型已经被 RFC 4329 废弃。
图片类型
只有一小部分图片类型是被广泛支持的,Web安全的,可随时在Web页面中使用的:
MIME 类型 | 图片类型 |
---|---|
image/gif |
GIF 图片 (无损耗压缩方面被PNG所替代) |
image/jpeg |
JPEG 图片 |
image/png |
PNG 图片 |
image/svg+xml |
SVG图片 (矢量图) |
此处的类型划分有一定的争议,有人认为此处应该增加 WebP(image/webp
),但是每个新增的图片类型都会增加代码的数量,这会带来一些新的安全问题,所以浏览器供应商对于添加类型非常小心。
另外的一些图片种类可以在Web文档中找到。比如很多浏览器支持 icon 类型的图标作为 favicons或者类似的图标,并且浏览器在MIME类型中的 image/x-icon
支持ICO图像。
- Footnote 1
- 尽管
image/vnd.microsoft.icon
在ANA注册, 它仍然不被广泛支持,image/x-icon
被作为替代品使用。
音频与视频类型
HTML并没有明确定义被用于<audio>
和<video>
元素所支持的文件类型,所以在web上使用的只有相对较小的一组类型。 文章 Media formats supported by the HTML audio and video elements 解释了可以被使用的解码器或视频文件格式。
在web环境最常用的视频文件的格式,是以下这些这些文件类型:
MIME 类型 | 音频或视频类型 |
---|---|
audio/wave audio/wav audio/x-wav audio/x-pn-wav |
音频流媒体文件。一般支持PCM音频编码 (WAVE codec "1") ,其他解码器有限支持(如果有的话)。 |
audio/webm |
WebM 音频文件格式。Vorbis 和 Opus 是其最常用的解码器。 |
video/webm |
采用WebM视频文件格式的音视频文件。VP8 和 VP9是其最常用的视频解码器。Vorbis 和 Opus 是其最常用的音频解码器。 |
audio/ogg |
采用OGG多媒体文件格式的音频文件。 Vorbis 是这个多媒体文件格式最常用的音频解码器。 |
video/ogg |
采用OGG多媒体文件格式的音视频文件。常用的视频解码器是 Theora;音频解码器为Vorbis 。 |
application/ogg |
采用OGG多媒体文件格式的音视频文件。常用的视频解码器是 Theora;音频解码器为Vorbis 。 |
application/json |
application/json (MIME_type) https://en.wikipedia.org/wiki/Media_type#Common_examples https://www.iana.org/assignments/media-types/application/json |
multipart/form-data
multipart/form-data
可用于HTML表单从浏览器发送信息给服务器。作为多部分文档格式,它由边界线(一个由'--'
开始的字符串)划分出的不同部分组成。每一部分有自己的实体,以及自己的 HTTP 请求头,Content-Disposition
和 Content-Type
用于文件上传领域,最常用的 (Content-Length
因为边界线作为分隔符而被忽略)。
Content-Type: multipart/form-data; boundary=aBoundaryString (other headers associated with the multipart document as a whole) --aBoundaryString Content-Disposition: form-data; name="myFile"; filename="img.jpg" Content-Type: image/jpeg (data) --aBoundaryString Content-Disposition: form-data; name="myField" (data) --aBoundaryString (more subparts) --aBoundaryString--
如下所示的表单:
<form action="http://localhost:8000/" method="post" enctype="multipart/form-data">
<input type="text" name="myTextField">
<input type="checkbox" name="myCheckBox">Check</input>
<input type="file" name="myFile">
<button>Send the file</button>
</form>
会发送这样的请求:
POST / HTTP/1.1
Host: localhost:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Content-Type: multipart/form-data; boundary=---------------------------8721656041911415653955004498
Content-Length: 465
-----------------------------8721656041911415653955004498
Content-Disposition: form-data; name="myTextField"
Test
-----------------------------8721656041911415653955004498
Content-Disposition: form-data; name="myCheckBox"
on
-----------------------------8721656041911415653955004498
Content-Disposition: form-data; name="myFile"; filename="test.txt"
Content-Type: text/plain
Simple file.
-----------------------------8721656041911415653955004498--
multipart/byteranges
multipart/byteranges
用于把部分的响应报文发送回浏览器。当发送状态码206
Partial Content
时,这个MIME类型用于指出这个文件由若干部分组成,每一个都有其请求范围。就像其他很多类型Content-Type
使用分隔符来制定分界线。每一个不同的部分都有Content-Type
这样的HTTP头来说明文件的实际类型,以及 Content-Range
来说明其范围。
HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Content-Type: multipart/byteranges; boundary=3d6b6a416f9b5
Content-Length: 385
--3d6b6a416f9b5
Content-Type: text/html
Content-Range: bytes 100-200/1270
eta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="vieport" content
--3d6b6a416f9b5
Content-Type: text/html
Content-Range: bytes 300-400/1270
-color: #f0f0f2;
margin: 0;
padding: 0;
font-family: "Open Sans", "Helvetica
--3d6b6a416f9b5--
设置正确的MIME类型的重要性
很多web服务器使用默认的 application/octet-stream
来发送未知类型。出于一些安全原因,对于这些资源浏览器不允许设置一些自定义默认操作,导致用户必须存储到本地以使用。常见的导致服务器配置错误的文件类型如下所示:
-
RAR编码文件。在这种情况,理想状态是,设置真实的编码文件类型;但这通常不可能(可能是服务器所未知的类型或者这个文件包含许多其他的不同的文件类型)。这这种情况服务器将发送
application/x-rar-compressed
作为MIME类型,用户不会将其定义为有用的默认操作。 -
音频或视频文件。只有正确设置了MIME类型的文件才能被
<video>
或<audio>
识别和播放。 可参照 use the correct type for audio and video。 -
专有文件类型。是专有文件时需要特别注意。使用
application/octet-stream
作为特殊处理是不被允许的:对于一般的MIME类型浏览器不允许定义默认行为(比如“在Word中打开”)