uMail - A lightweight SMTP client for MicroPython

Discussion about programs, libraries and tools that work with MicroPython. Mostly these are provided by a third party.
Target audience: All users and developers of MicroPython.
ScotsDon
Posts: 4
Joined: Wed Jul 22, 2020 9:18 pm

Re error reporting: uMail - A lightweight SMTP client for MicroPython

Post by ScotsDon » Fri Dec 18, 2020 7:29 pm

I am using uMail in an esp32. This runs autonomously in a box, logging data, and emails data to me. Occasionally the email fails, for which the causes could be my broadband is down or Google is playing up. This causes the ESP32 to crash. Is there a way to detect errors and take some action, so avoiding the crash?

davef
Posts: 811
Joined: Thu Apr 30, 2020 1:03 am
Location: Christchurch, NZ

Re: uMail - A lightweight SMTP client for MicroPython

Post by davef » Fri Dec 18, 2020 9:26 pm

Hi ScotsDon,

I was doing the same thing on an ESP32, but I gave-up on that implementation. As my ESP32 was about 1 metre away from the hotspot and a RaspberryPi running a similar system never failed I concluded that there was something "hanging" in the ESP32. I tried a software WDT and that didn't sort it so I then concluded that there was something going wrong in the ESP32 (maybe the OS).

I have since being using the ESP8266, specifically the ESP-07S as a UDP link to a remote. It has worked without an issue for several weeks.

I am now looking at ESP-NOW (for the remote sensor) and plan to switch to WiFi (on the local ESP-07S) when I want to send alarms or datalogs.

There were several tricks to getting Gmail's SMTP to play ball so I will attach my send_alarm and send_datalog code.

Code: Select all

import network
import umail
import utime
import machine
#import ubinascii


def send_alarm(alarm_msg):

#    smtp = umail.SMTP('smtp.gmail.com', 587, ssl=False)
    smtp = umail.SMTP('smtp.gmail.com', 465, ssl=True)

#    print(str(smtp))
#    print('uMail.SMTP return value = ' + str(smtp))

    result = str(smtp).find('SMTP object')
    if (result != -1):
        print('successful SSL connection')
    else:
        machine.reset()

    test1 = smtp.login('dave@gmail.com', 'xxxxxx')
    print('test1 = ' + str(test1))

    result = str(test1).find('Accepted')
    if (result != -1):
        print('success')

#  use a list for multiple recipents, but probably can't use the To: lines
#        test2 = smtp.to('xxxxx@aussiesms.com.au')
        test2 = smtp.to('dave@gmail.com')
        print('test2 = ' + str(test2))

        result = str(test2).find('Go ahead')

        if (result != -1):
            print('success')

            smtp.write('From: dave@gmail.com\n')
            smtp.write('To: dave@gmail.com\n') #  gets rid of the bcc line
#            smtp.write('To: xxxxxxx@aussiesms.com.au\n') #  gets rid of the bcc line

            smtp.write('Subject:497590\n')
            smtp.write(alarm_msg + '\n')
            smtp.write('...\n') #  appears to be very important
            smtp.send() #  does the proper ending
            smtp.quit()

        else:
            machine.reset()
    else:
        machine.reset()

    print('alarm has been sent')


def send_csv(date):

#    smtp = umail.SMTP('smtp.gmail.com', 587, ssl=False)
    smtp = umail.SMTP('smtp.gmail.com', 465, ssl=True)

#    print(str(smtp))
#    print('uMail.SMTP return value = ' + str(smtp))

    result = str(smtp).find('SMTP object')
    if (result != -1):
        print('successful SSL connection')
    else:
     #  try to capture the failure
        try:
            with open('/errors.txt', 'a') as outfile:
                outfile.write('did NOT get a SSL connection')
                machine.reset()
        except IOError:
            print('oops')

    test1 = smtp.login('dave@gmail.com', 'xxxxxxxx')
    print('test1 = ' + str(test1))

    result = str(test1).find('Accepted')
    if (result != -1):
        print('test1 success')
    else:
     #  try to capture the failure
        try:
            with open('/errors.txt', 'a') as outfile:
                outfile.write('smtp.login did NOT work')
                machine.reset()
        except IOError:
            print('oops')

    test2 = smtp.to('dave@gmail.com')
    print('test2 = ' + str(test2))

    result = str(test2).find('Go ahead')
    if (result != -1):
        print('test2 success')
    else:
     #  try to capture the failure
        try:
            with open('/errors.txt', 'a') as outfile:
                outfile.write('smtp.to did NOT work')
                machine.reset()
        except IOError:
            print('oops')

    smtp.write('From: dave@gmail.com\n')
    smtp.write('To: dave@gmail.com\n')
    smtp.write('Subject: Today\'s ESP32 datalog\n')
    smtp.write('MIME-Version: 1.0\n')
    smtp.write('Content-type: multipart/mixed; boundary=12345678900987654321\n')

    smtp.write('--12345678900987654321\n')
    smtp.write('Content-Type: text/plain; charset=utf-8\n')
    smtp.write('see attachment\n')
    smtp.write('--12345678900987654321\n')

 #  build today's filename into Content-Type and Content-Disposition
    csv_file = 'ESP32-' + date + '.csv\n'

    content_type = 'Content-Type: text/csv; name=' + csv_file
    content_disposition = 'Content-Disposition: attachment; filename=' + csv_file 
    smtp.write(content_type)
    smtp.write(content_disposition)

    try:
        with open('/ramdisk/datalog.csv', 'r') as infile:
            content = infile.read()
    except IOError:
        print('oops!')

#  evidently for images
#    b64 = ubinascii.b2a_base64(content['bytes'])
#    smtp.write(b64)

    smtp.write(content) #  my content has a \n at the end
    smtp.write('--12345678900987654321--')
    smtp.write('...\n') #  appears to be very important
    smtp.send()
    smtp.quit()

    print('log has been sent')

    utime.sleep(5) # so I can see the above print statement
Good luck!

ScotsDon
Posts: 4
Joined: Wed Jul 22, 2020 9:18 pm

Re: uMail - A lightweight SMTP client for MicroPython

Post by ScotsDon » Sat Dec 19, 2020 10:31 am

Many thanks, davef. Will take a close look when I get some time. Christmas and family are pressing!

davef
Posts: 811
Joined: Thu Apr 30, 2020 1:03 am
Location: Christchurch, NZ

Re: uMail - A lightweight SMTP client for MicroPython

Post by davef » Thu Feb 25, 2021 9:40 pm

Hi ScotsDon,

Get any further? Do you know how to log assert errors in umail? I have also tried:

Code: Select all

    try:
        smtp = umail.SMTP('smtp.gmail.com', 465, ssl=True)
    except AssertionError as error:
        try:
            with open('errors.txt', 'a') as outfile:
                outfile.write(str(error) + '\n')
        except OSError:
            print('oops')
but never seem to catch what is going wrong in the def __init__ block ... I think here:

Code: Select all

if ssl:
    sock = ussl.wrap_socket(sock)
Thanks.

Post Reply