我试图将SMTP服务器连接到域名
import socket()
import smtplib
import dns.resolver
getdomain = user_email.split('@')
check_domain = dns.resolver.query(getdomain[1], 'MX')
mxrecords=check_domain[0].exchange
host=socket.gethostname()
server=SMTP()
server.connect(mxrecords)
这会引发我的错误
if not port and (host.find(':') == host.rfind(':')):
AttributeError: 'Name' object has no attribute 'find'
但是当我将mxrecords更改为字符串时,它可以正常工作
mxrecords=str(check_domain[0].exchange)
任何人都可以解释为什么它接受字符串吗?
答案 0 :(得分:2)
来自https://docs.python.org/3/library/smtplib.html
您可以知道connect()
需要字符串参数host
。
SMTP实例封装了SMTP连接。它具有支持完整的SMTP和ESMTP操作的方法。如果给出了可选的主机和端口参数,则在初始化期间使用这些参数调用SMTP connect()方法。
connect()
可以点击然后重定向到链接,然后您可以看到:
SMTP.connect(host =' localhost',port = 0)
连接到给定端口上的主机。默认设置是连接到标准SMTP端口(25)的本地主机。如果主机名以冒号(':')结尾,后跟一个数字,则该后缀将被删除,并且该数字将被解释为要使用的端口号。如果在实例化期间指定了主机,则构造函数会自动调用此方法。返回服务器在其连接响应中发送的响应代码和消息的2元组。
在那里你可以知道param host='localhost'
默认是一个字符串。
修改强>
我检查了你的代码,
print(type(mxrecords))
打印
<class 'dns.name.Name'>
表示mxrecords
对象是dns.name.Name
对象,而不是字符串。
如果您点击connect
方法的源代码,您会发现host
应为字符串:
def connect(self, host='localhost', port=0, source_address=None):
"""Connect to a host on a given port.
If the hostname ends with a colon (`:') followed by a number, and
there is no port specified, that suffix will be stripped off and the
number interpreted as the port number to use.
Note: This method is automatically invoked by __init__, if a host is
specified during instantiation.
"""
if source_address:
self.source_address = source_address
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 OSError("nonnumeric port")
if not port:
port = self.default_port
if self.debuglevel > 0:
self._print_debug('connect:', (host, port))
self.sock = self._get_socket(host, port, self.timeout)
self.file = None
(code, msg) = self.getreply()
if self.debuglevel > 0:
self._print_debug('connect:', repr(msg))
return (code, msg)
在代码中,您可以找到与您的错误匹配的host.find(':') == host.rfind(':')
。
检查dns.name.Name
源代码,您会发现Name
类有to_text
方法:
def to_text(self, omit_final_dot=False):
"""Convert name to text format.
@param omit_final_dot: If True, don't emit the final dot (denoting the
root label) for absolute names. The default is False.
@rtype: string
"""
if len(self.labels) == 0:
return maybe_decode(b'@')
if len(self.labels) == 1 and self.labels[0] == b'':
return maybe_decode(b'.')
if omit_final_dot and self.is_absolute():
l = self.labels[:-1]
else:
l = self.labels
s = b'.'.join(map(_escapify, l))
return maybe_decode(s)
因此,您应该使用mxrecords.to_text()
来获取MX服务器名称。
答案 1 :(得分:1)
第三方dns.resolver
包返回的对象不是标准库smtplib
知道任何内容的类型(或类,如果有帮助)。
很多时候,当连接库API时,作为程序员的任务是从一个API作为输出返回的自定义表示转换为适合作为另一个API调用的输入的不同表示。
系统库需要特别注意这一点。如果smtplib
(或甚至socket
)了解您的特定解析器,则与其他解析器一起使用会更加困难。即使你的解析器也是Python标准库的一部分,这样的内部依赖会引入不受欢迎的僵化,内部耦合,以及可能的一些讨厌的内部版本问题。