Python Email on Error

2463
8
11-14-2013 02:56 PM
ScottBallard
New Contributor II
Anyone written python email code that sends an email if the python script fails?
Tags (2)
8 Replies
FabianBlau
Occasional Contributor II
I never tried it, but maybe this helps:
http://docs.python.org/2/library/smtplib.html#module-smtplib
0 Kudos
XanderBakker
Esri Esteemed Contributor
Hi Scott,

ArcGIS 10.2 still comes with a python script tool in the Server Tools\Data Extraction: Send Email With Zip File Attachment. It uses the old arcgisscripting.create(9.3), but shows how you can send email with Python code.


import arcgisscripting, smtplib, os, sys, traceback

from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders

gp = arcgisscripting.create(9.3)

#**********************************************************************
# Description:
#   Emails a file. File is assumed to be a zip file. Routine either attaches
#   the zip file to the email or sends the URL to the zip file.
#
# Parameters:
#   1 - File to send.
#   2 - Email address to send file.
#   3 - Name of outgoing email server.
#   4 - Output boolean success flag.
#**********************************************************************

def send_mail(send_from, send_to, subject, text, f, server, smtpUser="", smtpPwd=""):
    try:
        msg = MIMEMultipart()
        msg['From'] = send_from
        msg['To'] = COMMASPACE.join(send_to)
        msg['Date'] = formatdate(localtime=True)
        msg['Subject'] = subject

        msg.attach( MIMEText(text) )
        part = MIMEBase('application', "zip")   # Change if different file type sent.
        part.set_payload( open(f,"rb").read() )
        Encoders.encode_base64(part)
        part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
        msg.attach(part)
            
        smtp = smtplib.SMTP(server)
        
        # If your server requires user/password
        if smtpUser != "" and smtpPwd != "":
            smtp.login(smtpUser, smtpPwd)
        
        smtp.sendmail(send_from, send_to, msg.as_string())
        smtp.close()
    except:
        tb = sys.exc_info()[2]
        tbinfo = traceback.format_tb(tb)[0]
        pymsg = "PYTHON ERRORS:\nTraceback Info:\n" + tbinfo + "\nError Info:\n    " + \
                str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"
        raise Exception("SendEmailError:" + pymsg)

   
if __name__ == '__main__':

    sendto = gp.GetParameterAsText(0).split(";")
    fromaddr = gp.GetParameterAsText(1)
    subject = gp.GetParameterAsText(2)
    text = gp.GetParameterAsText(3)
    zipfile = gp.GetParameterAsText(4).replace("\\",os.sep)
    maxsize = int(gp.GetParameterAsText(5)) * 1000000
    smtpMailServer = gp.GetParameterAsText(6)
    smtpUser = gp.GetParameterAsText(7)
    smtpPwd = gp.GetParameterAsText(8)
    
    try: 
        zipsize = os.path.getsize(zipfile)
        #Message"Zip file size = "
        gp.AddMessage(gp.GetIDMessage(86156) + str(zipsize))
        if  zipsize <= maxsize:
            send_mail(fromaddr, sendto, subject, text, zipfile, smtpMailServer, smtpUser, smtpPwd)
            #Message "Sent zipfile to %s from %s"
            gp.AddIDMessage("INFORMATIVE", 86154, sendto, fromaddr)
            gp.SetParameterAsText(9, "True")
        else:
            #Message "The resulting zip file is too large (%sMB).  Must be less than %MB.  Please
            # digitize a smaller Area of Interest."
            gp.AddIDMessage("ERROR", 86155, str(round(zipsize / 1000000.0, 2)),
                            str(round(maxsize / 1000000.0, 2)))
            gp.SetParameterAsText(9, "False")
            raise Exception

    except:
        # Return any python specific errors as well as any errors from the geoprocessor
        tb = sys.exc_info()[2]
        tbinfo = traceback.format_tb(tb)[0]
        pymsg = "PYTHON ERRORS:\nTraceback Info:\n" + tbinfo + "\nError Info:\n    " + \
                str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"
        gp.AddError(pymsg)
        #Message "Unable to send email"
        #gp.AddIDMessage("ERROR", 86157)
        gp.AddError("ERROR, Unable to send email")


Kind regards,

Xander
0 Kudos
StacyRendall1
Occasional Contributor III
Here is a post on from blog describing another way to do it, using smtplib.

http://pythongisandstuff.wordpress.com/2011/09/06/arcpy-sending-a-result-email/
0 Kudos
MartinHvidberg
Occasional Contributor
Anyone written python email code that sends an email if the python script fails?


I use the email part from this help page with our data base administration, it works well.

http://resources.arcgis.com/en/help/main/10.2/index.html#//003n000000v7000000

/M
0 Kudos
RDHarles
Occasional Contributor
I do it like this:


# import smtplib module
import smtplib

# This is the body of the email
file = open('c:/temp/log.txt').read()

# Create a connection to our email server via the IP address
server = smtplib.SMTP('333.333.333.3')

# The key here is the word "Subject:"  It's a keyword to put the text that follows on the subject line.
subj = "Subject: Python Email"

# Send out the email (must separate subj+"\n"+file or all will go into subject line)
# 3 ARGS only: fromEmail, toEmail, subject and body
server.sendmail('rdh@xxx.com','rdh@xx.xx.com', subj+"\n"+file)

# Terminate the connection to server and quit
server.quit()
0 Kudos
MathewCoyle
Frequent Contributor
Any one have this error?

[Errno 10061] No connection could be made because the target machine actively refused it


Are you sure you are using the right hostname and the port is open on your server?
0 Kudos
MathewCoyle
Frequent Contributor
No, can you give me some examples.


To borrow from the previous post, this line connects to your server.
server = smtplib.SMTP('333.333.333.3')

The IP address used is just an example of course, filling in your own IP or DNS where your email server is hosted. This assumes the default email port of 25 is used, as no port parameter is passed. If your email server has a custom configuration that uses a different port you may need to find that out from your IT people.

I get the same error you posted if I try to connect using an incorrect port.
server = smtplib.SMTP('my.email.server', 22)

error: [Errno 10061] No connection could be made because the target machine actively refused it
0 Kudos
MathewCoyle
Frequent Contributor
Great.  Thanks for the quick reply. 

Any idea where I would find this information?


Are you using an exchange server or something else? If they are not using the default SMTP port 25 your best source would be whoever setup the email server.

Here's a quick list of possible ports depending on your setup.

    POP3 - port 110
    IMAP - port 143
    SMTP - port 25/587
    HTTP - port 80
    Secure SMTP (SSMTP) - port 465
    Secure IMAP (IMAP4-SSL) - port 585
    IMAP4 over SSL (IMAPS) - port 993
    Secure POP3 (SSL-POP) - port 995
0 Kudos