Skip to content

Commit

Permalink
Merge pull request #418 from mjcaley/new-docs
Browse files Browse the repository at this point in the history
Updating documentation for 1.0
  • Loading branch information
mjcaley committed Oct 10, 2023
2 parents e6a5302 + 0c174d5 commit 3634e1d
Show file tree
Hide file tree
Showing 7 changed files with 200 additions and 98 deletions.
113 changes: 75 additions & 38 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
========
########
aiospamc
========
########

|pypi| |docs| |license| |unit| |integration| |python|

Expand All @@ -22,54 +22,58 @@ aiospamc
.. |python| image:: https://img.shields.io/pypi/pyversions/aiospamc
:target: https://python.org

-----------
Description
-----------
**aiospamc** is a client for SpamAssassin that you can use as a library or command line tool.

Python asyncio-based library that implements the SPAMC/SPAMD client protocol used by SpamAssassin.
The implementation is based on asyncio; so you can use it in your applications for asynchronous calls.

-------------
The command line interface provides user-friendly access to SpamAssassin server commands and provides both JSON
and user-consumable outputs.

*************
Documentation
-------------
*************

Documentation can be found at: https://aiospamc.readthedocs.io/
Detailed documentation can be found at: https://aiospamc.readthedocs.io/

------------
************
Requirements
------------
************

* Python 3.8 or higher
* `certifi` for updated certificate authorities
* `loguru` for structured logging
* `typer` for the command line interface

********
Examples
********

----------------------
As a Command Line Tool
----------------------
Command-Line Tool
=================

`aiospamc` is your interface to SpamAssassin through CLI. To submit a message
for a score, use:

.. code::
cat ./gtube.msg | aiospamc check
and the response will be the score of the message:

.. code::
.. code-block:: console
# Take the output of gtube.msg and have SpamAssasin return a score
$ cat ./gtube.msg | aiospamc check
1000.0/5.0
Sub-commands for learning and reporting are also supported.
# Ping the server
$ aiospamc ping
PONG
------------
As a Library
------------
Library
=======

.. code:: python
.. code-block:: python
import asyncio
import aiospamc
GTUBE = '''Subject: Test spam mail (GTUBE)
GTUBE = """Subject: Test spam mail (GTUBE)
Message-ID: <GTUBE1.1010101@example.net>
Date: Wed, 23 Jul 2003 23:30:00 +0200
From: Sender <sender@example.net>
Expand All @@ -94,14 +98,47 @@ As a Library
XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
You should send this test mail from an account outside of your network.
'''.encode('ascii')
loop = asyncio.get_event_loop()
responses = loop.run_until_complete(asyncio.gather(
aiospamc.ping(host='localhost'),
aiospamc.check(GTUBE, host='localhost'),
aiospamc.headers(GTUBE, host='localhost')
))
print(responses)
""".encode("ascii")
# Ping the SpamAssassin server
async def is_alive():
pong = await aiospamc.ping()
return True if pong.status_code == 0 else False
asyncio.run(is_alive())
# True
# Get the spam score of a message
async def get_score(message):
response = await aiospamc.check(message)
return response.headers.spam.score, response.headers.spam.threshold
asyncio.run(get_score(GTUBE))
# (1000.0, 5.0)
# List the modified headers
async def list_headers(message):
response = await aiospamc.headers(message)
for line in response.body.splitlines():
print(line.decode())
asyncio.run(list_headers(GTUBE))
# Received: from localhost by DESKTOP.
# with SpamAssassin (version 4.0.0);
# Wed, 30 Aug 2023 20:11:34 -0400
# From: Sender <sender@example.net>
# To: Recipient <recipient@example.net>
# Subject: Test spam mail (GTUBE)
# Date: Wed, 23 Jul 2003 23:30:00 +0200
# Message-Id: <GTUBE1.1010101@example.net>
# X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-14) on DESKTOP.
# X-Spam-Flag: YES
# X-Spam-Level: **************************************************
# X-Spam-Status: Yes, score=1000.0 required=5.0 tests=GTUBE,NO_RECEIVED,
# NO_RELAYS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no
# version=4.0.0
# MIME-Version: 1.0
# Content-Type: multipart/mixed; boundary="----------=_64EFDAB6.3640FAEF"
4 changes: 2 additions & 2 deletions aiospamc/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@ class CliClientBuilder:
"""Client builder for CLI arguments."""

def __init__(self):
"""Constructor for the ClieClientBuilder."""
"""Constructor for the CliClientBuilder."""

self._connection_builder = ConnectionManagerBuilder()
self._ssl = False
self._ssl_builder = SSLContextBuilder()

def build(self) -> Client:
"""Builds the `Client`.
"""Builds the :class:`aiospamc.client.Client`.
:return: An instance of :class:`aiospamc.client.Client`.
"""
Expand Down
14 changes: 7 additions & 7 deletions aiospamc/connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def __init__(self):
self._timeout = None

def build(self) -> Union[UnixConnectionManager, TcpConnectionManager]:
"""Builds the `ConnectionManager`.
"""Builds the :class:`aiospamc.connections.ConnectionManager`.
:return: An instance of :class:`aiospamc.connections.TcpConnectionManager`
or :class:`aiospamc.connections.UnixConnectionManager`
Expand Down Expand Up @@ -116,7 +116,7 @@ def with_tcp(self, host: str, port: int = 783) -> ConnectionManagerBuilder:
def add_ssl_context(self, context: ssl.SSLContext) -> ConnectionManagerBuilder:
"""Adds an SSL context when a TCP connection is being used.
:param context: `ssl.SSLContext` instance.
:param context: :class:`ssl.SSLContext` instance.
:return: This builder instance.
"""
Expand Down Expand Up @@ -259,7 +259,7 @@ def __init__(self):
self._args = {}

def build(self) -> TcpConnectionManager:
"""Builds the `TcpConnectionManager`.
"""Builds the :class:`aiospamc.connections.TcpConnectionManager`.
:return: An instance of :class:`aiospamc.connections.TcpConnectionManager`.
"""
Expand Down Expand Up @@ -291,7 +291,7 @@ def set_port(self, port: int) -> TcpConnectionManagerBuilder:
def set_ssl_context(self, context: ssl.SSLContext) -> TcpConnectionManagerBuilder:
"""Set an SSL context.
:param context: An instance of `ssl.SSLContext`.
:param context: An instance of :class:`ssl.SSLContext`.
:return: This builder instance.
"""
Expand Down Expand Up @@ -354,15 +354,15 @@ async def open(self) -> Tuple[asyncio.StreamReader, asyncio.StreamWriter]:


class UnixConnectionManagerBuilder:
"""Builder for `UnixConnectionManager`."""
"""Builder for :class:`aiospamc.connections.UnixConnectionManager`."""

def __init__(self):
"""`UnixConnectionManagerBuilder` constructor."""

self._args = {}

def build(self) -> UnixConnectionManager:
"""Builds a `UnixConnectionManager`.
"""Builds a :class:`aiospamc.connections.UnixConnectionManager`.
:return: An instance of :class:`aiospamc.connections.UnixConnectionManager`.
"""
Expand Down Expand Up @@ -433,7 +433,7 @@ def __init__(self):
def build(self) -> ssl.SSLContext:
"""Builds the SSL context.
:return: An instance of `ssl.SSLContext`.
:return: An instance of :class:`ssl.SSLContext`.
"""

return self._context
Expand Down

0 comments on commit 3634e1d

Please sign in to comment.