I created an example playbook using the 4th suggestion from MikZuit's answer with the literal block syntax and it works like a charm. It sets the variable with set_fact which I tried to both debug and copy (print to a file). This is it:
- name: variable test
hosts: 127.0.0.1
connection: local
vars:
mailbody: "I am a mail body."
PROFILE_NAME: "my profile"
SERVER_NAME: "myserver.example.org"
NODE_NAME: "I feel on edge today."
tasks:
- name: variable test | set variable
ansible.builtin.set_fact:
mailbody: |
{{ mailbody | default('') }}
PROFILE_NAME: {{ PROFILE_NAME }}
SERVER_NAME: {{ SERVER_NAME }}
NODE_NAME: {{ NODE_NAME }}
- name: variable test | print variable to stdout
ansible.builtin.debug:
var: mailbody
- name: variable test | print variable to file
ansible.builtin.copy:
content: "{{ mailbody }}"
dest: "/tmp/mailbody.txt"
When I run the playbook the debug output looks like this:
ok: [localhost] => {
"mailbody": "I am a mail body.\n\nPROFILE_NAME: my profile\n\nSERVER_NAME: myserver.example.org\n\nNODE_NAME: I feel on edge today.\n"
}
Note that the debug module prints the output as JSON and escapes any special characters, unlike the copy module which, in this playbook, prints the following output to /tmp/mailbody.txt:
I am a mail body.
PROFILE_NAME: my profile
SERVER_NAME: myserver.example.org
NODE_NAME: I feel on edge today.
Some general notes:
Since v2.10 or so, Ansible has been strongly modularized. This means that task names should now be fully qualified collection names (e.g. ansible.builtin.copy instead of copy) in order to avoid possible name collisions with other collections. Also it does not accept any plays or tasks without a name anymore.
When using the literal block syntax, it will truncate trailing newlines (like the empty line after NODE_NAME: {{ NODE_NAME }}) down to at most one. Btw, you don't need any quotes inside these blocks except for literals in evaluated expressions, e.g. {{ mailbody | default('') }}.
Quoting in Ansible works very similar to quoting in Linux shells. Double quotes can evaluate expressions and escaped characters while single quotes pass everything "as is".
Concerning the unexpected end of print statement error in Ashar's comment: the error occurs because the concatenation operator (~) expects a second operand but instead finds closed curly braces which mark the end of the expression. Just delete all the tildes shown in your error message and you should be good to go.