# Waiting for certain time to send email with executeAndDistribute

**URL:** <https://forum.inductiveautomation.com/t/waiting-for-certain-time-to-send-email-with-executeanddistribute/26448>\
**Category:** Ignition\
**Created:** [July 10, 2019, 7:12pm UTC](https://forum.inductiveautomation.com/t/waiting-for-certain-time-to-send-email-with-executeanddistribute/26448 "2019-07-10T19:12:30Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![mriederer](https://avatars.discourse-cdn.com/v4/letter/m/4af34b/32.png) [@mriederer](https://forum.inductiveautomation.com/u/mriederer)\
**Post date:** [July 10, 2019, 7:12pm UTC](https://forum.inductiveautomation.com/t/waiting-for-certain-time-to-send-email-with-executeanddistribute/26448/1 "2019-07-10T19:12:30Z")

</div>

Hi,

Is there a better way to send reports with system.report.executeAndDistribute() at a specified time through tag event scripting?

This uses time.sleep and waits until ‘work hours’ to send the report.

```auto
hourOfDay = system.date.getHour24(system.date.now())
minuteOfHour = system.date.getMinute(system.date.now())
floatOfDay = hourOfDay + minuteOfHour / 60.0
print floatOfDay
#start time at hour 7, end time at hour 17
workStartHour = 7.0
workEndHour = 17.0
if floatOfDay < workStartHour or floatOfDay > workEndHour:
	from time import sleep
	diffTime = workStartHour-floatOfDay
	if diffTime > 0: 	
		hoursTillWork = diffTime * 60 * 60 #convert to seconds
		print 'y'
	else:
		hoursTillWork = (24 + diffTime) * 60 * 60
		print 'x'
	sleep(hoursTillWork)
	print 'a', hoursTillWork
	#generate report after waiting
	#system.report.executeAndDistribute()
else:
	print 'b'
	#generate report now
	#system.report.executeAndDistribute()

```

Just making sure this isn’t using unnecessary overhead.

---

<div class="post-metadata">

**Author:** ![cmallonee](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmallonee/32/6416_2.png) [@cmallonee](https://forum.inductiveautomation.com/u/cmallonee)\
**Post date:** [July 10, 2019, 8:33pm UTC](https://forum.inductiveautomation.com/t/waiting-for-certain-time-to-send-email-with-executeanddistribute/26448/2 "2019-07-10T20:33:00Z")

</div>

This is probably not a good idea, because you’re holding onto the thread for `hoursTillWord` hours.

A better (but probably still not best) solution would be to place this into a Gateway Timer Script which executes every hour (or some time differential you determine) to check if it’s “working hours” before executing the report.

If doing this, you should also make a check against a tag which determines if the report has already been run once “today” to prevent this script from sending the report multiple times.

```auto
hourOfDay = system.date.getHour24(system.date.now())
minuteOfHour = system.date.getMinute(system.date.now())
floatOfDay = hourOfDay + minuteOfHour / 60.0
print floatOfDay
#start time at hour 7, end time at hour 17
workStartHour = 7.0
workEndHour = 17.0
tagPath = "tag_which_determines_execution"
reportAlreadySent = system.tag.readBlocking([tagPath], timeout)[0].value
timeout = 3000
if (floatOfDay > workStartHour) and (floatOfDay < workEndHour) and (not reportAlreadySent):
	system.report.executeAndDistribute()
    system.tag.writeBlocking([tagPath], [True], timeout)
else:
	system.tag.writeBlocking([tagPath], [False], timeout)

```

\*Use `system.tag.read()` and `system.tag.write()` if using a version before 8.0.

---

<div class="post-metadata">

**Author:** ![mriederer](https://avatars.discourse-cdn.com/v4/letter/m/4af34b/32.png) [@mriederer](https://forum.inductiveautomation.com/u/mriederer)\
**Post date:** [July 10, 2019, 8:45pm UTC](https://forum.inductiveautomation.com/t/waiting-for-certain-time-to-send-email-with-executeanddistribute/26448/3 "2019-07-10T20:45:59Z")

</div>

Great, thanks for the quick reply.

---

<div class="post-metadata">

**Author:** ![mriederer](https://avatars.discourse-cdn.com/v4/letter/m/4af34b/32.png) [@mriederer](https://forum.inductiveautomation.com/u/mriederer)\
**Post date:** [July 24, 2019, 6:05pm UTC](https://forum.inductiveautomation.com/t/waiting-for-certain-time-to-send-email-with-executeanddistribute/26448/4 "2019-07-24T18:05:41Z")

</div>

The emails seem to be sending now, but there is an INDENT EOF error occurring after the script runs. I’m not sure if this is a cause for concern or how to prevent the error.

FWIW, this code is in a Gateway Event Timer Script contained within a for loop.

```auto
			def sendEmail(tankNo=tankNo, tank = tank):	
				import system
				recipients=["jane@test.com","jon@xyz.com"] #
				system.report.executeAndDistribute(path="xyz", parameters = {"tankNumber":tankNo}, project="xyz", action= "email", actionSettings = {"to":recipients, "smtpServerName":"Mail Server", "from":"jon@xyz.com", "subject":tank + 'test email', "body":tank + " test "})
			system.util.invokeAsynchronous(sendEmail)
			print 'post-email function'
#end of gateway timer script

```

```auto

INFO | jvm 1 | 2019/07/24 09:51:50 | post-email function
INFO | jvm 1 | 2019/07/24 09:51:50 | W [r.Data] [17:51:50]: Unable to compile script. 
INFO | jvm 1 | 2019/07/24 09:51:50 | org.python.core.PySyntaxError: SyntaxError: ("mismatched input '<EOF>' expecting INDENT", ('<function:updateData>', 1, 29, 'def updateData(data, sample):\n'))
INFO | jvm 1 | 2019/07/24 09:51:50 | 
INFO | jvm 1 | 2019/07/24 09:51:50 | at org.python.core.ParserFacade.fixParseError(ParserFacade.java:92)
INFO | jvm 1 | 2019/07/24 09:51:50 | at org.python.core.ParserFacade.parse(ParserFacade.java:199)
INFO | jvm 1 | 2019/07/24 09:51:50 | at org.python.core.Py.compile_flags(Py.java:1751)
INFO | jvm 1 | 2019/07/24 09:51:50 | at com.inductiveautomation.ignition.common.script.ScriptManager.compileFunction(ScriptManager.java:689)
INFO | jvm 1 | 2019/07/24 09:51:50 | at com.inductiveautomation.ignition.common.script.ScriptManager.compileFunction(ScriptManager.java:673)
INFO | jvm 1 | 2019/07/24 09:51:50 | at com.inductiveautomation.reporting.gateway.data.ScriptReportDataSource.gatherData(ScriptReportDataSource.java:50)
INFO | jvm 1 | 2019/07/24 09:51:50 | at com.inductiveautomation.reporting.gateway.ReportingGatewayHook.getReportData(ReportingGatewayHook.java:338)
INFO | jvm 1 | 2019/07/24 09:51:50 | at com.inductiveautomation.reporting.gateway.ReportingGatewayHook.getReportData(ReportingGatewayHook.java:239)
INFO | jvm 1 | 2019/07/24 09:51:50 | at com.inductiveautomation.reporting.gateway.scripting.GatewayScriptingFunctions.executeAndDistribute(GatewayScriptingFunctions.java:290)
INFO | jvm 1 | 2019/07/24 09:51:50 | at com.inductiveautomation.reporting.common.scripting.ReportScriptingFunctionsPyWrapper.executeAndDistribute(ReportScriptingFunctionsPyWrapper.java:74)
INFO | jvm 1 | 2019/07/24 09:51:50 | at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
INFO | jvm 1 | 2019/07/24 09:51:50 | at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
INFO | jvm 1 | 2019/07/24 09:51:50 | at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
INFO | jvm 1 | 2019/07/24 09:51:50 | at java.lang.reflect.Method.invoke(Unknown Source)
INFO | jvm 1 | 2019/07/24 09:51:50 | at org.python.core.PyReflectedFunction. __call__ (PyReflectedFunction.java:186)
INFO | jvm 1 | 2019/07/24 09:51:50 | at com.inductiveautomation.ignition.common.script.ScriptManager$ReflectedInstanceFunction. __call__ (ScriptManager.java:429)
INFO | jvm 1 | 2019/07/24 09:51:50 | at org.python.core.PyObject. __call__ (PyObject.java:320)
INFO | jvm 1 | 2019/07/24 09:51:50 | at org.python.pycode._pyx156.sendEmail$1(<TimerScript:xyz/checkWorkHours10min @10,000ms >:64)
INFO | jvm 1 | 2019/07/24 09:51:50 | at org.python.pycode._pyx156.call_function(<TimerScript:xyz/checkWorkHours10min @10,000ms >)
INFO | jvm 1 | 2019/07/24 09:51:50 | at org.python.core.PyTableCode.call(PyTableCode.java:165)
INFO | jvm 1 | 2019/07/24 09:51:50 | at org.python.core.PyBaseCode.call(PyBaseCode.java:301)
INFO | jvm 1 | 2019/07/24 09:51:50 | at org.python.core.PyFunction.function ___call__ (PyFunction.java:376)
INFO | jvm 1 | 2019/07/24 09:51:50 | at org.python.core.PyFunction. __call__ (PyFunction.java:371)
INFO | jvm 1 | 2019/07/24 09:51:50 | at org.python.core.PyFunction. __call__ (PyFunction.java:361)
INFO | jvm 1 | 2019/07/24 09:51:50 | at org.python.core.PyFunction. __call__ (PyFunction.java:356)
INFO | jvm 1 | 2019/07/24 09:51:50 | at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:647)
INFO | jvm 1 | 2019/07/24 09:51:50 | at com.inductiveautomation.ignition.gateway.script.GatewaySystemUtilities$1.run(GatewaySystemUtilities.java:69)
INFO | jvm 1 | 2019/07/24 09:51:50 | at java.lang.Thread.run(Unknown Source)

```

Is the updateData function the issue? If it is, I don’t where the function is located.

---

<div class="post-metadata">

**Author:** ![cmallonee](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmallonee/32/6416_2.png) [@cmallonee](https://forum.inductiveautomation.com/u/cmallonee)\
**Post date:** [July 24, 2019, 6:22pm UTC](https://forum.inductiveautomation.com/t/waiting-for-certain-time-to-send-email-with-executeanddistribute/26448/5 "2019-07-24T18:22:01Z")

</div>

I think the supplied code is the issue:

```auto
    def sendEmail(tankNo=tankNo, tank = tank):	
		import system
		recipients=["jane@test.com","jon@xyz.com"] #
		system.report.executeAndDistribute(path="xyz", parameters = {"tankNumber":tankNo}, project="xyz", action= "email", actionSettings = {"to":recipients, "smtpServerName":"Mail Server", "from":"jon@xyz.com", "subject":tank + 'test email', "body":tank + " test "})
	system.util.invokeAsynchronous(sendEmail)
	print 'post-email function'

```

COULD be the problem because indentation and lines mean something in Python.

try:

```auto
def sendEmail(tankNo=tankNo, tank = tank):	
	import system
	recipients=["jane@test.com","jon@xyz.com"] #
	system.report.executeAndDistribute(path="xyz", parameters = {"tankNumber":tankNo}, project="xyz", action= "email", actionSettings = {"to":recipients, "smtpServerName":"Mail Server", "from":"jon@xyz.com", "subject":tank + 'test email', "body":tank + " test "})
	
system.util.invokeAsynchronous(sendEmail)
print 'post-email function'

```

if that doesn’t work, then what you should look for are instances where:  
you have a conditional statement which contains no logic (an `if:` or `for` which does nothing)

OR it could be because the `def` is inside a loop - don’t do that. the `def` should be immediately following whatever imports the Script needs

```auto
import one_thing
import something_else

def sendEmail():
    import system
	recipients=["jane@test.com","jon@xyz.com"] #
	system.report.executeAndDistribute(path="xyz", parameters = {"tankNumber":tankNo}, project="xyz", action= "email", actionSettings = {"to":recipients, "smtpServerName":"Mail Server", "from":"jon@xyz.com", "subject":tank + 'test email', "body":tank + " test "})
			
code()
y = other_code()
for x in y:
    system.util.invokeAsynchronous(sendEmail)
    print 'post-email function'

```

---

<div class="post-metadata">

**Author:** ![mriederer](https://avatars.discourse-cdn.com/v4/letter/m/4af34b/32.png) [@mriederer](https://forum.inductiveautomation.com/u/mriederer)\
**Post date:** [July 24, 2019, 6:49pm UTC](https://forum.inductiveautomation.com/t/waiting-for-certain-time-to-send-email-with-executeanddistribute/26448/6 "2019-07-24T18:49:35Z")

</div>

The def is inside of a for loop, but I don’t see how to prevent this.

The for loop is reading through a SQL table and then taking those tank numbers and searching for tag data. This data is then input into the exectuteAndDistribute function as parameters, so each tag would need a different variable name if not part of the for loop… which I don’t know how it would be sent to the executeAndDistribute command then as parameters.

I tried removing the invokeAsynchronous and still get the same error. Maybe just don’t worry about it now because it seems to be working correctly?

---

<div class="post-metadata">

**Author:** ![cmallonee](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmallonee/32/6416_2.png) [@cmallonee](https://forum.inductiveautomation.com/u/cmallonee)\
**Post date:** [July 24, 2019, 7:49pm UTC](https://forum.inductiveautomation.com/t/waiting-for-certain-time-to-send-email-with-executeanddistribute/26448/7 "2019-07-24T19:49:40Z")

</div>

After speaking with a member of Development, it seems like your issue is actually in the Report. `updateData` is the `def` given to Report Data Sources which are Scripts.

 ![15%20PM](https://us1.discourse-cdn.com/inductiveautomation/original/2X/f/f8a99cb741f09f4eda33181ff5e6eb6ff9e946f5.png)  
So look in that script for line 29 (probably the last line). Sorry I directed you to the wrong place - I presumed your encompassing function was named `updateData`, and I missed the part where you claimed to not know where updateData lived.

---

<div class="post-metadata">

**Author:** ![mriederer](https://avatars.discourse-cdn.com/v4/letter/m/4af34b/32.png) [@mriederer](https://forum.inductiveautomation.com/u/mriederer)\
**Post date:** [July 24, 2019, 8:08pm UTC](https://forum.inductiveautomation.com/t/waiting-for-certain-time-to-send-email-with-executeanddistribute/26448/8 "2019-07-24T20:08:23Z")

</div>

Ah, thank you! I knew I had seen it somewhere.

I deleted this Data Source and the error is gone.

-Michael
