Python Sends Mail (Four Common Mail Contents)

Keywords: Python Session Linux shell

From: http://lizhenliang.blog.51cto.com/7876557/1875330

When writing scripts, run in the background, want to know the implementation, will inform the administrator by mail, SMS (short message), Flying Letter, Wechat, etc., the most used is mail. Under linux, it is very simple for Shell scripts to send mail alerts. There are ready-made mail service software or call operator mailbox servers.

For Python, scripts need to be written to call the mail server to send mail. The protocol used is SMTP. To receive mail, the protocol used is POP3 and IMAP. I think it is necessary to clarify the difference between POP3 and IMAP: the operation of POP3 in the client mailbox will not be fed back to the mailbox server, such as deleting an email, and the mailbox server will not be deleted. IMAP will feed back to the mailbox server and do the corresponding operations.

Python provides libraries for sending and receiving mail, smtplib, poplib and imaplib, respectively.

This chapter mainly explains how to use smtplib library to send various forms of mail content. In smtplib library, smtplib.SMTP() is mainly used to connect SMTP servers and send mail.

This class has several commonly used methods:

Method

describe

SMTP.set_debuglevel(level) Set output debug debugging information, default does not output
SMTP.docmd(cmd[, argstring]) Send a command to the SMTP server
SMTP.connect([host[, port]]) Connect to the specified SMTP server
SMTP.helo([hostname]) Confirm your identity to the SMTP server using the helo command
SMTP.ehlo(hostname) Use ehlo commands like ESMTP (SMTP extension) to confirm your identity
SMTP.ehlo_or_helo_if_needed() If no ehlo or helo instructions are provided in previous session connections, this method calls ehlo() or helo().
SMTP.has_extn(name) Determine whether the specified name is on the SMTP server
SMTP.verify(address) Determine whether the mail address is on the SMTP server
SMTP.starttls([keyfile[, certfile]]) Make the SMTP connection run in TLS mode, and all SMTP instructions will be encrypted
SMTP.login(user, password) Log on to SMTP Server
SMTP.sendmail(from_addr, to_addrs, msg, mail_options=[], rcpt_options=[])

Send mail

from_addr: Mail sender

to_addrs: mail recipient

msg: Send messages

SMTP.quit() Close SMTP session
SMTP.close() Close SMTP Server Connection

Look at the official examples:

>>> import smtplib
>>> s=smtplib.SMTP("localhost")
>>> tolist=["one@one.org","two@two.org","three@three.org","four@four.org"]
>>> msg = '''\
     ... From: Me@my.org
     ... Subject: testin'...
     ...
     ... This is a test '''
>>> s.sendmail("me@my.org",tolist,msg)
     { "three@three.org" : ( 550 ,"User unknown" ) }
>>> s.quit()

Let's send ourselves an email test based on an example.

I'm testing the use of a local SMTP server, that is, to install a service that supports the SMTP protocol, such as sendmail, postfix and so on.

CentOS installation sendmail: yum install sendmail

>>> import smtplib
>>> s = smtplib.SMTP("localhost")
>>> tolist = ["xxx@qq.com", "xxx@163.com"]
>>> msg = '''\
... From: Me@my.org
... Subject: test
... This is a test '''
>>> s.sendmail("me@my.org", tolist, msg)
{}

Enter Tencent and Netease recipient mailboxes, you can see the test mails just sent, which are usually filtered into spam by the mailbox server, so there is no inbox, you have to go to the garbage bin to see.


As you can see, multiple recipients can be placed in a list for group distribution. In the msg object, From represents the sender, Subject is the header of the mail, and the content of the mail is entered after a new line.

Above is the mail sent using the local SMTP server. Test sending mail with 163 server to see the effect:

>>> import smtplib
>>> s = smtplib.SMTP("smtp.163.com")
>>> s.login("baojingtongzhi@163.com", "xxx")
(235, 'Authentication successful')
>>> tolist = ["xxx@qq.com", "xxx@163.com"]
>>> msg = '''\
... From: baojingtongzhi@163.com
... Subject: test
... This is a test '''
>>> s.sendmail("baojingtongzhi@163.com", tolist, msg)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.6/smtplib.py", line 725, in sendmail
    raise SMTPDataError(code, resp)
smtplib.SMTPDataError: (554, 'DT:SPM 163 smtp10,DsCowAAXIdDIJAtYkZiTAA--.65425S2 1477125592,please see http://mail.163.com/help/help_spam_16.htm?ip=119.57.73.67&hostid=smtp10&time=1477125592')

When visiting the 163 web sites given, SMTP554 made a mistake: "554 DT:SUM envelope sender does not match the sender of the letter;"

Perhaps you already know what it means. When using the local SMTP server above, the recipient's location is undisclosed-recipients. The reason why the 163 SMTP server does not serve us is that the recipient is not specified here.

Re-modify the msg object and add the recipient:

>>> msg = '''\           
... From: baojingtongzhi@163.com
... To: 962510244@qq.com ,zhenliang369@163.com
... Subject: test
...
... This is a test '''
>>> s.sendmail("baojingtongzhi@163.com", tolist, msg)
{}


Okay, you can send mail normally. The format of msg is stipulated by SMTP and must be complied with.

1. Python sends mail and transcribes it

#!/usr/bin/python
# -*- coding: utf-8 -*-
import smtplib
def sendMail(body):
    smtp_server = 'smtp.163.com'
    from_mail = 'baojingtongzhi@163.com'
    mail_pass = 'xxx'
    to_mail = ['962510244@qq.com', 'zhenliang369@163.com']
    cc_mail = ['lizhenliang@xxx.com']
    from_name = 'monitor' 
    subject = u'Monitor'.encode('gbk')   # Sending by gbk code, the general mail client can recognize
#     msg = '''\
# From: %s <%s>
# To: %s
# Subject: %s
# %s''' %(from_name, from_mail, to_mail_str, subject, body)  # In this way, the header information must be left-handed, that is, no blanks can be used at the beginning of each line, otherwise SMTP 554 will be reported.
    mail = [
        "From: %s <%s>" % (from_name, from_mail),
        "To: %s" % ','.join(to_mail),   # Convert to a string, separating elements by commas
        "Subject: %s" % subject,
        "Cc: %s" % ','.join(cc_mail),
        "",
        body
        ]
    msg = '\n'.join(mail)  # In this way, the header information is placed in the list, then join ed together, and the elements are separated by newline characters. The result is the same as the annotations above.
    try:
        s = smtplib.SMTP()
        s.connect(smtp_server, '25')
        s.login(from_mail, mail_pass)
        s.sendmail(from_mail, to_mail+cc_mail, msg)   
        s.quit()
    except smtplib.SMTPException as e:
        print "Error: %s" %e
if __name__ == "__main__":
    sendMail("This is a test!")


s.sendmail(from_mail, to_mail+cc_mail, msg) Here, notice why the recipient and the copycat send together? In fact, whether the recipient or the copycat, they receive the same mail, SMTP is that the recipient such a one-by-one delivery. So in fact, there is no concept of copying, just adding the information of the Copyer to the header of the mail. In addition, if you don't need to copy, just remove the information of CC above.

2 Python sends mail with attachments

Since the SMTP.sendmail() method does not support adding attachments, you can use the email module to meet the requirements. The email module is a module for constructing and parsing mail.

Let's first look at how to construct a simple email using the email library:

message = Message()
message['Subject'] = 'Mail theme'
message['From'] = from_mail
message['To'] = to_mail
message['Cc'] = cc_mail
message.set_payload('Mail content')

That's the basic format!

Go back to the subject and send an email with an attachment:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email import encoders
from email.mime.base import MIMEBase
from email.utils import parseaddr, formataddr
# Format mail address
def formatAddr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))
def sendMail(body, attachment):
    smtp_server = 'smtp.163.com'
    from_mail = 'baojingtongzhi@163.com'
    mail_pass = 'xxx'
    to_mail = ['962510244@qq.com', 'zhenliang369@163.com']
    # Construct a MIME Multipart object to represent the mail itself
    msg = MIMEMultipart()
    # Header Transcoding Chinese
    msg['From'] = formatAddr('Administrators <%s>' % from_mail).encode()
    msg['To'] = ','.join(to_mail)
    msg['Subject'] = Header('Monitor', 'utf-8').encode()
    # Plain stands for plain text
    msg.attach(MIMEText(body, 'plain', 'utf-8'))
    # Binary mode file
    with open(attachment, 'rb') as f:
        # MIMEBase represents the object of the attachment
        mime = MIMEBase('text', 'txt', filename=attachment)
        # filename is the name of the display attachment
        mime.add_header('Content-Disposition', 'attachment', filename=attachment)
        # Get attachment content
        mime.set_payload(f.read())
        encoders.encode_base64(mime)
        # Added to mail as an attachment
        msg.attach(mime)
    try:
        s = smtplib.SMTP()
        s.connect(smtp_server, "25")
        s.login(from_mail, mail_pass)
        s.sendmail(from_mail, to_mail, msg.as_string())  # as_string() turns MIMEText objects into str
        s.quit()
    except smtplib.SMTPException as e:
        print "Error: %s" % e
if __name__ == "__main__":
    sendMail('Attached is the test data., Enclosed please find!', 'test.txt')

3 Python Sends HTML Mail

#!/usr/bin/python
# -*- coding: utf-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.utils import parseaddr, formataddr
# Format mail address
def formatAddr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))
def sendMail(body):
    smtp_server = 'smtp.163.com'
    from_mail = 'baojingtongzhi@163.com'
    mail_pass = 'xxx'
    to_mail = ['962510244@qq.com', 'zhenliang369@163.com']
    # Construct a MIME Multipart object to represent the mail itself
    msg = MIMEMultipart() 
    # Header Transcoding Chinese
    msg['From'] = formatAddr('Administrators <%s>' % from_mail).encode()
    msg['To'] = ','.join(to_mail)
    msg['Subject'] = Header('Monitor', 'utf-8').encode()
    msg.attach(MIMEText(body, 'html', 'utf-8'))
    try:
        s = smtplib.SMTP()     
        s.connect(smtp_server, "25")   
        s.login(from_mail, mail_pass)
        s.sendmail(from_mail, to_mail, msg.as_string())  # as_string() turns MIMEText objects into str     
        s.quit()
    except smtplib.SMTPException as e:
        print "Error: %s" % e
if __name__ == "__main__":
    body = """
    <h1>Test mail</h1>
    <h2 style="color:red">This is a test</h1>
    """
    sendMail(body)

4 Python Sends Picture Mail

#!/usr/bin/python
# -*- coding: utf-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.utils import parseaddr, formataddr
# Format mail address
def formatAddr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))
def sendMail(body, image):
    smtp_server = 'smtp.163.com'
    from_mail = 'baojingtongzhi@163.com'
    mail_pass = 'xxx'
    to_mail = ['962510244@qq.com', 'zhenliang369@163.com']
    # Construct a MIME Multipart object to represent the mail itself
    msg = MIMEMultipart() 
    # Header Transcoding Chinese
    msg['From'] = formatAddr('Administrators <%s>' % from_mail).encode()
    msg['To'] = ','.join(to_mail)
    msg['Subject'] = Header('Monitor', 'utf-8').encode()
    msg.attach(MIMEText(body, 'html', 'utf-8'))
    # Read pictures in binary mode
    with open(image, 'rb') as f:
        msgImage = MIMEImage(f.read())
    # Define picture ID
    msgImage.add_header('Content-ID', '<image1>')
    msg.attach(msgImage)
    try:
        s = smtplib.SMTP()     
        s.connect(smtp_server, "25")   
        s.login(from_mail, mail_pass)
        s.sendmail(from_mail, to_mail, msg.as_string())  # as_string() turns MIMEText objects into str     
        s.quit()
    except smtplib.SMTPException as e:
        print "Error: %s" % e
if __name__ == "__main__":
    body = """
    <h1>Test picture</h1>
    <img src="cid:image1"/>    # Quote pictures
    """
    sendMail(body, 'test.png')

Several common methods of sending email above basically meet the daily needs.



Posted by meandrew on Wed, 10 Apr 2019 15:12:32 -0700