--- a/mercurial/mail.py Tue Apr 20 04:27:03 2021 +0200
+++ b/mercurial/mail.py Mon Apr 19 17:26:57 2021 -0400
@@ -151,6 +151,32 @@
if starttls or smtps:
ui.note(_(b'(verifying remote certificate)\n'))
sslutil.validatesocket(s.sock)
+
+ try:
+ _smtp_login(ui, s, mailhost, mailport)
+ except smtplib.SMTPException as inst:
+ raise error.Abort(stringutil.forcebytestr(inst))
+
+ def send(sender, recipients, msg):
+ try:
+ return s.sendmail(sender, recipients, msg)
+ except smtplib.SMTPRecipientsRefused as inst:
+ recipients = [r[1] for r in inst.recipients.values()]
+ raise error.Abort(b'\n' + b'\n'.join(recipients))
+ except smtplib.SMTPException as inst:
+ raise error.Abort(inst)
+
+ return send
+
+
+def _smtp_login(ui, smtp, mailhost, mailport):
+ """A hook for the keyring extension to perform the actual SMTP login.
+
+ An already connected SMTP object of the proper type is provided, based on
+ the current configuration. The host and port to which the connection was
+ established are provided for accessibility, since the SMTP object doesn't
+ provide an accessor. ``smtplib.SMTPException`` is raised on error.
+ """
username = ui.config(b'smtp', b'username')
password = ui.config(b'smtp', b'password')
if username:
@@ -163,21 +189,7 @@
if username and password:
ui.note(_(b'(authenticating to mail server as %s)\n') % username)
username = encoding.strfromlocal(username)
- try:
- s.login(username, password)
- except smtplib.SMTPException as inst:
- raise error.Abort(stringutil.forcebytestr(inst))
-
- def send(sender, recipients, msg):
- try:
- return s.sendmail(sender, recipients, msg)
- except smtplib.SMTPRecipientsRefused as inst:
- recipients = [r[1] for r in inst.recipients.values()]
- raise error.Abort(b'\n' + b'\n'.join(recipients))
- except smtplib.SMTPException as inst:
- raise error.Abort(inst)
-
- return send
+ smtp.login(username, password)
def _sendmail(ui, sender, recipients, msg):