Server Tools, Extract Data Model, Email link instead of ZIP

Discussion created by kwobbe on Apr 9, 2013
Latest reply on Aug 8, 2013 by boerw
I'm struggling with this one, and hope someone out there can help!

I have added a customization to the out of the box, ArcToolbox/Server Tool/Extract Data task, because if the data to download is over 1 Mb, I want the program to email a link to the user pointing to a folder location on the web server.  This way the user can retrieve the ZIP containing the data via the web link, rather than emailing the ZIP itself.

The model runs FINE in ArcMAP and emails the link correctly and puts the zip in the web folder:

NOT FINE (Send Email With Zip File Attachment script):
When you use the Web GUI (and the geoprocessing service) it emails the link with the backslash directly before the UUID going the wrong direction.
With the result being it can't put the zip in the folder with the backslash going the wrong direction.


import arcgisscripting, smtplib, os, sys, traceback
import shutil
import uuid

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)

_email_server = ""

_email_send_from = "BLM Geoportal"
_email_subject = "The ZIP file containing your area of interest"
_email_body_zip_file_attached = "Attached is a ZIP file containing the data in the area of interest you specified."
_email_body_zip_file_oversize = "The resulting ZIP file is too large (%sMB).  Must be less than 5MB.  Please digitize a smaller Area of Interest."

_email_body_link_attached = "Click the link below to open the ZIP file containing the area of interest you specified."

# 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="", sendZip="" ):
        msg = MIMEMultipart()
        msg['From'] = send_from
        msg['To'] = COMMASPACE.join(send_to)
        msg['Date'] = formatdate(localtime=True)
        msg['Subject'] = subject

        if not sendZip:         # send URL to zip file
            text = text + "\n\n" + f
            msg.attach ( MIMEText(text) )
            msg.attach( MIMEText(text) )
            part = MIMEBase('application', "zip")   # Change if different file type sent.
            part.set_payload( open(f,"rb").read() )
            part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
        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())
        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)
    sendZip = gp.GetParameterAsText(9)
    # If sendZip is true, the zip file will be attached to the email.
    # If false, the URL to the zip will be in the body of the email.
    sendZip = False
    subject = _email_subject
        if sendZip:
            # Attach zip
            text = _email_body_zip_file_attached
            #Don't email large zip files.
            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, sendZip)
                #Message "Sent zipfile to %s from %s"
                gp.AddIDMessage("INFORMATIVE", 86154, sendto, fromaddr)
                gp.SetParameterAsText(9, "True")
                #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

            # Send URL instead of .zip file.  The jobs and virtual directory can be found
            #  in service's properties dialog box.  UNIX note: this code converts pathnames
            #  to lower case to  do the string replace.
            text = "Click the link below to open zip file containing the area of interest you specified."
            #--- Start custom change to Send URL ---#
            # Purpose: Copy zipfile to URL virtual directory
            # And give the zipfile a unique filename
            # Requires import shutil and import uuid
            #TP downloadDir = r"C:\\arcgisserverdata\gpt_download"
            downloadDir = r"\\myserver\arcgisserverdata\gpt_download"
            virtualDir = ""
            # First generate a filename with a random unique identifier using uuid.uuid4()
            zipDownload = os.path.join(downloadDir, str(uuid.uuid4()) + ".zip")
            # Next copy the Source zipfile to the new Destination zipDownload
            shutil.copy2(zipfile, zipDownload)
            # Finally replace the local file system path with the web-accessible directory URL path
            url = zipDownload.replace(downloadDir, virtualDir)
            # Replace backslashes with URL forward slash convention
            #url = url.replace("\\", "/")
            newurl = url.replace("\\","/")
            #send_mail(_email_send_from, [sendto], subject, text, newurl, _email_server, sendZip)    
            send_mail(fromaddr, sendto, subject, text, newurl, smtpMailServer, smtpUser, smtpPwd, sendZip)
        # 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"
        #Message "Unable to send email"
  #gp.AddIDMessage("ERROR", 86157)
        gp.AddError("ERROR, Unable to send email")