smtlib 邮件不发送且无错误代码

smtlib mail does not send and no error code

如果两个文件的比较失败,我想从脚本中发送邮件。

(该脚本监控一个网站并将该页面的样本存储为日志文件并每天进行比较 到最后一天的版本并发送邮件以防发生变化)

我有以下代码片段,它工作正常并发送了邮件。

(当然,我已经用这里的示例替换了我的实际凭据,但代码适用于我输入的凭据)

示例代码(有效):

import smtplib

sender = "Sender <sender@example.com>"
receiver = "Receiver <receiver@example.com>"

message = f"""\
Subject: test notification mail
To: {receiver}
From: {sender}

This is a test e-mail notification."""

with smtplib.SMTP("smtp.example.com", 2525) as server:
    server.login("username", "password")
    server.sendmail(sender, receiver, message)

然而,当我将该代码片段插入主代码时,似乎 运行 没有错误,但没有发送邮件...

实际代码(邮件不起作用):

import time
import requests
from bs4 import BeautifulSoup
from datetime import datetime
import difflib
import filecmp
import smtplib


class App():

    def __init__(self):
        while True:
            # url to monitor
            url = 'https://www.website.com'
            headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36'}

            # download the webpage
            response = requests.get(url, headers=headers)
            # parse the downloaded webpage and grab all text
            soup = BeautifulSoup(response.text, "lxml")
            # find the class that contains all new id document entries, get the text and get rid of html expressions
            self.soup_class = soup.find(class_='row').text.strip()

            self.last_check = '2021-09-21'
            last_check_file = 'Log' + '_' + self.last_check + '.txt'

            while True:
                # create new current check file
                new_check_file = self.create_log_file()
                if filecmp.cmp(last_check_file, new_check_file, shallow=False):
                    print('No changes found', self.get_date(), self.get_time())
                else:
                    print('Changes detected: ' + self.get_date())
                    file1 = open(last_check_file, 'r', encoding='utf-8').readlines()
                    file2 = open(new_check_file, 'r', encoding='utf-8').readlines()
                    for line in difflib.unified_diff(file1, file2, fromfile='file1', tofile='file2', lineterm='', n=0):
                        print(line)

                    # send notification mail
                    self.send_mail()

                self.last_check = self.get_date()
                # wait 24h for next check
                time.sleep(86400)

    def get_time(self):
        date_now = datetime.now().time()
        return str(date_now)

    def get_date(self):
        time_now = datetime.now().date()
        return str(time_now)

    def create_log_file(self): # save a log.txt file with the current date in name
        log_file_name = 'Log' + '_' + str(self.get_date()) + '.txt'
        with open(log_file_name, "w", encoding='utf-8') as text_file:
            text_file.write(self.soup_class)
        return log_file_name

    def send_mail(self): # define mail contents / sender / receiver
        sender = "Sender <sender@example.com>"
        receiver = "Receiver <receiver@example.com>"

        message = f"""\
        Subject: test notification mail
        To: {receiver}
        From: {sender}

        This is a test e-mail notification."""

        with smtplib.SMTP("smtp.example.com", 2525) as server:
            server.login("username", "password")
            server.sendmail(sender, receiver, message)

        print('Notification mail sent to:', receiver)


if __name__ == '__main__':
    App()

也许有人知道这里出了什么问题。

调试级别输出:

send: 'ehlo LAPTOP\r\n'
reply: b'250-smtp.example.com\r\n'
reply: b'250-SIZE 5242880\r\n'
reply: b'250-PIPELINING\r\n'
reply: b'250-ENHANCEDSTATUSCODES\r\n'
reply: b'250-8BITMIME\r\n'
reply: b'250-DSN\r\n'
reply: b'250-AUTH PLAIN LOGIN CRAM-MD5\r\n'
reply: b'250 STARTTLS\r\n'
reply: retcode (250); Msg: b'smtp.example.com\nSIZE 5242880\nPIPELINING\nENHANCEDSTATUSCODES\n8BITMIME\nDSN\nAUTH PLAIN LOGIN CRAM-MD5\nSTARTTLS'
send: 'AUTH CRAM-MD5\r\n'
reply: b'334 MD5sum_removed==\r\n'
reply: retcode (334); Msg: b'MD5sum=='
send: 'MD5sum=\r\n'
reply: b'235 2.0.0 OK\r\n'
reply: retcode (235); Msg: b'2.0.0 OK'
send: 'mail FROM:<sender@example.com> size=175\r\n'
reply: b'250 2.1.0 Ok\r\n'
reply: retcode (250); Msg: b'2.1.0 Ok'
send: 'rcpt TO:<receiver@example.com>\r\n'
reply: b'250 2.1.0 Ok\r\n'
reply: retcode (250); Msg: b'2.1.0 Ok'
send: 'data\r\n'
reply: b'354 Go ahead\r\n'
reply: retcode (354); Msg: b'Go ahead'
data: (354, b'Go ahead')
send: b'        Subject: test notification mail\r\n        To: Receiver <receiver@example.com>\r\n        From: Sender <sender@example.com>\r\n\r\n        This is a test e-mail notification.\r\n.\r\n'
reply: b'250 2.0.0 Ok: queued\r\n'
reply: retcode (250); Msg: b'2.0.0 Ok: queued'
data: (250, b'2.0.0 Ok: queued')
send: 'QUIT\r\n'
reply: b'221 2.0.0 Bye\r\n'
reply: retcode (221); Msg: b'2.0.0 Bye'

Serge Ballesta描述的答案解决了问题。

消息字符串中的缩进会导致出现错误消息,smtp 服务器收到后无法进一步处理该消息。

这是正确的格式:

def send_mail(self): # define mail contents / sender / receiver
        sender = "Sender <sender@example.com>"
        receiver = "Receiver <receiver@example.com>"

        message = f"""\
Subject: test notification mail
To: {receiver}
From: {sender}

This is a test e-mail notification."""

        with smtplib.SMTP("smtp.example.com", 2525) as server:
            server.login("username", "password")
            server.sendmail(sender, receiver, message)

        print('Notification mail sent to:', receiver)