Tutorial on sending SMTP messages in Python in detail

Source: Internet
Author: User
Tags starttls how to send mail
SMTP is the protocol that sends messages, and Python's built-in support for SMTP can send plain text messages, HTML messages, and messages with attachments.

Python supports SMTP support with Smtplib and email two modules, email is responsible for structuring the mail, Smtplib is responsible for sending mail.

First, let's construct one of the simplest plain text messages:

From email.mime.text Import mimetextmsg = Mimetext (' Hello, send by Python ... ', ' plain ', ' utf-8 ')

Notice that when constructing the Mimetext object, the first parameter is the message body, the second parameter is the MIME subtype, passing in ' plain ', the final mime is ' Text/plain ', finally must use the UTF-8 code to guarantee the multi-language compatibility.

Then, send it out via SMTP:

# Enter email address and password: from_addr = Raw_input (' From: ') password = raw_input (' Password: ') # Enter the SMTP server address: Smtp_server = Raw_input (' SMTP server: ') # Enter the recipient address: To_addr = Raw_input (' to: ') import smtplibserver = Smtplib. SMTP (SMTP_SERVER) # SMTP protocol The default port is 25server.set_debuglevel (1) server.login (from_addr, password) server.sendmail (from _ADDR, [to_addr], msg.as_string ()) Server.quit ()

We use Set_debuglevel (1) To print out all the information that interacts with the SMTP server. The SMTP protocol is a simple text command and response. The login () method is used to log on to the SMTP server, and the SendMail () method is to send an email, because it can be sent to more than one person at a time, so pass in a list, the message body is a str,as_string () the Mimetext object into Str.

If all goes well, you can receive the email we just sent in the recipient's mailbox:

After careful observation, the following problems are found:

    • The message has no subject;
    • The recipient's name is not displayed as a friendly name, such as Mr Green ;
    • Obviously received the message, but the prompt is not in the recipient.

This is because the message subject, how to display the sender, the recipient, and so on is not sent to the MTA through the SMTP protocol, but is included in the text sent to the MTA, so we must add from, to and subject to Mimetext, which is a complete message:

#-*-coding:utf-8-*-from Email import encodersfrom email.header import headerfrom email.mime.text import Mimetextfrom E Mail.utils import parseaddr, Formataddrimport smtplibdef _format_addr (s):  name, addr = parseaddr (s)  return Formataddr ((\    Header (name, ' Utf-8 '). Encode (), \    addr.encode (' utf-8 ') if isinstance (addr, Unicode) Else addr))  FROM_ADDR = Raw_input (' From: ') password = raw_input (' Password: ') to_addr = Raw_input (' to: ') Smtp_server = Raw_input (' SMTP Server: ' msg = Mimetext (' Hello, send by Python ... ', ' plain ', ' utf-8 ') msg[' from '] = _format_addr (U ' Python enthusiast <%s> ' % from_addr) msg[' to '] = _format_addr (U ' admin <%s> '% to_addr) msg[' Subject '] = Header (U ' Greetings from SMTP ... ', ' utf-8 '). Encode () Server = Smtplib. SMTP (Smtp_server) server.set_debuglevel (1) server.login (from_addr, password) server.sendmail (from_addr, [to_addr ], msg.as_string ()) Server.quit ()

We have written a function _format_addr () to format an email address. Note You cannot simply pass in name, because if you include Chinese, you need to encode through the header object.

msg[' to ' receives a string instead of a list, and if there are multiple mail addresses, separate them.

Once you send the message again, you'll see the correct title, sender, and recipient in the recipient's mailbox:

The name of the recipient you see is probably not our incoming administrator, because many mail service providers will automatically replace the recipient name with the name of the user registration when displaying the message, but the display of the other recipient's name is not affected.

If we look at the original content of the email, we can see the following encoded headers:

From: =?utf-8?b? uhl0ag9u54ix5aw96icf?= to 
  : =?utf-8?b?566h55cg5zgy?= 
   Subject: =?utf-8?b? 5p2l6iequ01uuoeahomxruwamekapukapg==?=

This is the text that is encoded by the header object, containing UTF-8 encoded information and BASE64 encoded text. If we were to manually construct such coded text ourselves, it was obviously more complicated.
Send an HTML message

What if we want to send HTML messages instead of plain plain text files? The method is very simple, when the Mimetext object is constructed, the HTML string is passed in, and then the second parameter is changed from plain to HTML:

msg = Mimetext ('


' + '

Send by Python ...

' + ', ' html ', ' Utf-8 ')

Send the message again, and you'll see the message displayed in HTML:

Send Attachments

What if I add an attachment to an email? Messages with attachments can be viewed as messages that contain several parts: text and individual attachments, so you can construct a Mimemultipart object that represents the message itself, and then add a mimetext to it as the body of the message, Then continue to add the Mimebase object that represents the attachment:

# Mail object: msg = Mimemultipart () msg[' from '] = _format_addr (U ' python enthusiast <%s> '% from_addr) msg[' to '] = _FORMAT_ADDR ( U ' admin <%s> '% to_addr) msg[' Subject ' = Header (U ' Greetings from SMTP ... ', ' utf-8 '). Encode () # The message body is MIMEText:msg.attach ( Mimetext (' Send with File ... ', ' plain ', ' utf-8 ') # Add an attachment that adds a mimebase, reads a picture from the Local: with open ('/users/michael/downloads/ Test.png ', ' RB ') as F:  # Sets the mime and file name of the attachment, here is the PNG type:  MIME = mimebase (' image ', ' png ', filename= ' test.png ')  # Add the necessary header information:  mime.add_header (' content-disposition ', ' attachment ', filename= ' test.png ')  mime.add_header (' Content-id ', ' <0> ')  mime.add_header (' X-attachment-id ', ' 0 ')  # Read the contents of the attachment in:  mime.set_payload ( F.read ())  # Encoded with Base64:  encoders.encode_base64 (MIME)  # added to Mimemultipart:  Msg.attach (MIME)

Then, by sending the MSG (note type to Mimemultipart) as the normal sending process, you can receive the following message with attachments:

Send picture

What do I do if I want to embed a picture in the message body? Link a picture address directly in an HTML message. The answer is that most e-mail providers automatically block images with an outside chain because they don't know if the links are pointing to a malicious website.

To embed the image in the message body, we simply add the message as an attachment by sending it as an attachment, and then embed the attachment as a picture in HTML by referencing src= "cid:0". If you have multiple pictures, number them sequentially, and then refer to the different cid:x.

Add the above code to Mimemultipart Mimetext from plain to HTML and then reference the picture in the appropriate location:

Msg.attach (Mimetext ('


' + '

' + ', ' html ', ' Utf-8 ')

Send again, you can see the image directly embedded in the message body effect:

Supports both HTML and plain formats

If we send an HTML message, the recipient will be able to browse the contents of the message through a browser or software such as Outlook, but what if the recipient is using a device that is too old to view HTML mail?

By attaching a plain text while sending HTML, you can automatically downgrade to view plain text messages if the recipient cannot view the messages in HTML format.

With Mimemultipart, you can combine an HTML and a plain, noting that the specified subtype is alternative:

msg = Mimemultipart (' alternative ') msg[' from '] = ... msg[' to '] = ... msg[' Subject '] = ... msg.attach (mimetext (' Hello ', ' Plain ', ' utf-8 ')) Msg.attach (Mimetext ('


', ' HTML ', ' Utf-8 ') # Normal send Msg object ...

Encrypt SMTP

When you use the standard 25 port to connect to an SMTP server, you use clear text transmission, and the entire process of sending the message may be bugged. To send messages more securely, you can encrypt the SMTP session by creating an SSL secure connection before you send the message using the SMTP protocol.

Some mail service providers, such as Gmail, provide SMTP services that must be encrypted for transmission. Let's take a look at how to send mail via secure SMTP provided by Gmail.

It must be known that the SMTP port of Gmail is 587, so the code is modified as follows:

Smtp_server = ' smtp.gmail.com ' smtp_port = 587server = Smtplib. SMTP (Smtp_server, Smtp_port) Server.starttls () # The rest of the code is identical to the previous: Server.set_debuglevel (1) ...

You only need to call the STARTTLS () method immediately after you create the SMTP object to create a secure connection. The following code is exactly the same as the previous send message code.

If you are unable to connect to Gmail's SMTP server because of network problems, please believe that our code is not a problem, you need to make necessary adjustments to your network settings.

Using Python's smtplib to send mail is very simple, as long as you have mastered the various types of message construction methods, correctly set the message header, you can send a smooth.

Constructs a mail object is a Messag object, if constructs a Mimetext object, represents a text mail object, if constructs a Mimeimage object, represents one as the attachment picture, wants to combine several objects together, uses the Mimemultipart object, And mimebase can represent any object. Their inheritance relationships are as follows:

Copy the Code code as follows:


This nesting relationship allows for the construction of arbitrarily complex messages. You can view the packages they are in and detailed usage through the email.mime documentation.

Source Code Reference:


  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.