目录
发送文本邮件
代码:
import smtplib
from email.mime.text import MIMEText
host = 'smtp.163.com'
user = 'csuzhucong@163.com' #发件人
password = '123456789'
def send_mail(to_list,subject,content):
msg=MIMEText(content,'plain','utf-8')
msg['from'] = user
msg['to'] = ','.join(to_list) #注意,不是分号
msg['subject'] = subject
server = smtplib.SMTP()
server.set_debuglevel(1)
try:
server.connect(host,25)
except:
print('connect fail')
try:
server.ehlo(user)
server.login(user,password)
print('login ok')
except:
print('login fail')
try:
server.sendmail(user, to_list, str(msg))
server.close()
return True
except OSError:
print('OSError')
return False
except:
print('unexpect error')
return False
def test():
if(send_mail(['2802482801@qq.com'],'test','just test')):
print('send ok')
else:
print('send fail')
if __name__ == '__main__':
test()
解释:
1,smtplib是SMTP服务的模块,发送者邮箱要开启SMTP服务
2,host是发送者服务器地址,163邮箱的服务器地址是'smtp.163.com',其他邮箱的服务器地址可以在网上查,不过需要注意,QQ邮箱的服务器地址有2种,取决于发送者邮箱开启SMTP服务的时间
3,user是发送者的邮箱
4,password是user的授权码,不是邮箱密码,授权码是用来三方登录邮箱的(不要尝试以代码中的授权码登录我的邮箱。。。否则。。。你会发现授权码是错的,这里是这个代码唯一需要修改的地方,修改之后就能发邮件)
5,to_list是收件人列表,是列表类型,其中每个元素(至少1个元素)都是字符串,对应一个邮箱地址
6,subject是邮件标题,是字符串类型
7,content是邮件正文,是字符串类型
8, 'plain'是邮件类型,表示文本类型
9,','.join(to_list)是把列表转化成字符串,包含多个收件人,注意,连接符是逗号
10,server.set_debuglevel(1)是显示调试信息
11,SMTP的默认端口是25,某些邮箱(比如QQ邮箱)的端口不是25
12,ehlo和helo是SMTP的用户认证,ehlo的e是拓展的意思,就是对helo的拓展
发送混合格式邮件
前面详细讲解了如何发送文本文件,这里讲解如何发送html、附件和图片
html很简单,只要MIMEText中的参数改成html即可
附件也不难,难的是加图片
虽然图片可以当做附件发送,但是显然还需要一个加入正文的功能,方法是用html的img标签把图片加入。但是这样会有个问题,一般的邮箱都会将这种链接屏蔽掉。这个问题有2种解决方法,第一种是先把图片加入到附件,然后再把图片加入正文,第二种是利用MIMEMultipart的三层结构。第一种方法就不能把图片直接加入正文而不加入附件列表,所以我采用第二种。
代码:
#coding=utf-8
import smtplib
import json
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
host = ''
user = '' #发件人
password = ''
sender = ''
def send_mail(to_list, subject, content,content_type='plain'):
msg_alt = MIMEMultipart('alternative')
msg_rel = MIMEMultipart('related')
msg = MIMEMultipart('mixed')
msg_rel.attach(msg_alt)
msg.attach(msg_rel)
msg['from'] = user
msg['to'] = ','.join(to_list) #注意,不是分号
msg['subject'] = subject
if(content_type == 'plain'):
for type,item in content:
if type == 'text':
text = MIMEText(item,'plain','utf-8')
msg_alt.attach(text)
elif type == 'attach_path':
attachment = get_attach(item)
if(attachment):
msg.attach(attachment)
else:
#print('type error')
pass
elif content_type == 'html':
mailBody = ''
for type,item in content:
if type == 'html':
mailBody += item
elif type == 'image_path':
image = get_image(item)
if(image):
con = '<p><img src=cid:'+ item +'></p>'
mailBody = mailBody + con
msg_rel.attach(image)
elif type == 'attach_path':
attachment = get_attach(item)
if(attachment):
msg.attach(attachment)
else:
#print('type error')
pass
html = MIMEText(mailBody,'html','utf-8')
msg_alt.attach(html)
else:
return False
server = smtplib.SMTP()
#server.set_debuglevel(1)
try:
server.connect(host,25)
except:
print('connect fail')
try:
server.ehlo(user)
server.login(user,password)
print('login ok')
except:
print('login fail')
try:
server.sendmail(sender, to_list, str(msg))
server.close()
return True
except OSError:
print('OSError')
return False
except:
print('unexpect error')
return False
#添加图片内容到正文
def get_image(image_path):
try:
fp = open(image_path,'rb')
except:
return None
image = MIMEImage(fp.read())
fp.close()
image.add_header( 'Content-ID' , '<'+image_path+'>' )
return image
#添加附件
def get_attach(attach_path):
try:
f = open(attach_path,'rb')
att = MIMEText(f.read(),'base64', 'utf-8')
f.close()
except FileNotFoundError:
print('FileNotFound')
return None
except:
print('unexpect error')
return None
att['Content-Type'] = 'application/octet-stream'
att['Content-Disposition'] = 'attachment; filename='+attach_path
return att
def analysis(json_arg):
arg = json.loads(json_arg)
to_list = arg['to_list']
subject = arg['subject']
content = arg['content']
content_type = 'plain'
try:
content_type = arg['content_type']
except:
pass
return
def test1():
recv = ['']
content = (('text','这不是垃圾邮件啊啊啊啊啊'),('attach_path','1.txt'))
arg1 = {'to_list':recv, 'subject':'test', 'content':content}
json_arg = json.dumps(arg1)
if(analysis(json_arg)):
print('send ok')
else:
print('send fail')
def test2():
recv = ['']
html = '<a href="http://www.baidu.com">百度链接</a>'
content = (('html' ,'看图'),('attach_path','1.txt'),('image_path','1.jpg'),('image_path','2.png'),('html',html)) #html的值不一定非要html代码,普通字符串也行
arg2 = {'to_list':recv, 'subject':'test', 'content':content,'content_type':'html'}
json_arg = json.dumps(arg2)
if(analysis(json_arg)):
print('send ok')
else:
print('send fail')
if __name__ == '__main__':
test1()
test2()
'''
send_mail.py接口说明:
函数analysis(json_arg)只有1个参数,json_arg是json类型,元素有3-4个
4个元素的键依次是to_list,subject,content,content_type
(1)to_list是收件人列表,是列表类型,其中每个元素(至少1个元素)都是字符串,对应一个邮箱地址
(2)subject是邮件标题,是字符串类型
(3)content是元祖类型,每个元素(type,item)是邮件正文中的1个内容,
type是'text'或'html'或'attach_path'或'image_path',对应的item(都是字符串)分别代表文本、html代码、附件名、图片名(如果需要的话前面带上路径名)
(4)content_type是'plain'或'html',如果是'plain'(可以缺省)那么content是'text'或'attach_path',如果是'html'那么content是'html'或'attach_path'或'image_path'
'''
主送、抄送、暗送
前面我解释了如何发送各种内容的邮件,但是收件人都是主送,没有抄送和暗送。
相关代码如下:
msg['from'] = user
msg['to'] = ','.join(to_list) #注意,不是分号
msg['subject'] = subject
server.sendmail(sender, to_list, str(msg))
要想实现抄送和暗送,只需要自定义收件人列表即可:
msg['from'] = user
msg['to'] = ','.join(to_list) #注意,不是分号
msg['cc'] = ','.join(ccto_list)
receive = to_list
receive.extend(ccto_list)
receive.extend(bccto_list)
msg['subject'] = subject
server.sendmail(sender,receive, str(msg))
这样,邮件发送给receive,即所有人,但是邮件中只显示主送和抄送,不显示暗送。
那么所有人都知道主送人是哪些,抄送人是哪些,但是主送人和抄送人不知道暗送人是哪些(不知道有没有暗送人),而暗送人只知道自己是被暗送的,不知道有没有其他暗送人。