This article mainly introduces the example of SSLTLS secure mail sent by the pythonsmtplib module. This article describes two sending methods, for more information, see python's smtplib. It encapsulates the smtp protocol.
The basic commands for smtp protocol include:
HELO identifies a user to the server
MAIL initialize mail transmission MAIL from:
RCPT identifies a single email recipient. it is often behind the MAIL command and can have multiple rcpt:
After one or more RCPT commands, DATA indicates that all email recipients have been identified and DATA transmission is initialized to end.
VRFY is used to verify whether the specified user or email address exists. This command is often disabled by the server for security reasons.
EXPN verifies whether the specified mailbox list exists and expands the mailbox list.
HELP query commands supported by the server
No NOOP operation, the server should respond OK
QUIT end session
RSET resets the session and the current transmission is canceled.
Mail from specifies the sender address
Recipient address specified by RCPT
Generally, smtp session has two ways, one is direct mail delivery, that is to say, for example, you want to mail to the zzz@163.com, then directly connect to the 163.com mail server, the mail to the zzz@163.com; the other is the verification of the Mail, the process is, for example, you want to mail to the zzz@163.com, you do not directly cast to 163.com, but through their own in sina.com another mailbox to send. In this case, we need to first connect to the smtp server of sina.com, then authenticate it, and then send the mail to 163.com to sina.com. sina.com will help you send the mail to 163.com.
The command process in the first method is basically like this:
1. helo
2. mail from
3. rcpt
4. data
5. quit
However, the first sending method is generally restricted, that is, the email recipient specified by rcpt to must exist on this server, otherwise it will not be received. First look at the code:
The code is as follows:
#-*-Encoding: gb2312 -*-
Import OS, sys, string
Import smtplib
# Email server address
Mailserver = "smtp.163.com"
# Mail from address during smtp session
From_addr = "asfgysg@zxsdf.com"
# Rcpt to address during smtp session
To_addr = "zhaoweikid@163.com"
# Letter content
Msg = "test mail"
Svr = smtplib. SMTP (mailserver)
# Set it to debug mode, that is, there will be output information during the session
Svr. set_debuglevel (1)
# Helo command. the docmd method includes obtaining the response information of the other server.
Svr.doc md ("HELO server ")
# Mail from, mail sender
Svr.doc md ("mail from: <% s>" % from_addr)
# Rcpt to, email recipient
Svr.doc md ("rcpt to: <% s>" % to_addr)
# Data command to start sending data
Svr.doc md ("DATA ")
# Sending body data
Svr. send (msg)
# For example, if "." is used as the marker for sending the text and "send" is used, getreply is used to obtain the returned information.
Svr. send (".")
Svr. getreply ()
# End of sending and exit
Svr. quit ()
Note that 163.com has the anti-spam function. the above method may not be able to pass the anti-spam system detection. Therefore, it is generally not recommended for individuals to send such messages.
The second type is a bit different:
1. ehlo
2. auth login
3. mail from
4. rcpt
5. data
6. quit
Compared with the first one, there is an additional authentication process, namely the auth login process.
The code is as follows:
#-*-Encoding: gb2312 -*-
Import OS, sys, string
Import smtplib
Import base64
# Email server address
Mailserver = "smtp.163.com"
# Email user name
Username = "xxxxxx@163.com"
# Password
Password = "xxxxxxx"
# Mail from address during smtp session
From_addr = "xxxxxx@163.com"
# Rcpt to address during smtp session
To_addr = "yyyyyy@163.com"
# Letter content
Msg = "my test mail"
Svr = smtplib. SMTP (mailserver)
# Set it to debug mode, that is, there will be output information during the session
Svr. set_debuglevel (1)
# Ehlo command. the docmd method includes obtaining the information returned by the recipient's server.
Svr.doc md ("EHLO server ")
# Auth login command
Svr.doc md ("auth login ")
# Sending username, which is Base64-encoded and sent using send. Therefore, use getreply to obtain the returned information.
Svr. send (base64.encodestring (username ))
Svr. getreply ()
# Sending password
Svr. send (base64.encodestring (password ))
Svr. getreply ()
# Mail from, mail sender
Svr.doc md ("mail from: <% s>" % from_addr)
# Rcpt to, email recipient
Svr.doc md ("rcpt to: <% s>" % to_addr)
# Data command to start sending data
Svr.doc md ("DATA ")
# Sending body data
Svr. send (msg)
# For example, Mark with. as the end of text sending
Svr. send (".")
Svr. getreply ()
# End of sending and exit
Svr. quit ()
The above is the most common situation, but it cannot be ignored that many enterprise emails currently support secure mail, that is, emails sent through SSL. how can this problem be solved? SMTP supports SSL secure mail in two ways. the old one is to enable port 465 to receive ssl mail, another update method is to add a starttls command on the smtp of the standard port 25 to support it.
Let's take a look at the first method:
The code is as follows:
#-*-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)
Failed T 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 ssl connections
Sslobj = socket. ssl (self. sock, self. key, self. cert)
Failed T 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
# Setting 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 derived a new SMTP_SSL class from the original smtplib. SMTP, which is dedicated to handling ssl connections. The 192.168.2.10 I tested here is my own test server.
The second is the newly added starttls command. this method is very simple. it is called smtplib. starttls () in smtplib (). Of course, not all email systems support secure mail, which needs to be confirmed from the return value of ehlo. if starttls exists, it indicates support. Compared with the second method for sending a common mail, you only need to add a new line of code:
The code is as follows:
#-*-Encoding: gb2312 -*-
Import OS, sys, string
Import smtplib
Import base64
# Email server address
Mailserver = "smtp.163.com"
# Email user name
Username = "xxxxxx@163.com"
# Password
Password = "xxxxxxx"
# Mail from address during smtp session
From_addr = "xxxxxx@163.com"
# Rcpt to address during smtp session
To_addr = "yyyyyy@163.com"
# Letter content
Msg = "my test mail"
Svr = smtplib. SMTP (mailserver)
# Set it to debug mode, that is, there will be output information during the session
Svr. set_debuglevel (1)
# Ehlo command. the docmd method includes obtaining the information returned by the recipient's server. if secure mail is supported, a starttls prompt is returned.
Svr.doc md ("EHLO server ")
Svr. starttls () # <------ this line is the newly added code that supports secure mail!
# Auth login command
Svr.doc md ("auth login ")
# Sending username, which is Base64-encoded and sent using send. Therefore, use getreply to obtain the returned information.
Svr. send (base64.encodestring (username ))
Svr. getreply ()
# Sending password
Svr. send (base64.encodestring (password ))
Svr. getreply ()
# Mail from, mail sender
Svr.doc md ("mail from: <% s>" % from_addr)
# Rcpt to, email recipient
Svr.doc md ("rcpt to: <% s>" % to_addr)
# Data command to start sending data
Svr.doc md ("DATA ")
# Sending body data
Svr. send (msg)
# For example, Mark with. as the end of text sending
Svr. send (".")
Svr. getreply ()
# End of sending and exit
Svr. quit ()
Note: I did not judge the return value for the convenience of the above code. Strictly speaking, we should judge the returned Code. in smtp protocol, only 2xx or 3xx codes can be returned to continue the next step, errors occur when 4xx or 5xx is returned.