Change edX logo in Activation mail

Hi!
I’m running tutor-Koa with indigo theme. I could change logo everywhere except in automated e-mails such as account activation, course enrolment, reset mails etc.

Can you suggest a way to change this ?

Hi @nadheemabdulla! I did not realize that the edX logo was present in the platform emails. I investigated a bit and this looks like an upstream issue in edx-platform.

Basically, in open-release/koa.master, the logo url is hardcoded to be “https://media.sailthru.com/595/1k1/8/o/599f355101b3f.png”, which is an email opening link tracker – which is an absolute horror because it means that all emails sent to Open edX users from all Open edX platforms (even outside of edx.org) include the tracking image.

This behaviour was modified after the Koa branch was cut in the following PR: Rebranding: Logo Swap by awaisdar001 · Pull Request #25654 · edx/edx-platform · GitHub
I think these changes should be backported to the Koa branch.

I created an upstream issue here: Agile Board - JIRA

2 Likes

Thanks for looking into it @regis !
Let’s hope it’ll be solved soon.

In my case, as a temporary solution, I changed the activation email logo by customizing the base_body.html template. This uses the comprehensive theming approach.

Copy the base_body.html template from the edx-platform repo to

path/to/custom-theme-dir/theme/lms/templates/ace_common/edx_ace/common/base_body.html

Then in lines 63-65, change the

(1) src reference in the img element to point to where you store your logo.
(2) href to point to the desired location (and removing the tracking links)

Hope this helps!

2 Likes

Thanks @eragon for this solution.
Let me try it out.

Thanks for that solution Eragon.

I’m trying to include it in my fork of the indigo theme, but when I run make, it tries to compile it as a Jinja template:

tutor config render --extra-config ./config-totem.yml ./theme "$(tutor config printroot)/env/build/openedx/themes/indigo-totem"
Error loading template lms/templates/ace_common/edx_ace/common/base_body.html
Traceback (most recent call last):
  File "/home/maarten/.local/bin/tutor", line 8, in <module>
    sys.exit(main())
  File "/home/maarten/.local/lib/python3.8/site-packages/tutor/commands/cli.py", line 38, in main
    cli()  # pylint: disable=no-value-for-parameter
  File "/usr/lib/python3/dist-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python3/dist-packages/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/lib/python3/dist-packages/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/lib/python3/dist-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python3/dist-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/decorators.py", line 27, in new_func
    return f(get_current_context().obj, *args, **kwargs)
  File "/home/maarten/.local/lib/python3.8/site-packages/tutor/commands/config.py", line 87, in render
    renderer.render_all_to(dst)
  File "/home/maarten/.local/lib/python3.8/site-packages/tutor/env.py", line 159, in render_all_to
    rendered = self.render_template(template_name)
  File "/home/maarten/.local/lib/python3.8/site-packages/tutor/env.py", line 140, in render_template
    template = self.environment.get_template(template_name)
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 830, in get_template
    return self._load_template(name, self.make_globals(globals))
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 804, in _load_template
    template = self.loader.load(self, name, globals)
  File "/usr/lib/python3/dist-packages/jinja2/loaders.py", line 125, in load
    code = environment.compile(source, name, filename)
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 591, in compile
    self.handle_exception(exc_info, source_hint=source_hint)
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 780, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/lib/python3/dist-packages/jinja2/_compat.py", line 37, in reraise
    raise value.with_traceback(tb)
  File "/datadisk/maarten/projects/totem/indigo-totem/theme/lms/templates/ace_common/edx_ace/common/base_body.html", line 8, in <module>
    {% load i18n %}
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 497, in _parse
    return Parser(self, source, name, encode_filename(filename)).parse()
  File "/usr/lib/python3/dist-packages/jinja2/parser.py", line 901, in parse
    result = nodes.Template(self.subparse(), lineno=1)
  File "/usr/lib/python3/dist-packages/jinja2/parser.py", line 883, in subparse
    rv = self.parse_statement()
  File "/usr/lib/python3/dist-packages/jinja2/parser.py", line 144, in parse_statement
    self.fail_unknown_tag(token.value, token.lineno)
  File "/usr/lib/python3/dist-packages/jinja2/parser.py", line 97, in fail_unknown_tag
    return self._fail_ut_eof(name, self._end_token_stack, lineno)
  File "/usr/lib/python3/dist-packages/jinja2/parser.py", line 90, in _fail_ut_eof
    self.fail(' '.join(message), lineno)
  File "/usr/lib/python3/dist-packages/jinja2/parser.py", line 59, in fail
    raise exc(msg, lineno, self.name, self.filename)
jinja2.exceptions.TemplateSyntaxError: Encountered unknown tag 'load'.
make: *** [Makefile:2: render] Error 1

Did you run into this too, or did you immediately copy the base_body.html file directly into your edx platform without using the indigo makefile?

Does anyone know of a way to tell Tutor not to compile this as a Jinja template?

Hi @eragon

I tried this numerous times without success. Copied all the contents from here to mytheme/theme/lms/templates/ace_common/edx_ace/common/base_body.html, edited lines 63-65
as

<td width="70">
                            <a href="https://mysite.com"><img
                                    src="https://mysite.com/logo.png"
                                    height="30" alt="{% filter force_escape %}{% blocktrans %}Go to {{ platform_name }} Home Page{% endblocktrans %}{% endfilter %}"/>
                            </a>
</td>

and rendered it. But it encountered an error

TemplateSyntaxError: Encountered unknown tag ‘load’.

So I put base_body.html contents between {% raw %} and {% endraw %} tags. Though it rendered without errors, Activation e-mail still looks the same after building images and restarting the platform.

Oh, that’s interesting @nadheemabdulla

I tried doing the same as you, and it does bring me one step further. Indeed the theme compiles fine (I use the make command that comes with the indigo theme) when you put the email template between {% raw %} tags, but when I try to get a password reset email in my devstack, I get the following error message:

2021-02-08 15:02:23,851 INFO 17 [tracking] [user None] logger.py:49 - {"host": "totem.local:8000", "accept_language": "en-GB,en;q=0.5", "page": null, "event_source": "server", "ip": "172.18.0.1", "time": "2021-02-08T15:02:23.851528+00:00", "event": "{\"GET\": {}, \"POST\": {\"email\": [\"maarten@greenhost.nl\"]}}", "context": {"user_id": null, "org_id": "", "course_id": "", "path": "/account/password"}, "agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:85.0) Gecko/20100101 Firefox/85.0", "event_type": "/account/password", "referer": "http://totem.local:8000/login?next=/", "username": ""}
2021-02-08 15:02:24,033 ERROR 17 [openedx.core.djangoapps.user_api.helpers] [user None] helpers.py:85 - An unexpected error occurred when calling 'request_password_change' with arguments '('maarten@greenhost.nl', False)' and keyword arguments '{}' from File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/password_reset.py", line 565, in password_change_request_handler
    request_password_change(email, request.is_secure()): AttributeError("'Template' object has no attribute 'nodelist'",)
Traceback (most recent call last):
  File "/openedx/edx-platform/openedx/core/djangoapps/user_api/helpers.py", line 53, in _wrapped
    return func(*args, **kwargs)
  File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/password_reset.py", line 232, in request_password_change
    request=get_current_request(),
  File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/password_reset.py", line 184, in save
    send_password_reset_email_for_user(user, request)
  File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/password_reset.py", line 131, in send_password_reset_email_for_user
    ace.send(msg)
  File "/openedx/venv/lib/python3.5/site-packages/edx_ace/ace.py", line 58, in send
    rendered_message = presentation.render(channel, msg)
  File "/openedx/venv/lib/python3.5/site-packages/edx_ace/presentation.py", line 28, in render
    return renderer.render(channel, message)
  File "/openedx/venv/lib/python3.5/site-packages/edx_ace/renderers.py", line 51, in render
    rendered[field] = template.render(render_context)
  File "/openedx/venv/lib/python3.5/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/openedx/venv/lib/python3.5/site-packages/django/template/base.py", line 171, in render
    return self._render(context)
  File "/openedx/venv/lib/python3.5/site-packages/django/template/base.py", line 163, in _render
    return self.nodelist.render(context)
  File "/openedx/venv/lib/python3.5/site-packages/django/template/base.py", line 937, in render
    bit = node.render_annotated(context)
  File "/openedx/venv/lib/python3.5/site-packages/django/template/base.py", line 904, in render_annotated
    return self.render(context)
  File "/openedx/venv/lib/python3.5/site-packages/django/template/loader_tags.py", line 138, in render
    for node in compiled_parent.nodelist:
AttributeError: 'Template' object has no attribute 'nodelist'
2021-02-08 15:02:24,061 ERROR 17 [edx.student] [user None] password_reset.py:591 - Error occured during password change for user maarten@greenhost.nl: An unexpected error occurred when calling 'request_password_change' with arguments '('maarten@greenhost.nl', False)' and keyword arguments '{}' from File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/password_reset.py", line 565, in password_change_request_handler
    request_password_change(email, request.is_secure()): AttributeError("'Template' object has no attribute 'nodelist'",)
Traceback (most recent call last):
  File "/openedx/edx-platform/openedx/core/djangoapps/user_api/helpers.py", line 53, in _wrapped
    return func(*args, **kwargs)
  File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/password_reset.py", line 232, in request_password_change
    request=get_current_request(),
  File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/password_reset.py", line 184, in save
    send_password_reset_email_for_user(user, request)
  File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/password_reset.py", line 131, in send_password_reset_email_for_user
    ace.send(msg)
  File "/openedx/venv/lib/python3.5/site-packages/edx_ace/ace.py", line 58, in send
    rendered_message = presentation.render(channel, msg)
  File "/openedx/venv/lib/python3.5/site-packages/edx_ace/presentation.py", line 28, in render
    return renderer.render(channel, message)
  File "/openedx/venv/lib/python3.5/site-packages/edx_ace/renderers.py", line 51, in render
    rendered[field] = template.render(render_context)
  File "/openedx/venv/lib/python3.5/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/openedx/venv/lib/python3.5/site-packages/django/template/base.py", line 171, in render
    return self._render(context)
  File "/openedx/venv/lib/python3.5/site-packages/django/template/base.py", line 163, in _render
    return self.nodelist.render(context)
  File "/openedx/venv/lib/python3.5/site-packages/django/template/base.py", line 937, in render
    bit = node.render_annotated(context)
  File "/openedx/venv/lib/python3.5/site-packages/django/template/base.py", line 904, in render_annotated
    return self.render(context)
  File "/openedx/venv/lib/python3.5/site-packages/django/template/loader_tags.py", line 138, in render
    for node in compiled_parent.nodelist:
AttributeError: 'Template' object has no attribute 'nodelist'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/password_reset.py", line 565, in password_change_request_handler
    request_password_change(email, request.is_secure())
  File "/openedx/edx-platform/openedx/core/djangoapps/user_api/helpers.py", line 86, in _wrapped
    raise api_error(msg)
openedx.core.djangoapps.user_api.errors.UserAPIInternalError: An unexpected error occurred when calling 'request_password_change' with arguments '('maarten@greenhost.nl', False)' and keyword arguments '{}' from File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/password_reset.py", line 565, in password_change_request_handler
    request_password_change(email, request.is_secure()): AttributeError("'Template' object has no attribute 'nodelist'",)
Internal Server Error: /account/password

I’m not sure how relevant this is, but I’m using tutor version 10.5.3 with open-release/juniper.3.