[IMP] mail: make connection test attempt to send an email

The "connection test" was only attempting to establish a socket to the
SMTP server and then trying to login, if credentials were setup.

This would catch basic config errors but would fail to detect setups
were the SMTP server would forbid relaying, because of missing
credentials, missing STARTSSL mode, and other more complex cases.

By actually beginning a real SMTP session and sending the MAIL FROM,
RCPT TO and DATA command, we make sure that the server appeas willing to
relay emails from the current user address to an arbitrary recipient
address. Then we close the session before actually sending the message.

In order to have a valid destination domain with a valid MX server, we
use an odoo.com recipient address for the test, which should prove that
the destination server will relay to arbitrary addresses (unless the
destination server is an Odoo.com MX server ;-))
This commit is contained in:
Olivier Dony
2018-06-06 10:26:30 +02:00
parent c72eec46f9
commit 86ae4b90a3
+26 -1
View File
@@ -156,12 +156,37 @@ class IrMailServer(models.Model):
smtp = False
try:
smtp = self.connect(mail_server_id=server.id)
# simulate sending an email from current user's address - without sending it!
email_from, email_to = self.env.user.email, 'noreply@odoo.com'
if not email_from:
raise UserError(_('Please configure an email on the current user to simulate '
'sending an email message via this outgoing server'))
# Testing the MAIL FROM step should detect sender filter problems
(code, repl) = smtp.mail(email_from)
if code != 250:
raise UserError(_('The server refused the sender address (%(email_from)s) '
'with error %(repl)s') % locals())
# Testing the RCPT TO step should detect most relaying problems
(code, repl) = smtp.rcpt(email_to)
if code not in (250, 251):
raise UserError(_('The server refused the test recipient (%(email_to)s) '
'with error %(repl)s') % locals())
# Beginning the DATA step should detect some deferred rejections
# Can't use self.data() as it would actually send the mail!
smtp.putcmd("data")
(code, repl) = smtp.getreply()
if code != 354:
raise UserError(_('The server refused the test connection '
'with error %(repl)s') % locals())
except UserError as e:
# let UserErrors (messages) bubble up
raise e
except Exception as e:
raise UserError(_("Connection Test Failed! Here is what we got instead:\n %s") % ustr(e))
finally:
try:
if smtp:
smtp.quit()
smtp.close()
except Exception:
# ignored, just a consequence of the previous exception
pass