The python smtplib module sends SSL and TLS secure mail instances

smtplib of python provides a very convenient way to send E-mail. It simply encapsulates the smtp protocol.

The basic commands of the smtp protocol include:

HELO identifies the user to the server
MAIL initializes mail transfer mail from:
RCPT identifies a single mail recipient; Often followed by the MAIL command, there may be more than one rcpt to:
After a single or multiple RCPT commands, DATA indicates that all mail recipients have been identified and the data transfer has been initiated, ending with
VRFY is used to verify the existence of the specified user/mailbox; The server often disables this command for security reasons
EXPN validates the existence of a given mailbox list, and extending the mailbox list is often disabled
What commands does the HELP query server support
NOOP no operation, the server should respond OK
QUIT ends the session
RSET resets the session and the current transfer is cancelled
MAIL FROM specifies the sender address
RCPT TO specified recipient address

There are two ways to use smtp, one is direct mail delivery, that is, if you want to send email to the 163.com 163.com email server, then directly connect to the 163.com email server and send the message to the 163.com email server. The other one is a verified email. The process is, for example, if you want to send an email to email:.zzz@163.com, you don’t send it directly to 163.com. This means first connecting to sina.com’s smtp server, then authenticating, and then Posting the letter to sina.com before sending the letter to 163.com. sina.com will deliver the letter to 163.com.

The command flow of type 1 is basically like this:
1. helo
2. mail from
3. rcpt to
4. data
5. quit

However, the first mode of sending, rcpt to, is limited in that the recipient specified by rcpt to must exist on the server or it will not be received. First look at the code:


#-*- encoding: gb2312 -*-
import os, sys, string
import smtplib
#  Mail server address 
mailserver = "smtp.163.com"
# smtp In conversation mail from address 
from_addr = "asfgysg@zxsdf.com"
# smtp In conversation rcpt to address 
to_addr = "zhaoweikid@163.com"
#  letter 
msg = "test mail"
svr = smtplib.SMTP(mailserver)
#  Set to debug mode, that is, there will be output during the session 
svr.set_debuglevel(1)
# helo Command, docmd The method includes getting the return information from the other server 
svr.docmd("HELO server")
# mail from,  The sender of the message 
svr.docmd("MAIL FROM: <%s>" % from_addr)
# rcpt to,  Mail receiver 
svr.docmd("RCPT TO: <%s>" % to_addr)
# data Command to start sending data 
svr.docmd("DATA")
#  Send text data 
svr.send(msg)
#  Such as to  .  A mark that ends the text transmission , with send Sent, so use getreply Get the return information 
svr.send(" . ")
svr.getreply()
#  Send over, exit 
svr.quit()

 

Note that 163.com has an anti-spam function, and this method of mail delivery is not guaranteed to pass the detection of anti-spam system. So 1 is generally not recommended for individuals to send in this way.

  2 is a bit different:

1.ehlo
2.auth login
3.mail from
4.rcpt to
5.data
6.quit

Compared to the first one, there is one more authentication process, which is auth login.


#-*- encoding: gb2312 -*-
import os, sys, string
import smtplib
import base64
#  Mail server address 
mailserver = "smtp.163.com"
#  Mail username 
username = "xxxxxx@163.com"
#  password 
password = "xxxxxxx"
# smtp In conversation mail from address 
from_addr = "xxxxxx@163.com"
# smtp In conversation rcpt to address 
to_addr = "yyyyyy@163.com"
#  letter 
msg = "my test mail"
svr = smtplib.SMTP(mailserver)
#  Set to debug mode, that is, there will be output during the session 
svr.set_debuglevel(1)
# ehlo Command, docmd The method includes getting the return information from the other server 
svr.docmd("EHLO server")
# auth login  The command 
svr.docmd("AUTH LOGIN")
#  Send the username, yes base64 Coded. Used send Sent, so use getreply Get the return information 
svr.send(base64.encodestring(username))
svr.getreply()
#  Sending the password) 
svr.send(base64.encodestring(password))
svr.getreply()
# mail from,  The sender of the message 
svr.docmd("MAIL FROM: <%s>" % from_addr)
# rcpt to,  Mail receiver 
svr.docmd("RCPT TO: <%s>" % to_addr)
# data Command to start sending data 
svr.docmd("DATA")
#  Send text data 
svr.send(msg)
#  Such as to  .  A mark that ends the text transmission 
svr.send(" . ")
svr.getreply()
#  Send over, exit 
svr.quit()

What is mentioned above is the most common case, but what can’t be ignored is that many enterprise emails now support secure emails, that is, emails sent via SSL. How to send this? SMTP supports SSL secure mail in two ways. One is to open 1 465 port to receive ssl mail, and the other is to add 1 starttls command to the standard smtp port 25. 

Let’s see how the first one works:


#-*- encoding: gb2312 -*-
import os, sys, string, socket
import smtplib
class SMTP_SSL (smtplib.SMTP):
def __init__(self, host='', port=465, local_hostname=None, key=None, cert=None):
self.cert = cert
self.key = key
smtplib.SMTP.__init__(self, host, port, local_hostname)
def connect(self, host='localhost', port=465):
if not port and (host.find(':') == host.rfind(':')):
i = host.rfind(':')
if i >= 0:
host, port = host[:i], host[i+1:]
try: port = int(port)
except ValueError:
raise socket.error, "nonnumeric port"
if not port: port = 654
if self.debuglevel > 0: print>>stderr, 'connect:', (host, port)
msg = "getaddrinfo returns an empty list"
self.sock = None
for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
try:
self.sock = socket.socket(af, socktype, proto)
if self.debuglevel > 0: print>>stderr, 'connect:', (host, port)
self.sock.connect(sa)
#  Newly added creation ssl The connection 
sslobj = socket.ssl(self.sock, self.key, self.cert)
except socket.error, msg:
if self.debuglevel > 0: 
print>>stderr, 'connect fail:', (host, port)
if self.sock:
self.sock.close()
self.sock = None
continue
break
if not self.sock:
raise socket.error, msg
#  Set up the ssl
self.sock = smtplib.SSLFakeSocket(self.sock, sslobj)
self.file = smtplib.SSLFakeFile(sslobj);
(code, msg) = self.getreply()
if self.debuglevel > 0: print>>stderr, "connect:", msg
return (code, msg)
if __name__ == '__main__':
smtp = SMTP_SSL('192.168.2.10')
smtp.set_debuglevel(1)
smtp.sendmail("zzz@xxx.com", "zhaowei@zhaowei.com", "xxxxxxxxxxxxxxxxx")
smtp.quit()

 

Here I have derived the new SMTP_SSL class from the original smtplib.SMTP, which handles ssl connections. The 192.168.2.10 I tested here is my own test server.

The second is the new starttls command, which is very simple. smtplib has this method called smtplib.starttls (). Of course, not all mail systems support secure mail, this needs to be confirmed from the return value of ehlo, if there is starttls, then support. Compared to the second method of sending regular mail, it only needs to add 1 line of code:


#-*- encoding: gb2312 -*-
import os, sys, string
import smtplib
import base64
#  Mail server address 
mailserver = "smtp.163.com"
#  Mail username 
username = "xxxxxx@163.com"
#  password 
password = "xxxxxxx"
# smtp In conversation mail from address 
from_addr = "xxxxxx@163.com"
# smtp In conversation rcpt to address 
to_addr = "yyyyyy@163.com"
#  letter 
msg = "my test mail"
svr = smtplib.SMTP(mailserver)
#  Set to debug mode, that is, there will be output during the session 
svr.set_debuglevel(1)
# ehlo Command, docmd Methods include getting the return information from the other server, which will be included in the return value if secure mail is supported starttls prompt 
svr.docmd("EHLO server")
svr.starttls()  # <------  This line is the new support for secure mail code! 
# auth login  The command 
svr.docmd("AUTH LOGIN")
#  Send the username, yes base64 Coded. Used send Sent, so use getreply Get the return information 
svr.send(base64.encodestring(username))
svr.getreply()
#  Sending the password) 
svr.send(base64.encodestring(password))
svr.getreply()
# mail from,  The sender of the message 
svr.docmd("MAIL FROM: <%s>" % from_addr)
# rcpt to,  Mail receiver 
svr.docmd("RCPT TO: <%s>" % to_addr)
# data Command to start sending data 
svr.docmd("DATA")
#  Send text data 
svr.send(msg)
#  Such as to  .  A mark that ends the text transmission 
svr.send(" . ")
svr.getreply()
#  Send over, exit 
svr.quit()

Note: in order to facilitate the above code, I did not judge the return value. Strictly speaking, I should judge the code returned under 1. In smtp protocol, only the return code is 2xx or 3xx can continue the next step. 


原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/267020.html

(0)
上一篇 2022年6月14日 15:38
下一篇 2022年6月14日

相关推荐

发表回复

登录后才能评论