Skip to content

Commit

Permalink
Replace (broken) email alerts with email_event
Browse files Browse the repository at this point in the history
A future honeybee change will send emails based on
new entries in the table.
  • Loading branch information
DougLau committed Dec 13, 2024
1 parent 2fbefbe commit 61bc587
Show file tree
Hide file tree
Showing 22 changed files with 141 additions and 248 deletions.
4 changes: 0 additions & 4 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,6 @@
<target name="check-rpm">
<antcall target="check-dep">
<param name="file.dep" value="iris-build.properties"/>
<param name="file.dep" value="javax.activation.jar"/>
<param name="file.dep" value="mail.jar"/>
<param name="file.dep" value="jna-${jna_version}.jar"/>
<param name="file.dep"
value="jna-platform-${jna_version}.jar"/>
Expand Down Expand Up @@ -237,8 +235,6 @@
</copy>
<copy todir="${dist.server}">
<fileset dir="${lib.dir}">
<include name="javax.activation.jar"/>
<include name="mail.jar"/>
<include name="json-${json_version}.jar"/>
<include name="postgis-jdbc-${postgis_version}.jar"/>
<include name="postgis-geometry-${postgis_version}.jar"/>
Expand Down
4 changes: 2 additions & 2 deletions docs/action_plans.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,8 @@ be `NULL` for "any":

On the **Plan** tab of the client interface, users can manually change the phase
of an action plan. If the user is in the list specified by the
`action_plan_alert_list` [system attribute], an email will be sent to the
address specified by the `email_recipient_action_plan` [system attribute].
`action_plan_alert_list` [system attribute], an email event will be logged
to the `email_event` table.

## Events

Expand Down
3 changes: 1 addition & 2 deletions docs/gate_arms.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,7 @@ interlock_. Once they are both open, the prerequisite will have a _close
interlock_ until the dependent is closed.

If a constraint is broken, IRIS will not automatically try to resolve it.
Instead, an _alert_ email will be sent to the address in the
`email_recipient_gate_arm` [system attribute].
Instead, an _alert_ will logged in the `email_event` table.

## Security

Expand Down
4 changes: 0 additions & 4 deletions docs/system_attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,7 @@ System Attribute | Description
`dms_pixel_test_timeout_secs` | Time to wait for [DMS] pixel test to complete
`dms_send_confirmation_enable` | Enable a confirmation dialog box when the [DMS] Send button is pressed
`dms_update_font_table` | Enable the updating of the [DMS] controller font table to match the font table in IRIS
`dmsxml_reinit_detect` | Enable [DMS] reinitialization detection for DMSXML controllers
`email_rate_limit_hours` | Hours to wait before sending duplicate emails
`email_recipient_action_plan` | Recipient of [action plan] emails
`email_recipient_dmsxml_reinit` | Recipient of [DMS] reinit detection emails
`email_recipient_gate_arm` | Recipient of gate arm alert emails
`email_sender_server` | Sender email address of IRIS server
`email_smtp_host` | SMTP host for sending email
`gate_arm_alert_timeout_secs` | Time to wait before sending gate arm alerts after comm failure
Expand Down
4 changes: 0 additions & 4 deletions etc/i18n/messages_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1404,11 +1404,7 @@ dms_pixel_on_limit=Number of adjacent stuck-on pixels allowed in a DMS message o
dms_pixel_test_timeout_secs=Time to wait for DMS pixel test to complete.
dms_send_confirmation_enable=Enable a confirmation dialog box when the DMS Send button is pressed.
dms_update_font_table=Enable the updating of the DMS controller font table to match the font table in IRIS.
dmsxml_reinit_detect=Enable DMS reinitialization detection for DMSXML controllers.
email_rate_limit_hours=Hours to wait before sending duplicate emails.
email_recipient_action_plan=Recipient of Action Plan emails.
email_recipient_dmsxml_reinit=Recipient of DMS reinit detection emails.
email_recipient_gate_arm=Recipient of gate arm alert emails.
email_sender_server=Sender email address of IRIS server.
email_smtp_host=SMTP host for sending email.
gate_arm_alert_timeout_secs=Time to wait before sending gate arm alerts after comm failure.
Expand Down
2 changes: 0 additions & 2 deletions etc/i18n/messages_en_US_CA.properties
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,4 @@ dms_pixel_off_limit=Number of stuck-off pixels allowed in a CMS message or -1 to
dms_pixel_on_limit=Number of adjacent stuck-on pixels allowed in a CMS message or -1 to ignore.
dms_pixel_test_timeout_secs=Time to wait for CMS pixel test to complete.
dms_send_confirmation_enable=Enable a confirmation dialog box when the CMS Send button is pressed.
dmsxml_reinit_detect=Enable CMS reinitialization detection for DMSXML controllers.
email_recipient_dmsxml_reinit=Recipient of CMS reinit detection emails.
msg_feed_verify=Require CMS messages from msg_feed to exist in message library.
2 changes: 0 additions & 2 deletions etc/iris.spec
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,6 @@ ln -sf /usr/lib/jvm/jre-openjdk/lib/amd64/jli/libjli.so /usr/lib64
%dir %{_serverdir}
%{_serverdir}/iris-server-%{version}.jar
%{_serverdir}/iris-common-%{version}.jar
%{_serverdir}/javax.activation.jar
%{_serverdir}/mail.jar
%{_serverdir}/json-@@JSON.VERSION@@.jar
%{_serverdir}/postgis-jdbc-@@POSTGIS.VERSION@@.jar
%{_serverdir}/postgis-geometry-@@POSTGIS.VERSION@@.jar
Expand Down
1 change: 0 additions & 1 deletion lib/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
mail.jar is GPL licensed from Oracle.
jna is LGPL / Apache-2.0 licensed
gst1-java-core is LPGL licensed
Binary file removed lib/javax.activation.jar
Binary file not shown.
Binary file removed lib/mail.jar
Binary file not shown.
29 changes: 28 additions & 1 deletion sql/migrate-5.64.sql
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,37 @@ CREATE TRIGGER toll_zone_table_notify_trig
-- Delete obsolete system attributes
DELETE FROM iris.system_attribute WHERE name IN (
'camera_wiper_precip_mm_hr',
'email_recipient_aws'
'dmsxml_reinit_detect',
'email_recipient_action_plan',
'email_recipient_aws',
'email_recipient_dmsxml_reinit',
'email_recipient_gate_arm'
);

-- Reset all controller status to blank
UPDATE iris.controller SET status = NULL;

-- Add email events
INSERT INTO iris.event_config (name, enable_store, enable_purge, purge_days)
VALUES ('email_event', true, true, 30);

INSERT INTO event.event_description (event_desc_id, description)
VALUES
(308, 'Gate Arm SYSTEM'),
(903, 'Action Plan SYSTEM');

CREATE TABLE event.email_event (
id SERIAL PRIMARY KEY,
event_date TIMESTAMP WITH time zone DEFAULT NOW() NOT NULL,
event_desc INTEGER NOT NULL REFERENCES event.event_description,
subject VARCHAR(32) NOT NULL,
message VARCHAR NOT NULL
);

CREATE VIEW email_event_view AS
SELECT ev.id, event_date, ed.description, subject, message
FROM event.email_event ev
JOIN event.event_description ed ON ev.event_desc = ed.event_desc_id;
GRANT SELECT ON email_event_view TO PUBLIC;

COMMIT;
1 change: 0 additions & 1 deletion sql/remove_private_data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ DELETE FROM iris.map_extent;
UPDATE iris.system_attribute SET value = '' WHERE name = 'clearguide_key';
UPDATE iris.system_attribute SET value = '' WHERE name = 'email_smtp_host';
UPDATE iris.system_attribute SET value = '' WHERE name = 'email_sender_server';
UPDATE iris.system_attribute SET value = '' WHERE name LIKE 'email_recipient_%';
UPDATE iris.system_attribute SET value = '' WHERE name = 'work_request_url';
UPDATE iris.system_attribute SET value = '' WHERE name LIKE 'subnet_target_%';
UPDATE iris.system_attribute SET value = '' WHERE name LIKE 'camera_%_url';
Expand Down
21 changes: 17 additions & 4 deletions sql/tms-template.sql
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,7 @@ dms_pixel_on_limit 1
dms_pixel_test_timeout_secs 30
dms_send_confirmation_enable false
dms_update_font_table true
dmsxml_reinit_detect false
email_rate_limit_hours 0
email_recipient_action_plan
email_recipient_dmsxml_reinit
email_recipient_gate_arm
email_sender_server
email_smtp_host
gate_arm_alert_timeout_secs 90
Expand Down Expand Up @@ -324,6 +320,7 @@ VALUES
('client_event', true, false, 0),
('comm_event', true, true, 14),
('detector_event', true, true, 90),
('email_event', true, true, 30),
('gate_arm_event', true, false, 0),
('incident', true, false, 0),
('incident_update', true, false, 0),
Expand Down Expand Up @@ -392,6 +389,7 @@ COPY event.event_description (event_desc_id, description) FROM stdin;
305 Gate Arm WARN CLOSE
306 Gate Arm CLOSING
307 Gate Arm CLOSED
308 Gate Arm SYSTEM
401 Meter event
402 Meter LOCK
501 Beacon STATE
Expand All @@ -408,8 +406,23 @@ COPY event.event_description (event_desc_id, description) FROM stdin;
900 Action Plan ACTIVATED
901 Action Plan DEACTIVATED
902 Action Plan Phase CHANGED
903 Action Plan SYSTEM
\.

CREATE TABLE event.email_event (
id SERIAL PRIMARY KEY,
event_date TIMESTAMP WITH time zone DEFAULT NOW() NOT NULL,
event_desc INTEGER NOT NULL REFERENCES event.event_description,
subject VARCHAR(32) NOT NULL,
message VARCHAR NOT NULL
);

CREATE VIEW email_event_view AS
SELECT ev.id, event_date, ed.description, subject, message
FROM event.email_event ev
JOIN event.event_description ed ON ev.event_desc = ed.event_desc_id;
GRANT SELECT ON email_event_view TO PUBLIC;

--
-- Lane Codes, Direction, Road, Map Extent, Geo Loc
--
Expand Down
4 changes: 2 additions & 2 deletions src/us/mn/state/dot/tms/EventType.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public enum EventType {
CLIENT_UPDATE_PASSWORD(209),
GATE_ARM_UNKNOWN(301), GATE_ARM_FAULT(302), GATE_ARM_OPENING(303),
GATE_ARM_OPEN(304), GATE_ARM_WARN_CLOSE(305), GATE_ARM_CLOSING(306),
GATE_ARM_CLOSED(307),
GATE_ARM_CLOSED(307), GATE_ARM_SYSTEM(308),
METER_EVENT(401), METER_LOCK_EVENT(402),
BEACON_EVENT(501),
TAG_READ(601),
Expand All @@ -51,7 +51,7 @@ public enum EventType {
CAMERA_SWITCHED(801),
CAMERA_VIDEO_LOST(811), CAMERA_VIDEO_RESTORED(812),
ACTION_PLAN_ACTIVATED(900), ACTION_PLAN_DEACTIVATED(901),
ACTION_PLAN_PHASE_CHANGED(902);
ACTION_PLAN_PHASE_CHANGED(902), ACTION_PLAN_SYSTEM(903);

/** Event type ID */
public final int id;
Expand Down
4 changes: 0 additions & 4 deletions src/us/mn/state/dot/tms/SystemAttrEnum.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,7 @@ public enum SystemAttrEnum {
DMS_PIXEL_TEST_TIMEOUT_SECS(30, 5, 90),
DMS_SEND_CONFIRMATION_ENABLE(false, Change.RESTART_CLIENT),
DMS_UPDATE_FONT_TABLE(true),
DMSXML_REINIT_DETECT(false),
EMAIL_RATE_LIMIT_HOURS(0, 0),
EMAIL_RECIPIENT_ACTION_PLAN(String.class),
EMAIL_RECIPIENT_DMSXML_REINIT(String.class),
EMAIL_RECIPIENT_GATE_ARM(String.class),
EMAIL_SENDER_SERVER(String.class),
EMAIL_SMTP_HOST(String.class),
GATE_ARM_ALERT_TIMEOUT_SECS(90, 10),
Expand Down
8 changes: 4 additions & 4 deletions src/us/mn/state/dot/tms/server/ActionPlanSystem.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* IRIS -- Intelligent Roadway Information System
* Copyright (C) 2018 Iteris Inc.
* Copyright (C) 2018 Minnesota Department of Transportation
* Copyright (C) 2018-2024 Minnesota Department of Transportation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -16,6 +16,7 @@
package us.mn.state.dot.tms.server;

import java.util.Date;
import us.mn.state.dot.tms.EventType;
import us.mn.state.dot.tms.SystemAttrEnum;

/**
Expand Down Expand Up @@ -54,9 +55,8 @@ static public void sendEmailAlert(String usr, boolean active,
(active ? " actived" : " deactivated") +
" action plan " + "'" + pname + "' on " +
new Date().toString();
String recip = SystemAttrEnum.
EMAIL_RECIPIENT_ACTION_PLAN.getString();
EmailHandler.sendEmail(sub, msg, recip);
EmailHandler.send(EventType.ACTION_PLAN_SYSTEM, sub,
msg);
}
}
}
96 changes: 8 additions & 88 deletions src/us/mn/state/dot/tms/server/EmailHandler.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/*
* IRIS -- Intelligent Roadway Information System
* Copyright (C) 2013-2024 Minnesota Department of Transportation
* Copyright (C) 2018 Iteris Inc.
* Copyright (C) 2024 Minnesota Department of Transportation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -15,99 +14,20 @@
*/
package us.mn.state.dot.tms.server;

import java.util.HashMap;
import javax.mail.MessagingException;
import us.mn.state.dot.sched.Job;
import us.mn.state.dot.sched.Scheduler;
import us.mn.state.dot.sched.TimeSteward;
import us.mn.state.dot.tms.SystemAttrEnum;
import us.mn.state.dot.tms.units.Interval;
import static us.mn.state.dot.tms.units.Interval.Units.HOURS;
import us.mn.state.dot.tms.EventType;
import us.mn.state.dot.tms.server.event.EmailEvent;

/**
* Handler for email.
* Email event handler
*
* @author Douglas Lau
* @author Michael Darter
*/
public class EmailHandler {

/** Interval value of one hour (ms) */
static private final long HOUR_MS = new Interval(1, HOURS).ms();

/** Get email rate limiting time (hours) */
static private int getEmailRateLimitHours() {
return SystemAttrEnum.EMAIL_RATE_LIMIT_HOURS.getInt();
}

/** Get email rate limiting time (ms) */
static private long getEmailRateLimitMs() {
return getEmailRateLimitHours() * HOUR_MS;
}

/** Mapping of messages to last sent time */
static private final HashMap<String, Long> MSG_TIME =
new HashMap<String, Long>();

/** Scheduler for email jobs */
static private final Scheduler EMAIL = new Scheduler("email");

/** Disallow instantiation */
private EmailHandler() { }

/** Log an error to stderr */
static private void logEmailError(String msg, String reason) {
System.err.println(TimeSteward.currentDateTimeString(true) +
" Email not sent (" + msg + "), " + reason);
}

/** Send an email. This method does not block.
* @param sub Subject of email.
* @param msg Text of email.
* @param recip Recipient of email. */
static public void sendEmail(final String sub, final String msg,
final String recip)
/** Send an email */
static public void send(final EventType et, final String sub,
final String msg)
{
EMAIL.addJob(new Job(0) {
@Override public String getName() {
return sub;
}
@Override public void perform() {
doSendEmail(sub, msg, recip);
}
});
}

/** Send an email. This method blocks while sending.
* @param sub Subject of email.
* @param msg Text of email.
* @param recip Recipient of email. */
static private void doSendEmail(String sub, String msg, String recip) {
Long p = MSG_TIME.get(msg);
if (p != null) {
long elapsed_ms = TimeSteward.currentTimeMillis() - p;
if (elapsed_ms < getEmailRateLimitMs())
return;
}
if (null == recip || recip.length() <= 0)
return;
String host = SystemAttrEnum.EMAIL_SMTP_HOST.getString();
if (null == host || host.length() <= 0) {
logEmailError(msg, "invalid host");
return;
}
String sender = SystemAttrEnum.EMAIL_SENDER_SERVER.getString();
if (null == sender || sender.length() <= 0) {
logEmailError(msg, "invalid sender");
return;
}
try {
Emailer email = new Emailer(host, sender, recip);
email.send(sub, msg);
MSG_TIME.put(msg, TimeSteward.currentTimeMillis());
}
catch (MessagingException e) {
logEmailError(msg, "failed: " + e.getMessage());
}
BaseObjectImpl.logEvent(new EmailEvent(et, sub, msg));
}
}
Loading

0 comments on commit 61bc587

Please sign in to comment.