Sorry if title is unclear.
I'm trying to send an email through python 3.10 through the standard library. It works locally on my machine with these default settings.
smtp_server = "smtp.office365.com"
port = 587 # For starttls
sender_email = os.environ.get("EMAIL")
password = os.environ.get("EMAIL_PASSWORD")
# Create a secure SSL context
context = ssl.create_default_context()
server = smtplib.SMTP(smtp_server,port)
try:
server.starttls(context=context) # Secure the connection
server.login(sender_email, password)
except Exception as e:
print(e)
However when I run this code manually from my company's server, I get a "unable to get local issuer certificate" error.
I've been able to remedy the issue by setting the ssl context to unverified:
context = ssl._create_unverified_context() # was ssl.create_default_context()
And this works when running the python file manually. However, this needs to run as a cronjob, and when the crontab runs the script with this 'fix' I get a different error.
Authentication unsuccessful, the user credentials were incorrect.
Which is ridiculous, because the same credentials worked with a different ssl context.
I'm using pythons virtualenv to run the script. I don't know any networking or certificate specific things to the company ubuntu server, but there's clearly something up. I just don't know what specifically.
Yes, I have looked through the multitude of similar questions, though none of them seem to quite fit this set of circumstances to help me.
Thanks in advance.
CodePudding user response:
You are seeing two separate issues. TLS/certificate issues, and then an authentication issue which most likely has nothing to do with TLS.
There is no need for you to use unverified TLS. You can get the catrust from mozilla via the certifi package. Not sure if microsoft uses browser trust to sign their certificates.
>>> import certifi, ssl
>>> context = ssl.create_default_context()
>>> context.load_verify_locations(certifi.where())
That being said, a common mistake people make is assuming that cron jobs will load the same shell profile files that a login does. I would add error checking/debug loggin to make sure EMAIL_PASSWORD and EMAIL are set according to your expectations, since the error message is most likely coming from server.login
line which has nothing to do with TLS.