.\" -*- mode: troff; coding: utf-8 -*- .\" Automatically generated by Pod::Man 5.01 (Pod::Simple 3.43) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. .ie n \{\ . ds C` "" . ds C' "" 'br\} .el\{\ . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Mail::SpamAssassin::Pyzor::Client 3pm" .TH Mail::SpamAssassin::Pyzor::Client 3pm 2024-04-02 "perl v5.38.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH NAME Mail::SpamAssassin::Pyzor::Client \- Pyzor client logic .SH SYNOPSIS .IX Header "SYNOPSIS" .Vb 2 \& use Mail::SpamAssassin::Pyzor::Client (); \& use Mail::SpamAssassin::Pyzor::Digest (); \& \& my $client = Mail::SpamAssassin::Pyzor::Client\->new(); \& \& my $digest = Mail::SpamAssassin::Pyzor::Digest::get( $msg ); \& \& my $check_ref = $client\->check($digest); \& die $check_ref\->{\*(AqDiag\*(Aq} if $check_ref\->{\*(AqCode\*(Aq} ne \*(Aq200\*(Aq; \& \& my $report_ref = $client\->report($digest); \& die $report_ref\->{\*(AqDiag\*(Aq} if $report_ref\->{\*(AqCode\*(Aq} ne \*(Aq200\*(Aq; .Ve .SH DESCRIPTION .IX Header "DESCRIPTION" A bare-bones Pyzor client that currently only implements the functionality needed for Mail::SpamAssassin. .SH "PROTOCOL DETAILS" .IX Header "PROTOCOL DETAILS" The Pyzor protocol is not a published standard, and there appears to be no meaningful public documentation. What follows is enough information, largely gleaned through forum posts and reverse engineering, to facilitate effective use of this module: .PP Pyzor is an RPC-oriented, message-based protocol. Each message is a simple dictionary of 7\-bit ASCII keys and values. Server responses always include at least the following: .IP \(bu 4 \&\f(CW\*(C`Code\*(C'\fR \- Similar to HTTP status codes; anything besides \f(CW200\fR is an error. .IP \(bu 4 \&\f(CW\*(C`Diag\*(C'\fR \- Similar to HTTP status reasons: a text description of the status. .PP (NB: There are additional standard response headers that are useful only for the protocol itself and thus are not part of this module's returns.) .SS Reliability .IX Subsection "Reliability" Pyzor uses UDP rather than TCP, so no message is guaranteed to reach its destination. A transmission failure can happen in either the request or the response; in either case, a timeout error will result. Such errors are represented as thrown instances of Mail::Pyzor::X::Timeout. .SH CONSTRUCTOR .IX Header "CONSTRUCTOR" .SS new(%OPTS) .IX Subsection "new(%OPTS)" Create a new pyzor client. .IP Input 2 .IX Item "Input" \&\f(CW%OPTS\fR are (all optional): .RS 2 .IP \(bu 3 \&\f(CW\*(C`server_host\*(C'\fR \- The pyzor server host to connect to (default is \&\f(CW\*(C`public.pyzor.org\*(C'\fR) .IP \(bu 3 \&\f(CW\*(C`server_port\*(C'\fR \- The pyzor server port to connect to (default is 24441) .IP \(bu 3 \&\f(CW\*(C`username\*(C'\fR \- The username to present to the pyzor server (default is \f(CW\*(C`anonymous\*(C'\fR) .IP \(bu 3 \&\f(CW\*(C`password\*(C'\fR \- The password to present to the pyzor server (default is empty) .IP \(bu 3 \&\f(CW\*(C`timeout\*(C'\fR \- The maximum time, in seconds, to wait for a response from the pyzor server (defeault is 3.5) .RE .RS 2 .RE .IP Output 2 .IX Item "Output" .RS 2 .RS 3 Returns a Mail::SpamAssassin::Pyzor::Client object. .RE .RE .RS 2 .RE .SH "REQUEST METHODS" .IX Header "REQUEST METHODS" .SS report($digest) .IX Subsection "report($digest)" Report the digest of a spam message to the pyzor server. This function will throw if a messaging failure or timeout happens. .IP Input 2 .IX Item "Input" .RS 2 .PD 0 .ie n .IP "$digest ""SCALAR""" 3 .el .IP "\f(CW$digest\fR \f(CWSCALAR\fR" 3 .IX Item "$digest SCALAR" .PD The message digest to report, as given by \&\f(CWMail::SpamAssassin::Pyzor::Digest::get()\fR. .RE .RS 2 .RE .IP Output 2 .IX Item "Output" .RS 2 .PD 0 .ie n .IP """HASHREF""" 3 .el .IP \f(CWHASHREF\fR 3 .IX Item "HASHREF" .PD Returns a hashref of the standard attributes noted above. .RE .RS 2 .RE .SS check($digest) .IX Subsection "check($digest)" Check the digest of a message to see if the pyzor server has a report for it. This function will throw if a messaging failure or timeout happens. .IP Input 2 .IX Item "Input" .RS 2 .PD 0 .ie n .IP "$digest ""SCALAR""" 3 .el .IP "\f(CW$digest\fR \f(CWSCALAR\fR" 3 .IX Item "$digest SCALAR" .PD The message digest to check, as given by \&\f(CWMail::SpamAssassin::Pyzor::Digest::get()\fR. .RE .RS 2 .RE .IP Output 2 .IX Item "Output" .RS 2 .PD 0 .ie n .IP """HASHREF""" 3 .el .IP \f(CWHASHREF\fR 3 .IX Item "HASHREF" .PD Returns a hashref of the standard attributes noted above as well as the following: .RS 3 .IP \(bu 4 \&\f(CW\*(C`Count\*(C'\fR \- The number of reports the server has received for the given digest. .IP \(bu 4 \&\f(CW\*(C`WL\-Count\*(C'\fR \- The number of whitelist requests the server has received for the given digest. .RE .RS 3 .RE .RE .RS 2 .RE