Python 3:使用“ for循环”发送多个邮件,而不是单个邮件

时间:2018-10-08 04:07:07

标签: python-3.x

我有下面的脚本,它可以正常工作,但是当我使用for循环读取Cisco设备的状态并使用用户定义的函数send_mail()发送邮件时,我收到的是两封邮件,而不是一封邮件建议获得一封邮件,将不胜感激:

username = 'cisco'
password = 'cisco'
hosts = ['10.0.10.100','10.0.10.101']
platform = 'cisco_ios'

def send_mail():
    fromaddr = "@gmail.com"
    toaddr = "@hotmail.com"
    msg = MIMEMultipart()
    msg['From'] = '@gmail.com'
    msg['To'] = '@hotmail.com'
    msg['Subject'] = "This is Health check"
    msg.attach(MIMEText(status, 'plain'))   
    server = smtplib.SMTP('smtp.gmail.com', 587)
    server.starttls()
    server.login(fromaddr, "password")
    text = msg.as_string()
    server.sendmail(fromaddr, toaddr, text)
    server.quit()

for host in hosts:
    #print(host)
    connect = ConnectHandler(device_type=platform, ip=host, username=username, password=password)
    output = connect.send_command('terminal length 0', expect_string=r'#')
    output = connect.send_command('enable',expect_string=r'#')
    host_name = connect.send_command('show run | in hostname',expect_string=r'#')
    interface_status = connect.send_command(f'show ip int brief',expect_string=r'#')
    #print(interface_status)
    old_stdout = sys.stdout
    interface_result = StringIO()
    sys.stdout = interface_result
    sys.stdout = old_stdout
    data = pd.read_fwf(StringIO(interface_status),  widths=[27, 16, 3, 7, 23, 8])

    status = " "
    for index, row in data.iterrows():
        if row[4] == 'administratively down' or row[4] == 'down':
            log = (f"\nInterface {row[0]} is down in {host_name}\n")
            status += log


    bgp_status = connect.send_command('show ip bgp summary | be N',expect_string=r'#')
    old_stdout = sys.stdout
    bgp_result = StringIO()
    sys.stdout = bgp_result
    sys.stdout = old_stdout
    bgp_data = pd.read_fwf(StringIO(bgp_status),  delim_whitespace=True, header=None)
    for index, row in bgp_data.iterrows():
        if row[9] == 'Down' or row[9] == 'Idle' or row[9] == 'Active':
            bgp = (f"\nNeighbor {row[0]} is down in {host_name}\n")
            status += bgp
    send_mail()

1 个答案:

答案 0 :(得分:0)

我想我明白您的问题所在。简而言之,您正在每个send_mail()循环中调用for,而实际上您想收集每个主机的状态,然后以一封电子邮件的形式发送最终状态报告。这是一个简短的示例,说明了如何执行此操作-显然,您将必须相应地修改代码。

几点:

  • 传入send_mail参数,而不是让status依赖全局status变量。这有助于将功能彼此分离。

  • 您可能希望收集列表中每个主机的状态,然后在发送状态电子邮件时以逻辑方式组合它们。

  • 字符串连接很慢。最好建立一个字符串列表,然后使用字符串join函数将它们连接起来。

这是一些示例代码:

hosts = ['10.0.10.100','10.0.10.101']

def send_mail(status=''):
    '''A placeholder function for testing'''
    print("Sending email:\n{status}".format(status=status))
    return

status_for_hosts = []

for host in hosts:
    status_list = []
    # An example of how you might collect statuses for a host
    status_list.append("Host {host_ip} is up".format(host_ip=host))
    # Use join() instead of string concatenation
    full_status = ''.join(status_list)
    status_for_hosts.append(full_status)

send_mail(status='\n'.join(status_for_hosts))