Email with template

I’ve verified the email challenge-response feature. The user gets the briefest of all possible emails with “<otp>”. Now I want to build out that email with the use of an external template. I followed the example exactly, down to the file:/etc/privacyidea/emailtemplate.html name. The file is world-readable.

Now the C-R fails, and it looks like it is because of some low-level issue in processing the template file. I turned on DEBUG logging and this is what I see:

[2019-09-13 00:20:06,934][27530][139931553847040][WARNING][privacyidea.lib.tokens.emailtoken:294] The PIN was correct, but the EMail could not be sent: KeyError(u'user',)
[2019-09-13 00:20:06,936][27530][139931553847040][DEBUG][privacyidea.lib.tokens.emailtoken:295] Traceback (most recent call last):
  File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/tokens/emailtoken.py", line 289, in create_challenge mimetype=mimetype)
  File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/log.py", line 193, in log_wrapper     f_result = func(*args, **kwds)
  File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/tokens/emailtoken.py", line 447, in _compose_email  message = message.format(otp=otp, serial=serial)
KeyError: u'user'

It’s not entirely clear from the docs if I should be using {} or <> as keyword placeholders in the template, but it seems to be complaining about USER, even though USER is listed as a valid keyword. So I’m at a loss.

I think the documentation is very clear:
https://privacyidea.readthedocs.io/en/latest/policies/authentication.html#emailtext

Reread what user actually means and check if the user object really has the attribute you are referring to.

Docs say {user} is “the given name of the token owner”. My resolver is LDAP. Does an AD source support a literal “user” attribute? No, but it does support “the given name”. There is also a {givenname} substitution with the exact same definition as {user}, and this one would seem to be more appropriate for AD (where givenName maps to the First Name attribute).

Sorry, Cornelius, I guess I’m just stupid. This would appear to have nothing to do with user attributes, AD/LDAP, etc.

I tried something simple using the user-agnostic {date} and {time} tags within an HTML message template. If I use angle brackets <date> – such as works perfectly for <otp> – I get a successful email with no substitutions (because the tags are treated like non-functional HTML entities). If I use curly braces {} – whether alone, bound by angles, or bounding an angled tag – the GUI throws an error during substitution and no email is received.

I’m literally using keywords “date” and “time”. Is there a different incantation I should use, like u’date or ???

Basically you can use all these tags in curly brackes:

  • username
  • client_ip
  • surname
  • recipient_givenname
  • time
  • date
  • user
  • registrationcode
  • serial
  • givenname
  • googleurl_value
  • userrealm
  • realm
  • tokentype
  • url
  • admin
  • recipient_surname
  • ua_string
  • action
  • ua_browser

Some of the tags may be empty and some may not be sensible in this situation.

The question remains how your template looks like.

Instead of using a file with a full blown html template you might at first try a simple template in the policy like:

Hi, your OTP is <otp>.

(I am not sure, if the tag {otp} would work . <otp> will)

Note: Previously we only used the tags <otp> and <serial> tags. We switched to using python format strings with the curly brackets like {serial}. It coul dhowever be, that the transition is not complete and we might have missed the otp.

Checked again. We did not miss it. You can use <otp> (old format) and {otp} (new style).

Yup, confirmed the {otp}. Here is my simple-minded HTML template.

<p>The One-Time Password generated is: {otp}</p>

<pre>
Time: <time>
Date: <date>
IP: <client_ip>
Agent: <ua_browser> <ua_string>
</pre>

If I change <time> to {time} – or any of the others – the Python substitution process throws an error as below and the GUI immediately fails the login with no C-R followup.

[2019-09-17 00:20:18,807][7940][140392997590784][WARNING][privacyidea.lib.tokens.emailtoken:294] The PIN was correct, but the EMail could not be sent: KeyError(u'time',)
[2019-09-17 00:20:18,812][7940][140392997590784][DEBUG][privacyidea.lib.tokens.emailtoken:295] Traceback (most recent call last):
  File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/tokens/emailtoken.py", line 289, in create_challenge
    mimetype=mimetype)
  File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/log.py", line 193, in log_wrapper
    f_result = func(*args, **kwds)
  File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/tokens/emailtoken.py", line 447, in _compose_email
    message = message.format(otp=otp, serial=serial)
KeyError: u'time'

[2019-09-17 00:20:18,812][7940][140392997590784][DEBUG][privacyidea.lib.tokens.emailtoken:295] Traceback (most recent call last):
  File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/tokens/emailtoken.py", line 289, in create_challenge
    mimetype=mimetype)
  File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/log.py", line 193, in log_wrapper
    f_result = func(*args, **kwds)
  File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/tokens/emailtoken.py", line 447, in _compose_email
    message = message.format(otp=otp, serial=serial)
KeyError: u'time'

I’m currently running DEBUG level and that’s all it tells me. Any other areas I can look?

You mentioned in another thread that You are using 3.0.2. Unfortunately these extended tags are available in the current community release 3.1.
In 3.0.2 only {otp} and {serial} work.

1 Like

OMG thank you! I thought I was going crazy. Docs say “starting with 2.20 you can use {challenge}”, but it doesn’t say “starting with 3.1 you can use these other tags”. Thought I was safe. Thanks again.