I have a threaded python script that pings 20 nodes on a local area network, and prints out the status of each: Node is Alive, Node is Down, etc.. I would like to have this outp
A great resource on the topic of sending email with Python is Al Sweigart's 'Automate the Boring Stuff with Python'. Chapter 18 is the part you want. In short, if you have an email address with one of the big email providers (think Google, Outlook, Yahoo, etc.) you can use their Simple Mail Transfer Protocol (SMTP) server(s) to handle your messages from Python. As Al says:
If you don't have an email address with one of the big providers or you're not in a position where you can use an email address from an outside provider, then it's a bit harder. Perhaps someone at your company can tell you 1) if your company has an SMTP server and 2) what its domain name and port number are.
Once you have all that, sending out an email message from your program is a piece of cake:
import smtplib
def main():
# get message from node
message1 = 'Node 1 is up :)'
# print message from node
print(message1)
# get message from another node
message2 = 'Node 2 is down :('
# print that too
print(message2)
# now, all done talking to nodes.
# time to compile node response results and send an email.
# first, let's get every thing setup for the email
from_me = 'awesome.name@my_email_provider.com'
to_me = 'awesome.name@my_email_provider.com'
email_message = message1 + '\n' + message2
# second, let's make sure we have a connection to a Simple Mail Transfer Protocol (SMTP) server
# this server will receive and then send out our email message
domain_name = 'smtp.my_email_provider.com'
port_number = 587 # or maybe, 465
server = smtplib.SMTP(domain_name, port_number)
# alright! if that last line didn't raise an exceptions, then you're good to go. Send that bad boy off.
server.sendmail(from_me, to_me, email_message)
if __name__ == '__main__':
main()
Loggers are great too, so don't discount what everyone's said about them. Print to the terminal. Log to a file. AND email out! Loggers can do everything.
Instead of having your main print
the output, you could use a logger
to print to stout and to the logger
You can set up a logger as follows according to the Logging Cookbook:
import logging
log_file = r'C:\Users\user\Downloads\LogFileName.log'
logger = logging.getLogger('simple_example')
logger.setLevel(logging.INFO)
# create file handler which logs even debug messages
fh = logging.FileHandler('log_file')
fh.setLevel(logging.DEBUG)
# create console handler with a higher log level
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
# create formatter and add it to the handlers
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
fh.setFormatter(formatter)
# add the handlers to logger
logger.addHandler(ch)
logger.addHandler(fh)
Now in replace print
in your script with logger.info
Example before:
print("Printing status")
Example after:
logger.info("Printing status")
Then you can email the log to yourself as follows:
import smtplib
from email.message import EmailMessage
import os
msg_body = "Body Text"
msg = EmailMessage()
msg['Subject'] = "Subject"
msg['From'] = "send_from@email.com"
msg['To'] = "send_to@email.com"
msg.set_content(msg_body)
if os.path.isfile(log_file):
msg.add_attachment(open(log_file, "r").read(), filename=os.path.basename(log_file))
# Send the message via our own SMTP server.
s = smtplib.SMTP("smtpa.server")
s.send_message(msg)
s.quit()
You need a SMTP server to send Email. Check out the smtplib for Python
If it runs once a week, you will probably run it from crontab?
30 2 * * 5 python yourScript.py | mail -s outputFromScript your@email.address
Take a look at the logging and logging.config, I've used this before to receive error messages from a script running in the background
http://docs.python.org/library/logging.html
For example
import logging
import logging.config
logDir = "./logs/"
logging.config.fileConfig(logDir+'logging.conf')
logger = logging.getLogger('email')
logger.debug('THIS IS A DEBUG MESSAGE')
logger.error('THIS IS AN ERROR')
And then the logging.conf
[loggers]
keys=root,email
[logger_root]
level=DEBUG
handlers=rotatingFileHandler
[logger_email]
level=ERROR
handlers=email
qualname=email
[formatters]
keys=emailFormatter,rotatingFormatter
[formatter_emailFormatter]
format=%(asctime)s %(name)-12s %(levelname)-8s %(message)s
[formatter_rotatingFormatter]
format=%(asctime)s %(name)-12s %(levelname)-8s %(message)s
datefmt=%m-%d %H:%M
[handlers]
keys=email,rotatingFileHandler
[handler_email]
class=handlers.SMTPHandler
level=ERROR
formatter=emailFormatter
args=('mail.xxx','x@x.com',['y@y.com',],'ERROR!',('x@x.com','xxx'))
[handler_rotatingFileHandler]
class=handlers.RotatingFileHandler
level=DEBUG
formatter=rotatingFormatter
args=('./logs/log.out', 'maxBytes=1000000', 'backupCount=5')
From the above I would receive "THIS IS AN ERROR" in my email.
Use smtplib. The example they provide is pretty good.
import smtplib
def prompt(prompt):
return raw_input(prompt).strip()
fromaddr = prompt("From: ")
toaddrs = prompt("To: ").split()
print "Enter message, end with ^D (Unix) or ^Z (Windows):"
# Add the From: and To: headers at the start!
msg = ("From: %s\r\nTo: %s\r\n\r\n"
% (fromaddr, ", ".join(toaddrs)))
while True:
try:
line = raw_input()
except EOFError:
break
if not line:
break
msg += line
print "Message length is " + repr(len(msg))
server = smtplib.SMTP('localhost')
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()