Example 2

The following example is a little more involved and does the XML parsing without using the helper module, which is useful only for discovery incidents.
#Send an email to the recipients of a DLP incident
# XML search path constants for easier XML handling
NS1=u".//{http://www.portauthoritytech.com/schmea/xml-rpc/ 1.0}"
EVT=u".//{http://www.portauthoritytech.com/schmea/incident/ 1.0}"
EVTSOURCE=EVT+u"source" 
EVTDETAIL=EVT+u"detail" 
EVTDESTINATIONS=EVT+u"destinations" 
EVTDESTINATION=EVT+u"destination" 
EVTSUBJECT=EVT+u"subject"
## Email message to send to the users 
EMAILMESSAGE="""From: Forcepoint DLP <dlp@example.com>\r 
To: %(deststring)s\r
Subject: Re: %(subject)s\r
\r
Dear Sir or Madam,\r
\r
A message sent to you from %(source)s with the subject "%(subject)s" has violated PCI regulations, and has been blocked by Forcepoint DLP. Please contact the sender and request that they redact all cardholder information (such as name, credit card number, expiration date, CVV) from the message and resend it.\r
\r 
Regards,\r
\r
Forcepoint DLP\r 
"""
# Email gateway 
SMTPGATEWAY='10.4.228.240:25'
import sys
import xml.etree.ElementTree as ET 
import smtplib
# Parse the XML file 
oXMLTree=ET.parse(sys.argv[1])
## Search for a few key pieces of data
dIncidentDetails={}
# source
dIncidentDetails['source']=oXMLTree.find(EVTSOURCE).find(EVT DETAIL).get('value')
# destinations 
lDests=[
elem.find(EVTDETAIL).get('value') 
for elem
in oXMLTree.find(EVTDESTINATIONS)
]
dIncidentDetails['deststring']=', '.join(lDests)
# extract the subject 
dIncidentDetails['subject']=oXMLTree.find(EVTSUBJECT).text
## send an email message
oSMTP=smtplib.SMTP(SMTPGATEWAY)
oSMTP.sendmail(dIncidentDetails['source'],lDests,EMAILMESSAG E % dIncidentDetails)
oSMTP=None
Please note several important aspects of this example:
  • The search paths constructed on lines 4–10 do not contain the xmlns shortcuts for the namespaces but rather the full URL. This is a requirement of the particular XML library used (xml.etree). It is also more resilient to future changes in the XML format.
  • Lines 13 to 24 contain an IMF message (RFC5322) ready to be sent by SMTP. The Pythonic variable substitutions inside the script makes for an easy ad-hock template language.
  • Lines 30 and 34 are all that is required to parse the XML file. Then, extracting information from the XML file is done in a series of searches on lines 40, 44, 46, and 51. It does not get easier than this.
  • Lines 43–47 are a Python construct called “list comprehension”—a powerful and useful Python constructs for transforming lists. Find more information about it at http://www.python.org/dev/peps/pep-0202/.
  • Lines 55–57 send an SMTP message. The gateway must accept SMTP connections for this to work.
  • There is a bug in this code: if an incoming mail has destinations outside of the organization as well as inside, then all of the destinations will receive the notification message. This is usually not the desired action. Fixing it is easy and left as an exercise to the reader.