14 print("ERROR: python yaml module not installed - run the following and try again:", file=sys
.stderr
)
15 print("sudo apt-get install python3-yaml", file=sys
.stderr
)
18 def do_tls(conn
, sslv
):
19 # Possible values of smtp_sslv: none|peer|client_once|fail_if_no_peer_cert
21 # Creating a context with the purpose of server authentication implies verifying the certificate
22 sslcontext
=ssl
.create_default_context(purpose
=ssl
.Purpose
.SERVER_AUTH
)
23 # The None below looks like might be a typo but it's not - it represents the ActiveRecord default (to verify)
24 if sslv
in (None, 'peer', 'client_once', 'fail_if_no_peer_cert'):
26 conn
.starttls(context
=sslcontext
)
27 elif sslv
in ('none',):
28 # disable cert checking
29 sslcontext
.check_hostname
= False
30 sslcontext
.verify_mode
= ssl
.CERT_NONE
31 conn
.starttls(context
=sslcontext
)
33 raise ValueError('invalid value for DISCOURSE_SMTP_OPENSSL_VERIFY_MODE: {}'.format(sslv
))
34 except smtplib
.SMTPException
as e
:
35 if (sslv
is None) and ('STARTTLS extension not supported by server' in e
.args
[0]):
36 print("unable to establish TLS, continuing: {}".format(e
.args
[0]))
40 ### Start of execution ###
43 destemail
= sys
.argv
[2]
45 destemail
= input('Enter your email address: ')
46 srcemail
= 'nobody+launcher-mailtest@discourse.org'
48 # Read in the container yaml and grab the env section
49 cfgdata
= yaml
.safe_load(open(cfgfile
).read())
50 envdata
= cfgdata
['env']
52 # Here are the variables we'll test
53 smtp_addr
= envdata
.get('DISCOURSE_SMTP_ADDRESS')
54 smtp_port
= envdata
.get('DISCOURSE_SMTP_PORT')
55 smtp_user
= envdata
.get('DISCOURSE_SMTP_USER_NAME')
56 smtp_pass
= envdata
.get('DISCOURSE_SMTP_PASSWORD')
57 smtp_sslv
= envdata
.get('DISCOURSE_SMTP_OPENSSL_VERIFY_MODE')
59 # Yoink out the settings from the file - we'll print them and put them in the email
60 testinfo
= 'DISCOURSE_SMTP_ settings:\n'
61 for k
,v
in filter(lambda x
: x
[0].startswith('DISCOURSE_SMTP_'), envdata
.items()):
64 testinfo
+= ' {} = {}\n'.format(k
,v
)
67 # Ensure at least smtp-addr is specified - everything else is optional
69 print("ERROR: DISCOURSE_SMTP_ADDRESS not specified", file=sys
.stderr
)
72 if (smtp_user
is None and smtp_pass
is not None) or (smtp_user
is not None and smtp_pass
is None):
73 print("ERROR: both username and password must be specified for auth", file=sys
.stderr
)
76 # Try and ensure the test is valid
77 if destemail
.split('@',1)[1] in smtp_addr
:
78 print('WARNING: {} may be allowed to relay mail to {}, this may not be a valid test!'.format(smtp_addr
, destemail
))
80 msg
= email
.message
.Message()
81 msg
.add_header('From', 'nobody+launcher-mailtest@discourse.org')
82 msg
.add_header('To', destemail
)
83 msg
.add_header('Subject', 'discourse launcher mailtest for {}'.format(os
.path
.basename(cfgfile
)))
84 msg
.set_payload(testinfo
)
87 smtp
= smtplib
.SMTP(smtp_addr
, smtp_port
, timeout
=5)
89 do_tls(smtp
,smtp_sslv
)
91 smtp
.login(smtp_user
, smtp_pass
)
92 result
= smtp
.sendmail('nobody+launcher-mailtest@discourse.org', destemail
, msg
.as_string())
93 except socket
.gaierror
as e
:
94 print("ERROR: {}".format(e
.args
[-1]), file=sys
.stderr
)
95 print(" Ensure that the host '{}' exists".format(smtp_addr
), file=sys
.stderr
)
97 except socket
.timeout
as e
:
98 print("ERROR: {}".format(e
.args
[-1]), file=sys
.stderr
)
99 print(" Ensure that the host '{}' is up and reachable".format(smtp_addr
), file=sys
.stderr
)
101 except smtplib
.SMTPConnectError
as e
:
102 print("ERROR: {}".format(e
.args
[-1]), file=sys
.stderr
)
103 print(" Ensure that the host '{}' is up and reachable", file=sys
.stderr
)
105 except ssl
.SSLError
as e
:
106 print("ERROR: unable to establish TLS: {}".format(e
.args
[-1]), file=sys
.stderr
)
107 if 'certificate verify failed' in e
.args
[-1]:
108 print(" Fix the host certificate or disable validation".format(smtp_addr
), file=sys
.stderr
)
110 except smtplib
.SMTPRecipientsRefused
as e
:
111 print("ERROR: {}".format(e
.args
[-1].popitem()[1][1].decode()), file=sys
.stderr
)
112 print(" You must provide a username/password to send to this host", file=sys
.stderr
)
114 except smtplib
.SMTPAuthenticationError
as e
:
115 print("ERROR: {}".format(e
.args
[-1].decode()), file=sys
.stderr
)
116 print(" Check to ensure your username and password are correct", file=sys
.stderr
)
118 except smtplib
.SMTPException
as e
:
119 print("ERROR: {}".format(e
.args
[-1]), file=sys
.stderr
)
120 if 'SMTP AUTH extension not supported by server' in e
.args
[0]:
121 print(" Authorization is not available - you may need to use TLS", file=sys
.stderr
)
124 print("ERROR: {}".format(e
.args
[-1]), file=sys
.stderr
)