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.