docs: def parse(raw_email):
      # type: (six.string_types) -> Tuple[six.string_types, six.string_types]
      """Extract email from a full address. Example:
        'John Doe <jdoe+github@foo.com>' -> jdoe@foo.com
  
      >>> parse("John Doe <me+github.com@someorg.com")
      ('me', 'someorg.com')
      >>> parse(42)  # doctest: +IGNORE_EXCEPTION_DETAIL
      Traceback (most recent call last):
          ...
      InvalidEmail: 'Invalid email: 42'
      >>> parse(None)  # doctest: +IGNORE_EXCEPTION_DETAIL
      Traceback (most recent call last):
          ...
      InvalidEmail: 'None or NaN is not a valid email address'
      """
      if not isinstance(raw_email, six.string_types):
          raise InvalidEmail("Invalid email: %s" % raw_email)
      if not raw_email or pd.isnull(raw_email):
          raise InvalidEmail("None or NaN is not a valid email address")
      email = raw_email.split("<", 1)[-1].split(">", 1)[0]
      chunks = email.split("@", 3)
      # git-svn generates emails with several @, e.g.:
      # <rossberg@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
      if len(chunks) < 2:
          raise InvalidEmail("Invalid email")
      uname = chunks[0].rsplit(" ", 1)[-1]
      addr_domain = chunks[1].split(" ", 1)[0]
  
      return uname.split("+", 1)[0], addr_domain