kilter.service.session module
Sessions are the kernel of a filter, providing it with an async API to access messages
- exception Aborted[source]
Bases:
BaseExceptionAn exception for aborting filters on receipt of an Abort message
- class Filter(*args, **kwargs)[source]
Bases:
ProtocolFilters are callables that accept a
Sessionand return a response
- class Phase(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]
-
Session phases indicate what messages to expect and are impacted by received messages
Users should not generally need to use these values, however an understanding of the state-flow they represent is useful for understanding some error exception raised by
Sessionmethods.- CONNECT = 1
This phase is the starting phase of a session, during which a HELO/EHLO message may be awaited with
Session.helo().
- MAIL = 2
This phase is entered after HELO/EHLO, during which a MAIL message may be awaited with
Session.envelope_from(). TheSession.extension()method may also be used to get the raw MAIL command with any extension arguments, or any other extension commands that the MTA does not support (if the MTA supports passing these commands to a filter).
- ENVELOPE = 3
This phase is entered after MAIL, during which any RCPT commands may be awaited with
Session.envelope_recipients(). TheSession.extension()method may also be used to get the raw RCPT command with any extension arguments, or any other extension commands that the MTA does not support (if the MTA supports passing these commands to a filter).
- HEADERS = 4
This phase is entered after a DATA command, while message headers are processed. Headers may be iterated as they arrive, or be collected for later through the
Session.headersobject.
- BODY = 5
This phase is entered after a message’s headers have been processed. The raw message body may be iterated over in chunks through the
Session.bodyobject.
- POST = 6
This phase is entered once a message’s body has been completed (or skipped). During this phase the message editing methods of a
Sessionobject or theSession.headersandSession.bodyobjects may be used.
- class Position(subject: Union[Header, Literal['start'], Literal['end']])[source]
Bases:
objectA base class for
BeforeandAfter, this class is not intended to be used directly
- class Before(subject: Header)[source]
Bases:
PositionIndicates a relative position preceding a subject
Headerin a header list- subject: Header
- class After(subject: Header)[source]
Bases:
PositionIndicates a relative position following a subject
Headerin a header list- subject: Header
- START = Position(subject='start')
Indicates the start of a header list, before the first (current) header
- END = Position(subject='end')
Indicates the end of a header list, after the last (current) header
- class Session(connmsg: Connect, sender: AsyncGenerator[None, kilter.service.session.EditMessage], broadcast: Optional[Broadcast[kilter.service.session.EventMessage]] = None)[source]
Bases:
objectThe kernel of a filter, providing an API for filters to access messages from an MTA
- host: str
A hostname from a reverse address lookup performed when a client connects
If no name is found this value defaults to the standard presentation format for
Session.addresssurrounded by “[” and “]”, e.g. “[192.0.2.100]”
- address: ipaddress.IPv4Address | ipaddress.IPv6Address | pathlib.Path | None
The address of the connected client, or None if unknown
- macros: dict[str, str]
A mapping of string replacements sent by the MTA
See smfi_getsymval from libmilter for more information.
Warning
The current implementation is very naïve and does not behave exactly like libmilter, nor is it very robust. It will definitely change in the future.
- headers: HeadersAccessor
A
HeadersAccessorobject for accessing and modifying the message header fields
- body: BodyAccessor
A
BodyAccessorobject for accessing and modifying the message body
- async deliver(message: kilter.service.session.EventMessage) type[kilter.protocol.messages.Continue] | type[kilter.protocol.messages.Skip][source]
Deliver a message (or its contents) to a task waiting for it
- async envelope_from() str[source]
Wait for a MAIL command message and return the sender identity
Note that if extensions arguments are wanted, users should use
Session.extension()instead with a name of"MAIL".
- async envelope_recipients() AsyncIterator[str][source]
Wait for RCPT command messages and iteratively yield the recipients’ identities
Note that if extensions arguments are wanted, users should use
Session.extension()instead with a name of"RCPT".
- async extension(name: str) memoryview[source]
Wait for the named command extension and return the raw command for processing
- async change_sender(sender: str, args: str = '') None[source]
Move onto the
Phase.POSTphase and instruct the MTA to change the sender address
- async add_recipient(recipient: str, args: str = '') None[source]
Move onto the
Phase.POSTphase and instruct the MTA to add a new recipient address
- async remove_recipient(recipient: str) None[source]
Move onto the
Phase.POSTphase and instruct the MTA to remove a recipient address
- class HeadersAccessor(session: Session, sender: AsyncGenerator[None, kilter.service.session.EditMessage])[source]
Bases:
AsyncContextManager[HeaderIterator]A class that allows access and modification of the message headers sent from an MTA
To access headers (which are only available iteratively), use an instance as an asynchronous context manager; a
HeaderIteratoris returned when the context is entered.- async collect() None[source]
Collect all headers without producing an iterator
Calling this method before the
Phase.BODYphase allows later processing of headers (after the HEADER phase) without the need for an empty loop.
- async delete(header: Header) None[source]
Move onto the
Phase.POSTphase and Instruct the MTA to delete the given header
- async update(header: Header, value: bytes) None[source]
Move onto the
Phase.POSTphase and Instruct the MTA to modify the value of a header
- class HeaderIterator(aiter: AsyncGenerator[Header, None])[source]
Bases:
AsyncGenerator[Header,None]Iterator for headers obtained by using a
HeadersAccessoras a context manager- async asend(value: None = None) Header[source]
Send a value into the asynchronous generator. Return next yielded value or raise StopAsyncIteration.
- async athrow(e: type[BaseException] | BaseException, m: object = None, t: types.TracebackType | None = None, /) Header[source]
Raise an exception in the asynchronous generator. Return next yielded value or raise StopAsyncIteration.
- async restrict(*names: str) AsyncIterator[Header][source]
Return an asynchronous generator that filters headers by name
- class BodyAccessor(session: Session, sender: AsyncGenerator[None, kilter.service.session.EditMessage])[source]
Bases:
AsyncContextManager[AsyncIterator[memoryview]]A class that allows access and modification of the message body sent from an MTA
To access chunks of a body (which are only available iteratively), use an instance as an asynchronous context manager; an asynchronous iterator is returned when the context is entered.
- async write(chunk: bytes) None[source]
Request that chunks of a new message body are sent to the MTA
This method should not be called from within the scope created by using it’s instance as an async context (async with); doing so may cause a warning to be issued and the rest of the message body to be skipped.