首页 > 解决方案 > 有没有一种简单的方法可以在不发送邮件的情况下检查邮件后端在 Django 中是否有效?

问题描述

在我的工具中,用户可以使用模型上的某些信息提供邮件后端,并通过从这些值创建的后端发送他们的邮件。这一切都有效,但我很想在使用它之前快速检查提供的后端是否真的可以工作。使用这样的东西check_mail_connection不起作用,因为即使我输入了有效的连接参数,它实际上也会返回 False。

from django.core.mail import get_connection

class User(models.Model):
    ...
    def get_mail_connection(self, fail_silently=False)
        return get_connection(host=self.email_host,
                   port=self.email_port,
                   username=self.email_username,
                   password=self.email_password ... )

    def check_mail_connection(self) -> bool:
        from socket import error as socket_error
        from smtplib import SMTP, SMTPConnectError
        smtp = SMTP(host=self.email_host, port=self.email_port)
        try:
            smtp.connect()
            return True
        except SMTPConnectError:
            return False
        except socket_error:
            return False

我不想发送测试邮件来确认,因为这很容易在系统的不同部分丢失或失败。此功能用于从用户邮件服务器发送电子邮件,因为我怀疑我的大多数用户无论如何都有邮件服务器,我基本上为他们提供白标和类似的东西。

标签: pythondjangosmtp

解决方案


您的代码中有以下行smtp.connect()尝试建立连接。如果您查看smtplib 的文档,则此方法的签名是:

SMTP.connect(host='localhost', port=0)

这意味着您正在尝试localhost使用端口 25(标准 SMTP 端口)连接。当然,那里没有服务器在监听,你会得到一个ConnectionRefusedError你捕获并返回False的。事实上,你甚至不需要打电话connect,因为文档指出:

如果给定了可选的主机和端口参数,则 connect()在初始化期间使用这些参数调用 SMTP 方法。

因此,您可以简单地编写:

def check_mail_connection(self) -> bool:
    from smtplib import SMTP
    try:
        smtp = SMTP(host=self.email_host, port=self.email_port)
        return True
    except OSError:
        return False

您也可以简单地使用open电子邮件后端实例的方法,而不是创建SMTP实例并调用connect自己:

def check_mail_connection(self) -> bool:
    try:
        email_backend = self.get_mail_connection()
        silent_exception = email_backend.open() is None
        email_backend.close()
        return not silent_exception
    except OSError:
        return False

推荐阅读