1

I cannot figure out how to escape an HTML closing tag, <\b> in this example, when used inside an Ansible Jinja conditional (ansible 2.9.27 in this case). Using an additional backslash <\\b> does not work and neither does putting the backslash between single quotes <'\'b>. Anyone have an idea how I can make this work?

Here is my entire Playbook with credentials and email addresses redacted:

- name: GET ADMIN GROUP USERS AND COMMENT (GECOS)
  ansible.builtin.shell: "lslogins --noheadings -g adm -o USER,GECOS|sed s'/$/<br>/'"
  register: lslogins_output
#
# 
- name: FORMAT LIST FOR HTML EMAIL
  ansible.builtin.set_fact:
    email_machine_list:  |-
      {% for host in ansible_play_batch %}
      {% if hostvars[host]['lslogins_output']['stdout'] | length > 0 %}
      <b>{{ hostvars[host]['ansible_hostname']|upper }}:<\b><br>
      {{ hostvars[host]['lslogins_output']['stdout'] }}<br><br>
      {% elif hostvars[host]['lslogins_output']['stdout'] | length == 0  %}
      <b>{{ hostvars[host]['ansible_hostname']|upper }}:<\b><br>
      NO ADMINS FOUND<br><br>
      {% endif %}
      {% endfor %}
  run_once: true
  delegate_to: localhost
#
#
- name: EMAIL USER LIST
  mail:
    to: Me <[email protected]>
    from: Ansible <[email protected]>
    subject: "Ansible Notification"
    subtype: html
    body:  '<!DOCTYPE html>
           <html>
           <body>
           <h3>{{ email_machine_list }}</h3><br><br>
           </body>
           </html>'
    host: mail.foo.bar
    port: 587
    secure: starttls
    password: mypassword
    username: [email protected]
  run_once: true
  become: false
  delegate_to: localhost

The emails I receive from Ansible appear like this. The <\b> should not appear and should be interpreted as a closing HTML tag:

HOST1:<\b>
syslog
user1


HOST2:<\b>
syslog
user1


HOST3:<\b>
syslog
user1

1 Answer 1

1

Put the template into a block. For example,

    - set_fact:
        email_machine_list: |-
          {% for host in ansible_play_batch %}
          <b>{{ hostvars[host]['ansible_hostname']|upper }}:<\b><br>
          {% endfor %}

Example of a complete playbook for testing

Given the inventory

shell> cat hosts
host_1 ansible_hostname=10.1.0.11
host_2 ansible_hostname=10.1.0.12
host_3 ansible_hostname=10.1.0.13

The playbook

- hosts: host_1,host_2,host_3
  gather_facts: false
  tasks:
    - set_fact:
        email_machine_list: |-
          {% for host in ansible_play_batch %}
          <b>{{ hostvars[host]['ansible_hostname']|upper }}:<\b><br>
          {% endfor %}
      run_once: true
    - debug:
        var: test
      run_once: true

gives (abridged)

TASK [debug] *************************************************
ok: [host_1] => 
  email_machine_list: |-
    <b>10.1.0.11:<\b><br>
    <b>10.1.0.12:<\b><br>
    <b>10.1.0.13:<\b><br>

Email

Put the body of the email into the block as well. For example,

    - name: email the list
      mail:
        to: Me <admin@localhost>
        from: Ansible <ansible@localhost>
        subject: "Ansible Notification"
        subtype: html
        body: |-
          <!DOCTYPE html>
          <html>
          <body>
          <h3>{{ email_machine_list }}</h3><br><br>
          </body>
          </html>
        host: localhost
        port: 25
      run_once: true
      delegate_to: localhost

The email was delivered as expected. I had to turn off the rendering of HTML to text in the email client.

Return-Path: <ansible@localhost>
X-Original-To: admin@localhost
Delivered-To: admin@localhost
Received: from [127.0.0.1] (localhost [127.0.0.1])
 by test.example.org (Postfix) with ESMTPS id 3664C180493
 for <admin@localhost>; Thu,  8 Sep 2022 23:48:00 +0200 (CEST)
Content-Type: multipart/mixed; -charset="utf-8"; boundary="===============4465080980945319992=="
MIME-Version: 1.0
From: Ansible <ansible@localhost>
Date: Thu, 08 Sep 2022 23:48:00 +0200
Subject: Ansible Notification
X-Mailer: Ansible mail module
To: Me <admin@localhost>
Cc: 
Message-Id: <[email protected]>


<!DOCTYPE html>
<html>
<body>
<h3><b>10.1.0.11:<\b><br>
<b>10.1.0.12:<\b><br>
<b>10.1.0.13:<\b><br>
</h3><br><br>
</body>
</html>

Enabled rendering of HTML to text works as well

10.1.0.11:
10.1.0.12:
10.1.0.13:
10
  • Thank you but it still did not work. I edited my post to include what I am doing with the email_machine_list set_fact. I still get this in my HTML emails: HOST1:<\b> user1 user2 HOST2:<\b> user1 user2 HOST3:<\b> user1 user2 Commented Sep 8, 2022 at 2:17
  • What is preventing you from updating the question with the current status? Minimize it and make it a reproducible example. Commented Sep 8, 2022 at 3:01
  • I edited my original post and added my entire Playbook. Is that what you are asking for? Commented Sep 8, 2022 at 20:17
  • No. It is not. I asked you to "Minimize it and make it a reproducible example". Start with my code and show me how "it still did not work". If you can't, proceed step by step and show the minimal and reproducible example that didn't work and you are not able to fix it. See How to create a Minimal, Reproducible Example. Commented Sep 8, 2022 at 21:14
  • I should have included my entire Playbook from the beginning and I see the confusion. I added some additional information on what I am trying to accomplish. Commented Sep 8, 2022 at 21:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.