Sending Mail Using SMTP

The standard protocol for sending mail on the Internet is the Simple Mail Transfer Protocol (SMTP). SMTP allows one computer to transfer email messages to another computer using a standard set of commands. Mail clients use SMTP to send outgoing messages, and mail servers use SMTP to forward messages to their final destination. The current specification for SMTP is defined in RFC 2821 (http://www.faqs.org/rfcs/rfc2821.html).

Twisted supports SMTP, using the twisted.protocols.smtp module. In addition to SMTP Protocol classes, this module has handy functions for sending mail. Combined with the email module in the Python standard library, you can create and send messages (even complex MIME messages with attachments) with only a few lines of code.

7.2.1. How Do I Do That?

Create your message using Python's email package. Then use the twisted.protocols.smtp.sendmail function to send the message using SMTP, as demonstrated in Example 7-3.

Example 7-3. smtpsend.py


from twisted.protocols import smtp

from twisted.internet import reactor, defer

from email.MIMEBase import MIMEBase

from email.MIMEMultipart import MIMEMultipart

from email import Encoders

import sys, mimetypes, os



def buildMessage(fromaddr, toaddr, subject, body, filenames):

 message = MIMEMultipart( )

 message['From'] = fromaddr

 message['To'] = toaddr

 message['Subject'] = subject

 textPart = MIMEBase('text', 'plain')

 textPart.set_payload(body)

 message.attach(textPart)

 for filename in filenames:

 # guess the mimetype

 mimetype = mimetypes.guess_type(filename)[0]

 if not mimetype: mimetype = 'application/octet-stream'

 maintype, subtype = mimetype.split('/')

 attachment = MIMEBase(maintype, subtype)

 attachment.set_payload(file(filename).read( ))

 # base64 encode for safety

 Encoders.encode_base64(attachment)

 # include filename info

 attachment.add_header('Content-Disposition', 'attachment',

 filename=os.path.split(filename)[1])

 message.attach(attachment)

 return message



def sendComplete(result):

 print "Message sent."

 reactor.stop( )



def handleError(error):

 print >> sys.stderr, "Error", error.getErrorMessage( )

 reactor.stop( )



if __name__ == "_ _main_ _":

 if len(sys.argv) < 5:

 print "Usage: %s smtphost fromaddr toaddr file1 [file2, ...]" % (

 sys.argv[0])

 sys.exit(1)



 smtphost = sys.argv[1]

 fromaddr = sys.argv[2]

 toaddr = sys.argv[3]

 filenames = sys.argv[4:]

 subject = raw_input("Subject: ")

 body = raw_input("Message (one line): ")

 message = buildMessage(fromaddr, toaddr, subject, body, filenames)

 messageData = message.as_string(unixfrom=False)

 sending = smtp.sendmail(smtphost, fromaddr, [toaddr], messageData)

 sending.addCallback(sendComplete).addErrback(handleError)

 reactor.run( )

Run smtpsend.py from the command line with four or more arguments: the name of your SMTP server, the address the message is from, the address it should be delivered to, and one or more files to attach. It will ask you for a subject line and single-line message body, and then create and send the email:


 $ python smtpsend.py smtp.myisp.com me@myisp.com 

 > user@otherisp.com logo.png homepage.html

 Subject: Project Files

 Message (one line): Here are those files I was talking about.

 Message sent.

 

7.2.2. How Does That Work?

The twisted.protocols.smtp.sendmail function is a simple, handy way to send email using Twisted. It encapsulates all the work of connecting to the STMP server, telling it the address the message is coming from and the address it should be delivered to, and transferring the message data. Call the sendmail function with four arguments: the SMTP server hostname, the address the message is coming from, a list of addresses it should be delivered to, and the message data itself (either as a string or a file-like object). It returns a Deferred that will call back when the transfer is complete.

There's one potentially tricky thing about smtp.sendmail that you should be aware of: if you're sending a message to multiple recipients, a successful callback means that the sever accepted the message for delivery to at least one of them. If you're sending the message to more than one address, therefore, be sure to check the return value passed to your callback function. This value will be a tuple in the form (numberDelivered, addressInfo), where numberDelivered is a count of the number of recipients for which the server accepted the message, and addressInfo is a list of tuples in the format (address, responseCode, responseMessage). If you're sending a message to a single address, as in Example 7-3, you don't have to check the return value; the callback itself indicates that the message was accepted for the single recipient it was addressed to.

The twisted.protocols.smtp module provides lower-level classes that can be used in SMTP clients, including SMTP-specific Protocol and Factory objects. But in most cases, the sendmail function will do everything you need in one line of code.

Because the sendmail function handles all the SMTP work, most of the code in smtpsend.py is involved with constructing the email message that will be sent. The Python email package contains modules for constructing messages of various types, and the buildMessage function uses two of them: MIMEMultipart, which creates a message of type multipart/mixed (suitable for storing a message body and attachments), and MIMEBase, which can hold any type of message data. The buildMessage function creates an email.MIMEMultipart.MIMEMultipart object called message. Then it iterates through the list of filenames and creates a MIMEBase object for each one containing the file's data. It uses the Python mimetypes module to guess the file type (based on the filename's extension). In addition, it Base64-encodes the attachment contents, which allows binary data to be represented as ASCII text (a requirement for passing through most mail servers).

Once the attachments have been added, the message is ready to be sent. smtpsend.py passes the message data to smtp.sendmail, along with the hostname of the SMTP server and the sender and recipient addresses. It sets up the callback and errback functions, and it hands off control to the reactor.

Getting Started

Building Simple Clients and Servers

Web Clients

Web Servers

Web Services and RPC

Authentication

Mail Clients

Mail Servers

NNTP Clients and Servers

SSH

Services, Processes, and Logging



Twisted Network Programming Essentials
Twisted Network Programming Essentials
ISBN: 0596100329
EAN: 2147483647
Year: 2004
Pages: 107
Authors: Abe Fettig

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net