# `email.parser`: 전자 메일 메시지 구문 분석

소스 코드: Lib/email/parser.py

메시지 객체 구조는 두 가지 방법으로 만들 수 있습니다: `EmailMessage` 객체를 만들고, 딕셔너리 인터페이스를 사용하여 헤더를 추가하고, `set_content()`와 관련 메서드를 사용하여 페이 로드를 추가하여 아예 새로 만들 수 있습니다. 또는 전자 메일 메시지의 직렬화된 표현을 구문 분석해서 만들 수 있습니다.

`email` 패키지는 MIME 문서를 포함한 대부분의 전자 우편 문서 구조를 이해하는 표준 구문 분석기를 제공합니다. 구문 분석기에 바이트열, 문자열 또는 파일 객체를 전달하면 구문 분석기가 객체 구조의 루트 `EmailMessage` 인스턴스를 반환합니다. MIME이 아닌 간단한 메시지의 경우 이 루트 객체의 페이 로드는 메시지의 텍스트를 포함하는 문자열일 수 있습니다. MIME 메시지의 경우 루트 객체는 `is_multipart()` 메서드가 `True`를 반환하고, `get_body()`, `iter_parts()` 및 `walk()`와 같은 페이 로드 조작 메서드를 통해 서브 파트에 액세스 할 수 있습니다.

실제로 사용 가능한 두 가지 구문 분석기 인터페이스가 있습니다, `Parser` API와 증분 `FeedParser` API. `Parser` API는 메시지의 전체 텍스트가 메모리에 있거나 전체 메시지가 파일 시스템의 파일에 있을 때 가장 유용합니다. 더 많은 입력을 기다리기 위해 블록할 수 있는 스트림에서 메시지를 읽을 때는 `FeedParser`가 더 적합합니다 (가령 소켓에서 전자 메일 메시지를 읽을 때). `FeedParser`는 메시지를 증분 적으로 소비하고 구문 분석 할 수 있으며, 구문 분석기를 닫을 때만 루트 객체를 반환합니다.

구문 분석기는 제한적인 방식으로 확장될 수 있음에 유의하십시오. 물론 구문 분석기는 처음부터 새로 구현할 수 있습니다. `email` 패키지에 포함된 구문 분석기와 `EmailMessage` 클래스를 연결하는 모든 로직은 `Policy` 클래스에 내장되므로, 사용자 정의 구문 분석기는 적절한 `Policy` 메서드의 사용자 정의 버전을 구현하여 필요한 방식으로 메시지 객체 트리를 만들 수 있습니다.

## FeedParser API

`email.feedparser` 모듈에서 임포트 한 `BytesFeedParser`는 전자 메일 메시지의 증분 구문 분석에 도움이 되는 API를 제공합니다. 블록할 수 있는 소스(가령 소켓)에서 전자 메일 메시지의 텍스트를 읽을 때 필요합니다. 물론 `BytesFeedParser`는 바이트열류 객체, 문자열 또는 파일에 완전히 포함된 전자 메일 메시지를 구문 분석하는 데 사용될 수 있지만, `BytesParser` API가 이러한 사용 사례에서는 더 편리 할 수 있습니다. 두 구문 분석기 API의 의미와 결과는 같습니다.

`BytesFeedParser`의 API는 간단합니다; 인스턴스를 만들고, 더는 공급할 것이 없을 때까지 바이트열을 공급한 다음 구문 분석기를 닫아 루트 메시지 객체를 얻습니다. `BytesFeedParser`는 표준 호환 메시지를 구문 분석할 때 매우 정확하고, 미준수 메시지를 구문 분석하는 데 매우 효과적이며 메시지를 어떻게 손상되었다고 간주하는지에 대한 정보를 제공합니다. 메시지에서 발견된 문제점 리스트로 메시지 객체의 `defects` 어트리뷰트를 채웁니다. 찾을 수 있는 결함 목록은 `email.errors` 모듈을 참조하십시오.

`BytesFeedParser` API는 다음과 같습니다:

class email.parser.BytesFeedParser(_factory=None, *, policy=policy.compat32)

  `BytesFeedParser` 인스턴스를 만듭니다. 선택적 _factory는 인자 없는 콜러블입니다; 지정되지 않으면 policy의 `message_factory`를 사용합니다. 새로운 메시지 객체가 필요할 때마다 _factory를 호출합니다.

  policy가 지정되면, 그것이 지정하는 규칙을 사용하여 메시지 표시를 갱신합니다. policy가 설정되지 않으면, `compat32` 정책을 사용합니다. 이 정책은 파이썬 3.2 버전의 email 패키지와의 호환성을 유지하고 `Message`를 기본 팩토리로 제공합니다. 다른 모든 정책은 `EmailMessage`를 기본 _factory로 제공합니다. policy가 제어하는 다른 기능에 대한 자세한 내용은 `policy` 설명서를 참조하십시오.

  참고: policy 키워드는 항상 지정해야 합니다; 이후 버전의 파이썬에서는 기본값이 `email.policy.default`로 변경됩니다.

  Added in version 3.2.

  버전 3.3에서 변경: policy 키워드를 추가했습니다.

  버전 3.6에서 변경: _factory는 기본적으로 정책 `message_factory`입니다.

  feed(data)

    구문 분석기에 데이터를 더 공급합니다. data는 하나 이상의 줄을 포함하는 바이트열류 객체여야 합니다. 줄은 부분적일 수 있고 구문 분석기는 그러한 부분적인 줄을 올바르게 이어붙입니다. 줄은 세 가지 일반 줄 종료 중 어느 것이라도 될 수 있습니다: 캐리지 리턴(carriage return), 줄 바꿈(newline) 또는 캐리지 리턴과 줄 바꿈 (이것들을 혼합할 수도 있습니다).

  close()

    이전에 제공된 모든 데이터의 구문 분석을 완료하고 루트 메시지 객체를 반환합니다. 이 메서드가 호출된 후 `feed()`가 호출되면 어떻게 되는지는 정의되지 않습니다.

class email.parser.FeedParser(_factory=None, *, policy=policy.compat32)

  Works like `BytesFeedParser` except that the input to the `feed()` method must be a string. This is of limited utility, since the only way for such a message to be valid is for it to contain only ASCII text or, if `utf8` is `True`, no binary attachments.

  버전 3.3에서 변경: policy 키워드를 추가했습니다.

## Parser API

The `BytesParser` class, imported from the `email.parser` module, provides an API that can be used to parse a message when the complete contents of the message are available in a bytes-like object or file. The `email.parser` module also provides `Parser` for parsing strings, and header-only parsers, `BytesHeaderParser` and `HeaderParser`, which can be used if you’re only interested in the headers of the message. `BytesHeaderParser` and `HeaderParser` can be much faster in these situations, since they do not attempt to parse the message body, instead setting the payload to the raw body.

class email.parser.BytesParser(_class=None, *, policy=policy.compat32)

  `BytesParser` 인스턴스를 만듭니다. _class와 policy 인자는 `BytesFeedParser` 의 _factory와 policy 인자와 같은 의미입니다.

  참고: policy 키워드는 항상 지정해야 합니다; 이후 버전의 파이썬에서는 기본값이 `email.policy.default`로 변경됩니다.

  버전 3.3에서 변경: 2.4에서 폐지된 strict 인자를 제거했습니다. policy 키워드를 추가했습니다.

  버전 3.6에서 변경: _class는 기본적으로 정책 `message_factory`입니다.

  parse(fp, headersonly=False)

    Read all the data from the binary file-like object fp, parse the resulting bytes, and return the message object. fp must support both the `readline()` and the `read()` methods.

    The bytes contained in fp must be formatted as a block of RFC 5322 (or, if `utf8` is `True`, RFC 6532) style headers and header continuation lines, optionally preceded by an envelope header. The header block is terminated either by the end of the data or by a blank line. Following the header block is the body of the message (which may contain MIME-encoded subparts, including subparts with a Content-Transfer-Encoding of `8bit`).

    선택적 headersonly는 헤더를 읽은 후에 구문 분석을 중지할지를 지정하는 플래그입니다. 기본값은 `False`이며 파일의 전체 내용을 구문 분석합니다.

  parsebytes(bytes, headersonly=False)

    파일류 객체 대신 바이트열류 객체를 취한다는 점을 제외하고는 `parse()` 메서드와 유사합니다. 바이트열류 객체로 이 메서드를 호출하는 것은 `BytesIO` 인스턴스로 bytes를 먼저 감싸고 `parse()`를 호출하는 것과 동등합니다.

    선택적 headersonly는 `parse()` 메서드와 같습니다.

  Added in version 3.2.

class email.parser.BytesHeaderParser(_class=None, *, policy=policy.compat32)

  headersonly의 기본값이 `True`라는 점을 제외하고는 `BytesParser`와 정확히 같습니다.

  Added in version 3.3.

class email.parser.Parser(_class=None, *, policy=policy.compat32)

  이 클래스는 `BytesParser`와 유사하지만, 문자열 입력을 처리합니다.

  버전 3.3에서 변경: strict 인자를 제거했습니다. policy 키워드를 추가했습니다.

  버전 3.6에서 변경: _class는 기본적으로 정책 `message_factory`입니다.

  parse(fp, headersonly=False)

    텍스트 모드 파일류 객체 fp에서 모든 데이터를 읽고, 결과 텍스트를 구문 분석한 후, 루트 메시지 객체를 반환합니다. fp는 파일류 객체의 `readline()`과 `read()` 메서드를 모두 지원해야 합니다.

    텍스트 모드 요구 사항 외에, 이 메서드는 `BytesParser.parse()`처럼 작동합니다.

  parsestr(text, headersonly=False)

    파일류 객체 대신 문자열 객체를 취한다는 점을 제외하고는 `parse()` 메서드와 유사합니다. 문자열로 이 메서드를 호출하는 것은 `StringIO` 인스턴스로 text를 먼저 감싸고 `parse()`를 호출하는 것과 동등합니다.

    선택적 headersonly는 `parse()` 메서드와 같습니다.

class email.parser.HeaderParser(_class=None, *, policy=policy.compat32)

  headersonly의 기본값이 `True`라는 점을 제외하고는 `Parser`와 정확히 같습니다.

문자열이나 파일 객체로부터 메시지 객체 구조를 만드는 것이 일반적인 작업이기 때문에, 편의상 4가지 함수가 제공됩니다. 최상위 `email` 패키지 이름 공간에 있습니다.

email.message_from_bytes(s, _class=None, *, policy=policy.compat32)

  바이트열류 객체로부터 메시지 객체 구조를 반환합니다. 이것은 `BytesParser().parsebytes(s)`와 동등합니다. 선택적 _class와 policy는 `BytesParser` 클래스 생성자에서처럼 해석됩니다.

  Added in version 3.2.

  버전 3.3에서 변경: strict 인자를 제거했습니다. policy 키워드를 추가했습니다.

email.message_from_binary_file(fp, _class=None, *, policy=policy.compat32)

  열린 바이너리 파일 객체로부터 메시지 객체 구조 트리를 반환합니다. 이것은 `BytesParser().parse(fp)`와 동등합니다. _class와 policy는 `BytesParser` 클래스 생성자에서처럼 해석됩니다.

  Added in version 3.2.

  버전 3.3에서 변경: strict 인자를 제거했습니다. policy 키워드를 추가했습니다.

email.message_from_string(s, _class=None, *, policy=policy.compat32)

  문자열로부터 메시지 객체 구조 트리를 반환합니다. 이것은 `Parser().parsestr(s)`와 동등합니다. _class와 policy는 `Parser` 클래스 생성자에서처럼 해석됩니다.

  버전 3.3에서 변경: strict 인자를 제거했습니다. policy 키워드를 추가했습니다.

email.message_from_file(fp, _class=None, *, policy=policy.compat32)

  열린 파일 객체로부터 메시지 객체 구조 트리를 반환합니다. 이것은 `Parser().parse(fp)`와 동등합니다. _class와 policy는 `Parser` 클래스 생성자에서처럼 해석됩니다.

  버전 3.3에서 변경: strict 인자를 제거했습니다. policy 키워드를 추가했습니다.

  버전 3.6에서 변경: _class는 기본적으로 정책 `message_factory`입니다.

대화식 파이썬 프롬프트에서 `message_from_bytes()`를 사용하는 방법의 예는 다음과 같습니다:

    >>> import email
    >>> msg = email.message_from_bytes(myBytes)

## 추가 사항

구문 분석 의미에 대한 참고 사항은 다음과 같습니다:

- 대부분의 multipart가 아닌 유형의 메시지는 문자열 페이 로드가 있는 단일 메시지 객체로 구문 분석됩니다. 이 객체는 `is_multipart()`가 `False`를 반환하고 `iter_parts()`는 빈 목록을 산출합니다.

- 모든 multipart 유형 메시지는 서브 메시지 객체 리스트 페이 로드가 있는 컨테이너 메시지 객체로 구문 분석됩니다. 바깥 컨테이너 메시지는 `is_multipart()`가 `True`를 반환하고 `iter_parts()`는 서브 파트 목록을 산출합니다.

- 콘텐츠 유형이 message/*(가령 message/delivery-status와 message/rfc822)인 대부분의 메시지는 길이가 1인 리스트 페이 로드를 포함하는 컨테이너 객체로 구문 분석됩니다. `is_multipart()` 메서드는 `True`를 반환합니다. `iter_parts()`가 산출하는 단일 요소가 서브 메시지 객체입니다.

- 일부 표준을 준수하지 않는 메시지는 multipart 처리에 대해 내부적으로 일관성이 없을 수 있습니다. 이러한 메시지는 multipart 유형의 Content-Type 헤더를 가지면서도 `is_multipart()` 메서드가 `False`를 반환할 수 있습니다. 이러한 메시지가 `FeedParser`로 구문 분석되었다면, defects 어트리뷰트 리스트에 `MultipartInvariantViolationDefect` 클래스의 인스턴스가 있습니다. 자세한 내용은 `email.errors`를 참조하십시오.