import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
class Template(object):
html = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{Title}</title>
</head>
<body>
<div style="color: red; font-size: 16px;">{Content}</div>
<div>bye bye</div>
</body>
</html>
"""
def __init__(self, **kwargs):
self.kwargs = kwargs
def simple_render(self):
return self.html.format(**self.kwargs)
class EmailSender(object):
def __init__(self, from_address, password, smtp_host, smtp_port, ssl=False, template:Template=None):
self.address = from_address
self.password = password
self.smtp_host = smtp_host
self.smtp_port = smtp_port
self.ssl = ssl
self.connected = False
self.template = template
self.init_client()
def create_attachment(self, filename=None, filepath=None, stream=None, charset='utf-8'):
"""
创建附件
:param filename:
:param filepath:
:param stream:
:param charset:
:return:
"""
assert any((filepath, stream)), "attachment must provide filepath or file"
assert filename, "filename can not be None"
if filepath:
f = open(filepath, 'rb')
stream = f.read()
f.close()
attachment = MIMEText(stream, 'base64', charset)
attachment["Content-Type"] = "application/octet-stream"
attachment["Content-Disposition"] = f"attachment; filename={filename}"
return attachment
def init_client(self):
"""
初始化客户端
:return:
"""
if self.ssl:
self.client = smtplib.SMTP_SSL()
else:
self.client = smtplib.SMTP()
try:
self.client.connect(self.smtp_host, self.smtp_port)
self.client.login(self.address, self.password)
self.connected = True
except smtplib.SMTPAuthenticationError:
print("username or password wrong.")
except smtplib.SMTPHeloError:
print("server didnt reply.")
except smtplib.SMTPException as e:
print(e)
def create_text_or_html(self, text, is_html=True, charset=None):
"""
创建email信件内容
:param text:
:param is_html:
:param charset:
:return:
"""
sub_type = "html" if is_html else "plain"
message = MIMEText(text, sub_type, charset)
return message
def send_with_attachment(self, Subject, attachment, sender, receiver, to_address):
"""
attachment: {"filename": filename,
"stream": file stream,
"filepath": file path}
must provide at least one of filepath & stream
"""
message = MIMEMultipart()
message["From"] = sender
message["To"] = receiver
message["Subject"] = Subject
message.attach(self.create_text_or_html(self.template.simple_render()))
message.attach(self.create_attachment(**attachment))
self.client.sendmail(self.address, to_address, message.as_string())
if __name__ == '__main__':
my_address = "address@126.com"
password = "PASSWORD"
to_address = "WANTED@qq.com"
email_smtp = "smtp.126.com"
context = "一对测试的内容"
template = Template(Content="测试内容,传递一个附件", Title="测试")
sender = EmailSender(my_address, password, email_smtp, 25, template=template)
sender.send_with_attachment('邮件测试',
{"filename": "example.xls", "filepath": r"C:\Users\Haiton\Desktop\name_list.xls"},
"126.com", "qq.com", to_address)