Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
bbe323e5
Commit
bbe323e5
authored
Jan 29, 1998
by
Guido van Rossum
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
SMTP client by The Dragon De Monsyne <dragondm@integral.org>.
parent
02505e48
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
278 additions
and
0 deletions
+278
-0
Lib/smtplib.py
Lib/smtplib.py
+278
-0
No files found.
Lib/smtplib.py
0 → 100755
View file @
bbe323e5
"""SMTP Client class.
Author: The Dragon De Monsyne <dragondm@integral.org>
(This was modified from the Python 1.5 library HTTP lib.)
This should follow RFC 821. (it dosen't do esmtp (yet))
Example:
>>> import smtplib
>>> s=smtplib.SMTP("localhost")
>>> print s.help()
This is Sendmail version 8.8.4
Topics:
HELO EHLO MAIL RCPT DATA
RSET NOOP QUIT HELP VRFY
EXPN VERB ETRN DSN
For more info use "HELP <topic>".
To report bugs in the implementation send email to
sendmail-bugs@sendmail.org.
For local information send email to Postmaster at your site.
End of HELP info
>>> s.putcmd("vrfy","someone@here")
>>> s.getreply()
(250, "Somebody OverHere <somebody@here.my.org>")
>>> s.quit()
"""
import
socket
import
string
,
re
SMTP_PORT
=
25
CRLF
=
"
\
r
\
n
"
# used for exceptions
SMTPSenderRefused
=
"Sender address refused"
SMTPRecipientsRefused
=
"All Recipients refused"
SMTPDataError
=
"Error transmoitting message data"
class
SMTP
:
"""This class manages a connection to an SMTP server."""
def
__init__
(
self
,
host
=
''
,
port
=
0
):
"""Initialize a new instance.
If specified, `host' is the name of the remote host to which
to connect. If specified, `port' specifies the port to which
to connect. By default, smtplib.SMTP_PORT is used.
"""
self
.
debuglevel
=
0
self
.
file
=
None
self
.
helo_resp
=
None
if
host
:
self
.
connect
(
host
,
port
)
def
set_debuglevel
(
self
,
debuglevel
):
"""Set the debug output level.
A non-false value results in debug messages for connection and
for all messages sent to and received from the server.
"""
self
.
debuglevel
=
debuglevel
def
connect
(
self
,
host
=
'localhost'
,
port
=
0
):
"""Connect to a host on a given port.
Note: This method is automatically invoked by __init__,
if a host is specified during instantiation.
"""
if
not
port
:
i
=
string
.
find
(
host
,
':'
)
if
i
>=
0
:
host
,
port
=
host
[:
i
],
host
[
i
+
1
:]
try
:
port
=
string
.
atoi
(
port
)
except
string
.
atoi_error
:
raise
socket
.
error
,
"nonnumeric port"
if
not
port
:
port
=
SMTP_PORT
self
.
sock
=
socket
.
socket
(
socket
.
AF_INET
,
socket
.
SOCK_STREAM
)
if
self
.
debuglevel
>
0
:
print
'connect:'
,
(
host
,
port
)
self
.
sock
.
connect
(
host
,
port
)
(
code
,
msg
)
=
self
.
getreply
()
if
self
.
debuglevel
>
0
:
print
"connect:"
,
msg
return
msg
def
send
(
self
,
str
):
"""Send `str' to the server."""
if
self
.
debuglevel
>
0
:
print
'send:'
,
`str`
self
.
sock
.
send
(
str
)
def
putcmd
(
self
,
cmd
,
args
=
""
):
"""Send a command to the server.
"""
str
=
'%s %s%s'
%
(
cmd
,
args
,
CRLF
)
self
.
send
(
str
)
def
getreply
(
self
):
"""Get a reply from the server.
Returns a tuple consisting of:
- server response code (e.g. '250', or such, if all goes well)
Note: returns -1 if it can't read responce code.
- server response string corresponding to response code
(note : multiline responces converted to a single, multiline
string)
"""
resp
=
[]
self
.
file
=
self
.
sock
.
makefile
(
'rb'
)
while
1
:
line
=
self
.
file
.
readline
()
if
self
.
debuglevel
>
0
:
print
'reply:'
,
`line`
resp
.
append
(
string
.
strip
(
line
[
4
:]))
code
=
line
[:
3
]
#check if multiline resp
if
line
[
3
:
4
]
!=
"-"
:
break
try
:
errcode
=
string
.
atoi
(
code
)
except
(
ValueError
):
errcode
=
-
1
errmsg
=
string
.
join
(
resp
,
"
\
n
"
)
if
self
.
debuglevel
>
0
:
print
'reply: retcode (%s); Msg: %s'
%
(
errcode
,
errmsg
)
return
errcode
,
errmsg
def
docmd
(
self
,
cmd
,
args
=
""
):
""" Send a command, and return it's responce code """
self
.
putcmd
(
cmd
,
args
)
(
code
,
msg
)
=
self
.
getreply
()
return
code
# std smtp commands
def
helo
(
self
,
name
=
''
):
""" SMTP 'helo' command. Hostname to send for this command
defaults to the FQDN of the local host """
name
=
string
.
strip
(
name
)
if
len
(
name
)
==
0
:
name
=
socket
.
gethostbyaddr
(
socket
.
gethostname
())[
0
]
self
.
putcmd
(
"helo"
,
name
)
(
code
,
msg
)
=
self
.
getreply
()
self
.
helo_resp
=
msg
return
code
def
help
(
self
):
""" SMTP 'help' command. Returns help text from server """
self
.
putcmd
(
"help"
)
(
code
,
msg
)
=
self
.
getreply
()
return
msg
def
rset
(
self
):
""" SMTP 'rset' command. Resets session. """
code
=
self
.
docmd
(
"rset"
)
return
code
def
noop
(
self
):
""" SMTP 'noop' command. Dosen't do anything :> """
code
=
self
.
docmd
(
"noop"
)
return
code
def
mail
(
self
,
sender
):
""" SMTP 'mail' command. Begins mail xfer session. """
self
.
putcmd
(
"mail"
,
"from: %s"
%
sender
)
return
self
.
getreply
()
def
rcpt
(
self
,
recip
):
""" SMTP 'rcpt' command. Indicates 1 recipient for this mail. """
self
.
putcmd
(
"rcpt"
,
"to: %s"
%
recip
)
return
self
.
getreply
()
def
data
(
self
,
msg
):
""" SMTP 'DATA' command. Sends message data to server.
Automatically quotes lines beginning with a period per rfc821 """
#quote periods in msg according to RFC821
# ps, I don't know why I have to do it this way... doing:
# quotepat=re.compile(r"^[.]",re.M)
# msg=re.sub(quotepat,"..",msg)
# should work, but it dosen't (it doubles the number of any
# contiguous series of .'s at the beginning of a line,
# instead of just adding one. )
quotepat
=
re
.
compile
(
r"^[.]+"
,
re
.
M
)
def
m
(
pat
):
return
"."
+
pat
.
group
(
0
)
msg
=
re
.
sub
(
quotepat
,
m
,
msg
)
self
.
putcmd
(
"data"
)
(
code
,
repl
)
=
self
.
getreply
()
if
self
.
debuglevel
>
0
:
print
"data:"
,
(
code
,
repl
)
if
code
<>
354
:
return
-
1
else
:
self
.
send
(
msg
)
self
.
send
(
"
\
n
.
\
n
"
)
(
code
,
msg
)
=
self
.
getreply
()
if
self
.
debuglevel
>
0
:
print
"data:"
,
(
code
,
msg
)
return
code
#some usefull methods
def
sendmail
(
self
,
from_addr
,
to_addrs
,
msg
):
""" This command performs an entire mail transaction.
The arguments are:
- from_addr : The address sending this mail.
- to_addrs : a list of addresses to send this mail to
- msg : the message to send.
This method will return normally if the mail is accepted for at
least one recipiant .Otherwise it will throw an exception (either
SMTPSenderRefused,SMTPRecipientsRefused, or SMTPDataError)
That is, if this method does not throw an excception, then someone
should get your mail.
It returns a dictionary , with one entry for each recipient that
was refused.
example:
>>> 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()
In the above example, the message was accepted for delivery to three
of the four addresses, and one was rejected, with the error code 550.
If all addresses are accepted, then the method will return an
empty dictionary.
"""
if
not
self
.
helo_resp
:
self
.
helo
()
(
code
,
resp
)
=
self
.
mail
(
from_addr
)
if
code
<>
250
:
self
.
rset
()
raise
SMTPSenderRefused
senderrs
=
{}
for
each
in
to_addrs
:
(
code
,
resp
)
=
self
.
rcpt
(
each
)
if
(
code
<>
250
)
and
(
code
<>
251
):
senderr
[
each
]
=
(
code
,
resp
)
if
len
(
senderrs
)
==
len
(
to_addrs
):
#th' server refused all our recipients
self
.
rset
()
raise
SMTPRecipientsRefused
code
=
self
.
data
(
msg
)
if
code
<>
250
:
self
.
rset
()
raise
SMTPDataError
#if we got here then somebody got our mail
return
senderrs
def
close
(
self
):
"""Close the connection to the SMTP server."""
if
self
.
file
:
self
.
file
.
close
()
self
.
file
=
None
if
self
.
sock
:
self
.
sock
.
close
()
self
.
sock
=
None
def
quit
(
self
):
self
.
docmd
(
"quit"
)
self
.
close
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment