Have you seen the latter half of this thread? It may help you: How do I reset a user's password? - #7 by dercni
BTW, if you share the exact error message, someone might recognize the issue and be able to help.
Have you seen the latter half of this thread? It may help you: How do I reset a user's password? - #7 by dercni
BTW, if you share the exact error message, someone might recognize the issue and be able to help.
Hi all
I am having a similar issue with password reset email and was hoping someone can give me some tips/things to check so I can troubleshoot. Basically, the reset pw functionality is not sending emails because of authentication (log snippet below) issues but I have confirmed from the same box that I can send emails via a bash script/openssl s_client (script below). I am pretty sure I am missing something but just can’t figure it out ![]()
Please lmk if I can share more info/logs
Thank you in advance
My server info running in gcp
=========================
Gramps 6.0.4
Gramps Web API 3.3.0
Gramps Web Frontend 25.9.0
Gramps QL 0.4.0
Sifts 1.0.0
locale: en
multi-tree: false
task queue: true
OCR: true
chat: false
=========================
celery log
====================
[2025-10-22 22:39:33,684: INFO/MainProcess] Task gramps_webapi.api.tasks.send_email_reset_password[c6f1b0e0-f4d2-418f-86a1-0371a9fad96b] received
[2025-10-22 22:39:34,298: WARNING/ForkPoolWorker-1] [2025-10-22 22:39:34,298] ERROR in util: Error while trying to send e-mail.
[2025-10-22 22:39:34,298: ERROR/ForkPoolWorker-1] Error while trying to send e-mail.
[2025-10-22 22:39:34,310: ERROR/ForkPoolWorker-1] Task gramps_webapi.api.tasks.send_email_reset_password[c6f1b0e0-f4d2-418f-86a1-0371a9fad96b] 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 554, 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 887, in sendmail
raise SMTPSenderRefused(code, resp, from_addr)
smtplib.SMTPSenderRefused: (530, b'Authentication required', '')
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 108, in send_email_reset_password
send_email(subject=subject, body=body, to=[email], body_html=body_html)
File "/usr/local/lib/python3.11/dist-packages/gramps_webapi/api/util.py", line 564, in send_email
raise ValueError("Error while trying to send e-mail.")
ValueError: Error while trying to send e-mail.
====================
Snippet from docker yaml
====================
GRAMPSWEB_EMAIL_HOST: mysmtp.smtp.com
GRAMPSWEB_EMAIL_PORT: 465
GRAMPSWEB_EMAIL_USER: myusername
GRAMPSWEB_EMAIL_PASSWORD: mypw
GRAMPSWEB_EMAIL_USE_TLS: True
GRAMPSWEB_DEFAULT_EMAIL: "admin@khemanifamilytree.com"
====================
script that i used to test email functionality on the same box
=============================================
SMTP_SERVER=“mysmtp.smtp.com”
SMTP_PORT=“465”
USERNAME=“myusername”
PASSWORD=“mypw”
FROM_EMAIL="admin@khemanifamilytree.com"
TO_EMAIL="testingemail@gmail.com"
SUBJECT=“SMTP Test from Bash”
MESSAGE=“This is a test email sent from a Bash script using OpenSSL.”
AUTH_USERNAME_B64=$(echo -ne “\0${USERNAME}\0${PASSWORD}” | base64 -w 0)
{
sleep 1
echo “EHLO $(hostname)”
sleep 1
echo “AUTH PLAIN ${AUTH_USERNAME_B64}”
sleep 1
echo “MAIL FROM:<${FROM_EMAIL}>”
sleep 1
echo “RCPT TO:<${TO_EMAIL}>”
sleep 1
echo “DATA”
sleep 1
echo “Subject: ${SUBJECT}”
echo “”
echo “${MESSAGE}”
echo “.”
sleep 1
echo “QUIT”
} | openssl s_client -connect “${SMTP_SERVER}:${SMTP_PORT}” -crlf -quiet
echo “SMTP test script finished.”
=============================================
Snippet of me getting the email from the same box to my gmail
========================
========================
Thanks codefarmer! I tried everything I could think of reviewing your notes, but no joy. Some of the programming is too deep for my skill set, I had wanted to see how to get to the sqllite tables, etc., but no bandwidth to dive in now. So I had to back off. I went ahead and spooled up a new server, importing backup data into a fresh instance. This time I entered the info for the SMTP server, email, port, etc., but still not working!
I see akhemani’s note here too - hopefully this is something could be tended to over time.
Still love Gramps program! Truly amazing! Thanks,
Hi chrisfchb… Just curious.. what is the exact error that you are getting (from the grampsweb_celery logs). Wondering if it’s the same as me. Secondly.. This line from your comment..
GRAMPSWEB_EMAIL_USE_TLS: “True” (for all the ‘case sensitive’ discussion, I believe this is correct)
I am a bit confused about this in general. The doc says lowercase Server configuration - Gramps Web here but the example it gave has uppercase T and then some of the chats here also has T
Do you know for sure it’s upper T? btw, in my case I have tried both with no success ![]()
Thanks
Quick update for future folks…
Looks like this question was already addressed — I must’ve missed that earlier… I made the same mistake as this post SMTP authentication error inside Docker - #4 by DavidMStraub
Did not have the word HOST for username/password….. smh
Found this posting marooned in a hidden automated rejection queue. No doubt its no longer pertinent but regardless…
Perhaps it was automatically rejected because it reads like it was written by a bot and its main point is to advertise something??
Yep. User was only on once. I hoped that there was a public support forum where SMTP troubleshooting info was available. But no. It was straight commercial info only for a bulk emailer.
So the posting is gone again.
Still, it is worriesome that something could sit unreviewed so long.
The Discourse moderator features make it hard to discover some queues.
Increases my appreciation for the indicators in Gramps tabs that indicate that there is data. Saves a lot of fruitless drilling down.
I got the email password reset link working with Gmail using the following docker-compose.yml extract:
environment:
GRAMPSWEB_EMAIL_HOST: "smtp.gmail.com"
GRAMPSWEB_EMAIL_PORT: "465"
GRAMPSWEB_EMAIL_HOST_USER: "your-email@gmail.com"
GRAMPSWEB_EMAIL_HOST_PASSWORD: "your-app-password"
GRAMPSWEB_EMAIL_USE_TLS: "true"
GRAMPSWEB_DEFAULT_FROM_EMAIL: "your-email@gmail.com"
Use port 465 with EMAIL_USE_TLS=true
You need a Gmail App Password (not your regular password): https://myaccount.google.com/apppasswords
Make sure 2-factor authentication is enabled on your Google account first
Port 587 doesn’t work due to a bug in how Gramps Web handles the EMAIL_USE_TLS environment variable.
If you have identified a bug, please report it. Thanks!
In the send_email function around line 490-530 in gramps_webapi/api/util.py.
When EMAIL_USE_TLS=True is configured, the code incorrectly uses smtplib.SMTP_SSL() for port 587:
Port 465 needs SMTP_SSL (implicit SSL - connection is encrypted from the start)
Port 587 needs SMTP + starttls() (STARTTLS - starts plain, then upgrades to TLS)
The current code does this:
if use_tls:
smtp = smtplib.SMTP_SSL(host=host, port=port, timeout=10) # ← WRONG for port 587!
else:
smtp = smtplib.SMTP(host=host, port=port, timeout=10)
The logic should be based on the port number, not just the use_tls flag:
if port == 465:
# Implicit SSL (port 465)
smtp = smtplib.SMTP_SSL(host=host, port=port, timeout=10)
smtp.ehlo()
else:
# Plain connection with optional STARTTLS (port 587 or 25)
smtp = smtplib.SMTP(host=host, port=port, timeout=10)
smtp.ehlo()
if use_tls:
smtp.starttls()
smtp.ehlo()
Incorrect is a strong word. I’d rather say the naming of `EMAIL_USE_TLS` is not great. What it actually means is “use implicit SSL”.
In any case, whether the original naming choice was good or not, changing it now would break many users’ working config.
In my view, what’s most important is that the documentation is clear. Any suggestions for improvement are highly welcome. Right now, it says:
`EMAIL_USE_TLS` – Boolean, whether to use TLS for sending e-mails. Defaults to True. When using STARTTLS, set this to False and use a port different from 25.
The only thing that’s not possible right now is to use unencrypted SMTP over ports different from 25.
In your version, it wouldn’t be possible to use SMTPS on ports other than 465.
I’m not sure if anyone needs any of those two possibilities, but I don’t see why we should make the secure case less customizable rathern than the insecure case (which, if it all, is only useful for development).
Hi David,
Thanks for clarifying how EMAIL_USE_TLS works, I did not catch that until now. You’re right that changing it would break existing configs. I have a proposal that maintains backward compatibility while making the configuration more intuitive for new users.
You could add two new optional parameters:
The logic would be:
Existing deployments continue working as before
New users can configure port 587 intuitively with EMAIL_USE_STARTTLS=true
Custom ports work with both SSL and STARTTLS
Example configs:
New way:
EMAIL_PORT=587
EMAIL_USE_STARTTLS=true
Old way:
EMAIL_PORT=587
EMAIL_USE_TLS=false
What do you think?
I think that’s a great idea. We could issue a warning when the “old” config parameter is changed from its default.
Here is a small patch for this proposal. Let me know what you think. I’ve tried to keep it minimal.
diff --git a/gramps_webapi/api/util.py b/gramps_webapi/api/util.py
index 1234567..abcdefg 100644
--- a/gramps_webapi/api/util.py
+++ b/gramps_webapi/api/util.py
@@ -18,20 +18,46 @@ def send_email(
msg["Message-ID"] = make_msgid()
msg["Date"] = formatdate(localtime=True)
host = get_config("EMAIL_HOST")
port = int(get_config("EMAIL_PORT"))
user = get_config("EMAIL_HOST_USER")
password = get_config("EMAIL_HOST_PASSWORD")
+
+ # New explicit configuration options (preferred)
+ use_ssl = get_config("EMAIL_USE_SSL") # None if not set
+ use_starttls = get_config("EMAIL_USE_STARTTLS") # None if not set
+
+ # Legacy configuration option (for backward compatibility)
use_tls = get_config("EMAIL_USE_TLS") # Defaults to True
+
+ # Issue deprecation warning if using old config without new params
+ if use_ssl is None and use_starttls is None and use_tls is not None:
+ current_app.logger.warning(
+ "EMAIL_USE_TLS is deprecated. Please migrate to EMAIL_USE_SSL "
+ "(for implicit SSL on port 465) or EMAIL_USE_STARTTLS "
+ "(for STARTTLS on port 587). See documentation for details."
+ )
+
+ # Determine connection method with priority to new explicit params
+ if use_ssl is not None:
+ use_implicit_ssl = use_ssl
+ elif use_starttls is not None:
+ use_implicit_ssl = False
+ else:
+ use_implicit_ssl = use_tls
+
+ # Determine if STARTTLS should be used
+ if use_starttls is not None:
+ should_starttls = use_starttls
+ elif use_ssl is not None:
+ should_starttls = False
+ else:
+ should_starttls = (not use_implicit_ssl) and (port != 25)
try:
smtp: smtplib.SMTP | smtplib.SMTP_SSL
- if use_tls:
+
+ if use_implicit_ssl:
smtp = smtplib.SMTP_SSL(host=host, port=port, timeout=10)
+ smtp.ehlo()
else:
smtp = smtplib.SMTP(host=host, port=port, timeout=10)
- smtp.ehlo()
- if port != 25:
- smtp.starttls()
- smtp.ehlo()
+ smtp.ehlo()
+
+ if should_starttls:
+ smtp.starttls()
+ smtp.ehlo()
+
if user:
smtp.login(user, password)
smtp.send_message(msg)
Hi,
yes, let’s go for `EMAIL_USE_SSL` and EMAIL_USE_STARTTLS`.
I find the patch a bit difficult to read, if you can submit a pull request, it’s easier to comment. I think the only nontrivial part is handling the flask default config option values.