email.parser: Phân tích tin nhắn email

Source code: Lib/email/parser.py


Cấu trúc đối tượng thư có thể được tạo theo một trong hai cách: chúng có thể được tạo từ toàn bộ vải bằng cách tạo đối tượng EmailMessage, thêm tiêu đề bằng giao diện từ điển và thêm (các) tải trọng bằng set_content() và các phương thức liên quan hoặc chúng có thể được tạo bằng cách phân tích cú pháp trình bày được tuần tự hóa của thư email.

Gói email cung cấp trình phân tích cú pháp tiêu chuẩn có thể hiểu hầu hết các cấu trúc tài liệu email, bao gồm cả tài liệu MIME. Bạn có thể truyền cho trình phân tích cú pháp một đối tượng byte, chuỗi hoặc tệp và trình phân tích cú pháp sẽ trả về cho bạn phiên bản EmailMessage gốc của cấu trúc đối tượng. Đối với các tin nhắn đơn giản, không phải MIME, tải trọng của đối tượng gốc này có thể sẽ là một chuỗi chứa văn bản của tin nhắn. Đối với các tin nhắn MIME, đối tượng gốc sẽ trả về True từ phương thức is_multipart() của nó và các phần con có thể được truy cập thông qua các phương thức thao tác tải trọng, chẳng hạn như get_body(), iter_parts()walk().

Thực tế có hai giao diện phân tích cú pháp có sẵn để sử dụng, Parser API và FeedParser API gia tăng. Parser API hữu ích nhất nếu bạn có toàn bộ nội dung của tin nhắn trong bộ nhớ hoặc nếu toàn bộ tin nhắn nằm trong một tệp trên hệ thống tệp. FeedParser thích hợp hơn khi bạn đang đọc tin nhắn từ một luồng có thể chặn việc chờ thêm đầu vào (chẳng hạn như đọc tin nhắn email từ ổ cắm). Zz004zz có thể sử dụng và phân tích thông báo tăng dần và chỉ trả về đối tượng gốc khi bạn đóng trình phân tích cú pháp.

Lưu ý rằng trình phân tích cú pháp có thể được mở rộng theo những cách hạn chế và tất nhiên bạn có thể triển khai trình phân tích cú pháp của riêng mình hoàn toàn từ đầu. Tất cả logic kết nối trình phân tích cú pháp đi kèm của gói email và lớp EmailMessage đều được thể hiện trong lớp Policy, do đó, trình phân tích cú pháp tùy chỉnh có thể tạo cây đối tượng thông báo theo bất kỳ cách nào nó thấy cần thiết bằng cách triển khai các phiên bản tùy chỉnh của các phương thức Policy thích hợp.

FeedParser API

BytesFeedParser, được nhập từ mô-đun email.feedparser, cung cấp API có lợi cho việc phân tích cú pháp gia tăng các thông báo email, chẳng hạn như điều cần thiết khi đọc văn bản của thông báo email từ một nguồn có thể chặn (chẳng hạn như ổ cắm). Tất nhiên, BytesFeedParser có thể được sử dụng để phân tích cú pháp một email chứa đầy đủ trong bytes-like object, chuỗi hoặc tệp, nhưng BytesParser API có thể thuận tiện hơn cho những trường hợp sử dụng như vậy. Ngữ nghĩa và kết quả của hai API trình phân tích cú pháp giống hệt nhau.

API của BytesFeedParser rất đơn giản; bạn tạo một phiên bản, cung cấp cho nó một loạt byte cho đến khi không còn byte nào để cung cấp cho nó, sau đó đóng trình phân tích cú pháp để truy xuất đối tượng thông báo gốc. BytesFeedParser cực kỳ chính xác khi phân tích các tin nhắn tuân thủ tiêu chuẩn và thực hiện rất tốt việc phân tích các tin nhắn không tuân thủ, cung cấp thông tin về cách một tin nhắn được coi là bị hỏng. Nó sẽ điền vào thuộc tính defects của đối tượng tin nhắn một danh sách các vấn đề mà nó tìm thấy trong tin nhắn. Xem mô-đun email.errors để biết danh sách các lỗi mà nó có thể tìm thấy.

Đây là API cho BytesFeedParser:

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

Tạo một phiên bản BytesFeedParser. _factory tùy chọn là một lệnh gọi không có đối số; nếu không được chỉ định, hãy sử dụng message_factory từ policy. Gọi _factory bất cứ khi nào cần một đối tượng tin nhắn mới.

Nếu policy được chỉ định, hãy sử dụng các quy tắc mà nó chỉ định để cập nhật cách trình bày thông báo. Nếu policy không được đặt, hãy sử dụng chính sách compat32 để duy trì khả năng tương thích ngược với phiên bản Python 3.2 của gói email và cung cấp Message làm mặc định ban đầu. Tất cả các chính sách khác đều cung cấp EmailMessage làm _factory mặc định. Để biết thêm thông tin về những điều khiển khác của policy, hãy xem tài liệu về policy.

Lưu ý: The policy keyword should always be specified; Mặc định sẽ thay đổi thành email.policy.default trong phiên bản Python trong tương lai.

Added in version 3.2.

Thay đổi trong phiên bản 3.3: Đã thêm từ khóa policy.

Thay đổi trong phiên bản 3.6: _factory mặc định theo chính sách message_factory.

feed(data)

Cung cấp cho trình phân tích cú pháp thêm một số dữ liệu. data phải là bytes-like object chứa một hoặc nhiều dòng. Các dòng có thể là một phần và trình phân tích cú pháp sẽ ghép các dòng một phần đó lại với nhau một cách chính xác. Các dòng có thể có bất kỳ kết thúc nào trong ba kết thúc dòng phổ biến: xuống dòng, xuống dòng hoặc xuống dòng và xuống dòng (thậm chí chúng có thể được trộn lẫn).

close()

Hoàn thành việc phân tích cú pháp tất cả dữ liệu được cung cấp trước đó và trả về đối tượng thông báo gốc. Không xác định được điều gì sẽ xảy ra nếu feed() được gọi sau khi phương thức này được gọi.

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

Hoạt động giống như BytesFeedParser ngoại trừ đầu vào của phương thức feed() phải là một chuỗi. Đây là tiện ích hạn chế, vì cách duy nhất để một tin nhắn như vậy hợp lệ là nó chỉ chứa văn bản ASCII hoặc, nếu utf8True, không có tệp đính kèm nhị phân.

Thay đổi trong phiên bản 3.3: Đã thêm từ khóa policy.

Trình phân tích cú pháp API

Lớp BytesParser, được nhập từ mô-đun email.parser, cung cấp API có thể được sử dụng để phân tích thông báo khi nội dung đầy đủ của thông báo có sẵn trong bytes-like object hoặc tệp. Mô-đun email.parser cũng cung cấp Parser để phân tích chuỗi và các trình phân tích cú pháp chỉ có tiêu đề, BytesHeaderParserHeaderParser, có thể được sử dụng nếu bạn chỉ quan tâm đến tiêu đề của thư. BytesHeaderParserHeaderParser có thể nhanh hơn nhiều trong những trường hợp này, vì chúng không cố gắng phân tích nội dung thư mà thay vào đó đặt tải trọng vào nội dung thô.

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

Tạo một phiên bản BytesParser. Các đối số _classpolicy có cùng ý nghĩa và ngữ nghĩa như các đối số _factorypolicy của BytesFeedParser.

Lưu ý: The policy keyword should always be specified; Mặc định sẽ thay đổi thành email.policy.default trong phiên bản Python trong tương lai.

Thay đổi trong phiên bản 3.3: Đã xóa đối số strict không được dùng nữa trong 2.4. Đã thêm từ khóa policy.

Thay đổi trong phiên bản 3.6: _class mặc định theo chính sách message_factory.

parse(fp, headersonly=False)

Đọc tất cả dữ liệu từ đối tượng giống như tệp nhị phân fp, phân tích các byte kết quả và trả về đối tượng thông báo. fp phải hỗ trợ cả phương pháp readline()read().

Các byte chứa trong fp phải được định dạng dưới dạng một khối gồm các tiêu đề kiểu RFC 5322 (hoặc, nếu utf8True, RFC 6532) và các dòng tiếp tục tiêu đề, tùy chọn đặt trước một tiêu đề phong bì. Khối tiêu đề được kết thúc ở cuối dữ liệu hoặc bằng một dòng trống. Sau khối tiêu đề là nội dung của thông báo (có thể chứa các phần con được mã hóa MIME, bao gồm cả các phần con có Content-Transfer-Encoding8bit).

Tùy chọn headersonly là cờ chỉ định có dừng phân tích cú pháp sau khi đọc tiêu đề hay không. Mặc định là False, nghĩa là nó phân tích toàn bộ nội dung của tệp.

parsebytes(bytes, headersonly=False)

Tương tự như phương thức parse(), ngoại trừ việc nó sử dụng bytes-like object thay vì một đối tượng giống như tệp. Gọi phương thức này trên bytes-like object tương đương với việc gói bytes trong phiên bản BytesIO trước và gọi parse().

headersonly tùy chọn giống như phương pháp parse().

Added in version 3.2.

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

Hoàn toàn giống BytesParser, ngoại trừ headersonly mặc định là True.

Added in version 3.3.

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

Lớp này song song với BytesParser, nhưng xử lý đầu vào chuỗi.

Thay đổi trong phiên bản 3.3: Đã xóa đối số strict. Đã thêm từ khóa policy.

Thay đổi trong phiên bản 3.6: _class mặc định theo chính sách message_factory.

parse(fp, headersonly=False)

Đọc tất cả dữ liệu từ đối tượng giống như tệp chế độ văn bản fp, phân tích văn bản kết quả và trả về đối tượng thông báo gốc. fp phải hỗ trợ cả hai phương thức readline()read() trên các đối tượng giống như tệp.

Ngoài yêu cầu về chế độ văn bản, phương pháp này hoạt động giống như BytesParser.parse().

parsestr(text, headersonly=False)

Tương tự như phương thức parse(), ngoại trừ việc nó lấy một đối tượng chuỗi thay vì một đối tượng giống như tệp. Việc gọi phương thức này trên một chuỗi tương đương với việc gói text trong phiên bản StringIO trước và gọi parse().

headersonly tùy chọn giống như phương pháp parse().

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

Hoàn toàn giống Parser, ngoại trừ headersonly mặc định là True.

Vì việc tạo cấu trúc đối tượng thông báo từ một chuỗi hoặc một đối tượng tệp là một nhiệm vụ phổ biến nên bốn hàm được cung cấp để thuận tiện. Chúng có sẵn trong không gian tên gói email cấp cao nhất.

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

Trả về cấu trúc đối tượng tin nhắn từ bytes-like object. Điều này tương đương với BytesParser().parsebytes(s). _classpolicy tùy chọn được hiểu như với hàm tạo của lớp BytesParser.

Added in version 3.2.

Thay đổi trong phiên bản 3.3: Đã xóa đối số strict. Đã thêm từ khóa policy.

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

Trả về cây cấu trúc đối tượng thông báo từ một file object nhị phân mở. Điều này tương đương với BytesParser().parse(fp). _classpolicy được hiểu như với hàm tạo của lớp BytesParser.

Added in version 3.2.

Thay đổi trong phiên bản 3.3: Đã xóa đối số strict. Đã thêm từ khóa policy.

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

Trả về cấu trúc đối tượng tin nhắn từ một chuỗi. Điều này tương đương với Parser().parsestr(s). _classpolicy được hiểu như với hàm tạo của lớp Parser.

Thay đổi trong phiên bản 3.3: Đã xóa đối số strict. Đã thêm từ khóa policy.

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

Trả về cây cấu trúc đối tượng tin nhắn từ file object đang mở. Điều này tương đương với Parser().parse(fp). _classpolicy được hiểu như với hàm tạo của lớp Parser.

Thay đổi trong phiên bản 3.3: Đã xóa đối số strict. Đã thêm từ khóa policy.

Thay đổi trong phiên bản 3.6: _class mặc định theo chính sách message_factory.

Đây là ví dụ về cách bạn có thể sử dụng message_from_bytes() tại dấu nhắc Python tương tác:

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

Ghi chú bổ sung

Dưới đây là một số lưu ý về ngữ nghĩa phân tích cú pháp:

  • Hầu hết các tin nhắn loại không phải multipart đều được phân tích cú pháp dưới dạng một đối tượng tin nhắn duy nhất có tải trọng chuỗi. Các đối tượng này sẽ trả về False cho is_multipart()iter_parts() sẽ mang lại một danh sách trống.

  • Tất cả các tin nhắn loại multipart sẽ được phân tích cú pháp dưới dạng đối tượng tin nhắn chứa với danh sách các đối tượng tin nhắn phụ cho tải trọng của chúng. Thông báo vùng chứa bên ngoài sẽ trả về True cho is_multipart()iter_parts() sẽ mang lại danh sách các phần phụ.

  • Hầu hết các tin nhắn có loại nội dung message/* (chẳng hạn như message/delivery-statusmessage/rfc822) cũng sẽ được phân tích cú pháp dưới dạng đối tượng vùng chứa chứa tải trọng danh sách có độ dài 1. Phương thức is_multipart() của chúng sẽ trả về True. Phần tử duy nhất do iter_parts() mang lại sẽ là một đối tượng thông báo phụ.

  • Một số thông báo không tuân thủ tiêu chuẩn có thể không nhất quán nội bộ về độ multipart-edness của chúng. Những tin nhắn như vậy có thể có tiêu đề Content-Type thuộc loại multipart, nhưng phương thức is_multipart() của chúng có thể trả về False. Nếu những tin nhắn như vậy được phân tích cú pháp bằng FeedParser, chúng sẽ có một phiên bản của lớp MultipartInvariantViolationDefect trong danh sách thuộc tính defects của chúng. Xem email.errors để biết chi tiết.