Outgoing mail of SMTP protocol (plain text, HTML and attachment mail)

1. about SMTP

SMTP is a protocol for sending mail. Python has built-in support for SMTP, which can send plain text mail, HTML mail and mail with attachments.
Python supports two modules for SMTP: SMTP lib and email. Email is responsible for constructing mail, and SMTP lib is responsible for sending mail.

1.1 about smtplib

It's very easy to send mail using Python's SMTP lib. As long as you master the construction methods of various mail types and correctly set the mail header, you can send it smoothly.

Constructing a mail object is a messaging object. If you construct a MIMEText object, it represents a text mail object. If you construct a MIMEImage object, it represents a picture as an attachment. If you want to combine multiple objects, you use mimemiultipart object, and MIMEBase can represent any object. Their inheritance relationship is as follows:

Message
± MIMEBase
± MIMEMultipart
± MIMENonMultipart
± MIMEMessage
± MIMEText
± MIMEImage
This nesting relationship can be used to construct any complex message. You can check their packages and detailed usage through the email.mime document.

2. About qq email authorization code

The qq email I use is to enable qq authorization code and other functions to log in and send emails. Other mailboxes should be similar. This oneself direct Baidu once had detailed course.

3. Coding

3.1 plain text mail
# -*- coding: utf-8 -*-
# @Time: 10:36 am on March 9, 2020
# @Author  : lh
# @Email   : xx@lh.com
# @File    : test2.py
# @Software: PyCharm


import smtplib
from email.mime.text import MIMEText
from email.header import Header

qqAccout = 'XX@qq.com'  # Mailbox account
qqCode = '**********'  # Authorization code
smtp_server = 'smtp.qq.com'  # SMTP server address:
smtp_port = 465  # Server port

# Configure the server and log in (login() method is used to log in to the SMTP server,)
stmp = smtplib.SMTP_SSL(smtp_server, smtp_port)
stmp.set_debuglevel(1)  # With set debug level (1), we can print out all the information that interacts with the SMTP server.
stmp.login(qqAccout, qqCode)

# Assembly send plain text content
message = MIMEText('33333 There's no substance to it 3333', 'plain', 'utf-8')  # Note that when constructing a MIME text object, the first parameter is the message body, and the second parameter is the subtype of MIME. When passing in 'plain' for plain text, the final MIME is' text/plain '. Finally, utf-8 encoding must be used to ensure multilingual compatibility.
message['From'] = Header("Python Automatic monitoring system", 'utf-8')  # Sender
message['To'] = Header("Predestined person", 'utf-8')  # Addressee
subject = 'Python SMTP Send mail test'
message['Subject'] = Header(subject, 'utf-8')  # Mail title

try:
    # sendmail() method is to send mail. Since it can be sent to multiple people at a time, a list is passed in. The body of the mail is a str. as_string() changes the MIMEText object into a str
    stmp.sendmail(qqAccout, [qqAccout, ], message.as_string())  # From, to,
    print('Mail sent successfully')
except Exception as e:
    print('Failed to send mail--' + str(e))

Note that when constructing a MIME text object, the first parameter is the message body, the second parameter is the subtype of the MIME, and the incoming 'plain' represents plain text, and the final MIME is' text/plain '. Finally, utf-8 encoding must be used to ensure multilingual compatibility.
Run program:

This is an email sent by myself.

3.2 HTML mail

When constructing a MIMEText object, pass in the HTML string and change the second parameter from plain to HTML

msg = MIMEText('<html><body><p>This is a HTML mail</p><a href="www.baidu.com">Use Baidu Search</a></body></html>', 'html', 'utf-8')
3.3 attachment email

Mail with attachments can be regarded as a mail with several parts: text and each attachment itself. Therefore, you can construct a mimemiultipart object to represent the mail itself, then add a MIMEText as the mail body, and then continue to add the MIMEBase object to represent the attachment

# -*- coding: utf-8 -*-
# @Time: 10:21 am on March 12, 2020
# @Author  : lh
# @Email   : xx@lh.com
# @File    : test5.py
# @Software: PyCharm

import smtplib
from email import encoders
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.utils import parseaddr, formataddr


def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))


from_addr = input('From: ')
password = input('Password: ')
to_addr = input('To: ')
smtp_server = input('SMTP server: ')

# Mail object
msg = MIMEMultipart()
msg['From'] = _format_addr('Python Mail test<%s>' % from_addr)
msg['To'] = _format_addr('Administrators <%s>' % to_addr)
msg['Subject'] = Header('Are you from meituan, then you can send it', 'utf-8').encode()

# Message body is mime text
msg.attach(MIMEText('Send text message...', 'plain', 'utf-8'))

# To add an attachment is to add a mime base and read a picture locally
with open('test.html', 'rb') as f:
    # Set the MIME and filename of the attachment. This is an html file
    m = MIMEBase('file', 'html', filename='test.html')
    # Add header information
    m.add_header('Content-Disposition', 'attachment', filename='test.html')
    m.add_header('Content-ID', '<0>')
    m.add_header('X-Attachment-Id', '0')
    # Read in the content of the attachment
    m.set_payload(f.read())
    # Encoding with Base64
    encoders.encode_base64(m)
    msg.attach(m)

    server = smtplib.SMTP(smtp_server, 25)
    server.set_debuglevel(1)
    server.login(from_addr, password)
    server.sendmail(from_addr, [to_addr], msg.as_string())
    server.quit()
3.4 pictures in the mail

If you want to nest pictures directly into the mail, you need to set it up, because the general mail will block the pictures in the outer chain we bring.
According to the way of sending attachments, first add the email as an attachment, and then embed the attachment as a picture by referencing src="cid:0" in HTML. If there are multiple pictures, number them one by one, and then reference different cid:x.

The above code adds the MIMEText of mimemiultipart from plain to html, and then references the picture in the appropriate place

# -*- coding: utf-8 -*-
# @Time: 11:19 am on March 12, 2020
# @Author  : lh
# @Email   : xx@lh.com
# @File    : test6.py
# @Software: PyCharm

import smtplib
from email import encoders
from email.header import Header
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.utils import parseaddr, formataddr


def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))


from_addr = input('From: ')
password = input('Password: ')
to_addr = input('To: ')
smtp_server = input('SMTP server: ')

# Mail object
msg = MIMEMultipart()
msg['From'] = _format_addr('Python Mail test<%s>' % from_addr)
msg['To'] = _format_addr('Administrators <%s>' % to_addr)
msg['Subject'] = Header('Are you from meituan, then you can send it', 'utf-8').encode()

# Message body is mime text
msg.attach(MIMEText('<html><body><h1>Hello</h1>' +
                    '<p><img src="cid:0"></p>' +
                    '</body></html>', 'html', 'utf-8'))

# To add an attachment is to add a mime base and read a picture locally
with open('test.jpg', 'rb') as f:
    # Set the MIME and filename of the attachment. This is an html file
    m = MIMEBase('image', 'jpg', filename='test.jpg')
    # Add header information
    m.add_header('Content-Disposition', 'attachment', filename='test.jpg')
    m.add_header('Content-ID', '<0>')
    m.add_header('X-Attachment-Id', '0')
    # Read in the content of the attachment
    m.set_payload(f.read())
    # Encoding with Base64
    encoders.encode_base64(m)
    msg.attach(m)

    server = smtplib.SMTP(smtp_server, 25)
    server.set_debuglevel(1)
    server.login(from_addr, password)
    server.sendmail(from_addr, [to_addr], msg.as_string())
    server.quit()
3.5 downgrade to view mail

The recipient can browse the content of the mail normally through a browser or Outlook or other software. However, if the device used by the recipient is too old to view the HTML mail, the method is to attach a plain text while sending the HTML. If the recipient cannot view the HTML mail, the plain text mail can be automatically downgraded.
With mimemiultipart, you can combine HTML and Plain. Note that the subtype is alternative:

msg = MIMEMultipart('alternative')
msg['From'] = ...
msg['To'] = ...
msg['Subject'] = ...

msg.attach(MIMEText('hello', 'plain', 'utf-8'))
msg.attach(MIMEText('<html><body><h1>Hello</h1></body></html>', 'html', 'utf-8'))
# Send msg object normally
Published 61 original articles, won praise 22, visited 30000+
Private letter follow

Tags: Python encoding Pycharm

Posted on Thu, 12 Mar 2020 00:11:41 -0400 by ManicMax