Send Email When a Feature is Added to an ArcGIS Online Hosted Feature Service

49070
176
06-02-2017 05:46 AM

Send Email When a Feature is Added to an ArcGIS Online Hosted Feature Service

With ArcGIS GeoEvent it is very easy to setup a notification when a new feature is added to an ArcGIS Online Hosted Feature Service.  Instructions can be found here.  If you do not have GeoEvent you can still accomplish this using Python.  Below is an example on how to do this. 

When editor tracking is enabled, new features are recorded in a field called 'CreationDate'.  The script queries this field within the service and compares the time to the current time (minus one hour).  If the time is greater than the current time, it will send an e-mail with a specified field's values for the new features.

Windows Task Scheduler can be setup to execute this script at a given interval (i.e. every hour).  This will report any new features within that last hour.

The below example is written for the Citizen Problem Report application.  It utilizes 2 fields (probtype & status) when querying the service.  These variables can be commented out, or updated to reference different fields, if working with a different service:

JakeSkinner_4-1627925313899.png

 

The SUBJECT and TEXT variables in the sendEmail function can be updated to whatever you would like to include in the e-mail:

JakeSkinner_5-1627925339918.png

 

import requests, json, datetime, time, smtplib
from datetime import timedelta
from email.mime.text import MIMEText

# Disable warnings
requests.packages.urllib3.disable_warnings()

# Variables
username = 'jskinner_CountySandbox'                                                                                   # AGOL Username
password = '*******'                                                                                                  # AGOL Password

URL = 'https://services.arcgis.com/dlFJXQQtlWFB4qUk/arcgis/rest/services/CitizenProblems/FeatureServer/0'             # Feature Service URL
dateField = 'CreationDate'                                                                                            # Date field to query
hoursValue = 1                                                                                                        # Number of hours to check when a feature was added

fromEmail = 'no-reply@esri.com'                                                                                       # Email sender
toEmail = ['user1@esri.com', 'user2@esri.com']                                                                        # Email receiver(s)
smtpServer = 'smtp.esri.com'                                                                                          # SMTP Server Name
portNumber = 25                                                                                                       # SMTP Server port


# Function to send email
def sendEmail():
    SUBJECT = 'Problem Reported'
    TEXT = "{0} was created with status {1}".format(typeProb, status)
    smtpObj = smtplib.SMTP(host=smtpServer, port=portNumber)

    msg = MIMEText(TEXT)
    msg['Subject'] = SUBJECT
    msg['From'] = fromEmail
    msg['To'] = ", ".join(toEmail)

    smtpObj.sendmail(fromEmail, toEmail, msg.as_string())
    print("Successfully sent email")
    smtpObj.quit()

# Generate AGOL token
try:
        print('Generating Token')
        tokenURL = 'https://www.arcgis.com/sharing/rest/generateToken'
        params = {'f': 'pjson', 'username': username, 'password': password, 'referer': 'http://www.arcgis.com'}
        r = requests.post(tokenURL, data=params, verify=False)
        response = json.loads(r.content)
        token = response['token']
except:
        token = ''

# Return largest ObjectID
whereClause = '1=1'
params = {'where': whereClause, 'returnIdsOnly': 'true', 'token': token, 'f': 'json'}
r = requests.post(URL + '/query', data = params, verify = False)
response = json.loads(r.content)
try:
    response['objectIds'].sort()
except Exception as e:
    print("Error: {0}".format(e))

count = len(response['objectIds'])


# Query service and check if CreationDate time is within the last hour
if count < 1000:
    params = {'f': 'pjson', 'where': "1=1", 'outFields' : '*', 'returnGeometry' : 'false', 'token' : token}
    r = requests.post(URL + '/query', data=params, verify=False)
    response = json.loads(r.content)
    for feat in response['features']:
        typeProb = feat['attributes']['probtype']
        status = feat['attributes']['status']
        createDate = feat['attributes'][dateField]
        createDate = int(str(createDate)[0:-3])
        t = datetime.datetime.now() - timedelta(hours=hoursValue)
        t = time.mktime(t.timetuple())
        if createDate > t:
           sendEmail()
else:
    y = minOID
    x = minOID + 1000

    ids = response['objectIds']
    newIteration = (math.ceil(iteration/1000.0) * 1000)
    while y < newIteration:
        if x > int(newIteration):
            x = newIteration
        where = OID + '>' + str(y) + ' AND ' + OID + '<=' + str(x)
        print('Querying features with ObjectIDs from ' + str(y) + ' to ' + str(x))
        params = {'f': 'pjson', 'where': where, 'outFields' : '*', 'returnGeometry' : 'false', 'token' : token}
        r = requests.post(URL + '/query', data=params, verify=False)
        response = json.loads(r.content)
        for feat in response['features']:
            typeProb = feat['attributes']['probtype']
            status = feat['attributes']['status']
            createDate = feat['attributes'][dateField]
            createDate = int(str(createDate)[0:-3])
            t = datetime.datetime.now() - timedelta(hours=hoursValue)
            t = time.mktime(t.timetuple())
            if createDate > t:
                sendEmail()
        x += 1000
        y += 1000

 

Comments

@JakeSkinner 

Probably not the best way to do this but here it is: 

import requests, json, datetime, time, smtplib
from datetime import timedelta
import datetime
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
# Disable warnings
requests.packages.urllib3.disable_warnings()
print('This file is from sendEmail_addfields.py')
# Variables
username = ''         # AGOL Username or Portal username
password = ''           # AGOL Password or Portal password

URL = ''       # Feature Service URL
uniqueID = 'objectid'              # i.e. OBJECTID
dateField = 'created_date'         # Date field to query
hoursValue = 0.083                     # Number of hours to check when a feature was added
#0.083
fromEmail = ''     # Email sender
																						
TO = ['']       # Email receiver
smtpServer = ''        # SMTP Server Name
portNumber = 25                    # SMTP Server port

AGOL = True                       # True if service is hosted in AGOL, False if service is hosted in Portal
portalServer = 'portal.esri.com'   # Server name portal is installed on (not web adaptor)

# Create empty list for uniqueIDs
datesighted = []
name = []
phone = []
email = []
aggressive = []
numanimal = []
animaldoing = []
reaction = []
probtype = []
oidList = []
publicview   = []
details = []

# Generate AGOL token
if AGOL == True:
    try:
        print('Generating Token')
        tokenURL = 'https://www.arcgis.com/sharing/rest/generateToken'
        params = {'f': 'pjson', 'username': username, 'password': password, 'referer': 'http://www.arcgis.com'}
        r = requests.post(tokenURL, data=params, verify=False)
        response = json.loads(r.content)
        token = data['token']
    except:
        token = ''
else:
    # Generate Portal token
    tokenURL = '/'.format(portalServer)
    params = {'f': 'pjson', 'username': username, 'password': password, 'referer': ''.format(portalServer)}
    r = requests.post(tokenURL, data = params, verify=False)
    response = json.loads(r.content)
    token = response['token']

# Query service and check if created_date time is within the last hour
params = {'f': 'pjson', 'where': "1=1", 'outFields' : '*', 'statisticType' : 'count', 'returnGeometry' : 'false'}
r = requests.post(URL, data=params, verify=False)
response = json.loads(r.content)

print(params)

for feat in response['features']:
    createDate = feat['attributes']['created_date']
    createDate = int(str(createDate)[0:-3])
    t = datetime.datetime.now() - timedelta(hours=hoursValue)
    t = time.mktime(t.timetuple())
    if createDate > t:
        datesighted.append(str(feat['attributes']['datesighted']))
        name.append(str(feat['attributes']['name']))
        phone.append(str(feat['attributes']['phone']))
        email.append(str(feat['attributes']['email']))
        animaldoing.append(str(feat['attributes']['animaldoing']))
        numanimal.append(str(feat['attributes']['numanimal']))
        aggressive.append(str(feat['attributes']['aggressive']))
        reaction.append(str(feat['attributes']['reaction']))
        probtype.append(str(feat['attributes']['probtype']))
        oidList.append(str(feat['attributes']['objectid']))
        details.append(str(feat['attributes']['details']))
        publicview  .append(str(feat['attributes']['publicview']))
        
print(oidList)
mergelist = zip(probtype, details, publicview)
print(mergelist)
# Email Info
FROM = fromEmail
SUBJECT = 'New Wildlife Sighting Has been Reported'
Total= "Features with " + " " + str(publicview) + " " + " were added."
TotalAnimals = (Total.count("Yes")) 
print(TotalAnimals)


#TEXT = "There were " + " " + str(TotalAnimals) + " " + " sighting(s) added the Cougar Map within the past hour."
#TEXT = '<a href="http://maps.google.com/maps?z=12&t=m&q=loc:'+str(p['latitude'])+'+'+str(p['longitude'])+'">Click Here</a>'

tom = datesighted[0]

chosen_number = int(tom)
s = chosen_number / 1000.0
print s
dFormat = "%Y-%m-%d %H:%M:%S.%f"
datesightedconvert = datetime.datetime.fromtimestamp(s).strftime('%Y-%m-%d %H:%M:%S')

# Create the body of the message (a plain-text and an HTML version).
TotalSighted = "There were " + " " + str(TotalAnimals) + " " + " reports(s) added the Wildlife Map within the past 5 min."
Sighted = "\nAnimal Sighted : " + str(probtype)
TheDateSighted = "\nDate Sighted : " + str(datesightedconvert) + " " + " ***\n"
reported = "\nReporter Name: " + str(name)
PhoneNumber =  "\nReporter Phone Number: " + str(phone)
ReportedEmail =  "\nReporter Phone Email: " + str(email)
Aggressiveness = "'\n'Was animal Aggressive?: " + str(aggressive)
ReportedReaction = "'\nWhat was the animal Reaction?: " + str(reaction)
ReportedDetails = "'\n'More Details about the sighting: " + str(details)
AnimalDoing = "'\n'What was the Animal(s) Doing?: " + str(animaldoing)
AnimalSeen = "'\n'How Many were seen?: " + str(numanimal)
Link = "'\n\n'View more information on the : \ \n\n\n ***if there are more than 1 reports then only the first Date Sighted will be in this Email.***"

Text = TotalSighted + TheDateSighted + Sighted + reported +  PhoneNumber + ReportedEmail + Aggressiveness + ReportedReaction + ReportedDetails + AnimalDoing + AnimalSeen + Link
print  ''.join(Text)
message = """\
From: %s
To: %s
Subject: %s

%s
""" % (FROM, ", ".join(TO), SUBJECT, Text)

# If new features exist, send email
if len(oidList) > 0:
    smtpObj = smtplib.SMTP(host=smtpServer, port=portNumber)
    smtpObj.sendmail(FROM, TO, message)
    print("Successfully sent email")
    smtpObj.quit()

 

 Here is some of the output. Is there a way to remove the []

'Was animal Aggressive?: ['No']'

What was the animal Reaction?: ['Didnt see me']'

'More Details about the sighting: ['Mama and two cubs filmed by the motion-detecting doorbell camera as they passed across the yard']'

@JakeSkinner

Thank for your help. That works for me perfectly.

 

 

@RickeyFight 

For your e-mail text, try cleaning up the extra apostrophes.  For example, you have:

ReportedReaction = "'\nWhat was the animal Reaction?: " + str(reaction)

Try this instead:

ReportedReaction = "\nWhat was the animal Reaction?: " + str(reaction)

You won't need any quotes around \n, as long as it's enclosed by quotes, python will read it is a new line. 

 

To remove the [] around the answers, you have two options:

1.  Since you are appending to a list, you can specify the first value of the list using a [0].  Ex:

Sighted = "\nAnimal Sighted : " + str(probtype)[0]

2.  Instead of creating a list (i.e. probtype = []), you can remove this and set the probtype as a variable:

probtype = (str(feat['attributes']['probtype']))

 

I would recommend the second option.  In doing so, you should move everything within the for loop.  This will allow separate e-mails to be sent in the event there is more than 1 feature added within the allotted time the script executes:

for feat in response['features']:
    createDate = feat['attributes']['created_date']
    createDate = int(str(createDate)[0:-3])
    t = datetime.datetime.now() - timedelta(hours=hoursValue)
    t = time.mktime(t.timetuple())
    if createDate > t:
        datesighted.append(str(feat['attributes']['datesighted']))
        name.append(str(feat['attributes']['name']))
        phone.append(str(feat['attributes']['phone']))
        email.append(str(feat['attributes']['email']))
        animaldoing.append(str(feat['attributes']['animaldoing']))
        numanimal.append(str(feat['attributes']['numanimal']))
        aggressive.append(str(feat['attributes']['aggressive']))
        reaction.append(str(feat['attributes']['reaction']))
        probtype.append(str(feat['attributes']['probtype']))
        oidList.append(str(feat['attributes']['objectid']))
        details.append(str(feat['attributes']['details']))
        publicview  .append(str(feat['attributes']['publicview']))

        print(oidList)
        mergelist = zip(probtype, details, publicview)
        print(mergelist)
        # Email Info
        FROM = fromEmail
        SUBJECT = 'New Wildlife Sighting Has been Reported'
        Total= "Features with " + " " + str(publicview) + " " + " were added."
        TotalAnimals = (Total.count("Yes"))
        print(TotalAnimals)


        #TEXT = "There were " + " " + str(TotalAnimals) + " " + " sighting(s) added the Cougar Map within the past hour."
        #TEXT = '<a href="http://maps.google.com/maps?z=12&t=m&q=loc:'+str(p['latitude'])+'+'+str(p['longitude'])+'">Click Here</a>'

        tom = datesighted[0]

        chosen_number = int(tom)
        s = chosen_number / 1000.0
        print s
        dFormat = "%Y-%m-%d %H:%M:%S.%f"
        datesightedconvert = datetime.datetime.fromtimestamp(s).strftime('%Y-%m-%d %H:%M:%S')

        # Create the body of the message (a plain-text and an HTML version).
        TotalSighted = "There were " + " " + str(TotalAnimals) + " " + " reports(s) added the Wildlife Map within the past 5 min."
        Sighted = "\nAnimal Sighted : " + str(probtype)
        TheDateSighted = "\nDate Sighted : " + str(datesightedconvert) + " " + " ***\n"
        reported = "\nReporter Name: " + str(name)
        PhoneNumber =  "\nReporter Phone Number: " + str(phone)
        ReportedEmail =  "\nReporter Phone Email: " + str(email)
        Aggressiveness = "'\n'Was animal Aggressive?: " + str(aggressive)
        ReportedReaction = "'\nWhat was the animal Reaction?: " + str(reaction)
        ReportedDetails = "'\n'More Details about the sighting: " + str(details)
        AnimalDoing = "'\n'What was the Animal(s) Doing?: " + str(animaldoing)
        AnimalSeen = "'\n'How Many were seen?: " + str(numanimal)
        Link = "'\n\n'View more information on the : \ \n\n\n ***if there are more than 1 reports then only the first Date Sighted will be in this Email.***"

        Text = TotalSighted + TheDateSighted + Sighted + reported +  PhoneNumber + ReportedEmail + Aggressiveness + ReportedReaction + ReportedDetails + AnimalDoing + AnimalSeen + Link
        print  ''.join(Text)
        message = """\
        From: %s
        To: %s
        Subject: %s

        %s
        """ % (FROM, ", ".join(TO), SUBJECT, Text)

        # If new features exist, send email
        if len(oidList) > 0:
            smtpObj = smtplib.SMTP(host=smtpServer, port=portNumber)
            smtpObj.sendmail(FROM, TO, message)
            print("Successfully sent email")
            smtpObj.quit()

 

@JakeSkinner 

Your suggestions have made my email script way better thank you! 

I am getting this error when someone inputs a ' in a word for their response

Traceback (most recent call last):
File "C:Loc", line 81, in <module>
reaction.append(str(feat['attributes']['reaction']))
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2019' in position 5: ordinal not in range(128)

RickeyFight_1-1620395743094.png

In this case the don't is giving me that error. 

 

@RickeyFighttry the following:

reaction.append(str(feat['attributes']['reaction']).replace(u"\u2018", "'").replace(u"\u2019", "'"))

@JakeSkinner 

Yes that works. But you recommended that I switch to: 

 

reaction = (str(feat['attributes']['reaction'])

 

 

How would I add to the modified code above? 

.replace(u"\u2018", "'").replace(u"\u2019", "'"))

 

@RickeyFight 

reaction = str(feat['attributes']['reaction']).replace(u"\u2018", "'").replace(u"\u2019", "'")

 

@JakeSkinner 

I must have done something wrong when I added it the first time because it works now. 

Thank you for your help! 

Hi @JakeSkinner 

I have the following situation.

I have a feature class with related table via globalId. Both the feature class and table are editable and stored in the AGS. 

In the e-mail I would like to have the information both from the related table and from the feature class. SO the script will be looking in two URL's, and the connection with the globalID = relglobalID.

Additionaly, I would like to send the e-mail, when a related table will be modified, to a person who originally created a FC.

Can you please advice how I can change the script?

Thank for help!

 

Hi @JakeSkinner

I realize that this is an older post so I may not get a response. My organization is trying to set up the Esri Citizen Problem Reporter. There have been some issues with the send emails script included with the solution and our webmail server so I have been trying to find a different way to trigger an email when a new feature is added. I have tried your provided code but just cannot seem to get it to work. I just get an error of:

Something went wrong...
Generating Token
[]

I have tried running just the part of the code that sends an email and it works without any issues. I'm not sure what is going wrong.

@Michael_Wozniakcan you share the service to an AGOL Group and invite my user account (jskinner_CountySandbox)?  It looks like there are no new features added within the timeframe you're querying.  The default in the code is 1 hour.

@Michael_Wozniak  I was able to get the script to work with the service you shared.  Try the one below.  It sends multiple e-mails instead of one e-mail with a list of OBJECTIDs for the features that were created.

You will just need to update the username and password.

import requests, json, datetime, time, smtplib, math
from datetime import timedelta
from email.mime.text import MIMEText


# Disable warnings
requests.packages.urllib3.disable_warnings()

# Variables
username = 'jskinner_CountySandbox'                                                                                   # AGOL Username
password = '*******'                                                                                                  # AGOL Password

URL = 'https://services9.arcgis.com/8FOQ9nDvQJjqML1o/arcgis/rest/services/CitizenProblems_4ccc650e579c469697018f64006e9acc/FeatureServer/0/query'       # Feature Service URL
dateField = 'CreationDate'                                                                                            # Date field to query
hoursValue = 1                                                                                                        # Number of hours to check when a feature was added

fromEmail = 'no-reply@esri.com'                                                                                       # Email sender
toEmail = ['jskinner@esri.com']                                                                                       # Email receiver(s)
smtpServer = 'smtp.esri.com'                                                                                          # SMTP Server Name
portNumber = 25    # SMTP Server port


# Function to send email
def sendEmail():
    SUBJECT = 'Problem Reported'
    TEXT = "{0} was created with status {1} and has been assigned to {2}".format(typeProb, status, assignedto)
    smtpObj = smtplib.SMTP(host=smtpServer, port=portNumber)

    msg = MIMEText(TEXT)
    msg['Subject'] = SUBJECT
    msg['From'] = fromEmail
    msg['To'] = ", ".join(toEmail)

    smtpObj.sendmail(fromEmail, toEmail, msg.as_string())
    print("Successfully sent email")
    smtpObj.quit()

# Generate AGOL token
try:
        print('Generating Token')
        tokenURL = 'https://www.arcgis.com/sharing/rest/generateToken'
        params = {'f': 'pjson', 'username': username, 'password': password, 'referer': 'http://www.arcgis.com'}
        r = requests.post(tokenURL, data=params, verify=False)
        response = json.loads(r.content)
        token = response['token']
except:
        token = ''

# Return largest ObjectID
whereClause = '1=1'
params = {'where': whereClause, 'returnIdsOnly': 'true', 'token': token, 'f': 'json'}
r = requests.post(URL, data = params, verify = False)
response = json.loads(r.content)
try:
    response['objectIds'].sort()
except Exception as e:
    print("Error: {0}".format(e))

count = len(response['objectIds'])


# Query service and check if editDate time is within the last hour
if count < 1000:
    params = {'f': 'pjson', 'where': "1=1", 'outFields' : '*', 'returnGeometry' : 'false', 'token' : token}
    r = requests.post(URL, data=params, verify=False)
    response = json.loads(r.content)
    for feat in response['features']:
        typeProb = feat['attributes']['probtype']
        status = feat['attributes']['status']
        assignedto = feat['attributes']['assignedto']
        createDate = feat['attributes'][dateField]
        createDate = int(str(createDate)[0:-3])
        t = datetime.datetime.now() - timedelta(hours=hoursValue)
        t = time.mktime(t.timetuple())
        if createDate > t:
           sendEmail()

@JakeSkinner 

Thank you so much. This works perfectly.

I'm wondering if it is possible to send an email based on which Problem Category is selected. For instance an Animal Control problem would only send an email to our Animal Control officer or a road problem would only send an email to the Public Works supervisor.

Thanks again for your help.

@Michael_Wozniak  you can accomplish this with the following steps:

1.  Remove the toEmail under Variables

2.  Add a dictionary of the Problem Categories followed by the e-mail(s) that should be notified.  Ex:

# E-mail Dictionary
emailDict = {'Animal Control': ['jskinner@esri.com'], 'Public Works': ['jdoe@esri.com', 'awalker@esri.com']}

3.   Add a new toEmail variable (line 10 below) referencing the dictionary:

# Query service and check if editDate time is within the last hour
if count < 1000:
    params = {'f': 'pjson', 'where': "1=1", 'outFields' : '*', 'returnGeometry' : 'false', 'token' : token}
    r = requests.post(URL, data=params, verify=False)
    response = json.loads(r.content)
    for feat in response['features']:
        typeProb = feat['attributes']['probtype']
        status = feat['attributes']['status']
        assignedto = feat['attributes']['assignedto']
        toEmail = emailDict[assignedto]
        createDate = feat['attributes'][dateField]
        createDate = int(str(createDate)[0:-3])
        t = datetime.datetime.now() - timedelta(hours=hoursValue)
        t = time.mktime(t.timetuple())
        if createDate > t:
            sendEmail()

 

@JakeSkinner 

Thank you once again. Everything works perfectly. 

@JakeSkinner 

Thank you for taking the time to create this extremely helpful thread.

It seems as though the majority of the responses in this thread are about sending emails when new features are created, however I am hoping to create a script that can be initiated by Windows Task Scheduler that will send an email to notify a coworker every time 1 specific field is updated from one status to another. Additionally, I would need the script to only send an email when it notices a change to the field update, and it needs to be unaffected by fields with null values.

I am a novice when it comes to scripting so any guidance that you can provide would be tremendously appreciated. Thank you in advance.

@JoshConrad1 instead of using the CreationDate field, you can use the EditDate when Editor Tracking is enabled.  Not quite sure if this will work since the EditDate field will update when any field is edited. 

@JakeSkinner 

Thank you for clarifying. I am trying to automate our workorder workflows by having an email sent to managers when a "status" field is updated and was exploring work arounds to webhooks.

I thank you once again for your time and response.

@JakeSkinner 

This feed was super helpful. 

However, I simply want to notify two people via email when there is a new Citizen Problem reported as a reminder for them to review it. I am brand new to Python scripting and any assistance you can provide would be greatly apprecieated. Essentially, I just need to know what lines I can remove from the above scripts but still have it work and send an email as notification to those managing our Citizen Propblem Reporter.

Also, thank you to everyone that has contributed to this thread. The GIS community is the best at supporting one another!

-Cody

@cmerwin you will just have to update the # Variables section in the script with your information.  Scroll to the right to see a description on each variable.

 

# Variables
username = 'jskinner_CountySandbox'                                                                                   # AGOL Username
password = '*******'                                                                                                  # AGOL Password

URL = 'https://services.arcgis.com/dlFJXQQtlWFB4qUk/arcgis/rest/services/CitizenProblems/FeatureServer/0'             # Feature Service URL
dateField = 'CreationDate'                                                                                            # Date field to query
hoursValue = 1                                                                                                        # Number of hours to check when a feature was added

fromEmail = 'no-reply@esri.com'                                                                                       # Email sender
toEmail = ['user1@esri.com', 'user2@esri.com']                                                                        # Email receiver(s)
smtpServer = 'smtp.esri.com'                                                                                          # SMTP Server Name
portNumber = 25                                                                                                       # SMTP Server port

 

Hi @JakeSkinner ,

I have added a field called address_mail into my original Feature Class. How can I modify the script so that email is sent to the address contained in this in the Feature Class. 

Any advice would be much appreciated.

 

Regards,

Monika

@MonikaSamorajska 

See below, I removed the toEmail variable under the # Variables section.  I also added line 92:

toEmail = feat['attributes']['email']

Replace 'email' with the name of the field containing the email addresses.

import requests, json, datetime, time, smtplib
from datetime import timedelta
from email.mime.text import MIMEText

# Disable warnings
requests.packages.urllib3.disable_warnings()

# Variables
username = 'jskinner_CountySandbox'                                                                                   # AGOL Username
password = '*******'                                                                                                  # AGOL Password

URL = 'https://services.arcgis.com/dlFJXQQtlWFB4qUk/arcgis/rest/services/CitizenProblems/FeatureServer/0'             # Feature Service URL
dateField = 'CreationDate'                                                                                            # Date field to query
hoursValue = 1                                                                                                        # Number of hours to check when a feature was added

fromEmail = 'no-reply@esri.com'                                                                                       # Email sender
receiver(s)
smtpServer = 'smtp.esri.com'                                                                                          # SMTP Server Name
portNumber = 25                                                                                                       # SMTP Server port


# Function to send email
def sendEmail():
    SUBJECT = 'Problem Reported'
    TEXT = "{0} was created with status {1}".format(typeProb, status)
    smtpObj = smtplib.SMTP(host=smtpServer, port=portNumber)

    msg = MIMEText(TEXT)
    msg['Subject'] = SUBJECT
    msg['From'] = fromEmail
    msg['To'] = ", ".join(toEmail)

    smtpObj.sendmail(fromEmail, toEmail, msg.as_string())
    print("Successfully sent email")
    smtpObj.quit()

# Generate AGOL token
try:
        print('Generating Token')
        tokenURL = 'https://www.arcgis.com/sharing/rest/generateToken'
        params = {'f': 'pjson', 'username': username, 'password': password, 'referer': 'http://www.arcgis.com'}
        r = requests.post(tokenURL, data=params, verify=False)
        response = json.loads(r.content)
        token = response['token']
except:
        token = ''

# Return largest ObjectID
whereClause = '1=1'
params = {'where': whereClause, 'returnIdsOnly': 'true', 'token': token, 'f': 'json'}
r = requests.post(URL + '/query', data = params, verify = False)
response = json.loads(r.content)
try:
    response['objectIds'].sort()
except Exception as e:
    print("Error: {0}".format(e))

count = len(response['objectIds'])


# Query service and check if CreationDate time is within the last hour
if count < 1000:
    params = {'f': 'pjson', 'where': "1=1", 'outFields' : '*', 'returnGeometry' : 'false', 'token' : token}
    r = requests.post(URL + '/query', data=params, verify=False)
    response = json.loads(r.content)
    for feat in response['features']:
        typeProb = feat['attributes']['probtype']
        status = feat['attributes']['status']
        createDate = feat['attributes'][dateField]
        createDate = int(str(createDate)[0:-3])
        t = datetime.datetime.now() - timedelta(hours=hoursValue)
        t = time.mktime(t.timetuple())
        if createDate > t:
           sendEmail()
else:
    y = minOID
    x = minOID + 1000

    ids = response['objectIds']
    newIteration = (math.ceil(iteration/1000.0) * 1000)
    while y < newIteration:
        if x > int(newIteration):
            x = newIteration
        where = OID + '>' + str(y) + ' AND ' + OID + '<=' + str(x)
        print('Querying features with ObjectIDs from ' + str(y) + ' to ' + str(x))
        params = {'f': 'pjson', 'where': where, 'outFields' : '*', 'returnGeometry' : 'false', 'token' : token}
        r = requests.post(URL + '/query', data=params, verify=False)
        response = json.loads(r.content)
        for feat in response['features']:
            typeProb = feat['attributes']['probtype']
            status = feat['attributes']['status']
            toEmail = feat['attributes']['email']
            createDate = feat['attributes'][dateField]
            createDate = int(str(createDate)[0:-3])
            t = datetime.datetime.now() - timedelta(hours=hoursValue)
            t = time.mktime(t.timetuple())
            if createDate > t:
                sendEmail()
        x += 1000
        y += 1000

 

Hi @JakeSkinner 

Thanks for your response!

Just one more: how can I modify the script to to send an e-mail to define person (like in a original script) and additionally sent an email to a person added in a new field called email?

Regards,

Monika

 

Thanks to @JakeSkinner I've been using this script successfully for several years now (thanks so much Jake!).

However, for the past month I've been getting the TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.

Has anyone ran into this issue recently? 

Hi @Karlie_Kendall,

Can you configure the script to another feature service as a test and see if you get the same error?

@JakeSkinner I just tried testing it from another feature service, as well as a feature service from a different AGO account, and tried running the script on a different computer, but unfortunately got the same error each time.  

Version history
Last update:
‎08-02-2021 10:30 AM
Updated by:
Contributors