docs: def send_mail(subject, body_text, addr_from, recipient_list,
                fail_silently=False, auth_user=None, auth_password=None,
                attachments=None, body_html=None, html_message=None,
                connection=None, headers=None):
      """
      Sends a multipart email containing text and html versions which
      are encrypted for each recipient that has a valid gpg key
      installed.
      """
  
      # Make sure only one HTML option is specified
      if body_html is not None and html_message is not None:  # pragma: no cover
          raise ValueError("You cannot specify body_html and html_message at "
                           "the same time. Please only use html_message.")
  
      # Push users to update their code
      if body_html is not None:  # pragma: no cover
          warn("Using body_html is deprecated; use the html_message argument "
               "instead. Please update your code.", DeprecationWarning)
          html_message = body_html
  
      # Allow for a single address to be passed in.
      if isinstance(recipient_list, six.string_types):
          recipient_list = [recipient_list]
  
      connection = connection or get_connection(
          username=auth_user, password=auth_password,
          fail_silently=fail_silently)
  
      # Obtain a list of the recipients that have gpg keys installed.
      key_addresses = {}
      if USE_GNUPG:
          from email_extras.models import Address
          key_addresses = dict(Address.objects.filter(address__in=recipient_list)
                                              .values_list('address', 'use_asc'))
          # Create the gpg object.
          if key_addresses:
              gpg = GPG(gnupghome=GNUPG_HOME)
              if GNUPG_ENCODING is not None:
                  gpg.encoding = GNUPG_ENCODING
  
      # Check if recipient has a gpg key installed
      def has_pgp_key(addr):
          return addr in key_addresses
  
      # Encrypts body if recipient has a gpg key installed.
      def encrypt_if_key(body, addr_list):
          if has_pgp_key(addr_list[0]):
              encrypted = gpg.encrypt(body, addr_list[0],
                                      always_trust=ALWAYS_TRUST)
              if encrypted == "" and body != "":  # encryption failed
                  raise EncryptionFailedError("Encrypting mail to %s failed.",
                                              addr_list[0])
              return smart_text(encrypted)
          return body
  
      # Load attachments and create name/data tuples.
      attachments_parts = []
      if attachments is not None:
          for attachment in attachments:
              # Attachments can be pairs of name/data, or filesystem paths.
              if not hasattr(attachment, "__iter__"):
                  with open(attachment, "rb") as f:
                      attachments_parts.append((basename(attachment), f.read()))
              else:
                  attachments_parts.append(attachment)
  
      # Send emails - encrypted emails needs to be sent individually, while
      # non-encrypted emails can be sent in one send. So the final list of
      # lists of addresses to send to looks like:
      # [[unencrypted1, unencrypted2, unencrypted3], [encrypted1], [encrypted2]]
      unencrypted = [addr for addr in recipient_list
                     if addr not in key_addresses]
      unencrypted = [unencrypted] if unencrypted else unencrypted
      encrypted = [[addr] for addr in key_addresses]
      for addr_list in unencrypted + encrypted:
          msg = EmailMultiAlternatives(subject,
                                       encrypt_if_key(body_text, addr_list),
                                       addr_from, addr_list,
                                       connection=connection, headers=headers)
          if html_message is not None:
              if has_pgp_key(addr_list[0]):
                  mimetype = "application/gpg-encrypted"
              else:
                  mimetype = "text/html"
              msg.attach_alternative(encrypt_if_key(html_message, addr_list),
                                     mimetype)
          for parts in attachments_parts:
              name = parts[0]
              if key_addresses.get(addr_list[0]):
                  name += ".asc"
              msg.attach(name, encrypt_if_key(parts[1], addr_list))
          msg.send(fail_silently=fail_silently)