一、实现内容

        本实例使用Python发送一份带附件的邮件。

二、实现步骤

2.1 连接邮箱服务器

        使用代码发送邮件时,第一步是连接到指定邮箱的服务器。这里,我们以QQ邮箱为例。

1、开启SMTP服务

        连接邮箱服务器之前,我们需要先在QQ邮箱中开启SMTP服务。SMTP代表简单邮件传输协议,相当于一种计算机之间发邮件的约定。

        第一步,打开网址mail.qq.com,输入自己的帐号和密码,登录QQ邮箱并找到「设置」。

        第二步,点击「设置」,找到「账户」。

        第三步,滑动页面找到「IMAP/SMTP服务 」,点击开启。

2、获取授权码

        因为后续使用代码登录邮箱时,我们需要使用授权码而非QQ密码。所以,在开启STMP服务后,顺便获取它的授权码。如图,点击「开启」后会弹出验证密保,需要用自己的手机号发送指定内容到指定号码。

        发送完成后,点击「我已发送」。完成验证后,将会获得一个「授权码」(授权码不要告诉其他人)。复制并保存授权码,我们后续在登录邮箱时需要使用。

3、连接邮件服务器

        导入内置模块smtplib,通过该模块的类SMTP_SSL,创建了一个实例对象qqMail。smtplib是Python的内置模块,可以直接导入使用。该模块主要负责发送邮件的动作,比如:连接邮箱服务器,登录邮箱,发送邮件等。

# 导入smtplib模块
import smtplib
# 连接邮箱服务器:连接邮箱服务器:使用smtplib模块的类SMTP_SSL,创建一个实例对象qqMail
qqMail = smtplib.SMTP_SSL("smtp.qq.com", 465)

        使用smtplib模块的SMTP_SSL类创建一个实例,并为这个实例传入两个参数

        第一个参数是服务器地址。简单来说,我们需要使用该地址帮我们代收发邮件。该地址以字符串形式传入。

        第二个参数是端口号,每个服务器有多个端口,只有通过对应的端口,程序才能访问到该服务器。QQ邮箱的SMTP的端口号是465。

2.2 登陆邮箱

        接下来,我们定义用户名、密码两个变量,用户和密码使用自己的QQ邮箱和第一步得到的授权码,就可以通过login()方法,来登陆自己的邮箱。

# 设置登录邮箱的帐号为:"aLing@qq.com",赋值给mailUser
mailUser = "zhangxiaofan@qq.com"
# 将邮箱授权码"abcnawckdujkdace",赋值给mailPass 
mailPass = "xxxxx"
# 登录邮箱:调用对象qqMail的login()方法,传入邮箱账号和授权码
qqMail.login(mailUser, mailPass)

2.3 编辑收发件人

        登录邮箱后,我们通常要先设置好邮件的主题、发件人和收件人等信息。要构建以上信息,还需要用到另外一个内置模块emailemail模块主要负责构造邮件页面的布局,比如发件人,收件人,主题,正文,附件等。

  email模块的类MIMEMultipart,可以整合邮件头、正文和附件等信息。所以,当我们要发送带附件的组合型邮件时,需要从email.mime.multipart中导入MIMEMultipart类。示例中,为导入MIMEMultipart类的固定写法。

  email模块的类Header,用于设置邮件头,即邮件的主题,收发件人。所以,当我们要设置邮件的主题,收发件人时,就需要从email.header中导入Header类。示例中,为导入Header类的固定写法。

# 从email.mime.multipart中导入MIMEMultipart类
from email.mime.multipart import MIMEMultipart
# 从email.header中导入Header类
from email.header import Header

# 设置发件人和收件人
sender = "zhangxiaofan@qq.com"
receiver = "luxueqi@qq.com"
# 使用类MIMEMultipart,创建一个实例对象message
message = MIMEMultipart()
# 将主题写入 message["Subject"]
message["Subject"] = Header("合照")
# 将发件人信息写入 message["From"]
message["From"] = Header(f"xiaofan<{sender}>")
# 将收件人信息写入 message["To"]
message["To"] = Header(f"xueqi<{receiver}>")

        导入模块后,我们先设置收发件人的邮箱信息,然后通过类MIMEMultipart,创建了一个实例对象message。最后,将主题、收发件人信息依次写入了对象message中。

2.4 构建正文

        接下来,就可以来构建邮件的正文了。构建邮件正文,需要从email.mime.text中导入MIMEText类示例中,为导入MIMEText类的固定写法。

# 从email.mime.text中导入MIMEText类
from email.mime.text import MIMEText

# 设置邮件的内容,赋值给变量textContent
textContent = "雪琪,看我们的合影帅不帅"
# 编辑邮件正文:使用类MIMEText,创建一个实例对象mailContent
mailContent = MIMEText(textContent, "plain", "utf-8")

        使用MIMEText类创建一个实例对象,为这个实例传入三个参数。

        第一个参数是文本内容,即我们需要发送邮件的正文内容。

        第二个参数是文本格式,表示我们的正文内容以何种格式展示。"plain"表示纯文本的格式。纯文本格式就是文本内容不加任何修饰,比如粗体,斜体等。

        第三个参数是编码。示例中的"utf-8"编码,能防止中文乱码。

        小凡与雪琪的合照无法直接添加到邮件的正文,需要将其设置为邮件的附件。但是,由于程序无法直接将图片文件设置为附件。所以,我们要将图片文件以程序能识别的方式打开并读取出来。而这需要使用Python的 open()函数和with…as语句。

# 将文件路径,赋值给filePath
filePath = r"D:\学习资料\Python\test\zhangandlu.jpg"
# 使用with open() as语句以rb的方式,打开路径为filePath的图片,并赋值给imageFile
with open(filePath, "rb") as imageFile:
    # 使用read()函数读取文件内容,赋值给fileContent
    fileContent = imageFile.read()

  open()函数,用于打开一个文件,并将其以对象的形式返回。通常来说,open() 函数接收两个参数:文件路径和打开方式。当然,在本地使用图片时,需要本地图片的真实路径。

        第一个参数是路径,Windows系统的用户,路径前面加r来防止转义。比如:r"D:\学习资料\Python\test\zhangandlu.jpg"

        第二个参数是打开方式,用特定的字符串表示。比如这里的"rb"。示例中,"rb"Read Binary的缩写,表示以二进制形式读取文件的内容。

  with open() as,先执行with后的open()函数,将open()函数的返回值,赋值给as后面的变量。

2.5 设置附件

        读取了图片文件的内容后,我们就可以将其添加到邮件的附件中了。而设置图片附件,需要从email.mime.image中导入MIMEImage类。

# 从email.mime.image中导入MIMEImage类
from email.mime.image import MIMEImage

# 设置邮件附件:使用类MIMEImage,创建一个实例对象attachment
attachment = MIMEImage(fileContent)
# 调用add_header()方法,设置附件标题
attachment.add_header("Content-Disposition", "attachment", filename="合照.jpg")

        使用类MIMEImage,创建了实例对象attachment,即设置邮件的附件。类中传入的参数为读取的文件内容fileContent

  调用add_header()方法,用于设置邮件附件的名称。该方法,通常接收三个参数,前两个为固定参数,使用时直接抄写即可,第三个参数用于设置附件的名称。

        接下来,需要调用对象message的attach()方法,要将正文和附件添加到邮件中。

# 添加正文:调用对象message的attach()方法,传入正文对象mailContent作为参数
message.attach(mailContent)
# 添加附件:调用对象message的attach()方法,传入附件对象attachment作为参数
message.attach(attachment)

2.6 发送邮件

        最后,调用对象qqMail的sendmail()方法来发送邮件,需要传入发件人、收件人、邮件内容,邮件内容需要为字符串类型,所以在示例中,使用as_string()方法将对象message变为字符串类型。

# 发送邮件:使用对象qqMail的sendmail方法发送邮件
qqMail.sendmail(sender, receiver, message.as_string())
# 输出"发送成功"
print("发送成功")

三、总结

3.1 完整代码

# 导入smtplib模块
import smtplib

# 从email.mime.multipart中导入MIMEMultipart类
from email.mime.multipart import MIMEMultipart
# 从email.header中导入Header类
from email.header import Header

# 从email.mime.text中导入MIMEText类
from email.mime.text import MIMEText

# 从email.mime.image中导入MIMEImage类
from email.mime.image import MIMEImage

# 1、连接邮箱服务器
# 连接邮箱服务器:连接邮箱服务器:使用smtplib模块的类SMTP_SSL,创建一个实例对象qqMail
qqMail = smtplib.SMTP_SSL("smtp.qq.com", 465)

# 2、登陆邮箱
# 设置登录邮箱的帐号为:"zhangxiaofan@qq.com",赋值给mailUser
mailUser = "zhangxiaofan@qq.com"
# 将邮箱授权码"xxxxx",赋值给mailPass 
mailPass = "xxxxx"
# 登录邮箱:调用对象qqMail的login()方法,传入邮箱账号和授权码
qqMail.login(mailUser, mailPass)

# 3、编辑收发件人
# 设置发件人和收件人
sender = "zhangxiaofan@qq.com"
receiver = "luxueqi@163.com"
# 使用类MIMEMultipart,创建一个实例对象message
message = MIMEMultipart()
# 将主题写入 message["Subject"]
message["Subject"] = Header("合照")
# 将发件人信息写入 message["From"]
message["From"] = Header(f"xiaofan<{sender}>")
# 将收件人信息写入 message["To"]
message["To"] = Header(f"xueqi<{receiver}>")

# 4、构建正文
# 设置邮件的内容,赋值给变量textContent
textContent = "雪琪,看我们的合影帅不帅"
# 编辑邮件正文:使用类MIMEText,创建一个实例对象mailContent
mailContent = MIMEText(textContent, "plain", "utf-8")

# 将文件路径,赋值给filePath
filePath = r"D:\学习资料\Python\test\zhangandlu.jpg"
# 使用with open() as语句以rb的方式,打开路径为filePath的图片,并赋值给imageFile
with open(filePath, "rb") as imageFile:
    # 使用read()函数读取文件内容,赋值给fileContent
    fileContent = imageFile.read()

# 5、设置附件
# 设置邮件附件:使用类MIMEImage,创建一个实例对象attachment
attachment = MIMEImage(fileContent)
# 调用add_header()方法,设置附件标题
attachment.add_header("Content-Disposition", "attachment", filename="合照.jpg")

# 添加正文:调用对象message的attach()方法,传入正文对象mailContent作为参数
message.attach(mailContent)
# 添加附件:调用对象message的attach()方法,传入附件对象attachment作为参数
message.attach(attachment)

# 6、发送邮件
# 发送邮件:使用对象qqMail的sendmail方法发送邮件
qqMail.sendmail(sender, receiver, message.as_string())
# 输出"发送成功"
print("发送成功")

        执行结果如下图:

  在这个实例中,我们分别用到了以下模块和类:

  smtplib模块主要负责发送邮件的动作,比如:连接邮箱服务器,登录邮箱,发送邮件等。

  email.header中的Header类,用于编辑收发件人和主题等信息。

  email.mime.multipart中的MIMEMultipart类,用于将信息整合在一起。

       email.mime.text模块中的 MIMEText 类用于构建邮件正文。

       email.mime.image模块中的类 MIMEImage 用于设置图片附件。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐