Repository: ansible/ansible

Issue:
The subject of emails is not encoded to UTF-8
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report

##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
mail

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
$ ansible --version
ansible 2.3.2.0
  config file = /work/ansible/configuration/ansible.cfg
  configured module search path = Default w/o overrides
  python version = 2.7.5 (default, Nov  6 2016, 00:28:07) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]

```

##### CONFIGURATION
<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.
-->
from RHEL7 to RHEL7

##### SUMMARY
<!--- Explain the problem briefly -->
An email is sent that contains accented letters in both the body and subject. the mail module charset is set tp utf-8. On reception, the body is shown properly, but the subject is mangled. It appears the subject contains no encoding information.

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
- name: Email with UTF8 characters
  mail:
    from:    whoever@example.com
    to:      somebody@example.com
    charset: utf-8
    subject: "Création"
    body:    "Création"
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
Both the body and subject should be properly encoded to UTF-8 so they can be displayed correctly.
The subject header should be something like:
<!--- Paste verbatim command output between quotes below -->
```
Subject: =?utf-8?B?Q3LDqWF0aW9u?=
```


##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
The subject was simply set verbatim in the email, instead of being encoded properly.
From the email headers as shown in the MUA:
<!--- Paste verbatim command output between quotes below -->
```
Subject: Cr??ation
```



Discussion:
cc @dagwieers
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/modules/notification/mail.py b/lib/ansible/modules/notification/mail.py
--- a/lib/ansible/modules/notification/mail.py
+++ b/lib/ansible/modules/notification/mail.py
@@ -199,6 +199,7 @@
 from email.mime.base import MIMEBase
 from email.mime.multipart import MIMEMultipart
 from email.mime.text import MIMEText
+from email.header import Header
 
 from ansible.module_utils.basic import AnsibleModule
 from ansible.module_utils._text import to_native
@@ -310,14 +311,16 @@ def main():
             module.fail_json(rc=1, msg="No Authentication on the server at %s:%s" % (host, port))
 
     msg = MIMEMultipart()
-    msg['Subject'] = subject
-    msg['From'] = formataddr((sender_phrase, sender_addr))
+    msg['Subject'] = Header(subject, charset)
+    msg['From'] = Header(formataddr((sender_phrase, sender_addr)), charset)
     msg.preamble = "Multipart message"
+    msg.set_charset(charset)
 
     if headers is not None:
         for hdr in [x.strip() for x in headers.split('|')]:
             try:
                 h_key, h_val = hdr.split('=')
+                h_val = to_native(Header(h_val, charset))
                 msg.add_header(h_key, h_val)
             except:
                 pass


Test patch: