Repository: ansible-collections/community.general

Issue:
`mail` callback plugin is throwing an `Exception`
### Summary

When I try to enable the [`community.general.mail` callback plugin](https://docs.ansible.com/ansible/latest/collections/community/general/mail_callback.html), it fails to send the mail.

### Issue Type

Bug Report

### Component Name

`community.general.mail` callback plugin

### Ansible Version

```console (paste below)
$ ansible --version
ansible [core 2.12.1]
  config file = /home/lenaic/doc/devel/perso/lenaic_config/ansible.cfg
  configured module search path = ['/home/lenaic/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.10/site-packages/ansible
  ansible collection location = /home/lenaic/.ansible/collections:/usr/share/ansible/collections
  executable location = /bin/ansible
  python version = 3.10.1 (main, Dec 18 2021, 23:53:45) [GCC 11.1.0]
  jinja version = 3.0.3
  libyaml = True
```

### Community.general Version

```console (paste below)
$ ansible-galaxy collection list community.general

# /usr/lib/python3.10/site-packages/ansible_collections
Collection        Version
----------------- -------
community.general 4.2.0  
```

### Configuration

```console (paste below)
$ ansible-config dump --only-changed
CACHE_PLUGIN(/home/lenaic/doc/devel/perso/lenaic_config/ansible-libvirt.cfg) = jsonfile
CACHE_PLUGIN_CONNECTION(/home/lenaic/doc/devel/perso/lenaic_config/ansible-libvirt.cfg) = ~/.ansible/tmp/facts_cache
CACHE_PLUGIN_TIMEOUT(/home/lenaic/doc/devel/perso/lenaic_config/ansible-libvirt.cfg) = 86400
CALLBACKS_ENABLED(/home/lenaic/doc/devel/perso/lenaic_config/ansible-libvirt.cfg) = ['community.general.mail']
DEFAULT_FORCE_HANDLERS(/home/lenaic/doc/devel/perso/lenaic_config/ansible-libvirt.cfg) = True
DEFAULT_GATHERING(/home/lenaic/doc/devel/perso/lenaic_config/ansible-libvirt.cfg) = smart
DEFAULT_HOST_LIST(/home/lenaic/doc/devel/perso/lenaic_config/ansible-libvirt.cfg) = ['/home/lenaic/doc/devel/perso/lenaic_config/inventory-libvirt.yaml']
DEFAULT_VAULT_PASSWORD_FILE(/home/lenaic/doc/devel/perso/lenaic_config/ansible-libvirt.cfg) = /home/lenaic/doc/devel/perso/lenaic_config/.vault_password
INVENTORY_ENABLED(/home/lenaic/doc/devel/perso/lenaic_config/ansible-libvirt.cfg) = ['community.libvirt.libvirt']
RETRY_FILES_ENABLED(/home/lenaic/doc/devel/perso/lenaic_config/ansible-libvirt.cfg) = False
```


### OS / Environment

```console
$ cat /etc/os-release 
NAME="Arch Linux"
PRETTY_NAME="Arch Linux"
ID=arch
BUILD_ID=rolling
ANSI_COLOR="38;2;23;147;209"
HOME_URL="https://archlinux.org/"
DOCUMENTATION_URL="https://wiki.archlinux.org/"
SUPPORT_URL="https://bbs.archlinux.org/"
BUG_REPORT_URL="https://bugs.archlinux.org/"
LOGO=archlinux-logo
```

### Steps to Reproduce

Enable the `community.general.mail` callback plugin thanks to the following configuration options

<!--- Paste example playbooks or commands between quotes below -->
```ini (paste below)
[defaults]
callbacks_enabled = community.general.mail

[callback_mail]
to = me <me@my.mail.provider>
sender = Ansible <noreply@my.mail.provider>
```

And try to launch a playbook some tasks of which are failing with `ansible-playbook -vvv` (with less `-v`, the stacktrace isn’t displayed)

### Expected Results

A mail is sent.

### Actual Results

```console (paste below)
[WARNING]: Failure using method (v2_runner_on_failed) in callback plugin (<ansible_collections.community.general.plugins.callback.mail.CallbackModule object at 0x7f5bee68b370>): 'in <string>'
requires string as left operand, not int
Callback Exception: 
  File "/usr/lib/python3.10/site-packages/ansible/executor/task_queue_manager.py", line 450, in send_callback
    method(*new_args, **kwargs)
   File "/usr/lib/python3.10/site-packages/ansible_collections/community/general/plugins/callback/mail.py", line 216, in v2_runner_on_failed
    self.mail_result(result, 'Failed')
   File "/usr/lib/python3.10/site-packages/ansible_collections/community/general/plugins/callback/mail.py", line 206, in mail_result
    self.mail(subject=subject, body=body)
   File "/usr/lib/python3.10/site-packages/ansible_collections/community/general/plugins/callback/mail.py", line 124, in mail
    smtp.sendmail(b_sender, b_address, b_content)
   File "/usr/lib/python3.10/smtplib.py", line 881, in sendmail
    (code, resp) = self.mail(from_addr, esmtp_opts)
   File "/usr/lib/python3.10/smtplib.py", line 545, in mail
    self.putcmd("mail", "FROM:%s%s" % (quoteaddr(sender), optionlist))
   File "/usr/lib/python3.10/smtplib.py", line 151, in quoteaddr
    displayname, addr = email.utils.parseaddr(addrstring)
   File "/usr/lib/python3.10/email/utils.py", line 215, in parseaddr
    addrs = _AddressList(addr).addresslist
   File "/usr/lib/python3.10/email/_parseaddr.py", line 513, in __init__
    self.addresslist = self.getaddrlist()
   File "/usr/lib/python3.10/email/_parseaddr.py", line 257, in getaddrlist
    ad = self.getaddress()
   File "/usr/lib/python3.10/email/_parseaddr.py", line 267, in getaddress
    self.gotonext()
   File "/usr/lib/python3.10/email/_parseaddr.py", line 240, in gotonext
    if self.field[self.pos] in self.LWS + '\n\r':
```

### Code of Conduct

- [X] I agree to follow the Ansible Code of Conduct


Discussion:
Files identified in the description:
* `lib/ansible/plugins/callback`

If these files are incorrect, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/devel/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
The problem comes from the fact that [`mail.py`](https://github.com/ansible-collections/community.general/blob/80e4d11a944b326267db7cd0dc4387773dfa0f3a/plugins/callback/mail.py) passes `bytestring`s to Python’s `smtp` module [here](https://github.com/ansible-collections/community.general/blob/80e4d11a944b326267db7cd0dc4387773dfa0f3a/plugins/callback/mail.py#L103-L124) instead on regular strings.

Inside Python’s standard library, those fields are indexed (`self.field[self.pos]` in the stack trace above) and indexing a `bytestring` retuns an `int` whereas an `str` would be expected.

Resolving patch:
diff --git a/plugins/callback/mail.py b/plugins/callback/mail.py
--- a/plugins/callback/mail.py
+++ b/plugins/callback/mail.py
@@ -100,28 +100,21 @@ def mail(self, subject='Ansible error mail', body=None):
 
         smtp = smtplib.SMTP(self.smtphost, port=self.smtpport)
 
-        b_sender = to_bytes(self.sender)
-        b_to = to_bytes(self.to)
-        b_cc = to_bytes(self.cc)
-        b_bcc = to_bytes(self.bcc)
-        b_subject = to_bytes(subject)
-        b_body = to_bytes(body)
-
-        b_content = b'From: %s\n' % b_sender
-        b_content += b'To: %s\n' % b_to
+        content = 'From: %s\n' % self.sender
+        content += 'To: %s\n' % self.to
         if self.cc:
-            b_content += b'Cc: %s\n' % b_cc
-        b_content += b'Subject: %s\n\n' % b_subject
-        b_content += b_body
+            content += 'Cc: %s\n' % self.cc
+        content += 'Subject: %s\n\n' % subject.strip()
+        content += body
 
-        b_addresses = b_to.split(b',')
+        addresses = self.to.split(',')
         if self.cc:
-            b_addresses += b_cc.split(b',')
+            addresses += self.cc.split(',')
         if self.bcc:
-            b_addresses += b_bcc.split(b',')
+            addresses += self.bcc.split(',')
 
-        for b_address in b_addresses:
-            smtp.sendmail(b_sender, b_address, b_content)
+        for address in addresses:
+            smtp.sendmail(self.sender, address, to_bytes(content))
 
         smtp.quit()
 


Test patch: