Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Email Results of Function
#1
Hello,

I created the following function to return the results of Linux mounts points with over a certain percentage of used space:

>>> def mounts():
...     devs = psutil.disk_partitions()
...     for dev in devs:
...             part = int(psutil.disk_usage(dev.mountpoint).percent)
...             if part > 60:
...                     print(dev.mountpoint, part)
...
>>> mounts()
/var 71
/u01 61
/backups 69
I'd like to email the output above. However, when I attempt to email the output I receive nothing in the body.

Here is the email code:

>>> import smtplib
>>> mail_server = 'localhost'
>>> mail_server_port = 25
>>> from_addr = 'test@domain'
>>> to_addr = 'email@domain'
>>> from_header = 'From: %s\r\n' % from_addr
>>> to_header = 'To: %s\r\n\r\n' % to_addr
>>> subject_header = 'Subject: TEST'
>>> body = mounts()
/var 71
/u01 61
/backups 69
>>> email_message = '%s' % body
>>> s = smtplib.SMTP(mail_server, mail_server_port)
>>> s.sendmail(from_addr, to_addr, email_message)
{}
>>> s.quit()
Any idea why the body of the email is empty?
Reply
#2
The mounts() function prints to stdout (and then returns None implicitly). But you're using it as if it's returning a string.
Reply
#3
Ok, I understand that part. How do I get the function to return the results to the body of the email?
Reply
#4
# the naive way
def mounts():
    results = []
    devs = psutil.disk_partitions()
    for dev in devs:
        part = int(psutil.disk_usage(dev.mountpoint).percent)
        if part > 60:
            results.append([dev.mountpoint, part])
    return results
    
list_with_mounts1 = mounts()

# or as a generator
def mounts():
    devs = psutil.disk_partitions()
    for dev in devs:
        part = int(psutil.disk_usage(dev.mountpoint).percent)
        if part > 60:
            yield [dev.mountpoint, part]
            
tuple_with_mounts2 = tuple(mounts())
list_with_mounts2 = list(mounts())
The second example is more advanced.
I guess you are not so far.

PS: The code returns a list with two objects. You have to convert it.
You can do it inside the function or you do it at the place where you assign email_message.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#5
That was it, thx!
Reply
#6
So I was able to put together the final piece of code but I'm still receiving error when passing the list to the body of the email.

from email.headerregistry import Address
from email.message import EmailMessage
import os
import smtplib
import psutil

# mail server details
mail_server = 'localhost'
mail_server_port = 25

# email addresses
email_address = '[email protected]'
recipient_address = '[email protected]'
subject_desc = 'Test'

# linux mount points
def mounts():
    results = []
    devs = psutil.disk_partitions()
    for dev in devs:
            part = int(psutil.disk_usage(dev.mountpoint).percent)
            if part > 60:
                    results.append([dev.mountpoint, part])
    return results

list_mounts = list(mounts())

def list_out(list_in):
    for drive in list_in:
            print('Drive: {0:10s} Used Space: {1:5.2f}'.format(*drive))

email_body = list_out(list_mounts)

# email function
def create_email_message(from_address, to_address, subject, body):
	msg = EmailMessage()
	msg['From'] = from_address
	msg['To'] = to_address
	msg['Subject'] = subject
	msg.set_content(body)
	return msg

if __name__ == '__main__':
	msg = create_email_message(
		from_address=email_address,
		to_address=recipient_address,
		subject=subject_desc,
		body=email_body
	)

with smtplib.SMTP(mail_server, mail_server_port) as smtp_server:
	smtp_server.ehlo()
	smtp_server.send_message(msg)

print('Email sent successfully')
I get the following message when I run the code:

Error:
$ python linux_mounts_email.py Drive: /var Used Space: 71.00 Drive: /u01 Used Space: 61.00 Drive: /backups Used Space: 69.00 Traceback (most recent call last): File "linux_mounts_email.py", line 48, in <module> body=email_body File "linux_mounts_email.py", line 40, in create_email_message msg.set_content(body) File "/usr/src/Python-3.6.1/Lib/email/message.py", line 1162, in set_content super().set_content(*args, **kw) File "/usr/src/Python-3.6.1/Lib/email/message.py", line 1092, in set_content content_manager.set_content(self, *args, **kw) File "/usr/src/Python-3.6.1/Lib/email/contentmanager.py", line 35, in set_content handler = self._find_set_handler(msg, obj) File "/usr/src/Python-3.6.1/Lib/email/contentmanager.py", line 58, in _find_set_handler raise KeyError(full_path_for_error) KeyError: 'builtins.NoneType'
I don't received an email, but there is output to the screen (guessing stdout as mentioned above - but how do i avoid that?).

Thanks for the help!
Reply
#7
So I removed the following from the create_email_message() function:

msg.set_content(body)
I no longer receive an error. The email is sent but the body is blank. Looking into that now but any ideas as to why it's blank would be helpful.

Thanks!
Reply
#8
There's no body, because you removed the line that added the body.

I'm not currently in a position to mess around with it and try to get it working, though.
Reply
#9
Ok, that makes sense.

I added the line back but am receiving NONE again in the email body. Also, when I run the script from the command prompt the list value is displayed and it says the email was sent.

Any ideas on how I can output the list values to the body of the email? My other option is to create a CSV file and output the list values to there and then read the CSV file into the email. That seems a bit much but I'm running out of options.

Thanks!
Reply
#10
Change your function to:
def list_out(list_in):
    return '\n'.join('Drive: {0:10s} Used Space: {1:5.2f}'.format(*drive) for drive in list_in)
This function converts the input list with the device name and percentage to a string with each information separated by new line.

Remember that if a function does not have a "return <something>" or has a simple "return", is like it ends with a "return None". That is the reason the set_content fails, does not knows what to do with a None...
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
Bug New to coding, Using the zip() function to create Diret and getting weird results Shagamatula 6 1,456 Apr-09-2023, 02:35 PM
Last Post: Shagamatula
  Search Results Web results Printing the number of days in a given month and year afefDXCTN 1 2,243 Aug-21-2020, 12:20 PM
Last Post: DeaD_EyE
  How to append one function1 results to function2 results SriRajesh 5 3,175 Jan-02-2020, 12:11 PM
Last Post: Killertjuh
  Python function returns inconsistent results bluethundr 4 3,199 Dec-21-2019, 02:11 AM
Last Post: stullis
  How do you add the results together each time a function is called? Exsul 10 5,145 Aug-09-2019, 09:18 PM
Last Post: ichabod801
  Greenplum Query results to Email HTML table krux_rap 1 2,515 Apr-10-2018, 09:12 PM
Last Post: Larz60+
  An email with inline jpg cannot be read by all email clients fpiraneo 4 3,993 Feb-25-2018, 07:17 PM
Last Post: fpiraneo
  Email - Send email using Windows Live Mail cyberzen 2 5,928 Apr-13-2017, 03:14 AM
Last Post: cyberzen

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020