吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2382|回复: 14
收起左侧

[Windows] 邮箱告警(检测网络是在否线 自动发送状态信息至邮箱)

[复制链接]
Azminis 发表于 2024-7-5 11:59
本帖最后由 Azminis 于 2024-7-5 14:55 编辑

此软件使用了python语言编写
软件功能很简单 当你的主机不在线 会自动发送邮件告警信息到你的邮箱上
因为我想了解我的网络情况 在论坛上又找到该类似的软件
部署监控平台又麻烦 干脆自己弄一个来检测网络情况

蓝奏云下载链接:https://azmin.lanzouw.com/i9wqV23kkoje密码:1g5h


源代码:


import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from ping3 import ping
import time
from datetime import datetime
import threading
import tkinter as tk
from tkinter import messagebox, filedialog
import json

def send_email(subject, body, to_emails, from_email, smtp_server, smtp_port, smtp_user, smtp_password):
    msg = MIMEMultipart()
    msg['From'] = from_email
    msg['To'] = ", ".join(to_emails)
    msg['Subject'] = subject

    msg.attach(MIMEText(body, 'plain', 'utf-8'))

    try:
        print("连接到SMTP服务器...")
        server = smtplib.SMTP_SSL(smtp_server, smtp_port)
        server.login(smtp_user, smtp_password)
        print("发送邮件...")
        text = msg.as_string()
        server.sendmail(from_email, to_emails, text)
        server.quit()
        print("邮件发送成功。")
    except Exception as e:
        print(f"发送邮件失败: {e}")
        messagebox.showerror("邮件发送失败", f"发送邮件失败: {e}")

def monitor_ping(hosts, timeout, check_interval, email_details):
    host_status = {host['address']: True for host in hosts}

    while True:
        for host in hosts:
            address = host['address']
            remark = host['remark']
            try:
                print(f"正在检测主机({remark})...")
                response = ping(address, timeout=timeout)
                if response is None:
                    if host_status[address]:
                        print(f"主机({remark}) 断开,发送告警邮件...")
                        subject = f"告警: ({remark}) 已断开"
                        body = f"主机 {address} ({remark}) 已断开连接\n断网时间为: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
                        send_email(subject, body, **email_details)
                        host_status[address] = False
                else:
                    if not host_status[address]:
                        print(f"主机({remark}) 已恢复,发送恢复邮件...")
                        subject = f"恢复: ({remark}) 已恢复"
                        body = f"主机 {address} ({remark}) 已恢复响应连接\n恢复时间为: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
                        send_email(subject, body, **email_details)
                        host_status[address] = True
                    print(f"主机({remark}) 可达,响应时间: {response} ms")
            except Exception as e:
                print(f"ping过程中出错: {e}")
                messagebox.showerror("ping出错", f"ping过程中出错: {e}")
        time.sleep(check_interval)

def start_monitoring():
    try:
        to_emails = [email.strip() for email in to_email_entry.get().split(",") if email.strip()]
        email_details = {
            'to_emails': to_emails,
            'from_email': from_email_entry.get(),
            'smtp_server': smtp_server_entry.get(),
            'smtp_port': int(smtp_port_entry.get()),
            'smtp_user': smtp_user_entry.get(),
            'smtp_password': smtp_password_entry.get()
        }

        hosts = []
        for i in range(len(host_entries)):
            if host_entries:
                address = host_entries.get()
                remark = remark_entries.get()
                if address and remark:
                    hosts.append({'address': address, 'remark': remark})

        timeout = int(timeout_entry.get())
        check_interval = int(check_interval_entry.get())

        if not email_details['to_emails'] or not email_details['from_email'] or not email_details['smtp_server'] or not email_details['smtp_user'] or not email_details['smtp_password']:
            raise ValueError("所有邮件配置项必须填写完整")

        if not hosts:
            raise ValueError("至少添加一个主机")

        print(f"开始监控,主机列表: {hosts}, 超时时间: {timeout}, 间隔时间: {check_interval}")
        print(f"邮件配置: {email_details}")

        monitoring_thread = threading.Thread(target=monitor_ping, args=(hosts, timeout, check_interval, email_details))
        monitoring_thread.daemon = True
        monitoring_thread.start()

    except ValueError as ve:
        messagebox.showerror("输入错误", str(ve))
    except Exception as e:
        messagebox.showerror("未知错误", str(e))

def add_host_entry():
    row = len(host_entries) + 8
    host_label = tk.Label(inner_frame, text=f"主机{len(host_entries) + 1}:")
    host_label.grid(row=row, column=0, padx=5, pady=5, sticky="ew")

    host_entry = tk.Entry(inner_frame)
    host_entry.grid(row=row, column=1, padx=5, pady=5, sticky="ew")
    host_entries.append(host_entry)

    remark_entry = tk.Entry(inner_frame)
    remark_entry.grid(row=row, column=2, padx=5, pady=5, sticky="ew")
    remark_entries.append(remark_entry)

    delete_button = tk.Button(inner_frame, text="删除", command=lambda row=row: delete_host_entry(row))
    delete_button.grid(row=row, column=3, padx=5, pady=5, sticky="ew")
    delete_buttons.append(delete_button)

    update_layout()

def delete_host_entry(row):
    index = row - 8
    if 0 <= index < len(host_entries):
        host_entries[index].grid_forget()
        host_entries[index].destroy()  # 销毁主机输入框
        remark_entries[index].grid_forget()
        remark_entries[index].destroy()  # 销毁备注输入框
        delete_buttons[index].grid_forget()
        delete_buttons[index].destroy()  # 销毁删除按钮

    # 重建列表,剔除已经销毁的项
    host_entries[:] = [entry for entry in host_entries if entry.winfo_exists()]
    remark_entries[:] = [entry for entry in remark_entries if entry.winfo_exists()]
    delete_buttons[:] = [button for button in delete_buttons if button.winfo_exists()]

    update_layout()

def update_layout():
    for i in range(len(host_entries)):
        host_entries.grid(row=i + 8, column=1, padx=5, pady=5, sticky="ew")
        remark_entries.grid(row=i + 8, column=2, padx=5, pady=5, sticky="ew")
        delete_buttons.grid(row=i + 8, column=3, padx=5, pady=5, sticky="ew")

    add_host_entry_button.grid(row=len(host_entries) + 8, column=0, columnspan=4, pady=5)
    start_button.grid(row=len(host_entries) + 9, column=0, columnspan=4, pady=5)
    save_button.grid(row=len(host_entries) + 10, column=0, columnspan=2, pady=5)
    load_button.grid(row=len(host_entries) + 10, column=2, columnspan=2, pady=5)

    canvas.config(scrollregion=canvas.bbox("all"))

def save_config():
    config = {
        'to_email': to_email_entry.get(),
        'from_email': from_email_entry.get(),
        'smtp_server': smtp_server_entry.get(),
        'smtp_port': smtp_port_entry.get(),
        'smtp_user': smtp_user_entry.get(),
        'smtp_password': smtp_password_entry.get(),
        'timeout': timeout_entry.get(),
        'check_interval': check_interval_entry.get(),
        'hosts': [{'address': host_entries.get(), 'remark': remark_entries.get()} for i in range(len(host_entries)) if host_entries.winfo_exists()]
    }
    with open('config.json', 'w', encoding='utf-8') as config_file:
        json.dump(config, config_file, ensure_ascii=False, indent=4)
    messagebox.showinfo("保存配置", "配置已保存成功")

def load_config():
    try:
        with open('config.json', 'r', encoding='utf-8') as config_file:
            config = json.load(config_file)
            to_email_entry.delete(0, tk.END)
            to_email_entry.insert(0, config['to_email'])
            from_email_entry.delete(0, tk.END)
            from_email_entry.insert(0, config['from_email'])
            smtp_server_entry.delete(0, tk.END)
            smtp_server_entry.insert(0, config['smtp_server'])
            smtp_port_entry.delete(0, tk.END)
            smtp_port_entry.insert(0, config['smtp_port'])
            smtp_user_entry.delete(0, tk.END)
            smtp_user_entry.insert(0, config['smtp_user'])
            smtp_password_entry.delete(0, tk.END)
            smtp_password_entry.insert(0, config['smtp_password'])
            timeout_entry.delete(0, tk.END)
            timeout_entry.insert(0, config['timeout'])
            check_interval_entry.delete(0, tk.END)
            check_interval_entry.insert(0, config['check_interval'])

            for entry in host_entries:
                entry.grid_forget()
                entry.destroy()
            for entry in remark_entries:
                entry.grid_forget()
                entry.destroy()
            for button in delete_buttons:
                button.grid_forget()
                button.destroy()

            host_entries.clear()
            remark_entries.clear()
            delete_buttons.clear()

            for host in config['hosts']:
                add_host_entry()
                host_entries[-1].insert(0, host['address'])
                remark_entries[-1].insert(0, host['remark'])

            update_layout()
    except Exception as e:
        messagebox.showerror("加载配置失败", f"加载配置失败: {e}")

window = tk.Tk()
window.title("Ping 监控程序")

canvas = tk.Canvas(window)
scrollbar = tk.Scrollbar(window, orient="vertical", command=canvas.yview)
canvas.configure(yscrollcommand=scrollbar.set)

scrollable_frame = tk.Frame(canvas)
scrollable_frame.bind("<Configure>", lambda e: canvas.configure(scrollregion=canvas.bbox("all")))

canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
canvas.pack(side="left", fill="both", expand=True)
scrollbar.pack(side="right", fill="y")

inner_frame = tk.Frame(scrollable_frame)
inner_frame.pack(fill="both", expand=True)

tk.Label(inner_frame, text="接收邮件地址(多个用逗号分隔):").grid(row=0, column=0, padx=5, pady=5, sticky="w")
to_email_entry = tk.Entry(inner_frame)
to_email_entry.grid(row=0, column=1, columnspan=3, padx=5, pady=5, sticky="ew")

tk.Label(inner_frame, text="发送邮件地址:").grid(row=1, column=0, padx=5, pady=5, sticky="w")
from_email_entry = tk.Entry(inner_frame)
from_email_entry.grid(row=1, column=1, columnspan=3, padx=5, pady=5, sticky="ew")

tk.Label(inner_frame, text="SMTP服务器:").grid(row=2, column=0, padx=5, pady=5, sticky="w")
smtp_server_entry = tk.Entry(inner_frame)
smtp_server_entry.grid(row=2, column=1, columnspan=3, padx=5, pady=5, sticky="ew")

tk.Label(inner_frame, text="SMTP端口:").grid(row=3, column=0, padx=5, pady=5, sticky="w")
smtp_port_entry = tk.Entry(inner_frame)
smtp_port_entry.grid(row=3, column=1, columnspan=3, padx=5, pady=5, sticky="ew")

tk.Label(inner_frame, text="SMTP用户:").grid(row=4, column=0, padx=5, pady=5, sticky="w")
smtp_user_entry = tk.Entry(inner_frame)
smtp_user_entry.grid(row=4, column=1, columnspan=3, padx=5, pady=5, sticky="ew")

tk.Label(inner_frame, text="SMTP密码:").grid(row=5, column=0, padx=5, pady=5, sticky="w")
smtp_password_entry = tk.Entry(inner_frame, show="*")
smtp_password_entry.grid(row=5, column=1, columnspan=3, padx=5, pady=5, sticky="ew")

tk.Label(inner_frame, text="超时时间():").grid(row=6, column=0, padx=5, pady=5, sticky="w")
timeout_entry = tk.Entry(inner_frame)
timeout_entry.grid(row=6, column=1, columnspan=3, padx=5, pady=5, sticky="ew")

tk.Label(inner_frame, text="检查间隔():").grid(row=7, column=0, padx=5, pady=5, sticky="w")
check_interval_entry = tk.Entry(inner_frame)
check_interval_entry.grid(row=7, column=1, columnspan=3, padx=5, pady=5, sticky="ew")

host_entries = []
remark_entries = []
delete_buttons = []

add_host_entry_button = tk.Button(inner_frame, text="添加主机", command=add_host_entry)
add_host_entry_button.grid(row=8, column=0, columnspan=4, pady=5)

start_button = tk.Button(inner_frame, text="开始监控", command=start_monitoring)
start_button.grid(row=9, column=0, columnspan=4, pady=5)

save_button = tk.Button(inner_frame, text="保存配置", command=save_config)
save_button.grid(row=10, column=0, columnspan=2, pady=5)

load_button = tk.Button(inner_frame, text="加载配置", command=load_config)
load_button.grid(row=10, column=2, columnspan=2, pady=5)

window.grid_columnconfigure(1, weight=1)
window.grid_columnconfigure(2, weight=1)

window.mainloop()


软件截图

软件截图

免费评分

参与人数 1吾爱币 +1 收起 理由
xiaocezi + 1 兄弟 能不能加个日志啊

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

AnyLine 发表于 2024-8-22 09:27
goblack 发表于 2024-7-5 17:53
这种通知最好还是部署在成熟稳定的IDC机房、云服务器。然后被监控设备定时去链接,由稳定的设备发送告警信 ...

都放机房了,为什么不用zabbix这一类的啊??
 楼主| Azminis 发表于 2024-7-8 09:41
hh3100 发表于 2024-7-5 23:20
请问楼主,主机1 后面两个框填写说明?

就是备注的意思
前面ip 后面可以备注是什么
goblack 发表于 2024-7-5 17:53
这种通知最好还是部署在成熟稳定的IDC机房、云服务器。然后被监控设备定时去链接,由稳定的设备发送告警信息才靠谱。。不然比如说网关断网,整个无法访问了,告警也无法发出了。

4g的lte cat.1模块很便宜,带小电池的设备就可以用这个构建发送短信、邮件各种断网告警的渠道。。或者在服务器取令牌,如果服务器一定时间检查不到令牌,就告警通知。

我是综合了两者。。ALERT以及以下的告警不通过这个接口,只有CRIT(critical,关键性)事件才会通过短信、主动电话外呼告警。而云服务器调用API主要是做掉线检测。节点5秒请求一次,产生一个30秒有效期的记录,服务器端另外每10秒检测一次令牌存在情况,如果超过3次检测不到,就发送节点离线的告警。手搓一份zabbix之外的独立在线告警。虽然nagios应该能搞得更好。
yang147 发表于 2024-7-5 17:22
没网的时候也能发送吗
 楼主| Azminis 发表于 2024-7-5 17:28
yang147 发表于 2024-7-5 17:22
没网的时候也能发送吗

就是为了监控主机断网 不能及时知道
头像被屏蔽
pj666a 发表于 2024-7-5 20:20
提示: 作者被禁止或删除 内容自动屏蔽
hgyes 发表于 2024-7-5 20:51
是主机本机运行吗?主机都掉线了,也能发邮件吗?还是说要监控A主机,需要用B主机运行软件,当B主机发现A不在线了,就发邮件?
pzk7891 发表于 2024-7-5 21:03
运维用途挺大的
hh3100 发表于 2024-7-5 23:20
请问楼主,主机1 后面两个框填写说明?
 楼主| Azminis 发表于 2024-7-8 09:42
本帖最后由 Azminis 于 2024-7-8 09:43 编辑
hgyes 发表于 2024-7-5 20:51
是主机本机运行吗?主机都掉线了,也能发邮件吗?还是说要监控A主机,需要用B主机运行软件,当B主机发现A不 ...

如你后面所说 监控B运行主机 监控A
监控A掉线 监控B发送消息 也可监控本身 这样子就可以了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-15 10:52

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表