首先,用到的模块
import logging
import traceback
from email.mime.application import MIMEApplication
import os
import smtplib
from email.mime.multipart import MIMEMultipart
from email.utils import formataddr
from email.mime.text import MIMEText
from poplib import POP3
from email.header import decode_header
from email.parser import Parser
from email.utils import parseaddr
发送带附件的邮件
def send(email_title, content, filepath, receiver_filename, receiver, smtpserver='smtp.mxhichina.com',
nick_name='开发者账号', sender, my_pass, del_file=True):
print("开始发送邮件........")
try:
# 创建一个带附件的实例
msg = MIMEMultipart()
msg['From'] = formataddr([nick_name, sender])
msg['To'] = ','.join(receiver)
msg['Subject'] = email_title
msg.attach(MIMEText(content, 'plain', 'utf-8')) # 邮件正文内容
xlsxpart = MIMEApplication(open(filepath, 'rb').read())
xlsxpart.add_header('Content-Disposition', 'attachment', filename=('gbk', '', receiver_filename))
msg.attach(xlsxpart)
# 登陆且发送邮件
server = smtplib.SMTP_SSL(smtpserver, 465)
server.login(sender, my_pass)
server.sendmail(sender, receiver, msg.as_string())
server.quit()
print("邮件发送成功")
if del_file == True:
if os.path.exists(filepath):
os.remove(filepath)
print("文件已删除")
else:
print("没有文件可以供删除")
except Exception as e:
print(e)
return "ok"
发送不带附件的html格式的邮件
def send_no_path(email_title, content, receiver, smtpserver, nick_name,
sender, my_pass):
"""
@auth
发送不带附件的html格式的邮件
"""
# 创建一个不带附件的实例
msg = MIMEText(content, "html", 'utf-8')
# 邮件标题
msg['Subject'] = email_title
# 发送人/收件人/抄送人
msg['From'] = formataddr([nick_name, sender])
msg['To'] = ','.join(receiver)
smtpobj = smtplib.SMTP_SSL(smtpserver, 465)
try:
# 连接到服务器
smtpobj.connect(smtpserver, 465)
# 登陆
smtpobj.login(sender, my_pass)
# 发送
smtpobj.sendmail(sender, receiver, msg.as_string())
except Exception:
print('ERROR:邮件发送错误')
finally:
smtpobj.quit()
接收邮件内容
class MailFileDownload:
"""
@author:
@date:2021/11/17
通过主题或者发件人为标签自动获取最新一封邮件的正文和附件
Attributes:
target_subject:要获取的邮件主题
target_from:要获取的邮件的发件人
file_download_path:附件下载路径
server:邮箱服务器
user:邮箱登陆账号
password:邮箱登陆密码
实用方法:
mail_text:获取邮件正文,返回字符串形式的正文
mail_file:下载邮件附件到指定路径,返回None
mail_file_text:获取邮件附件和正文,返回正文
"""
logging.basicConfig(level=logging.INFO, format="$asctime - $levelname - $message", style='$')
def __init__(self, target_subject=None, target_from=None, file_download_path=None, server,
user, password):
self.logger = logging.getLogger('email')
self.target_subject = target_subject
self.target_from = target_from
self.p = POP3(server)
self.logger.info(self.p.getwelcome().decode('utf-8'))
self.p.user(user)
self.p.pass_(password)
self.num = len(self.p.list()[1]) # 获取邮件位置的列表
self.logger.info(f'共有{self.num}份邮件')
if file_download_path[-1] == '/':
self.file_download_path = file_download_path
else:
self.file_download_path = file_download_path + '/'
# self.mail = Parser().parsestr(b'\r\n'.join(text_).decode('utf-8', 'ignore'))
def __target_mail(self):
"""获取指定的邮件信息"""
for i in range(self.num, 0, -1):
# 获取邮件信息,返回元组,第二个值为邮件信息
text_ = self.p.retr(i)[1]
# 导入为mail格式
mail = Parser().parsestr(b'\r\n'.join(text_).decode('utf-8', 'ignore'))
# 比较主题是否是目标主题
subject = mail.get('Subject')
if subject:
# 返回元组,索引0为正文内容,索引1为编码
dh = decode_header(subject)
result = dh[0][0].decode(dh[0][1])
from_ = mail.get('From')
if from_:
addr = parseaddr(from_)[1]
if self.target_from == addr or self.target_subject == result:
break
else:
self.logger.warning('未找到指定主题或发件人的邮件,请检查参数')
exit()
return result, addr, mail
@staticmethod
def guess_charset(msg):
"""定义函数,获取邮件正文的编码方式"""
charset = msg.get_charset()
if charset is None:
content_type = msg.get('Content-Type', '').lower()
pos = content_type.find('charset=')
if pos >= 0:
charset = content_type[pos + 8:].strip()
return charset
def __mail_text(self, mail):
for part in mail.walk():
charset = self.guess_charset(part)
content_type = part.get_content_type()
if content_type == 'text/plain':
content = part.get_payload(decode=True).decode(charset)
break
else:
self.logger.warning('该邮件缺失正文或正文格式不是txt,请检查邮件')
content = None
return content
def __mail_file(self, mail):
"""下载邮件附件"""
for part in mail.walk():
# 获取附件名称
filename = part.get_filename()
if filename:
# 附件名称是乱码,用decode_header解码一下
filename = decode_header(filename)
filename = filename[0][0].decode(filename[0][1])
data = part.get_payload(decode=True) # 取出文件内容
with open(os.path.join(self.file_download_path, filename), 'wb') as fp:
fp.write(data)
self.logger.info(f'{filename}下载完成')
def mail_text(self):
"""
获取邮件正文,目前只支持txt格式的,html格式的暂不支持
:return: content
:rtype:
"""
try:
result_, addr_, mail_ = self.__target_mail() # 获取邮件标题、发件人、邮箱对象
content = self.__mail_text(mail_)
return content
except Exception:
traceback.print_exc()
finally:
self.p.quit()
def mail_file(self):
"""
获取邮件附件
:return:
:rtype:
"""
try:
result_, addr_, mail_ = self.__target_mail() # 获取邮件标题、发件人、邮箱对象
self.__mail_file(mail_)
except Exception:
traceback.print_exc()
finally:
self.p.quit()
def mail_file_text(self):
"""
获取邮件正文和附件
:return: content
:rtype: str
"""
try:
result_, addr_, mail_ = self.__target_mail() # 获取邮件标题、发件人、邮箱对象
self.__mail_file(mail_)
content = self.__mail_text(mail_)
return content
except Exception:
traceback.print_exc()
finally:
self.p.quit()