目前用于发送邮件的协议是SMTP(简单文本传输协议)
python内置的smtplib模块提供了便捷的邮件发送方法,可以发送纯文本邮件、HTML邮件及带附件的邮件。
Python对SMTP支持有smtplib和email两个模块,email负责构造邮件,smtplib负责发送邮件
python创建SMTP对象的语法如下
import smtplib
smtpobj = smtplib.SMTP([host [, port [, local_hostname] ] ])
参数说明:
pythonSMTP随想使用sendmail方法发送邮件,其语法如下:
SMTP.sendmail(from_addr, to_addr, msg[, mail_options, rcpt_options] )
参数说明:
from email.mime.text import MIMEText
message = MIMEText(‘Python 邮件测试…’, ‘plain’, ‘utf-8’)
----------------------------------------------------------------------------------------------------------
# 构造MIMEText对象时 ,第一个参数就是邮件正文,第二个参数是MIMEText的subtype,传入palin,最终MIMEText就是’text/plain’,最后一定要用’utf-8’编码,保证语言的兼容性
网易邮箱服务器发送邮件常见问题:http://help.163.com/09/1224/17/5RAJ4LMH00753VB8.html
邮件代码:
import smtplib
from email.mime.text import MIMEText
# 第三方SMTP服务
mail_host = "smtp.qq.com" # 设置服务器(smtp.163.com是网易邮箱服务器,smtp.qq.com是QQ地址)
mail_user = "[email protected]" # 用户名
mail_pass = "aydzptaydrdpched" # 密码(注意,这里的密码指的是邮箱客户端授权码)
# 发送者邮箱
sender = "[email protected]"
# 接收者邮箱
receivers = ['[email protected]', '[email protected]'] # 邮件接受者,可设置多个
# 构造正文
message = MIMEText('这是正文:python test。。。', 'plain', 'utf-8') # 构造正文
# 构造发件人
message["From"] = sender # 发件人,这个必须构造,也可以使用Header来构造
# 收件人列表,这个不是必须的
message["To"] = ";".join(receivers)
# 定义邮件主题
message["Subject"] = "这是主题:SMTP 邮件测试"
try:
smtpObj = smtplib.SMTP() # 建立和SMTP邮件服务器的连接
smtpObj.connect(mail_host, 25) # 25 为端口号
smtpObj.login(mail_user, mail_pass)
smtpObj.sendmail(sender, receivers, message.as_string())
print('send mail Successfully')
smtpObj.quit() # 结束会话
except smtplib.SMTPException as e:
print(f"发送失败,错误原因:{e}")
执行结果:
[root@localhost MSTP]# ./sendmail.py
send mail Successfully
message = MIMEText(
'<html><body><h1>这是正文标题</h1>\
<p>正文内容<a href="#">https://blog.csdn.net/CN_LiTianpeng?spm=1001.2014.3001.5343 #《超链接》...\
</html></body>',
"html",
"utf-8"
)
[root@localhost MSTP]# vim sendmail.py
#!/bin/env python3
import smtplib
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.header import Header
# 第三方SMTP服务
mail_host = "smtp.qq.com" # 设置服务器(smtp.163.com是网易邮箱服务器,smtp.qq.com是QQ地址)
mail_user = "[email protected]" # 用户名
mail_pass = "aydzptaydrdpched" # 密码(注意,这里的密码指的是邮箱客户端授权码)
# 发送者邮箱
sender = "[email protected]"
# 接收者邮箱
receivers = ['[email protected]', '[email protected]'] # 邮件接受者,可设置多个
# 构造正文
# # -------------------- 文本类邮件 -------------------------------------------------
# message = MIMEText('这是正文:python test。。。', 'plain', 'utf-8') # 构造正文
# 构造正文
# # ------------------- html类邮件 -------------------------------------------------
# message = MIMEText(
# '这是正文标题
\
# 正文内容https://blog.csdn.net/CN_LiTianpeng?spm=1001.2014.3001.5343 #《超链接》...
\
# ',
# "html",
# "utf-8"
# )
# 构造正文
# ---------------------可添加附件的邮箱--------------------------------------------------
message = MIMEMultipart()
# 邮件正文部分
message.attach(MIMEText('这是正文:图片及附件发送测试
图片演示
', 'html', 'utf-8'))
# 指定图片路径
fp = open("baidu2.jpg", 'rb')
msgImage = MIMEImage(fp.read())
fp.close()
# 定义图片ID,在Html中引用
msgImage.add_header("Content_ID", "" )
message.attach(msgImage)
# 添加附件1,传送当前目录下的test.txt文件
att1 = MIMEText(open("test.txt", "rb").read(), "base64", "utf-8")
att1["Content-Type"] = "application/octet-stream"
# 这里的filename可以任意写,写什么名称,在邮件中就会显示什么名称
att1["Content-Dispostion"] = "attachment; filename='测试文件' "
message.attach(att1)
# --------------------------------------------------------------------
# 构造发件人
message["From"] = sender # 发件人,这个必须构造,也可以使用Header来构造
# 收件人列表,这个不是必须的
message["To"] = ";".join(receivers)
# 定义邮件主题
message["Subject"] = "这是主题:SMTP 邮件测试"
try:
smtpObj = smtplib.SMTP() # 建立和SMTP邮件服务器的连接
smtpObj.connect(mail_host, 25) # 25 为端口号
smtpObj.login(mail_user, mail_pass)
smtpObj.sendmail(sender, receivers, message.as_string())
print('send mail Successfully')
smtpObj.quit() # 结束会话
except smtplib.SMTPException as e:
print(f"发送失败,错误原因:{e}")
监控要求:
[email protected];[email protected]
xxx 程序告警
告警信息:…
…
…
/home/log/xxx.log,/tmp/yyy.log
告警代码:
import smtplib
import chardet
import codecs
import os
from email.mime.text import MIMEText
from email.header import Header
from email.mime.multipart import MIMEMultipart
# 接收告警的邮箱列表
recipient_list = ['[email protected]', '[email protected]']
# 第三方SMTP服务
class TxtMali(object):
def __init__(self, host=None, auth_user=None, auth_pass=None):
# 设置发送告警的邮件服务器
self.host = "smtp.qq.com" if host is None else host
# 设置专用告警账户的用户名
self.auhe_user = "[email protected]" if auth_user is None else auth_user
# 设置专用告警账户的用户的密码
self.auth_pass = "xxxxxxxxxxxx" if auth_pass is None else auth_pass
self.sender = "[email protected]"
def send_mail(self, subject, msg_str, recipient_list, attachment_list=None):
messgae = MIMEMultipart()
messgae["From"] = self.sender
messgae["To"] = Header(';'.join(recipient_list), "utf-8")
messgae["Subject"] = Header(subject, 'utf-8')
messgae.attach(MIMEText(msg_str, 'plain', 'utf-8'))
# 如果有附件,则添加附件
if attachment_list:
for att in attachment_list:
attachment = MIMEText(open(att, "rb").read(), "base64", "utf-8")
attachment["Content-Type"] = "application/octet-stream"
# 这里的filename可以任意写,会在邮件中显示
# attname = att.split("/")[-1]
filename = os.path.basename(att)
# attm["Content-Disposition"] = 'attachment;filename=%s'%attname
attachment.add_header(
"Content_Disposition",
"attachment",
filename=('utf-8', "", filename)
)
smptObj =smtplib.SMTP_SSL()
smptObj.connect(self.host, smtplib.SMTP_SSL_PORT)
smptObj.login(self.auhe_user, self.auth_pass)
smptObj.sendmail(self.sender, recipient_list, messgae.as_string())
smptObj.quit()
print("邮件发送成功")
def guess_chardet(self, filename):
"""
:param filename: 传入一个文本文件
:return: 返回文本文件的编码格式
"""
encoding = None
try:
# 由于本需求解析的文件不大,可以一次性读入内存
# 如果是大文件,则读取固定字节数
raw = open(filename, 'rb').read()
if raw.startswith(codecs.BOM_UTF8): # 处理UTF-8 with BOM
encoding = "utf-8-fig"
else:
result = chardet.detect(raw)
encoding = result["encoding"]
except:
pass
return encoding
def txt_sen_dmail(self, filename):
"""
:param filename:
:return:
将指定格式的txt文件发送到邮箱,txt文件样式如下:
[email protected];[email protected] # 收件人
xxx 程序告警 # 主题
告警信息:...... # 正文
......
file1,file2 # 附件
"""
with open(filename, encoding=self.guess_chardet(filename)) as f:
lines = f.readlines()
recipient_list = lines[0].strip().split(",")
subject = lines[1].strip()
msg_str = "".join(lines[2:])
attachment_list = []
for file in lines[-1].strip().split(","):
if os.path.isfile(file):
attachment_list.append(file)
# 如果没有这个附件,则为None
if attachment_list == []:
attachment_list = None
self.send_mail(
subject=subject,
msg_str=msg_str,
recipient_list=recipient_list,
attachment_list=attachment_list
)
if __name__ == '__main__':
mymail = TxtMali()
mymail.txt_sen_dmail(filename="./test.txt")
监控文件脚本:
# ----------------------------
#文件监控
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from test_alert_mail import TxtMail
class FileEventHandler(FileSystemEventHandler):
def __init__(self):
FileSystemEventHandler.__init__(self)
def on_created(self, event):
if event.is_directory:
print("directory is created:{0}".format(event.src_path))
else:
print("file created:{0}".format(event.src_path))
if event.src_path.endswith(".txt"):
time.sleep(0.5)
mail = TxtMail()
try:
mail.txt_send_mail(filename=event.src_path)
except:
print("文本文件格式不正确")
if __name__ == '__main__':
observer = Observer()
event_handler = FileEventHandler()
dir = "./"
observer.schedule(event_handler, dir, False)
print(f"当前监控的目录:{dir}")
observer.start()
observer.join()