You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python logging模块SMTPHandler报socket.gaierror错误如何解决?

问题描述

尝试使用Python logging模块的SMTPHandler类发送日志邮件时,出现socket.gaierror: [Errno 11001] getaddrinfo failed错误,但相同的邮件服务器参数在直接使用smtplib时可以正常发送邮件,单独调用socket.getaddrinfo也能解析出IP地址。

报错信息

--- Logging error ---
Traceback (most recent call last):
  File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\logging\handlers.py", line 1075, in emit
    smtp = smtplib.SMTP(self.mailhost, port, timeout=self.timeout)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\smtplib.py", line 255, in __init__
    (code, msg) = self.connect(host, port)
                  ^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\smtplib.py", line 341, in connect
    self.sock = self._get_socket(host, port, self.timeout)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\smtplib.py", line 312, in _get_socket
    return socket.create_connection((host, port), timeout,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\socket.py", line 827, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\socket.py", line 962, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
socket.gaierror: [Errno 11001] getaddrinfo failed
Call stack:
  File "<string>", line 1, in <module>
  File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\idlelib\run.py", line 165, in main
    ret = method(*args, **kwargs)
  File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\idlelib\run.py", line 579, in runcode
    exec(code, self.locals)
  File "C:\Users\User\Desktop\test_log\test_log.py", line 34, in <module>
    main()
  File "C:\Users\User\Desktop\test_log\test_log.py", line 28, in main
    log.critical('Testing email logging')
Message: 'Testing email logging'
Arguments: ()

配置与代码

日志处理器JSON配置

"emailhand": {
    "class": "logging.handlers.SMTPHandler",
    "level": "CRITICAL",
    "formatter": "a_formatter",
    "mailhost": "('send.smtp.com', 25)",
    "credentials": "('login@email.co.uk', 'password')",
    "fromaddr": "sender@email.co.uk",
    "toaddrs": "recipient@email.co.uk",
    "subject": "Test Log",
    "secure": "()",
    "timeout": 10.0
}

Python代码

import os
import json
import logging
import logging.config
import logging.handlers

def init_logging():
    logfile = r'C:\Users\User\Desktop\test_log\test_log.log'
    with open(r'C:\Users\User\Desktop\test_log\file-data\logging.json', 'r') as f:
        LOGGING_CONFIG = json.load(f)
    logging.config.dictConfig(LOGGING_CONFIG)

def main():
    init_logging()
    log = logging.getLogger('test_log')
    log.info('Some info from the main function')
    log.critical('Testing email logging')

if __name__ == "__main__":
    main()

问题原因

核心问题出在JSON配置的格式上:

  • mailhost、credentials、secure被设置为字符串形式的Python元组(比如"('send.smtp.com', 25)"),但logging.config.dictConfig只会将JSON值解析为基础类型(字符串、数字、列表、字典),不会自动把字符串解析成Python元组。
  • 这导致SMTPHandler拿到的mailhost是完整的字符串"('send.smtp.com', 25)",而不是预期的(host, port)元组。当smtplib尝试将这个字符串作为主机名解析时,自然会出现getaddrinfo失败的错误。

解决方法

修改JSON配置,将需要传递元组的参数改为JSON数组(因为JSON没有元组类型,数组会被dictConfig解析为Python列表,而SMTPHandler接受列表/元组作为这些参数的输入):

"emailhand": {
    "class": "logging.handlers.SMTPHandler",
    "level": "CRITICAL",
    "formatter": "a_formatter",
    "mailhost": ["send.smtp.com", 25],
    "credentials": ["login@email.co.uk", "password"],
    "fromaddr": "sender@email.co.uk",
    "toaddrs": "recipient@email.co.uk",
    "subject": "Test Log",
    "secure": [],
    "timeout": 10.0
}

补充说明

  • 如果不需要secure参数,可以直接删除该配置项,或者设置为null(对应Python的None)。
  • 对于SSL连接(端口465),只需将mailhost的端口改为465,并确保邮件服务器支持该端口的SSL连接即可,无需修改其他配置结构。

内容的提问来源于stack exchange,提问作者dabo_tusev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 23:37:04