Skip to content

Message

email_profile.serializers.email.Message

Bases: BaseModel

One email message as a validated DTO.

Source code in email_profile/serializers/email.py
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
class Message(BaseModel):
    """One email message as a validated DTO."""

    model_config = ConfigDict(
        populate_by_name=True, arbitrary_types_allowed=True
    )

    message_id: Optional[str] = None
    uid: str
    date: Optional[datetime] = None
    mailbox: str

    from_: Optional[str] = Field(default=None, alias="from")
    to_: Optional[str] = Field(default=None, alias="to")
    cc: Optional[str] = None
    bcc: Optional[str] = None
    reply_to: Optional[str] = None

    subject: Optional[str] = None
    file: str
    body_text_plain: str = ""
    body_text_html: str = ""
    content_type: Optional[str] = None

    in_reply_to: Optional[str] = None
    references: Optional[str] = None

    list_id: Optional[str] = None
    list_unsubscribe: Optional[str] = None

    attachments: list[Attachment] = []

    headers: dict[str, Union[str, list[str]]] = {}

    @classmethod
    def from_raw(
        cls,
        *,
        uid: str,
        mailbox: str,
        raw: bytes,
    ) -> Message:
        """Parse RFC822 bytes into a serializer."""
        parsed: ParsedBody = parse_rfc822(raw)

        return cls(
            message_id=parsed.message_id or sha256(raw).hexdigest(),
            uid=uid,
            mailbox=mailbox,
            date=parsed.date,
            **{"from": parsed.from_, "to": parsed.to_},
            cc=parsed.cc,
            bcc=parsed.bcc,
            reply_to=parsed.reply_to,
            subject=parsed.subject,
            file=raw.decode("utf-8", errors="replace"),
            body_text_plain=parsed.body_text_plain,
            body_text_html=parsed.body_text_html,
            content_type=parsed.content_type,
            in_reply_to=parsed.in_reply_to,
            references=parsed.references,
            list_id=parsed.list_id,
            list_unsubscribe=parsed.list_unsubscribe,
            attachments=parsed.attachments,
            headers=parsed.headers,
        )

    def __repr__(self) -> str:
        date = self.date.isoformat() if self.date else "?"
        subj = (self.subject or "")[:40]
        return (
            f"Message(uid={self.uid!r}, from={self.from_!r}, "
            f"date={date}, subject={subj!r})"
        )

attachments = [] class-attribute instance-attribute

bcc = None class-attribute instance-attribute

body_text_html = '' class-attribute instance-attribute

body_text_plain = '' class-attribute instance-attribute

cc = None class-attribute instance-attribute

content_type = None class-attribute instance-attribute

date = None class-attribute instance-attribute

file instance-attribute

from_ = Field(default=None, alias='from') class-attribute instance-attribute

headers = {} class-attribute instance-attribute

in_reply_to = None class-attribute instance-attribute

list_id = None class-attribute instance-attribute

list_unsubscribe = None class-attribute instance-attribute

mailbox instance-attribute

message_id = None class-attribute instance-attribute

model_config = ConfigDict(populate_by_name=True, arbitrary_types_allowed=True) class-attribute instance-attribute

references = None class-attribute instance-attribute

reply_to = None class-attribute instance-attribute

subject = None class-attribute instance-attribute

to_ = Field(default=None, alias='to') class-attribute instance-attribute

uid instance-attribute

__repr__()

Source code in email_profile/serializers/email.py
81
82
83
84
85
86
87
def __repr__(self) -> str:
    date = self.date.isoformat() if self.date else "?"
    subj = (self.subject or "")[:40]
    return (
        f"Message(uid={self.uid!r}, from={self.from_!r}, "
        f"date={date}, subject={subj!r})"
    )

from_raw(*, uid, mailbox, raw) classmethod

Parse RFC822 bytes into a serializer.

Source code in email_profile/serializers/email.py
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
@classmethod
def from_raw(
    cls,
    *,
    uid: str,
    mailbox: str,
    raw: bytes,
) -> Message:
    """Parse RFC822 bytes into a serializer."""
    parsed: ParsedBody = parse_rfc822(raw)

    return cls(
        message_id=parsed.message_id or sha256(raw).hexdigest(),
        uid=uid,
        mailbox=mailbox,
        date=parsed.date,
        **{"from": parsed.from_, "to": parsed.to_},
        cc=parsed.cc,
        bcc=parsed.bcc,
        reply_to=parsed.reply_to,
        subject=parsed.subject,
        file=raw.decode("utf-8", errors="replace"),
        body_text_plain=parsed.body_text_plain,
        body_text_html=parsed.body_text_html,
        content_type=parsed.content_type,
        in_reply_to=parsed.in_reply_to,
        references=parsed.references,
        list_id=parsed.list_id,
        list_unsubscribe=parsed.list_unsubscribe,
        attachments=parsed.attachments,
        headers=parsed.headers,
    )