Python's smtplib provides a convenient way to send emails. 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, there are two SMTP sessions, I
Mail direct 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;
Another is post-Verification mail. The process is, for example, if you want to send an email to the zzz@163.com, You don't directly cast it to 163.com, but through another one in Sina.com.
Email. In this way, 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
Send the email 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 Code :
#-*-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 is 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, sender
svr.doc MD ("mail from: <% S>" % from_addr)
# rcpt to, email recipient
svr.doc MD ("rcpt: <% S> "% to_addr)
# Data command to start sending data
svr.doc MD (" data ")
# Send body data
SVR. send (MSG)
# For example, use/R/n. /R/N is used as the end mark for sending the body. Therefore, getreply is used to obtain the returned information.
SVR. send ("/R/n. /R/N ")
SVR. getreply ()
# End of sending and exit
SVR. quit ()
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.
#-*-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 is output information during the session
SVR. set_debuglevel (1)
# EHLO command. The docmd method includes obtaining the response information of the other server.
svr.doc MD ("ehlo server ")
# auth login command
svr.doc MD ("auth login")
# username for sending, Which is base64-encoded and sent using send, therefore, getreply is used to obtain the returned information.
SVR. send (base64.encodestring (username)
SVR. getreply ()
# Send password
SVR. send (base64.encodestring (password)
SVR. getreply ()
# mail from, sender
svr.doc MD ("mail from: <% S>" % from_addr)
# rcpt, email Recipient
svr.doc MD ("rcpt to: <% S>" % to_addr)
# Data command to start sending data
svr.doc MD ("data ")
# Send body data
SVR. send (MSG)
# For example, use/R/n. /R/n indicates the End of message sending.
SVR. send ("/R/n. /R/N ")
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:
#-*-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 (). Compared with the second method for sending a common mail, you only need to add a new line of code:
#-*-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 in SMTP session
from_addr =" xxxxxx@163.com "
# rcpt to address in 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 ")
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, use/R/n./R/N as the end mark of the message sending.
SVR. Send ("/R/n./R/N ")
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.