有没有一种简单的方法可以在不发送邮件的情况下检查邮件后端在 Django 中是否有效?
Is there a simple way to check if a mail backend is valid in Django without sending a mail?
在我的工具中,用户可以使用模型上的某些信息提供邮件后端,并通过从这些值创建的后端发送他们的邮件。这一切都有效,但我很乐意在使用之前快速检查提供的后端是否真的有效。使用这样的东西 check_mail_connection
不起作用,因为这实际上 returns 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
我不想发送测试邮件来确认,因为这很容易丢失或在系统的不同部分失败。此功能用于从用户邮件服务器发送电子邮件,因为我怀疑我的大多数用户无论如何都有邮件服务器,我基本上为他们提供白标签和类似的东西。
我有几个问题要问你,希望你先回答这些问题,然后我们才能继续。
您 运行 服务器是什么类型的 OS?
您遵循的是什么邮件客户端和教程?后缀?
服务器上的用户能否将本地邮件发送给服务器上的另一个用户?
哪些端口是开放的,您安装了哪些类型的安全功能?
当电子邮件失败时,您的日志说了什么?
您是自托管/您是服务器管理员吗?
(如果这是你的第一次也没关系。每个人都有第一天。)
如果您只是发送邮件,SSL 和 FQDN 并不是太重要。系统仍然可以使用,只是您将无法接收邮件。
(我是从确保它至少会发送电子邮件的意义上说的。您至少应该使用 SSL,因为它可以免费获得。)
如果您检查了所有这些内容,那么您正在使用的邮件客户端的一部分可能不会发送邮件,除非获得批准。变数很多。
所有这些事情都很重要,否则就不会起作用。
抱歉,本意是将此作为评论。我不习惯在这里说话。
您的代码中有以下行 smtp.connect()
试图建立连接。如果您查看 documentation for smtplib,此方法的签名是:
SMTP.connect(host='localhost', port=0)
意味着您正在尝试使用端口 25(标准 SMTP 端口)连接到 localhost
。当然那里没有服务器监听,你会得到一个 ConnectionRefusedError
和 return False
。事实上,您甚至不需要调用 connect
因为文档指出:
If the optional host and port parameters are given, the SMTP
connect()
method is called with those parameters during
initialization.
因此你可以简单地写:
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
在我的工具中,用户可以使用模型上的某些信息提供邮件后端,并通过从这些值创建的后端发送他们的邮件。这一切都有效,但我很乐意在使用之前快速检查提供的后端是否真的有效。使用这样的东西 check_mail_connection
不起作用,因为这实际上 returns 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
我不想发送测试邮件来确认,因为这很容易丢失或在系统的不同部分失败。此功能用于从用户邮件服务器发送电子邮件,因为我怀疑我的大多数用户无论如何都有邮件服务器,我基本上为他们提供白标签和类似的东西。
我有几个问题要问你,希望你先回答这些问题,然后我们才能继续。
您 运行 服务器是什么类型的 OS? 您遵循的是什么邮件客户端和教程?后缀? 服务器上的用户能否将本地邮件发送给服务器上的另一个用户? 哪些端口是开放的,您安装了哪些类型的安全功能? 当电子邮件失败时,您的日志说了什么? 您是自托管/您是服务器管理员吗? (如果这是你的第一次也没关系。每个人都有第一天。)
如果您只是发送邮件,SSL 和 FQDN 并不是太重要。系统仍然可以使用,只是您将无法接收邮件。
(我是从确保它至少会发送电子邮件的意义上说的。您至少应该使用 SSL,因为它可以免费获得。)
如果您检查了所有这些内容,那么您正在使用的邮件客户端的一部分可能不会发送邮件,除非获得批准。变数很多。
所有这些事情都很重要,否则就不会起作用。
抱歉,本意是将此作为评论。我不习惯在这里说话。
您的代码中有以下行 smtp.connect()
试图建立连接。如果您查看 documentation for smtplib,此方法的签名是:
SMTP.connect(host='localhost', port=0)
意味着您正在尝试使用端口 25(标准 SMTP 端口)连接到 localhost
。当然那里没有服务器监听,你会得到一个 ConnectionRefusedError
和 return False
。事实上,您甚至不需要调用 connect
因为文档指出:
If the optional host and port parameters are given, the SMTP
connect()
method is called with those parameters during initialization.
因此你可以简单地写:
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