Home > Blockchain >  smtlib mail does not send and no error code
smtlib mail does not send and no error code

Time:09-27

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)
  • Related