本例使用的时 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 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 的, 再一个就是想补补编程(你打代码像蔡徐坤. gif).
总之在里面遇到很多坑, 而且大部分都是返回的 554(可能被判为垃圾邮件而拦截掉了), 这里的原因大概率是因为 Subject 有些文字不符 (像 "test" 这种都会被拦截). 还有在批量发送时, recivers 是一个 list, 那么 message['To'] 中需要用逗号和 join()函数转成字符串.
over!
来源: https://www.cnblogs.com/KRDecad3/p/10793138.html