Book Image

Programming ArcGIS with Python Cookbook, Second Edition

By : Donald Eric Pimpler, Eric Pimpler
Book Image

Programming ArcGIS with Python Cookbook, Second Edition

By: Donald Eric Pimpler, Eric Pimpler

Overview of this book

Table of Contents (22 chapters)
Programming ArcGIS with Python Cookbook Second Edition
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Sending e-mails


There will be occasions when you may need to send an e-mail from a Python script. An example of this might be an alert for the successful completion or errors incurred in a long-running geoprocessing operation. On these and other occasions, sending an e-mail can be helpful.

Getting ready

Sending an e-mail through a Python script will require you to have access to a mail server. This can be a public e-mail service, such as Yahoo, Gmail, or others. It can also use outgoing mail servers that is configured with applications, such as Microsoft Outlook. In either case, you'll need to know the host name and port of the e-mail server. The Python smtplib module is used to create connections to the mail server and to send e-mails.

The Python email module contains a Message class that represents e-mail messages. Each message contains both headers and a body. This class can't be used to send e-mails, it just handles its object representation. In this recipe, you'll learn how to use the smtp class to send e-mails containing an attachment through your script. The Message class can parse a stream of characters or a file containing an e-mail by using either the message_from_file() or message_from_string() functions. Both will create a new Message object. The body of the mail can be obtained by calling Message.getpayload().

Note

We are using the Google Mail service for this exercise. If you already have a Gmail account, then simply provide your username and password as the values for these variables. If you don't have a Gmail account, you'll need to create one or use a different mail service to complete this exercise. Gmail accounts are free. Google may block attempts to send an e-mail through scripts, so be aware that this may not work as expected if you're using Gmail.

How to do it…

Follow these steps to create a script that can send e-mails:

  1. Open IDLE and create a file called C:\ArcpyBook\Appendix2\SendEmail.py.

  2. In order to send e-mails with attachments, you're going to need to import the smtplib module along with the os module, and several classes from the e-mail module. Add the following import statements to your script:

    import smtplib
    from email.MIMEMultipart import MIMEMultipart
    from email.MIMEBase import MIMEBase
    from email.MIMEText import MIMEText
    from email import Encoders
    import os
  3. Create the following variables and assign your Gmail username and password as the values. Keep in mind that this method of e-mailing from your Python script can invite problems, as it requires that you include your username and password:

    gmail_user = "<username>"
    gmail_pwd = "<password>"

    Tip

    Note that including an e-mail username and password in a script is not secure so you wouldn't want to include these in a production script. There are ways of encrypting these values but that is beyond the scope of this recipe.

  4. Create a new Python function called mail(). This function will accept four parameters: to, subject, text, and attach. Each of these parameters should be self-explanatory. Create a new MIMEMultipart object and assign the from, to, and subject keys. You can also attach the text of the e-mail to this new msg object using MIMEMultipart.attach():

    def mail(to, subject, text, attach):
      msg = MIMEMultipart()
      msg['From'] = gmail_user
      msg['To'] = to
      msg['Subject'] = subject
      
      msg.attach(MIMEText(text))
  5. Attach the file to the e-mail:

      part = MIMEBase('application', 'octet-stream')
      part.set_payload(open(attach, 'rb').read())
      Encoders.encode_base64(part)
      part.add_header('Content-Disposition',
        'attachment; filename="%s"' % os.path.basename(attach))
      msg.attach(part)
  6. Create a new SMTP object that references the Google Mail service, passes in the username and password to connect to the mail services, sends the e-mail, and closes the connection:

      mailServer = smtplib.SMTP("smtp.gmail.com", 587)
      mailServer.ehlo()
      mailServer.starttls()
      mailServer.ehlo()
      mailServer.login(gmail_user, gmail_pwd)
      mailServer.sendmail(gmail_user, to, msg.as_string())
      mailServer.close()
  7. Call the mail() function, passing in the recipient of the e-mail, a subject for the e-mail, the text of the e-mail, and the attachment:

      mail("<email to send to>",
      "Hello from python!",
      "This is an email sent with python",
      "c:/ArcpyBook/data/bc_pop1996.csv")
  8. The entire script should appear as follows:

    import smtplib
    from email.MIMEMultipart import MIMEMultipart
    from email.MIMEBase import MIMEBase
    from email.MIMEText import MIMEText
    from email import Encoders
    import os
    
    gmail_user = "<username>"
    gmail_pwd = "<password>"
    
    def mail(to, subject, text, attach):
     msg = MIMEMultipart()
    
     msg['From'] = gmail_user
     msg['To'] = to
     msg['Subject'] = subject
    
     msg.attach(MIMEText(text))
    
     part = MIMEBase('application', 'octet-stream')
     part.set_payload(open(attach, 'rb').read())
     Encoders.encode_base64(part)
     part.add_header('Content-Disposition',
         'attachment; filename="%s"' % os.path.basename(attach))
     msg.attach(part)
    
     mailServer = smtplib.SMTP("smtp.gmail.com", 587)
     mailServer.ehlo()
     mailServer.starttls()
     mailServer.ehlo()
     mailServer.login(gmail_user, gmail_pwd)
     mailServer.sendmail(gmail_user, to, msg.as_string())
     mailServer.close()
    
    mail("<email to send to>", "Hello from python!", "This is an email sent with python", "bc_pop1996.csv")
  9. You can check your work by examining the C:\ArcpyBook\code\Appendix2\SendEmail.py solution file.

  10. Save and run the script. For testing, I used my personal Yahoo account as the recipient. You'll notice that my inbox has a new message from my Gmail account; also, notice the attachment:

How it works…

The first parameter passed into the mail() function is the e-mail address that will receive the e-mail. This can be any valid e-mail address, but you'll want to supply a mail account that you can actually check, so that you can make sure your script runs correctly. The second parameter is just the subject line of the e-mail. The third parameter is the text. The final parameter is the name of a file that will be attached to the e-mail. Here, I've simply defined that the bc_pop1996.csv file should be attached. You can use any file you have access to, but you may want to just use this file for testing.

We then create a new MIMEMultipart object inside the mail() function, and assign the from, to, and subject keys. You can also attach the text of the e-mail to this new msg object using MIMEMultipart.attach(). The bc_pop1996.csv file is then attached to the e-mail using a MIMEBase object and attached to the e-mail using msg.attach(part).

At this point, we've examined how a basic text e-mail can be sent. However, we want to send a more complex e-mail message that contains text and an attachment. This requires the use of MIME messages, which provide the functionality to handle multipart e-mails. MIME messages need boundaries between multiple parts of an e-mail along with extra headers to specify the content being sent. The MIMEBase class is an abstract subclass of Message and enables this type of an e-mail to be sent. Since it is an abstract class, you can't create actual instances of this class. Instead, you use one of the subclasses, such as MIMEText. The last step of the mail() function is to create a new SMTP object that references the Google Mail service, passes in the username and password in order to connect to the mail services, sends the e-mail, and then closes the connection.