Edit File by line
/home/barbar84/public_h.../wp-conte.../plugins/sujqvwi/ShExBy/shex_roo.../lib64/python3....
File: smtpd.py
#! /usr/libexec/platform-python
[0] Fix | Delete
"""An RFC 5321 smtp proxy with optional RFC 1870 and RFC 6531 extensions.
[1] Fix | Delete
[2] Fix | Delete
Usage: %(program)s [options] [localhost:localport [remotehost:remoteport]]
[3] Fix | Delete
[4] Fix | Delete
Options:
[5] Fix | Delete
[6] Fix | Delete
--nosetuid
[7] Fix | Delete
-n
[8] Fix | Delete
This program generally tries to setuid `nobody', unless this flag is
[9] Fix | Delete
set. The setuid call will fail if this program is not run as root (in
[10] Fix | Delete
which case, use this flag).
[11] Fix | Delete
[12] Fix | Delete
--version
[13] Fix | Delete
-V
[14] Fix | Delete
Print the version number and exit.
[15] Fix | Delete
[16] Fix | Delete
--class classname
[17] Fix | Delete
-c classname
[18] Fix | Delete
Use `classname' as the concrete SMTP proxy class. Uses `PureProxy' by
[19] Fix | Delete
default.
[20] Fix | Delete
[21] Fix | Delete
--size limit
[22] Fix | Delete
-s limit
[23] Fix | Delete
Restrict the total size of the incoming message to "limit" number of
[24] Fix | Delete
bytes via the RFC 1870 SIZE extension. Defaults to 33554432 bytes.
[25] Fix | Delete
[26] Fix | Delete
--smtputf8
[27] Fix | Delete
-u
[28] Fix | Delete
Enable the SMTPUTF8 extension and behave as an RFC 6531 smtp proxy.
[29] Fix | Delete
[30] Fix | Delete
--debug
[31] Fix | Delete
-d
[32] Fix | Delete
Turn on debugging prints.
[33] Fix | Delete
[34] Fix | Delete
--help
[35] Fix | Delete
-h
[36] Fix | Delete
Print this message and exit.
[37] Fix | Delete
[38] Fix | Delete
Version: %(__version__)s
[39] Fix | Delete
[40] Fix | Delete
If localhost is not given then `localhost' is used, and if localport is not
[41] Fix | Delete
given then 8025 is used. If remotehost is not given then `localhost' is used,
[42] Fix | Delete
and if remoteport is not given, then 25 is used.
[43] Fix | Delete
"""
[44] Fix | Delete
[45] Fix | Delete
# Overview:
[46] Fix | Delete
#
[47] Fix | Delete
# This file implements the minimal SMTP protocol as defined in RFC 5321. It
[48] Fix | Delete
# has a hierarchy of classes which implement the backend functionality for the
[49] Fix | Delete
# smtpd. A number of classes are provided:
[50] Fix | Delete
#
[51] Fix | Delete
# SMTPServer - the base class for the backend. Raises NotImplementedError
[52] Fix | Delete
# if you try to use it.
[53] Fix | Delete
#
[54] Fix | Delete
# DebuggingServer - simply prints each message it receives on stdout.
[55] Fix | Delete
#
[56] Fix | Delete
# PureProxy - Proxies all messages to a real smtpd which does final
[57] Fix | Delete
# delivery. One known problem with this class is that it doesn't handle
[58] Fix | Delete
# SMTP errors from the backend server at all. This should be fixed
[59] Fix | Delete
# (contributions are welcome!).
[60] Fix | Delete
#
[61] Fix | Delete
# MailmanProxy - An experimental hack to work with GNU Mailman
[62] Fix | Delete
# <www.list.org>. Using this server as your real incoming smtpd, your
[63] Fix | Delete
# mailhost will automatically recognize and accept mail destined to Mailman
[64] Fix | Delete
# lists when those lists are created. Every message not destined for a list
[65] Fix | Delete
# gets forwarded to a real backend smtpd, as with PureProxy. Again, errors
[66] Fix | Delete
# are not handled correctly yet.
[67] Fix | Delete
#
[68] Fix | Delete
#
[69] Fix | Delete
# Author: Barry Warsaw <barry@python.org>
[70] Fix | Delete
#
[71] Fix | Delete
# TODO:
[72] Fix | Delete
#
[73] Fix | Delete
# - support mailbox delivery
[74] Fix | Delete
# - alias files
[75] Fix | Delete
# - Handle more ESMTP extensions
[76] Fix | Delete
# - handle error codes from the backend smtpd
[77] Fix | Delete
[78] Fix | Delete
import sys
[79] Fix | Delete
import os
[80] Fix | Delete
import errno
[81] Fix | Delete
import getopt
[82] Fix | Delete
import time
[83] Fix | Delete
import socket
[84] Fix | Delete
import asyncore
[85] Fix | Delete
import asynchat
[86] Fix | Delete
import collections
[87] Fix | Delete
from warnings import warn
[88] Fix | Delete
from email._header_value_parser import get_addr_spec, get_angle_addr
[89] Fix | Delete
[90] Fix | Delete
__all__ = [
[91] Fix | Delete
"SMTPChannel", "SMTPServer", "DebuggingServer", "PureProxy",
[92] Fix | Delete
"MailmanProxy",
[93] Fix | Delete
]
[94] Fix | Delete
[95] Fix | Delete
program = sys.argv[0]
[96] Fix | Delete
__version__ = 'Python SMTP proxy version 0.3'
[97] Fix | Delete
[98] Fix | Delete
[99] Fix | Delete
class Devnull:
[100] Fix | Delete
def write(self, msg): pass
[101] Fix | Delete
def flush(self): pass
[102] Fix | Delete
[103] Fix | Delete
[104] Fix | Delete
DEBUGSTREAM = Devnull()
[105] Fix | Delete
NEWLINE = '\n'
[106] Fix | Delete
COMMASPACE = ', '
[107] Fix | Delete
DATA_SIZE_DEFAULT = 33554432
[108] Fix | Delete
[109] Fix | Delete
[110] Fix | Delete
def usage(code, msg=''):
[111] Fix | Delete
print(__doc__ % globals(), file=sys.stderr)
[112] Fix | Delete
if msg:
[113] Fix | Delete
print(msg, file=sys.stderr)
[114] Fix | Delete
sys.exit(code)
[115] Fix | Delete
[116] Fix | Delete
[117] Fix | Delete
class SMTPChannel(asynchat.async_chat):
[118] Fix | Delete
COMMAND = 0
[119] Fix | Delete
DATA = 1
[120] Fix | Delete
[121] Fix | Delete
command_size_limit = 512
[122] Fix | Delete
command_size_limits = collections.defaultdict(lambda x=command_size_limit: x)
[123] Fix | Delete
[124] Fix | Delete
@property
[125] Fix | Delete
def max_command_size_limit(self):
[126] Fix | Delete
try:
[127] Fix | Delete
return max(self.command_size_limits.values())
[128] Fix | Delete
except ValueError:
[129] Fix | Delete
return self.command_size_limit
[130] Fix | Delete
[131] Fix | Delete
def __init__(self, server, conn, addr, data_size_limit=DATA_SIZE_DEFAULT,
[132] Fix | Delete
map=None, enable_SMTPUTF8=False, decode_data=False):
[133] Fix | Delete
asynchat.async_chat.__init__(self, conn, map=map)
[134] Fix | Delete
self.smtp_server = server
[135] Fix | Delete
self.conn = conn
[136] Fix | Delete
self.addr = addr
[137] Fix | Delete
self.data_size_limit = data_size_limit
[138] Fix | Delete
self.enable_SMTPUTF8 = enable_SMTPUTF8
[139] Fix | Delete
self._decode_data = decode_data
[140] Fix | Delete
if enable_SMTPUTF8 and decode_data:
[141] Fix | Delete
raise ValueError("decode_data and enable_SMTPUTF8 cannot"
[142] Fix | Delete
" be set to True at the same time")
[143] Fix | Delete
if decode_data:
[144] Fix | Delete
self._emptystring = ''
[145] Fix | Delete
self._linesep = '\r\n'
[146] Fix | Delete
self._dotsep = '.'
[147] Fix | Delete
self._newline = NEWLINE
[148] Fix | Delete
else:
[149] Fix | Delete
self._emptystring = b''
[150] Fix | Delete
self._linesep = b'\r\n'
[151] Fix | Delete
self._dotsep = ord(b'.')
[152] Fix | Delete
self._newline = b'\n'
[153] Fix | Delete
self._set_rset_state()
[154] Fix | Delete
self.seen_greeting = ''
[155] Fix | Delete
self.extended_smtp = False
[156] Fix | Delete
self.command_size_limits.clear()
[157] Fix | Delete
self.fqdn = socket.getfqdn()
[158] Fix | Delete
try:
[159] Fix | Delete
self.peer = conn.getpeername()
[160] Fix | Delete
except OSError as err:
[161] Fix | Delete
# a race condition may occur if the other end is closing
[162] Fix | Delete
# before we can get the peername
[163] Fix | Delete
self.close()
[164] Fix | Delete
if err.args[0] != errno.ENOTCONN:
[165] Fix | Delete
raise
[166] Fix | Delete
return
[167] Fix | Delete
print('Peer:', repr(self.peer), file=DEBUGSTREAM)
[168] Fix | Delete
self.push('220 %s %s' % (self.fqdn, __version__))
[169] Fix | Delete
[170] Fix | Delete
def _set_post_data_state(self):
[171] Fix | Delete
"""Reset state variables to their post-DATA state."""
[172] Fix | Delete
self.smtp_state = self.COMMAND
[173] Fix | Delete
self.mailfrom = None
[174] Fix | Delete
self.rcpttos = []
[175] Fix | Delete
self.require_SMTPUTF8 = False
[176] Fix | Delete
self.num_bytes = 0
[177] Fix | Delete
self.set_terminator(b'\r\n')
[178] Fix | Delete
[179] Fix | Delete
def _set_rset_state(self):
[180] Fix | Delete
"""Reset all state variables except the greeting."""
[181] Fix | Delete
self._set_post_data_state()
[182] Fix | Delete
self.received_data = ''
[183] Fix | Delete
self.received_lines = []
[184] Fix | Delete
[185] Fix | Delete
[186] Fix | Delete
# properties for backwards-compatibility
[187] Fix | Delete
@property
[188] Fix | Delete
def __server(self):
[189] Fix | Delete
warn("Access to __server attribute on SMTPChannel is deprecated, "
[190] Fix | Delete
"use 'smtp_server' instead", DeprecationWarning, 2)
[191] Fix | Delete
return self.smtp_server
[192] Fix | Delete
@__server.setter
[193] Fix | Delete
def __server(self, value):
[194] Fix | Delete
warn("Setting __server attribute on SMTPChannel is deprecated, "
[195] Fix | Delete
"set 'smtp_server' instead", DeprecationWarning, 2)
[196] Fix | Delete
self.smtp_server = value
[197] Fix | Delete
[198] Fix | Delete
@property
[199] Fix | Delete
def __line(self):
[200] Fix | Delete
warn("Access to __line attribute on SMTPChannel is deprecated, "
[201] Fix | Delete
"use 'received_lines' instead", DeprecationWarning, 2)
[202] Fix | Delete
return self.received_lines
[203] Fix | Delete
@__line.setter
[204] Fix | Delete
def __line(self, value):
[205] Fix | Delete
warn("Setting __line attribute on SMTPChannel is deprecated, "
[206] Fix | Delete
"set 'received_lines' instead", DeprecationWarning, 2)
[207] Fix | Delete
self.received_lines = value
[208] Fix | Delete
[209] Fix | Delete
@property
[210] Fix | Delete
def __state(self):
[211] Fix | Delete
warn("Access to __state attribute on SMTPChannel is deprecated, "
[212] Fix | Delete
"use 'smtp_state' instead", DeprecationWarning, 2)
[213] Fix | Delete
return self.smtp_state
[214] Fix | Delete
@__state.setter
[215] Fix | Delete
def __state(self, value):
[216] Fix | Delete
warn("Setting __state attribute on SMTPChannel is deprecated, "
[217] Fix | Delete
"set 'smtp_state' instead", DeprecationWarning, 2)
[218] Fix | Delete
self.smtp_state = value
[219] Fix | Delete
[220] Fix | Delete
@property
[221] Fix | Delete
def __greeting(self):
[222] Fix | Delete
warn("Access to __greeting attribute on SMTPChannel is deprecated, "
[223] Fix | Delete
"use 'seen_greeting' instead", DeprecationWarning, 2)
[224] Fix | Delete
return self.seen_greeting
[225] Fix | Delete
@__greeting.setter
[226] Fix | Delete
def __greeting(self, value):
[227] Fix | Delete
warn("Setting __greeting attribute on SMTPChannel is deprecated, "
[228] Fix | Delete
"set 'seen_greeting' instead", DeprecationWarning, 2)
[229] Fix | Delete
self.seen_greeting = value
[230] Fix | Delete
[231] Fix | Delete
@property
[232] Fix | Delete
def __mailfrom(self):
[233] Fix | Delete
warn("Access to __mailfrom attribute on SMTPChannel is deprecated, "
[234] Fix | Delete
"use 'mailfrom' instead", DeprecationWarning, 2)
[235] Fix | Delete
return self.mailfrom
[236] Fix | Delete
@__mailfrom.setter
[237] Fix | Delete
def __mailfrom(self, value):
[238] Fix | Delete
warn("Setting __mailfrom attribute on SMTPChannel is deprecated, "
[239] Fix | Delete
"set 'mailfrom' instead", DeprecationWarning, 2)
[240] Fix | Delete
self.mailfrom = value
[241] Fix | Delete
[242] Fix | Delete
@property
[243] Fix | Delete
def __rcpttos(self):
[244] Fix | Delete
warn("Access to __rcpttos attribute on SMTPChannel is deprecated, "
[245] Fix | Delete
"use 'rcpttos' instead", DeprecationWarning, 2)
[246] Fix | Delete
return self.rcpttos
[247] Fix | Delete
@__rcpttos.setter
[248] Fix | Delete
def __rcpttos(self, value):
[249] Fix | Delete
warn("Setting __rcpttos attribute on SMTPChannel is deprecated, "
[250] Fix | Delete
"set 'rcpttos' instead", DeprecationWarning, 2)
[251] Fix | Delete
self.rcpttos = value
[252] Fix | Delete
[253] Fix | Delete
@property
[254] Fix | Delete
def __data(self):
[255] Fix | Delete
warn("Access to __data attribute on SMTPChannel is deprecated, "
[256] Fix | Delete
"use 'received_data' instead", DeprecationWarning, 2)
[257] Fix | Delete
return self.received_data
[258] Fix | Delete
@__data.setter
[259] Fix | Delete
def __data(self, value):
[260] Fix | Delete
warn("Setting __data attribute on SMTPChannel is deprecated, "
[261] Fix | Delete
"set 'received_data' instead", DeprecationWarning, 2)
[262] Fix | Delete
self.received_data = value
[263] Fix | Delete
[264] Fix | Delete
@property
[265] Fix | Delete
def __fqdn(self):
[266] Fix | Delete
warn("Access to __fqdn attribute on SMTPChannel is deprecated, "
[267] Fix | Delete
"use 'fqdn' instead", DeprecationWarning, 2)
[268] Fix | Delete
return self.fqdn
[269] Fix | Delete
@__fqdn.setter
[270] Fix | Delete
def __fqdn(self, value):
[271] Fix | Delete
warn("Setting __fqdn attribute on SMTPChannel is deprecated, "
[272] Fix | Delete
"set 'fqdn' instead", DeprecationWarning, 2)
[273] Fix | Delete
self.fqdn = value
[274] Fix | Delete
[275] Fix | Delete
@property
[276] Fix | Delete
def __peer(self):
[277] Fix | Delete
warn("Access to __peer attribute on SMTPChannel is deprecated, "
[278] Fix | Delete
"use 'peer' instead", DeprecationWarning, 2)
[279] Fix | Delete
return self.peer
[280] Fix | Delete
@__peer.setter
[281] Fix | Delete
def __peer(self, value):
[282] Fix | Delete
warn("Setting __peer attribute on SMTPChannel is deprecated, "
[283] Fix | Delete
"set 'peer' instead", DeprecationWarning, 2)
[284] Fix | Delete
self.peer = value
[285] Fix | Delete
[286] Fix | Delete
@property
[287] Fix | Delete
def __conn(self):
[288] Fix | Delete
warn("Access to __conn attribute on SMTPChannel is deprecated, "
[289] Fix | Delete
"use 'conn' instead", DeprecationWarning, 2)
[290] Fix | Delete
return self.conn
[291] Fix | Delete
@__conn.setter
[292] Fix | Delete
def __conn(self, value):
[293] Fix | Delete
warn("Setting __conn attribute on SMTPChannel is deprecated, "
[294] Fix | Delete
"set 'conn' instead", DeprecationWarning, 2)
[295] Fix | Delete
self.conn = value
[296] Fix | Delete
[297] Fix | Delete
@property
[298] Fix | Delete
def __addr(self):
[299] Fix | Delete
warn("Access to __addr attribute on SMTPChannel is deprecated, "
[300] Fix | Delete
"use 'addr' instead", DeprecationWarning, 2)
[301] Fix | Delete
return self.addr
[302] Fix | Delete
@__addr.setter
[303] Fix | Delete
def __addr(self, value):
[304] Fix | Delete
warn("Setting __addr attribute on SMTPChannel is deprecated, "
[305] Fix | Delete
"set 'addr' instead", DeprecationWarning, 2)
[306] Fix | Delete
self.addr = value
[307] Fix | Delete
[308] Fix | Delete
# Overrides base class for convenience.
[309] Fix | Delete
def push(self, msg):
[310] Fix | Delete
asynchat.async_chat.push(self, bytes(
[311] Fix | Delete
msg + '\r\n', 'utf-8' if self.require_SMTPUTF8 else 'ascii'))
[312] Fix | Delete
[313] Fix | Delete
# Implementation of base class abstract method
[314] Fix | Delete
def collect_incoming_data(self, data):
[315] Fix | Delete
limit = None
[316] Fix | Delete
if self.smtp_state == self.COMMAND:
[317] Fix | Delete
limit = self.max_command_size_limit
[318] Fix | Delete
elif self.smtp_state == self.DATA:
[319] Fix | Delete
limit = self.data_size_limit
[320] Fix | Delete
if limit and self.num_bytes > limit:
[321] Fix | Delete
return
[322] Fix | Delete
elif limit:
[323] Fix | Delete
self.num_bytes += len(data)
[324] Fix | Delete
if self._decode_data:
[325] Fix | Delete
self.received_lines.append(str(data, 'utf-8'))
[326] Fix | Delete
else:
[327] Fix | Delete
self.received_lines.append(data)
[328] Fix | Delete
[329] Fix | Delete
# Implementation of base class abstract method
[330] Fix | Delete
def found_terminator(self):
[331] Fix | Delete
line = self._emptystring.join(self.received_lines)
[332] Fix | Delete
print('Data:', repr(line), file=DEBUGSTREAM)
[333] Fix | Delete
self.received_lines = []
[334] Fix | Delete
if self.smtp_state == self.COMMAND:
[335] Fix | Delete
sz, self.num_bytes = self.num_bytes, 0
[336] Fix | Delete
if not line:
[337] Fix | Delete
self.push('500 Error: bad syntax')
[338] Fix | Delete
return
[339] Fix | Delete
if not self._decode_data:
[340] Fix | Delete
line = str(line, 'utf-8')
[341] Fix | Delete
i = line.find(' ')
[342] Fix | Delete
if i < 0:
[343] Fix | Delete
command = line.upper()
[344] Fix | Delete
arg = None
[345] Fix | Delete
else:
[346] Fix | Delete
command = line[:i].upper()
[347] Fix | Delete
arg = line[i+1:].strip()
[348] Fix | Delete
max_sz = (self.command_size_limits[command]
[349] Fix | Delete
if self.extended_smtp else self.command_size_limit)
[350] Fix | Delete
if sz > max_sz:
[351] Fix | Delete
self.push('500 Error: line too long')
[352] Fix | Delete
return
[353] Fix | Delete
method = getattr(self, 'smtp_' + command, None)
[354] Fix | Delete
if not method:
[355] Fix | Delete
self.push('500 Error: command "%s" not recognized' % command)
[356] Fix | Delete
return
[357] Fix | Delete
method(arg)
[358] Fix | Delete
return
[359] Fix | Delete
else:
[360] Fix | Delete
if self.smtp_state != self.DATA:
[361] Fix | Delete
self.push('451 Internal confusion')
[362] Fix | Delete
self.num_bytes = 0
[363] Fix | Delete
return
[364] Fix | Delete
if self.data_size_limit and self.num_bytes > self.data_size_limit:
[365] Fix | Delete
self.push('552 Error: Too much mail data')
[366] Fix | Delete
self.num_bytes = 0
[367] Fix | Delete
return
[368] Fix | Delete
# Remove extraneous carriage returns and de-transparency according
[369] Fix | Delete
# to RFC 5321, Section 4.5.2.
[370] Fix | Delete
data = []
[371] Fix | Delete
for text in line.split(self._linesep):
[372] Fix | Delete
if text and text[0] == self._dotsep:
[373] Fix | Delete
data.append(text[1:])
[374] Fix | Delete
else:
[375] Fix | Delete
data.append(text)
[376] Fix | Delete
self.received_data = self._newline.join(data)
[377] Fix | Delete
args = (self.peer, self.mailfrom, self.rcpttos, self.received_data)
[378] Fix | Delete
kwargs = {}
[379] Fix | Delete
if not self._decode_data:
[380] Fix | Delete
kwargs = {
[381] Fix | Delete
'mail_options': self.mail_options,
[382] Fix | Delete
'rcpt_options': self.rcpt_options,
[383] Fix | Delete
}
[384] Fix | Delete
status = self.smtp_server.process_message(*args, **kwargs)
[385] Fix | Delete
self._set_post_data_state()
[386] Fix | Delete
if not status:
[387] Fix | Delete
self.push('250 OK')
[388] Fix | Delete
else:
[389] Fix | Delete
self.push(status)
[390] Fix | Delete
[391] Fix | Delete
# SMTP and ESMTP commands
[392] Fix | Delete
def smtp_HELO(self, arg):
[393] Fix | Delete
if not arg:
[394] Fix | Delete
self.push('501 Syntax: HELO hostname')
[395] Fix | Delete
return
[396] Fix | Delete
# See issue #21783 for a discussion of this behavior.
[397] Fix | Delete
if self.seen_greeting:
[398] Fix | Delete
self.push('503 Duplicate HELO/EHLO')
[399] Fix | Delete
return
[400] Fix | Delete
self._set_rset_state()
[401] Fix | Delete
self.seen_greeting = arg
[402] Fix | Delete
self.push('250 %s' % self.fqdn)
[403] Fix | Delete
[404] Fix | Delete
def smtp_EHLO(self, arg):
[405] Fix | Delete
if not arg:
[406] Fix | Delete
self.push('501 Syntax: EHLO hostname')
[407] Fix | Delete
return
[408] Fix | Delete
# See issue #21783 for a discussion of this behavior.
[409] Fix | Delete
if self.seen_greeting:
[410] Fix | Delete
self.push('503 Duplicate HELO/EHLO')
[411] Fix | Delete
return
[412] Fix | Delete
self._set_rset_state()
[413] Fix | Delete
self.seen_greeting = arg
[414] Fix | Delete
self.extended_smtp = True
[415] Fix | Delete
self.push('250-%s' % self.fqdn)
[416] Fix | Delete
if self.data_size_limit:
[417] Fix | Delete
self.push('250-SIZE %s' % self.data_size_limit)
[418] Fix | Delete
self.command_size_limits['MAIL'] += 26
[419] Fix | Delete
if not self._decode_data:
[420] Fix | Delete
self.push('250-8BITMIME')
[421] Fix | Delete
if self.enable_SMTPUTF8:
[422] Fix | Delete
self.push('250-SMTPUTF8')
[423] Fix | Delete
self.command_size_limits['MAIL'] += 10
[424] Fix | Delete
self.push('250 HELP')
[425] Fix | Delete
[426] Fix | Delete
def smtp_NOOP(self, arg):
[427] Fix | Delete
if arg:
[428] Fix | Delete
self.push('501 Syntax: NOOP')
[429] Fix | Delete
else:
[430] Fix | Delete
self.push('250 OK')
[431] Fix | Delete
[432] Fix | Delete
def smtp_QUIT(self, arg):
[433] Fix | Delete
# args is ignored
[434] Fix | Delete
self.push('221 Bye')
[435] Fix | Delete
self.close_when_done()
[436] Fix | Delete
[437] Fix | Delete
def _strip_command_keyword(self, keyword, arg):
[438] Fix | Delete
keylen = len(keyword)
[439] Fix | Delete
if arg[:keylen].upper() == keyword:
[440] Fix | Delete
return arg[keylen:].strip()
[441] Fix | Delete
return ''
[442] Fix | Delete
[443] Fix | Delete
def _getaddr(self, arg):
[444] Fix | Delete
if not arg:
[445] Fix | Delete
return '', ''
[446] Fix | Delete
if arg.lstrip().startswith('<'):
[447] Fix | Delete
address, rest = get_angle_addr(arg)
[448] Fix | Delete
else:
[449] Fix | Delete
address, rest = get_addr_spec(arg)
[450] Fix | Delete
if not address:
[451] Fix | Delete
return address, rest
[452] Fix | Delete
return address.addr_spec, rest
[453] Fix | Delete
[454] Fix | Delete
def _getparams(self, params):
[455] Fix | Delete
# Return params as dictionary. Return None if not all parameters
[456] Fix | Delete
# appear to be syntactically valid according to RFC 1869.
[457] Fix | Delete
result = {}
[458] Fix | Delete
for param in params:
[459] Fix | Delete
param, eq, value = param.partition('=')
[460] Fix | Delete
if not param.isalnum() or eq and not value:
[461] Fix | Delete
return None
[462] Fix | Delete
result[param] = value if eq else True
[463] Fix | Delete
return result
[464] Fix | Delete
[465] Fix | Delete
def smtp_HELP(self, arg):
[466] Fix | Delete
if arg:
[467] Fix | Delete
extended = ' [SP <mail-parameters>]'
[468] Fix | Delete
lc_arg = arg.upper()
[469] Fix | Delete
if lc_arg == 'EHLO':
[470] Fix | Delete
self.push('250 Syntax: EHLO hostname')
[471] Fix | Delete
elif lc_arg == 'HELO':
[472] Fix | Delete
self.push('250 Syntax: HELO hostname')
[473] Fix | Delete
elif lc_arg == 'MAIL':
[474] Fix | Delete
msg = '250 Syntax: MAIL FROM: <address>'
[475] Fix | Delete
if self.extended_smtp:
[476] Fix | Delete
msg += extended
[477] Fix | Delete
self.push(msg)
[478] Fix | Delete
elif lc_arg == 'RCPT':
[479] Fix | Delete
msg = '250 Syntax: RCPT TO: <address>'
[480] Fix | Delete
if self.extended_smtp:
[481] Fix | Delete
msg += extended
[482] Fix | Delete
self.push(msg)
[483] Fix | Delete
elif lc_arg == 'DATA':
[484] Fix | Delete
self.push('250 Syntax: DATA')
[485] Fix | Delete
elif lc_arg == 'RSET':
[486] Fix | Delete
self.push('250 Syntax: RSET')
[487] Fix | Delete
elif lc_arg == 'NOOP':
[488] Fix | Delete
self.push('250 Syntax: NOOP')
[489] Fix | Delete
elif lc_arg == 'QUIT':
[490] Fix | Delete
self.push('250 Syntax: QUIT')
[491] Fix | Delete
elif lc_arg == 'VRFY':
[492] Fix | Delete
self.push('250 Syntax: VRFY <address>')
[493] Fix | Delete
else:
[494] Fix | Delete
self.push('501 Supported commands: EHLO HELO MAIL RCPT '
[495] Fix | Delete
'DATA RSET NOOP QUIT VRFY')
[496] Fix | Delete
else:
[497] Fix | Delete
self.push('250 Supported commands: EHLO HELO MAIL RCPT DATA '
[498] Fix | Delete
'RSET NOOP QUIT VRFY')
[499] Fix | Delete
12
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function