element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
    About the element14 Community
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Japan
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      •  Vietnam
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Sci Fi Your Pi
  • Challenges & Projects
  • Design Challenges
  • Sci Fi Your Pi
  • More
  • Cancel
Sci Fi Your Pi
Blog Escape The Past: SMTP Email Client
  • Blog
  • Forum
  • Documents
  • Files
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: frellwan
  • Date Created: 7 Aug 2015 1:18 AM Date Created
  • Views 564 views
  • Likes 1 like
  • Comments 0 comments
  • escape_the_past
Related
Recommended

Escape The Past: SMTP Email Client

frellwan
frellwan
7 Aug 2015

This week I was able to make progress on a couple of remaining items. First, I was able to get email notifications working and secondly, I was able to get recipes downloaded. I still need to get the recipe data into the PLC, but I should finish that up shortly. All code for this project is available at https://github.com/frellwan/SciFy-Pi.git under the Serial/df1 folder.

 

Email Notification

The typical protocol for sending mail on the Internet is the Simple Mail Transfer Protocol (SMTP).  I will be using Twisted Mail to send SMTP messages when alarm conditions are detected in the PLC. I outlined the steps necessary to install Twisted in a previous post, and Twisted Mail is part of that install.

 

SMTP is a plain-text protocol. To send an email, we need to know the IP address or hostname of an SMTP server. To do this we need to look up the mail exchange (MX) servers for the hostname we will be sending mail to (e.g. ME@google.com – MX lookup would give us the hostname of the mail exchange server for google.com). Most SMTP messages are sent using port 25.

 

A simple way to do this with Twisted Mail:

 

MXCALCULATOR = relaymanager.MXCalculator()

def getMailExchange(host):
    def cbMX(mxRecord):
        return str(mxRecord.name)
    return MXCALCULATOR.getMX(host).addCallback(cbMX)

 

 

In my company I am able to send email from a fictitious email address (such as MACHINENUMBER@hostname.com) and it will be delivered without issue as long as it goes to a hostname.com email address. This allows me to have each machine send emails that will allow the recipient to know which machine is having problems. These emails lack the authentication headers of typical emails and will usually end up in a spam filter when I attempt to send to an email address outside of my company’s mail exchange hostname.

 

Sending a SMTP email is a fairly easy task with Twisted Mail:

 

def sendEmail(mailFrom, mailTo, msg, subject=""):
    def dosend(host):
        mstring = "From: %s\nTo: %s\nSubject: %s\n\n%s\n"
        msgfile = StringIO(mstring % (mailFrom, mailTo, subject, msg))
        d = defer.Deferred()
        factory = smtp.ESMTPSenderFactory(None, None, mailFrom, mailTo, msgfile, d,
                                          requireAuthentication=False,
                                          requireTransportSecurity=False)
        reactor.connectTCP(host, 25, factory)
        return d
    return getMailExchange(mailTo.split("@")[1]).addCallback(dosend)

 

 

Recipe Download

As mentioned in the project description, I will be accessing a recipe database on an external server through an FTP connection. The PLC will set a bit when the recipe files need to be downloaded from the server. When this bit is set an FTP connection is established and a file that contains the names of all the recipe files is downloaded and then each recipe name is read from the file and downloaded separately.

 

if (bits[2]):
     # self.transferred added so multiple downloads won't be initiated
     if (not self.transferred):
          #Download Recipes from Server
          serialLog.debug("Downloading Recipes")
          d = self.ftpEndpoint.connect(FTPClientAFactory())
          d.addCallback(getRecipeFiles)
          d.addErrback(self.FTPfail, 'startFTPTransfer')
          self.transferred = True
     else:
          self.transferred = False

 

def getRecipeFiles(ftpProtocol, localDir):
  def downloadRecipes(self):
       filename = localDir + '/' + 'families.csv'
       fObj = open(filename, 'r')
       for recipe in fObj:
            recipeName = recipe.strip() + '.csv'
            recipeDir = localDir + recipeName
            recipeFile = FileReceiver(recipeDir)
            d = ftpProtocol.retrieveFile(recipeName, recipeFile)
            d.addErrback(fail, "getRecipeFiles")

  # Download recipes
  familynames = localDir + '/families.csv'
  recipeFile = FileReceiver(familynames)
  d = ftpProtocol.retrieveFile('families.csv', recipeFile)
  d.addCallback(downloadRecipes)
  d.addErrback(fail, "getRecipeFiles")

  • Sign in to reply
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2026 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube