本例使用的时python2.7环境,python3的操作应该也是差不多的。
需要用到smtplib和email两个包。
发送文本类型的邮件
下面看个发送文本邮件的例子(使用网易163的SMTP):
# -*- coding: UTF-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.header import Header
from email.utils import formataddr
# 第三方SMTP
mail_host = "smtp.163.com" # SMTP服务器
mail_user = "sender@163.com" # 发送者邮箱
mail_pass = "******" # 邮箱的客户端授权码
sender = "sender@163.com" # 邮件的发送者
recivers = ["bob@qq.com", "someone@gmail.com"] # 邮件接收者,可以指定多个
# 三个参数:第一个为文本内容,第二个设置文本格式,第三个设置字符编码
message = MIMEText('Python邮件发送测试', 'plain', 'utf-8')
message['From'] = sender;
# == message['From'] = formataddr(['sender', sender])
message['To'] = ", ".join(recivers)
# == message['To] = formataddr(['ok', ', '.join(recivers)])
subject = 'Python 邮件测试'
message['Subject'] = Header(subject, 'utf-8')
try:
smtpObj = smtplib.SMTP()
smtpObj.connect(mali_host, 25) # 连接SMTP,端口为25
smtpObj.set_debuglevel(1)
smtpObj.login(mail_user, mail_pass)
smtpObj.sendmail(sender, recivers,message.as_string())
print "emails send successfully"
except smtplib.SMTPException:
print "Error:cannot send emails"
smtpObj.quit() # 关闭连接
好像网易的SMTP有坑,message['From']和message['To']都要和sender和recivers一致才可以,还有标题和内容尽量不要有敏感词,否则会被服务器判为垃圾邮件而发不出去,我第一次就因为Subject带有“SMTP”而被拦截(滑稽.gif)。
如果邮件发送失败,可以查看set_debuglevel()函数返回的状态码来判定什么原因。
发送HTML格式的邮件
与发送文本不同的地方就是将MIMEText中的_subtype设为html,发送带图片的HTML还要创建MIMEMultipart()实例。
# -*- coding: UTF-8 -*-
import smtplib
from email.header import Header
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
# 第三方SMTP
mail_host = "smtp.163.com" # SMTP服务器
mail_user = "sender@163.com" # 发送者邮箱
mail_pass = "******" # 邮箱的客户端授权码
sender = "sender@163.com"
recivers = ["bob@qq.com", "alice@qq.com"] # 接收邮件
msg = MIMEMultipart('related')
msg['From'] = sender
msg['To'] = ", ".join(recivers)
subject = 'HTML 1m4g3'
msg['Subject'] = Header(subject, 'utf-8')
mail_msg = """
<h1>HTML image测试</h1>
<p><a href="http://www.baidu.com">learn more</a></p>
<p><img class="lazy" data-src="cid:image1"></p>
"""
msgAlternative = MIMEMultipart('alternative')
msg.attach(msgAlternative)
msgAlternative.attach(MIMEText(mail_msg, 'html', 'utf-8'))
# 指定当前目录的图片
fp = open('test1.gif', 'rb')
msgImage = MIMEImage(fp.read())
fp.close()
# 定义图片ID,在HTML中引用
msgImage.add_header('Content-ID', '<image1>')
msg.attach(msgImage)
try:
smtpObj = smtplib.SMTP()
smtpObj.connect(mail_host, 25) # 25 SMTP Port
smtpObj.set_debuglevel(1)
smtpObj.login(mail_user, mail_pass)
smtpObj.sendmail(sender, recivers, msg.as_string())
print "emails send sucessfully"
except smtplib.SMTPException:
print "Error:cannot send emails"
smtpObj.quit()
发送带附件的邮件
# -*- coding: UTF-8 -*-
import smtplib
from email.header import Header
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
# 第三方SMTP
mail_host = "smtp.163.com" # 设置服务器
mail_user = "sender@163.com"
mail_pass = "******"
sender = "sender@163.com"
recivers = ["bob@qq.com", "alice@qq.com"] # 接收邮件
# 创建附件实例
msg = MIMEMultipart()
msg['From'] = sender
msg['To'] = ", ".join(recivers)
subject = '邮件附件'
msg['Subject'] = Header(subject, 'utf-8')
# 邮件正文:
MIMEText('邮件正文如下', 'html', 'utf-8')
# 构造附件,传送当前目录下的txt文件:
att1 = MIMEText(open('test1.txt', 'rb').read(), 'base64', 'utf-8')
att1["Content-Type"] = 'application/octet-stream'
# 这里的filename可以任意命名,成为邮件中显示的文件名
att1["Content-Disposition"] = 'attachment;filename="test_1.txt"'
msg.attach(att1)
try:
smtpObj = smtplib.SMTP()
smtpObj.connect(mail_host, 25) # 25 SMTP Port
smtpObj.set_debuglevel(1)
smtpObj.login(mail_user, mail_pass)
smtpObj.sendmail(sender, recivers, msg.as_string())
print "emails send sucessfully"
except smtplib.SMTPException:
print "Error:cannot send emails"
smtpObj.quit()
发送正常的就会返回250状态码:
发送失败返回的554:
总结
搞这些操作一是想弄明白智能合约CTF里怎么实现用邮箱发来flag的,再一个就是想补补编程(你打代码像cxk.gif)。
总之在里面遇到很多坑,而且大部分都是返回的554(可能被判为垃圾邮件而拦截掉了),这里的原因大概率是因为Subject有些文字不符(像“test"这种都会被拦截)。还有在批量发送时,recivers是一个list,那么message['To']中需要用逗号和join()函数转成字符串。
over!