【问题标题】:Python try / except issue with SMTPLibPython尝试/除了SMTPLib问题
【发布时间】:2015-01-25 21:14:13
【问题描述】:

我使用 Python 的 SMTPLib 编写了一个简单的 SMTP 客户端。只是尝试添加一些错误处理 - 特别是在这种情况下,当要连接的目标服务器不可用时(例如,指定了错误的 IP!)

目前,回溯如下所示:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "smtplib_client.py", line 91, in runClient
    try:
  File "/usr/local/lib/python2.7/smtplib.py", line 251, in __init__
    (code, msg) = self.connect(host, port)
  File "/usr/local/lib/python2.7/smtplib.py", line 311, in connect
    self.sock = self._get_socket(host, port, self.timeout)
  File "/usr/local/lib/python2.7/smtplib.py", line 286, in _get_socket
    return socket.create_connection((host, port), timeout)
  File "/usr/local/lib/python2.7/socket.py", line 571, in create_connection
    raise err
socket.error: [Errno 111] Connection refused

很明显,socket.py 中的“create_connection”正在爆炸。这有它自己的 try / except 块:

for res in getaddrinfo(host, port, 0, SOCK_STREAM):
    af, socktype, proto, canonname, sa = res
    sock = None
    try:
      sock = socket(af, socktype, proto)
      if timeout is not _GLOBAL_DEFAULT_TIMEOUT:
          sock.settimeout(timeout)
      if source_address:
          sock.bind(source_address)
      sock.connect(sa)
      return sock

    except error as _:
      err = _
      if sock is not None:
          sock.close()

if err is not None:
  raise err
else:
  raise error("getaddrinfo returns an empty list")

我的 runClient() 函数如下所示:

def runClient(configName = 'default', testFile = './test.xml'):
  cliCfg = getClientConfig(configName)
  print cliCfg.find('logfile').text
  # startLogger(cliCfg.find('logfile').text)
  clientCert = cliCfg.find('cert').text
  clientKey = cliCfg.find('key').text
  serverHost = cliCfg.find('serverhost').text
  serverPort = int(cliCfg.find('serverport').text)

  myMail = MailMessageHandler()
  msgSrc = myMail.readMessageSource(testFile)
  allMsgs = myMail.processMessages(msgSrc)
  inx = 1
  for msg in allMsgs:
    validMsg = True
    requiredKeys = ('ehlo', 'sndr', 'rcpt', 'body')
    for msgItems in requiredKeys:
      if len(msg[msgItems]) == 0:
        validMsg = False
    if validMsg:
      try:
        server = smtplib.SMTP(serverHost, serverPort)
        server.ehlo(msg['ehlo'])
        thisSender = msg['sndr']
        thisRecipient = msg['rcpt']
        thisMessage = MIMEText(msg['body'])
        thisMessage['To'] = email.utils.formataddr(('', thisRecipient))
        thisMessage['From'] = email.utils.formataddr(('', thisSender))
        thisMessage['Subject'] = msg['subject']
        thisMessage['Message-id'] = email.utils.make_msgid()
        now = datetime.now()
        day = now.strftime('%a')
        date = now.strftime('%d %b %Y %X')
        thisMessage['Date'] = day + ', ' + date + ' -0000'
        if msg['tls'].lower() == 'true':
          server.starttls('certs/client/client.key', 'certs/client/client.crt')
          logging.info ("Message: " + thisMessage['Message-id'] + " to be sent over TLS")
        server.sendmail(thisSender, thisRecipient.split(","), thisMessage.as_string())
        logging.info ("Message: " + thisMessage['Message-id'] + " sent successfully to " + serverHost + ":" + cliCfg.find('serverport').text)
        logging.info ("Message: " + thisMessage['Message-id'] + " had sender: " + thisMessage['From'])
        logging.info ("Message: " + thisMessage['Message-id'] + " had recipient(s): " + thisMessage['To'])
      except socket.error as e:
        print "Could not connect to server - is it down? ({0}): {1}".format(e.strerrror)
      except:
        print "Unknown error:", sys.exc_info()[0]
      finally:
          server.quit()
    else:
      print "Improperly formatted source mail - please check"

我没有得到的是 - 回溯显示对 raise err 的调用。很明显err 不是None,因此必须将其设置为except error as _:....的一部分。因此最初会处理错误,但作为处理程序的一部分,会创建一个副本(err)-随后在 try/except 块之外引发 - 所以未处理。然后,这个未处理的错误应该被“传递回”调用堆栈(get_socket 没有 try/except 块,connect__init__ 也没有 - 所以在原始 error 的 try/except 块之外create_connection,错误的副本,err 肯定应该“级联”回到我的 runClient 函数中的 try/except 块?

【问题讨论】:

  • 您想在runClient 中捕获什么异常?
  • socket.error: [Errno 111] 连接被拒绝
  • except socket.error as e: 为我工作。您能否提供更多有关您如何尝试捕获它的信息?
  • 已编辑问题以包含 runClient 代码...希望对您有所帮助...
  • 所以即使使用第二个 except 语句也不会被捕获,它应该捕获所有内容......尝试剥离你的代码,留下一个 MVE。正如我所说,我尝试以与您完全相同的方式捕获异常,并且它对我有用。

标签: python error-handling try-catch smtplib


【解决方案1】:

在@AndreySobolev 的支持下,我得到了以下简单的代码工作正常:

import smtplib, socket

try:
   mylib = smtplib.SMTP("127.0.0.1", 25)
except socket.error as e:
   print "could not connect"

然后我返回到我的 smtplib_client.py,并块注释掉了大部分“try”部分。这工作得很好......所以一点一点地,我恢复了越来越多的尝试部分......并且每次都很好。最终版本如下。除了我在except socket.error 处理程序中所做的之外,我不能说我知道我所做的任何更改——除了我还添加了一个server = None 以停止finally 部分的工作。哦,我还必须在我的进口清单中添加“socket”。没有这个,我可以理解 except 没有正确处理 - 但我不明白为什么它根本没有触发,甚至产生“未定义”错误......奇怪!

工作代码:

def runClient(configName = 'default', testFile = './test.xml'):
  cliCfg = getClientConfig(configName)
  print cliCfg.find('logfile').text
  # startLogger(cliCfg.find('logfile').text)
  clientCert = cliCfg.find('cert').text
  clientKey = cliCfg.find('key').text
  serverHost = cliCfg.find('serverhost').text
  serverPort = int(cliCfg.find('serverport').text)

  myMail = MailMessageHandler()
  msgSrc = myMail.readMessageSource(testFile)
  allMsgs = myMail.processMessages(msgSrc)
  inx = 1
  for msg in allMsgs:
    validMsg = True
    requiredKeys = ('ehlo', 'sndr', 'rcpt', 'body')
    for msgItems in requiredKeys:
      if len(msg[msgItems]) == 0:
        validMsg = False
    if validMsg:
      try:
        server = None
        server = smtplib.SMTP(serverHost, serverPort)
        server.ehlo(msg['ehlo'])
        thisSender = msg['sndr']
        thisRecipient = msg['rcpt']
        thisMessage = MIMEText(msg['body'])
        thisMessage['To'] = email.utils.formataddr(('', thisRecipient))
        thisMessage['From'] = email.utils.formataddr(('', thisSender))
        thisMessage['Subject'] = msg['subject']
        thisMessage['Message-id'] = email.utils.make_msgid()
        now = datetime.now()
        day = now.strftime('%a')
        date = now.strftime('%d %b %Y %X')
        thisMessage['Date'] = day + ', ' + date + ' -0000'
        if msg['tls'].lower() == 'true':
          server.starttls('certs/client/client.key', 'certs/client/client.crt')
          logging.info ("Message: " + thisMessage['Message-id'] + " to be sent over TLS")
        server.sendmail(thisSender, thisRecipient.split(","), thisMessage.as_string())
        logging.info ("Message: " + thisMessage['Message-id'] + " sent successfully to " + serverHost + ":" + cliCfg.find('serverport').text)
        logging.info ("Message: " + thisMessage['Message-id'] + " had sender: " + thisMessage['From'])
        logging.info ("Message: " + thisMessage['Message-id'] + " had recipient(s): " + thisMessage['To'])
      except socket.error as e:
        logging.error ("Could not connect to " + serverHost + ":" + cliCfg.find('serverport').text + " - is it listening / up?")
      except:
        print "Unknown error:", sys.exc_info()[0]
      finally:
        if server != None:
          server.quit()
    else:
      print "Improperly formatted source mail - please check"

感到困惑,但松了一口气!谢谢安德烈!

【讨论】:

    猜你喜欢
    • 2014-03-29
    • 1970-01-01
    • 2013-04-25
    • 1970-01-01
    • 2020-08-02
    • 1970-01-01
    • 1970-01-01
    • 2019-08-13
    • 2019-01-29
    相关资源
    最近更新 更多