SMTP authentication error inside Docker

I’ve gotten Gramps Web seemingly running ok using Docker using compose, but have run into a puzzling issue with outbound emails.

Here’s I think all of the relevant snippets I can think of, though with specific hosts and credentials scrubbed:
from docker-compose.yml

environment: &grampsweb-env
  GRAMPSWEB_EMAIL_HOST: "my.smtp.host"
  GRAMPSWEB_EMAIL_USER: "user@host.example"
  GRAMPSWEB_EMAIL_PORT: 465
  GRAMPSWEB_EMAIL_USE_TLS: "True"
  GRAMPSWEB_EMAIL_PASSWORD: "password-was-here"
  GRAMPSWEB_DEFAULT_FROM_EMAIL: "user@host.example"

from output of docker logs grampsweb_celery

[2025-02-09 18:24:33,465: INFO/MainProcess] Task gramps_webapi.api.tasks.send_email_reset_password[2ff4137a-f1c7-4e3e-9199-45e461f805ee] received
[2025-02-09 18:24:37,656: WARNING/ForkPoolWorker-1] [2025-02-09 18:24:37,656] ERROR in util: Error while trying to send e-mail.
[2025-02-09 18:24:37,656: ERROR/ForkPoolWorker-1] Error while trying to send e-mail.
[2025-02-09 18:24:37,671: ERROR/ForkPoolWorker-1] Task gramps_webapi.api.tasks.send_email_reset_password[2ff4137a-f1c7-4e3e-9199-45e461f805ee] raised unexpected: ValueError('Error while trying to send e-mail.')
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/dist-packages/gramps_webapi/api/util.py", line 541, in send_email
    smtp.send_message(msg)
  File "/usr/lib/python3.11/smtplib.py", line 986, in send_message
    return self.sendmail(from_addr, to_addrs, flatmsg, mail_options,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/smtplib.py", line 901, in sendmail
    raise SMTPRecipientsRefused(senderrs)
smtplib.SMTPRecipientsRefused: {'redacted@email.example': (550, b'Unauthenticated mail not allowed from this range')}

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.11/dist-packages/celery/app/trace.py", line 453, in trace_task
    R = retval = fun(*args, **kwargs)
                 ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/gramps_webapi/util/celery.py", line 20, in __call__
    return self.run(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/gramps_webapi/api/tasks.py", line 95, in send_email_reset_password
    send_email(subject=subject, body=body, to=[email])
  File "/usr/local/lib/python3.11/dist-packages/gramps_webapi/api/util.py", line 551, in send_email
    raise ValueError("Error while trying to send e-mail.")
ValueError: Error while trying to send e-mail.

my testing python script

import smtplib
from email.message import EmailMessage
from email.utils import make_msgid

msg = EmailMessage()
msg.set_content("Hello World.")
msg["Subject"] = "Test"
msg["From"] = "user@host.example"
msg["To"] = "redacted@email.example"
msg["Message-ID"] = make_msgid()
host = "my.smtp.host"
port = 465
user = "user@host.example"
password = "password-was-here"
use_tls = True
smtp = smtplib.SMTP_SSL(host=host, port=port, timeout=10)
smtp.login(user, password)
smtp.send_message(msg)
smtp.quit()

When I docker exec -it into grampsweb_celery and run that test script, I get the same 550 error. When I just run the python script outside of docker on the same host, it sends the email successfully.

What could account for the different outcome when attempted inside the container vs. otherwise?

Given the apparent success invoking the test email outside of the container, I discarded my initial assumption that I’d done something wrong with the email provider, or my DNS records. On the other hand I could just be missing something still and maybe this isn’t actually a gramps-specific problem?

Hi,

that’s strange, but it can’t have anything to do with Gramps Web as demonstrated by your script. You could try with different containers and different Python versions.

Oh indeed, I should have though to try that out earlier.

So, with that in mind I fired up a random debugger container, and running the python test works fine. Ok, so thinking this makes no sense, I docker exec back in to grampsweb_celery and try again, and this too works fine. So apparently I was doing something different before.

And on closer review, the answer is perhaps just that I am bad at reading!

I was using wrong names for environment variables. You can see I these in there before:

  GRAMPSWEB_EMAIL_USER: "user@host.example"
  GRAMPSWEB_EMAIL_PASSWORD: "password-was-here"

When in fact, these needed to be:

  GRAMPSWEB_EMAIL_HOST_USER: "user@host.example"
  GRAMPSWEB_EMAIL_HOST_PASSWORD: "password-was-here"

(notice the important addition of _HOST_ in there)

What a foolish mistake, sorry for the trouble and thanks for helping me to find the right way forward here.

Now I have a new mystery to solve (the password reset link that got emailed starts with http://localhost/api/users/-/password/reset/ and both http without s, and localhost don’t quite seem right) but before I go wasting more of everybody’s time I’m going to try and do a bit more investigating myself first.

edit: this was much easier, I failed to set BASE_URL boy I am on a roll here with dumb and preventable errors.

1 Like

boy I am on a roll here with dumb and preventable errors.

Having those documented with debugging steps in the forum will certainly help future users falling into the same traps :wink:

1 Like