Есть ли простой способ проверить, действителен ли почтовый бэкенд в 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
Я не хочу отправлять тестовое письмо для подтверждения, так как оно может легко потеряться или выйти из строя в другой части системы.
У меня есть несколько вопросов к вам, и я хотел бы, чтобы вы ответили на них, прежде чем мы сможем продолжить.
На какой ОС вы запускаете сервер? Какой почтовый клиент и какой учебник вы использовали? Postfix? Может ли пользователь на сервере отправлять локальную почту другому пользователю на сервере? Какие порты открыты и какие средства безопасности у вас установлены? Что говорится в ваших журналах, когда электронная почта не работает? Являетесь ли вы самостоятельным хостингом/выступаете ли вы в качестве администратора сервера? (Ничего страшного, если это ваш первый раз. У каждого был первый день)
SSL и A FQDN не слишком важны, если вы просто отправляете почту. Система все равно будет работать, вы просто не сможете получать почту.
(Я говорю с точки зрения уверенности в том, что он хотя бы отправит электронное письмо. Вы должны по крайней мере использовать SSL, так как его можно получить бесплатно.)
Если вы проверили все эти вещи, есть часть почтового клиента, который вы используете, и он, вероятно, не будет отправлять почту, пока не получит одобрение. Существует множество переменных.
Все эти вещи важны, иначе ничего не получится.
Простите, что хотел сделать это как комментарий. Я не привык говорить здесь.
В вашем коде есть следующая строка smtp.connect()
, которая пытается установить соединение. Если вы посмотрите документацию по smtplib, сигнатура для этого метода следующая:
SMTP.connect(host='localhost', port=0)
Означает, что вы пытаетесь подключиться к localhost
с портом 25 (стандартный порт SMTP). Конечно, там нет никакого сервера, и вы получаете ConnectionRefusedError
, который вы ловите и возвращаете False
. На самом деле вам даже не нужно вызывать connect
, потому что в документации сказано:
Если указаны необязательные параметры хоста и порта, то метод SMTP
connect()
метод вызывается с этими параметрами во время инициализации.
Следовательно, вы можете просто написать:
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