blob: d6675d24c5133a01315dcc673d0ca9ca28f3ed44 [file]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from __future__ import annotations
import email
import email.policy
from email.message import EmailMessage
from oauth_draft.create_draft import build_mime, headers_from_thread, parse_args
def parse_built_message(raw: bytes) -> EmailMessage:
msg = email.message_from_bytes(raw, policy=email.policy.default)
assert isinstance(msg, EmailMessage)
return msg
def test_build_mime_sets_basic_headers():
raw = build_mime(
from_addr="me@example.com",
to=["a@example.com"],
cc=[],
bcc=[],
subject="Hello",
body="Body content.",
in_reply_to=None,
references=None,
)
msg = parse_built_message(raw)
assert msg["From"] == "me@example.com"
assert msg["To"] == "a@example.com"
assert msg["Subject"] == "Hello"
assert msg["Cc"] is None
assert msg["Bcc"] is None
assert msg["In-Reply-To"] is None
assert msg["References"] is None
assert msg.get_content().rstrip() == "Body content."
def test_build_mime_joins_multiple_recipients():
raw = build_mime(
from_addr="me@example.com",
to=["a@example.com", "b@example.com"],
cc=["cc1@example.com", "cc2@example.com"],
bcc=["bcc@example.com"],
subject="Multi",
body="x",
in_reply_to=None,
references=None,
)
msg = parse_built_message(raw)
assert msg["To"] == "a@example.com, b@example.com"
assert msg["Cc"] == "cc1@example.com, cc2@example.com"
assert msg["Bcc"] == "bcc@example.com"
def test_build_mime_sets_reply_headers_when_provided():
raw = build_mime(
from_addr="me@example.com",
to=["a@example.com"],
cc=[],
bcc=[],
subject="Re: Thing",
body="reply",
in_reply_to="<msg-1@example.com>",
references="<root@example.com> <msg-1@example.com>",
)
msg = parse_built_message(raw)
assert msg["In-Reply-To"] == "<msg-1@example.com>"
assert msg["References"] == "<root@example.com> <msg-1@example.com>"
def test_headers_from_thread_empty_returns_none_pair():
assert headers_from_thread({}) == (None, None)
assert headers_from_thread({"messages": []}) == (None, None)
def test_headers_from_thread_no_message_id_returns_none_pair():
thread = {"messages": [{"payload": {"headers": [{"name": "Subject", "value": "x"}]}}]}
assert headers_from_thread(thread) == (None, None)
def test_headers_from_thread_seeds_references_when_absent():
thread = {
"messages": [
{
"payload": {
"headers": [
{"name": "Message-ID", "value": "<a@example.com>"},
]
}
}
]
}
assert headers_from_thread(thread) == ("<a@example.com>", "<a@example.com>")
def test_headers_from_thread_appends_to_existing_references():
thread = {
"messages": [
{
"payload": {
"headers": [
{"name": "Message-ID", "value": "<root@example.com>"},
]
}
},
{
"payload": {
"headers": [
{"name": "Message-ID", "value": "<reply@example.com>"},
{"name": "References", "value": "<root@example.com>"},
]
}
},
]
}
in_reply_to, references = headers_from_thread(thread)
assert in_reply_to == "<reply@example.com>"
assert references == "<root@example.com> <reply@example.com>"
def test_headers_from_thread_is_case_insensitive_on_header_name():
thread = {
"messages": [
{
"payload": {
"headers": [
{"name": "message-id", "value": "<lower@example.com>"},
]
}
}
]
}
assert headers_from_thread(thread)[0] == "<lower@example.com>"
def test_parse_args_defaults():
args = parse_args(["--to", "x@example.com", "--subject", "S"])
assert args.to == ["x@example.com"]
assert args.cc == []
assert args.bcc == []
assert args.body_file == "-"
assert args.thread_id is None
assert args.no_reply_headers is False
def test_parse_args_repeats():
args = parse_args(
[
"--to",
"a@example.com",
"--to",
"b@example.com",
"--cc",
"c@example.com",
"--subject",
"S",
]
)
assert args.to == ["a@example.com", "b@example.com"]
assert args.cc == ["c@example.com"]