I want to send a mail from within a script if the comparison of two files fails.
(The script monitors a website and stores a sample of that page as log file and compares each day to the last day version and sends a mail in case something changes)
I have the following code snippet and it works fine and sends the mail.
(Of course I have replaced my actual credentials with samples here, but the code works with my credentials entered)
The sample code (working):
import smtplib
sender = "Sender <[email protected]>"
receiver = "Receiver <[email protected]>"
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)
However, when I insert that code snippet into the main code, it seems to run through without errors, but no mail is sent...
The actual code (mail not working):
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 <[email protected]>"
receiver = "Receiver <[email protected]>"
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()
Maybe someone knows what's wrong here.
The debuglevel output:
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:<[email protected]> 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:<[email protected]>\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 <[email protected]>\r\n From: Sender <[email protected]>\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'
CodePudding user response:
The answer described by Serge Ballesta solves the issue.
The indentation in the message string creates spaces which lead to a faulty message which cannot be processed further after received by the smtp server.
This is the right format:
def send_mail(self): # define mail contents / sender / receiver
sender = "Sender <[email protected]>"
receiver = "Receiver <[email protected]>"
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)