FlaskMail(1)

Mail电子邮件

1.简介

1.电子邮件定义

电子邮件,又称电子邮箱,简称电邮,是指一种由一寄件人将数字信息发送给一个人或多个人的信息交换方式,一般会通过互联网或其他电脑网络进行书写、发送和接收信件,目的是达成发信人和收信人之间的信息交互。

2.电子邮件的传输过程

FlaskMail(1)

假设Alice(alice@a.org)利用电子邮件客户端写了一封电邮,输入收信人Bob(Bob@b.org)的电邮地址,按下“寄信”钮后,后续的流程如下:

  • 1.Alice通过foxmail把邮件写好,填写了对方Bob的email地址,点击“发送”,电子邮件发出。(这样的电子邮件被成为MUA–Mail User Agent–邮件用户代理)
  • 2.Email从MUA发出去,不是直接到达对方的电脑,而是发给被的MTA(Mail Transfer Agent–邮件传输代理),也就是那些Email服务供应商,比如163,sina等,这里把邮件发送给a提供的MTA,再由a的MTA发送给b的MTA。在这个过程中还要经过别的MTA。
  • 3.Email到达b的MTA后,由于双方都是使用的@b.org,因此b的MTA投递到邮件的最终目的地MDA(Mail   Delivery Agent–邮件投递代理),email到达MDA后,就停留在服务器上,存放在某个文件或数据库中,我们将这个长期保存邮件的地方称为电子邮箱。
  • 4.Bob通过自己的foxmail,通过MUA从MDA上把邮件提取到自己的电脑上。
FlaskMail(1)

3.使用python发送邮件

所以要编写程序来发送和接受邮件,本质就是:

  • 1.编写MUA把邮件发送给MTA
  • 2.编写MUA把邮件从MDA上收取

发邮件时,MUA和MTA使用的协议就是SMTP:Simple Mail Transfer Protocol,后面的MTA到另一个MTA也是用SMTP协议。

收邮件时,MUA和MDA使用的协议有两种:

  • POP:Post Office Protocol,目前版本是3,俗称POP3;
  • IMAP:Internet Message Access Protocol,目前版本是4,优点是不但能取邮件,还可以直接操作MDA上存储的邮件,比如从收件箱移到垃圾箱,等等。

邮件客户端软件在发邮件时,会让你先配置SMTP服务器,也就是你要发到哪个MTA上。假设你正在使用163的邮箱,你就不能直接发到新浪的MTA上,因为它只服务新浪的用户,所以,你得填163提供的SMTP服务器地址:smtp.163.com,为了证明你是163的用户,SMTP服务器还要求你填写邮箱地址和邮箱口令,这样,MUA才能正常地把Email通过SMTP协议发送到MTA。

类似的,从MDA收邮件时,MDA服务器也要求验证你的邮箱口令,确保不会有人冒充你收取你的邮件,所以,Outlook之类的邮件客户端会要求你填写POP3或IMAP服务器地址、邮箱地址和口令,这样,MUA才能顺利地通过POP或IMAP协议从MDA取到邮件。

2.SMTP发送邮件

SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件、HTML邮件以及带附件的邮件。python发送邮件主要使用到了smtplib和email两个模块,email负责构造邮件,smtplib负责发送邮件。

1.邮件格式(RFC 2822)

每封邮件都有两个部分:邮件头和邮件体,两者使用一个空行分隔。邮件头每个字段 (Field) 包括两部分:字段名和字段值,两者使用冒号分隔。有两个字段需要注意:From和Sender字段。From字段指明的是邮件的作者,Sender字段指明的是邮件的发送者。如果From字段包含多于一个的作者,必须指定Sender字段;如果From字段只有一个作者并且作者和发送者相同,那么不应该再使用Sender字段,否则From字段和Sender字段应该同时使用。邮件体包含邮件的内容,它的类型由邮件头的Content-Type字段指明。RFC 2822定义的邮件格式中,邮件体只是单纯的ASCII编码的字符序列。

(Multipurpose Internet Mail Extensions) (RFC 1341)[现在使用]

MIME扩展邮件的格式,用以支持非ASCII编码的文本、非文本附件以及包含多个部分 (multi-part) 的邮件体等。MIME消息是由消息头和消息体2大部分组成,在邮件中对应了邮件头和邮件体。邮件头和邮件体之间以空行分割。

FlaskMail(1)

邮件头包含了发件人、收件人、主题、时间、MIME版本、邮件内容的类型等重要信息。每条信息称为一个域,由域名后加“: ”和信息内容构成,可以是一行,较长的也可以占用多行。域的首行必须“顶头”写,即左边不能有空白字符(空格和制表符);续行则必须以空白字符打头,且第一个空白字符不是信息本身固有的。

邮件体包含邮件的内容,它的类型由邮件头的“Content-Type”域指出。最常见的类型有text/plain(纯文本)和text/html(超文本)。邮件体被分为多个段,每个段又包含段头和段体两部分,这两部分之间也以空行分隔。常见的multipart类型有三种:multipart/mixed, multipart/related和multipart/alternative

2.MIME函数的层次结构

FlaskMail(1)

3.相关模块

1.smtplib

SMTP类构造函数,表示与smtp服务器之间的连接,通过这个连接可以向smtp服务器发送指令,执行相关操作,(登陆,发送邮件等等)

import smtplib
smtplib.SMTP([host[,port[local_hostname[,timeout]]]])
#host:smtp服务器主机名
#port:smtp服务器的端口,默认是25,ssl端口465

smtplib.SMTP的操作方法如下:

方法 含义
SMTP.set_debuglevel(level) 设置是否是调试模式,默认为false,表示不输出任何调试信息
SMTP.connect([host[,port]]) 连接到指定的smtp服务器,参数表示smtp主机和端口
注意:可以在host参数中指定端口号(eg:smtp.yeah.net:25),这样就不用给出port参数
SMTP.docmd(cmd[,argsring]) 向smtp服务器发送指令。可选参数argsring表示执行的参数
SMTP.hello([hostname]) 使用’helo’指令向服务器确认身份,相当于告诉smtp服务器’who am I’
SMTP.has_extn(name) 判断指定名称在服务器邮件列表中是否存在。出入安全考虑,smtp服务器往往屏蔽了该指令
SMTP.verify(address) 判断指定邮件地址是否在服务器中存在。出于安全考虑,smtp服务器往往屏蔽了该令。
SMTP.login(user,password) 登陆服务器
SMTP.sendmail(from_addr,to_addr,msg[,mail_options,rcpt_options]) 发送邮件。这里要注意一下第三个参数,msg是字符串,表示邮件。我们知道邮件一般由标题,发信人,收件人,邮件内容,附件等构成,发送邮件的时候,要注意msg的格式。这个格式就是smtp协议中定义的格式。
SMTP.quit() 断开于smtp服务器的连接

2.email模块

email模块是用来处理邮件消息,包括MIME和其他基于RFC 2822 的消息文档。使用这些模块来定义邮件的内容

名称 内容
class email.mime.base.MIMEBase(_maintype,_subtype, **_params ) 这是MIME的一个基类_maintype是内容类型(eg:text or image)_subtype是内容的minor type类型(eg:plain or gif) **_params是一个字典,直接传递给Message.add_header()。
class email.mine.multipart.MIMEMultipart([_subtype[,</br>boundary[,_subparts[,</br>_params]]]])</br> MIMEBase的一个子类多个MIME对象的集合,_subtype默认值为mixed。boundary是MIMEMultipart的边界,默认边界是可数的。
class email.mime.application.MIMEApplication(_data[,_subtype[, _encoder[,**_params]]]) MIMEMultipart的一个子类
class email.mime.audio.MIMEAudio(_audiodata[,_subtype[,_encoder[,</br> **_params]]]) MIME音频对象
class email.mime.image.MIMEImage(_imagedata[,_subtype[,</br> _encoder[,</br> **_params]]]) MIME二进制对象
class email.mime.message.MIMEMessage(_msg[,_subtype]) 具体的一个message实例
class email.mime.text.MIMEText(_text[,_subtype[,<_charset]]) MIME文本对象,其中_text是邮件内容,_subtype邮件类型,可以是text/plain(普通文本邮件),html/plain(html邮件),  _charset编码,可以是gb2312,utf-8等等。

3.发送邮件

#Python对SMTP支持有smtlib 和email 2个函数,email负责构造函数,smtplib负责发送函数
#导入发送函数smtplib
import smtplib
#导入邮件构造函数email
from email.mime.text import MIMEText
#设置服务器所需信息
#gmail服务器的smtp地址
mail_host = 'smtp.gmail.com'
#gmail用户名
mail_user = 'jack'
#密码(部分邮箱为授权码)
mail_pass = 'xxxxxxxx'
#邮件发送方邮箱地址
sender = 'jack@gmail.com'
#邮件接受方邮箱地址,注意需要[]包裹,这意味着你可以写多个邮件地址群发
receivers = ['185@163.com']

#设置email信息
#邮件内容设置
'''
纯文本内容发送
message = MIMEText('content','plain','utf-8')
'''

#邮件主题
message['Subject'] = u'这是来自gmail的Python测试邮件'
#发送方信息
message['From'] = sender
#接受方信息
message['To'] = receivers[0#message[‘To’]接受的字符串而不是list,如果有多个,可以用逗号隔开

#登录并发送邮件
try:
   #使用ssl加密传输数据
   smtpObj = smtplib.SMTP_SSL(mail_host,465)
   #连接到服务器
   #smtpObj.connect(mail_host,25)
   #登录到服务器
   smtpObj.login(mail_user,mail_pass)
   #发送
   #SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options]
   # from_addr 邮件发送者地址
   # to_addr 邮件接受者 地址
   # msg:发送的消息,这里发送的是字符串,表示邮件,可以用,as_string转换成字符串
   smtpObj.sendmail( sender,receivers,message.as_string())
   #退出
   smtpObj.quit()
   print('success')
except smtplib.SMTPException as e:
   print(e) #打印错误

流程

FlaskMail(1)
10320

4.发送富文本邮件

#Python对SMTP支持有smtlib 和email 2个函数,email负责构造函数,smtplib负责发送函数
#导入发送函数smtplib
import smtplib
#导入邮件构造函数email
from email.mime.text import MIMEText
#设置服务器所需信息
#gmail服务器的smtp地址
mail_host = 'smtp.gmail.com'
#gmail用户名
mail_user = 'jack'
#密码(部分邮箱为授权码)
mail_pass = 'xxxx'
#邮件发送方邮箱地址
sender = 'jack@gmail.com'
#邮件接受方邮箱地址,注意需要[]包裹,这意味着你可以写多个邮件地址群发
receivers = ['185@163.com']
#设置email信息
#邮件内容设置
'''
纯文本内容发送
message = MIMEText('content','plain','utf-8')
'''

#发送富文本内容
#MIMEText,第一个参数是邮件正文,第二个参数是MIME的subtype
#最后一个是用 utf-8编码保证多语言兼容性
message = MIMEText('<html><body><h1>Hello</h1>' +
'<p>send by <a href="http://www.python.org">Python</a>...</p>' +
'</body></html>''html''utf-8')
#邮件主题
message['Subject'] = u'这是来自gmail的Python测试邮件'
#发送方信息
message['From'] = sender
#接受方信息
message['To'] = receivers[0#message[‘To’]接受的字符串而不是list,如果有多个,可以用逗号隔开
#登录并发送邮件
try:
        #使用ssl加密传输数据
        smtpObj = smtplib.SMTP_SSL(mail_host,465)
        #连接到服务器
        #smtpObj.connect(mail_host,25)
        #登录到服务器
        smtpObj.login(mail_user,mail_pass)
        #发送
        #SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options]

        # from_addr 邮件发送者地址
        # to_addr 邮件接受者 地址
        # msg:发送的消息,这里发送的是字符串,表示邮件,可以用,as_string转换成字符串
          smtpObj.sendmail(
         sender,receivers,message.as_string())
         #退出
         smtpObj.quit()
except smtplib.SMTPException as e:
        pritnt(e)

5.发送点图片附件

#
from email.mime.text import MIMEText
import  smtplib
#
#
from email import  encoders
from email.header import Header
from  email.utils import parseaddr, formataddr
#
#
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.image import  MIMEImage
#
#
def _format_addr(s):
name, addr = parseaddr(s)
return  formataddr(( 
Header(name,'utf-8').encode(), 
addr.encode('utf-8'if isinstance(addr,unicode) else addr))
#
mail_host = 'smtp.gmail.com'
mail_user = 'jack'
mail_pass = '2008'
#
sender = 'jack@gmail.com'
receivers = ['185@163.com']
#
#设置email信息
#添加一个MIMEmultipart类,处理正文及附件
messages = MIMEMultipart()
#messages = MIMEText('python for mail','plain','utf-8')
messages['From'] = _format_addr( u'Python爱好者 <%s> ' % sender )
messages['To'] = _format_addr( u'管理员 <%s> ' % receivers[0])
messages['Subject'] =  Header( u'这是一份带附件的python邮件测试','utf-8').encode()
#
#
#邮件正文
messages.attach(MIMEText('<html><body><h1>Hello</h1>' +
'<p>send by <a href="http://www.python.org">Python</a>...</p>' +
'<p><img src="cid:0"></p>' +
'</body></html>''html''utf-8'))
#
with open(u'test.png','rb'as f:
        #设置附件的MIME和文件名,这是png类型
        mime = MIMEBase('image','png',filename='test.png')
        #加上必要的头信息
        mime.add_header('Content-Disposition','attachemen',filename='test.png')
        mime.add_header('Content-ID','<0>')
        mime.add_header('X-Attachment-Id','0')
        #把附件内容读进来
        mime.set_payload(f.read())
        #用Base64编码
        encoders.encode_base64(mime)
        #添加到MIMEutipart
        messages.attach(mime)
        #
        try:
                smtpObj = smtplib.SMTP_SSL(mail_host,465)
                smtpObj.login(mail_user,mail_pass)
                smtpObj.sendmail(sender,receivers,messages.as_string())
                print( u'邮件发送成功')
                smtpObj.quit()
        except smtplib.SMTPException as e:
                print(e)

6.发送带附件的电子邮件(定义为类)

#!/usr/bin/env python
#coding=utf-8
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.header import Header
import smtplib
def sendEmail(authInfo, fromAdd, toAdd, subject, plainText):
strFrom = fromAdd
strTo = '; '.join(toAdd)
server = authInfo.get('server')
smtpPort = 25
sslPort = 465
user = authInfo.get('user')
passwd = authInfo.get('password')
if not (server and user and passwd) :
        print('incomplete login info, exit now')
        return
# 设定root信息
msgRoot = MIMEMultipart('related')
msgRoot['Subject'] = subject
msgRoot['From'] = '%s<%s>' % (Header('测试''utf-8'), strFrom)
msgRoot['To'] = strTo
# 邮件正文内容
msgText = MIMEText(plainText, 'plain''utf-8')
msgRoot.attach(msgText)
msgAlternative = MIMEMultipart('alternative')
msgRoot.attach(msgAlternative)
# mail_msg = """
#         <p>Python 邮件发送测试...</p>
#         <p><a href="http://www.runoob.com">菜鸟教程链接</a></p>
#         <p>图片演示:</p>
#         <p><img src="cid:pic_attach"></p>
# """
# msgAlternative.attach(MIMEText(mail_msg, 'html', 'utf-8'))
#设定内置图片信息
fp = open('aa.png''rb')
msgImage = MIMEImage(fp.read())
msgImage["Content-Type"] = 'application/octet-stream'
#filename可自定义,供邮件中显示
msgImage["Content-Disposition"] = 'attachment; filename="aa.png"'
fp.close()
msgImage.add_header('Content-ID''<pic_attach>')
msgAlternative.attach(msgImage)
try:
    #发送邮件
    smtp = smtplib.SMTP()
    smtp.connect(server, smtpPort)
    #ssl加密方式,通信过程加密,邮件数据安全
    # smtp = smtplib.SMTP_SSL()
    # smtp.connect(server, sslPort)
    #设定调试级别,依情况而定
    # smtp.set_debuglevel(1)
    smtp.login(user, passwd)
    smtp.sendmail(strFrom, toAdd, msgRoot.as_string())
    smtp.quit()
    print("邮件发送成功!")
except Exception, e:
    print("失败:") + str(e)
if __name__ == '__main__' :
authInfo = {}
authInfo['server'] = 'smtp.gmail.com'
authInfo['user'] = 'jack'
authInfo['password'] = '2008'
fromAdd = jack2573270182@gmail.com'
toAdd = ['
185@163.com']
subject = '
Email Subject'
plainText = '
Email Content'
sendEmail(authInfo, fromAdd, toAdd, subject, plainText)

– END –


原文始发于微信公众号(Flask学习笔记):FlaskMail(1)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/36467.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!