User Guide¶
Requirements¶
Python 3.5 or later is required to use the new async/await syntax provided by the asyncio library.
SpamAssassin running as a service.
Install¶
With PIP¶
pip install aiospamc
With GIT¶
git clone https://github.com/mjcaley/aiospamc.git
poetry install
Note
aiospamc’s build system uses Poetry which you can get from here: https://poetry.eustace.io/
How to use aiospamc¶
aiospamc
provides top-level functions for basic functionality a lot like
the requests library.
For example, to ask SpamAssassin to check and score a message you can use the
aiospamc.check()
function. Just give it a bytes-encoded copy of the
message, specify the host and await on the request. In this case, the response
will contain a header called Spam with a boolean if the message is considered
spam as well as the score.
import asyncio
import aiospamc
example_message = ('From: John Doe <jdoe@machine.example>'
'To: Mary Smith <mary@example.net>'
'Subject: Saying Hello'
'Date: Fri, 21 Nov 1997 09:55:06 -0600'
'Message-ID: <1234@local.machine.example>'
''
'This is a message just to say hello.'
'So, "Hello".').encode('ascii')
async def check_for_spam(message):
response = await aiospamc.check(message, host='localhost')
return response
loop = asyncio.get_event_loop()
response = loop.run_until_complete(check_for_spam(example_message))
print(
'Is the message spam? {}'.format(response.headers['Spam'].value),
'The score and threshold is {} / {}'.format(
response.headers['Spam'].score,
response.headers['Spam'].threshold)
)
All the frontend functions instantiate the aiospamc.client.Client
class behind the scenes. Additional keywords arguments can be found in the
class constructor documentation.
Connect using SSL¶
Each frontend function and aiospamc.client.Client
has a verify
parameter which allows configuring an SSL connection.
If True is supplied, then root certificates from the certifi project will be used to verify the connection.
If a path is supplied as a string or pathlib.Path
object then the path
is used to load certificates to verify the connection.
If False then an SSL connection is established, but the server certificate is not verified.
Making your own requests¶
If a request that isn’t built into aiospamc is needed a new request can be created and sent.
A new request can be made by instantiating the
aiospamc.requests.Request
class. The
aiospamc.requests.Request.verb
defines the method/verb of the request.
The aiospamc.requests.Request
class provides a headers attribute that has
a dictionary-like interface. Defined headers can be referenced in the Headers
section in SPAMC/SPAMD Protocol As Implemented by SpamAssassin.
Once a request is composed, the aiospamc.client.Client
class can be
instantiated and the request can be sent through the
aiospamc.client.Client.send()
method. The method will automatically
add the User and Compress headers if required.
For example:
import asyncio
import aiospamc
from aiospamc import Client
from aiospamc.exceptions import ResponseException
from aiospamc.requests import Request
example_message = ('From: John Doe <jdoe@machine.example>'
'To: Mary Smith <mary@example.net>'
'Subject: Saying Hello'
'Date: Fri, 21 Nov 1997 09:55:06 -0600'
'Message-ID: <1234@local.machine.example>'
''
'This is a message just to say hello.'
'So, "Hello".').encode('ascii')
loop = asyncio.get_event_loop()
client = aiospamc.Client(host='localhost')
async def is_spam(message):
request = Request(verb='CHECK', body=message.encode())
try:
response = await client.send(request)
return response.get_header('Spam').value
except aiospamc.ResponseException:
raise
spam_result = loop.run_until_complete(is_spam(example_message))
print('Example message is spam:', spam_result)
Interpreting results¶
Responses are encapsulated in the aiospamc.responses.Response
class.
It includes the status code, headers and body.