forked from matrix0/send_email
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsend_email.py
185 lines (158 loc) · 6.97 KB
/
send_email.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
发送带附件的邮件基本思路如下:
1. 构造 MIMEMultipart 对象做为根容器
2. 构造 MIMEText 对象做为邮件显示内容并附加到根容器
3. 构造 MIMEImage 对象做为图片附件并附加到根容器
4. 构造 MIMEBase 对象做为文件附件内容并附加到根容器
a. 读入文件内容并格式化
b. 设置判断MIME类型并设置附件头
5. 设置根容器属性
6. 得到格式化后的完整文本
7. 用 smtp 发送邮件
20151016
"""
import os
import mimetypes
import smtplib
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from email import encoders
__author__ = "xxx_828@163.com"
def send_email(login=None, mail=None, images=None, attachments=None, use_ssl=None):
"""发送常规邮件,可以有图片和其它格式的附件
:param login: dict:登录信息,包括smtp服务器地址,帐号,密码
{'smtpserver': 'smtp.163.com',
'username': 'xxx@163.com',
'password': 'xxx'}
:param mail: dict:邮件内容,包含邮件类型,发送人,收件人(多人的话要使用列表),标题,内容.
{'email_type': "html", # 可以是:plain\html
'from': 'xxx@163.com',
'to': 'xxx@126.com',
'subject': "标题",
'content': "正文"}
:param images: # 图片附件列表(由路径组成)
:param attachments: # 其它附件列表(由路径组成)
:param use_ssl: # 否使用 ssl(暂时无用0
:return:
"""
smtpserver = login.get("smtpserver")
username = login.get("username")
password = login.get("password")
email_type = mail.get('email_type')
From = mail.get('from')
To = mail.get('to')
Subject = mail.get('subject')
content = mail.get('content')
if not To:
To = username
# To 是列表,就用分隔符合并
if isinstance(To, list):
To = ','.join(To)
if not email_type or (email_type not in ("plain", "html")):
email_type = "html"
# 构造MIME Multipart 对象做为根容器
main_msg = MIMEMultipart()
# 添加公共信息
main_msg['Subject'] = Subject
main_msg['From'] = From
main_msg['To'] = To
# main_msg.preamble = content[:100] # 序文
# 构造MIMEText对象做为邮件显示内容并附加到根容器,统一使用 utf-8
text_msg = MIMEText(content, email_type, 'utf-8')
main_msg.attach(text_msg)
if images:
for f in images:
fp = open(f, 'rb')
img_msg = MIMEImage(fp.read()) # 没有 _subtype 参数,MIMEImage 会自己探测图片类型
fp.close()
# 设置附件头
basename = os.path.basename(f)
img_msg.add_header('content-disposition',
'image' + str(images.index(f)), filename=basename)
main_msg.attach(img_msg)
if attachments:
# 构造MIMEBase对象做为文件附件内容并附加到根容器
for f in attachments:
basename = os.path.basename(f)
# 判断文件 MIME
if "." in basename: # 带扩展名的
content_type = mimetypes.types_map["." + basename.split(".")[-1]]
else: # 无扩展名的
content_type = 'application/octet-stream'
maintype, subtype = content_type.split('/', 1)
fp = open(f, 'rb')
file_msg = MIMEBase(maintype, subtype)
file_msg.set_payload(fp.read())
fp.close()
encoders.encode_base64(file_msg)
# 设置附件头
file_msg.add_header('Content-Disposition',
'attachment' + str(images.index(f)), filename=basename)
main_msg.attach(file_msg)
smtp = smtplib.SMTP(smtpserver)
# 使用 ssl 的情况
if use_ssl:
smtp.ehlo()
smtp.starttls()
smtp.ehlo()
smtp.login(username, password)
# smtp.set_debuglevel(1) # 调试模式
smtp.sendmail(From, To, main_msg.as_string())
smtp.quit()
if __name__ == '__main__':
d = [
{
"t": "plain",
"s": "测试纯文本的 email",
"c": """
测试一下纯文本内容,为什么不让我过?
•553 Requested action not taken: NULL sender is not allowed 不允许发件人为空,请使用真实发件人发送;
•553 Requested action not taken: Local user only SMTP类型的机器只允许发信人是本站用户;
""",
"a": None,
"i": None
},
{
"t": "html",
"s": "测试 html 格式的 email",
"c": """
测试一下HTML格式的内容,为什么不让我过?<br/>
•550 Requested mail action not taken: too much recipient 群发数量超过了限额;<br/>
<hr/>
•552 Requested mail action aborted: exceeded mailsize limit 发送的信件大小超过了网易邮箱允许接收的最大限制;<br/>
•553 Requested action not taken: NULL sender is not allowed 不允许发件人为空,请使用真实发件人发送;<br/>
•553 Requested action not taken: Local user only SMTP类型的机器只允许发信人是本站用户;<br/>
•553 Requested action not taken: no smtp MX only MX类型的机器不允许发信人是本站用户;<br/>
""",
"a": None,
"i": None
},
{
"t": "html",
"s": "测试 带图片的 email",
"c": """
测试一下带图片的内容<br/>
•550 Requested mail action not taken: too much recipient 群发数量超过了限额;<br/>
""",
"a": ("logo.png", "logo_s.png"),
"i": ("logo.png", "logo_s.png")
},
]
login = {'smtpserver': 'smtp.163.com',
'username': 'xxx@163.com',
'password': 'xxx'}
for i in d:
mail = {
'email_type': i["t"],
'from': 'xxx@163.com',
'to': ['xxx@126.com', 'xxx@163.com'], # 单人用字符串,多人用列表
'subject': i["s"],
'content': i["c"]
}
send_email(login=login, mail=mail, attachments=i["a"], images=i["i"])
print "发送完毕!"