├── .gitignore
├── LICENSE
├── README.md
├── composer.json
├── phpunit.xml.dist
├── src
└── Spamassassin
│ ├── Client.php
│ └── Client
│ ├── Exception.php
│ └── Result.php
└── tests
├── BaseTestCase.php
├── CheckTest.php
├── ConnectionTest.php
├── HeadersTest.php
├── LearnDisabledTest.php
├── LearnEnabledTest.php
├── MaxSizeTest.php
├── ProcessTest.php
├── ReportTest.php
├── RevokeTest.php
├── SpamReportTest.php
├── SymbolsTest.php
├── ZlibCompressionTest.php
└── files
├── Ham_testCheckHamMessage.txt
├── Ham_testLearnMessageAsHam.txt
├── Ham_testReportWithHamMessage.txt
├── HeadersTest_Ham.txt
├── Spam_GTUBE.txt
└── Spam_testCheckSpamMessage.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | /composer.lock
2 | /phpunit.xml
3 | /vendor/
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2010-2016 Pedro Padron and Templateria LTDA.
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | PHP SpamAssassin
2 | =====
3 | ## Installation
4 |
5 | ### Install via Composer
6 |
7 | Add the following lines to your `composer.json` file and then run `php composer.phar install` or `php composer.phar update`:
8 |
9 | ```json
10 | {
11 | "require": {
12 | "templateria/spamassassin": "dev-master"
13 | }
14 | }
15 | ```
16 |
17 | ## License
18 |
19 | Apache License 2.0. See [LICENSE](LICENSE) for details.
20 |
21 | ## Contributors
22 |
23 | This library is maintened by [Pedro Padron](https://github.com/ppadron) at [Templateria](https://templateria.com).
24 |
25 | A big *thank you* to all [our contributors](https://github.com/templateria/php-spamassassin/graphs/contributors):
26 |
27 | * [Alan Pinstein](https://github.com/apinstein)
28 | * [Buharin Eugene](https://github.com/webeith)
29 | * [Konstantin Pereyaslov](https://github.com/perk11)
30 | * [Christiaan Baartse](https://github.com/christiaan)
31 | * [Matt Clements](https://github.com/mattclements)
32 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "templateria/spamassassin",
3 | "description": "Spamd protocol client for PHP. PHP package that implements the spamd protocol specification",
4 | "keywords": ["spamassassin", "spamd"],
5 | "license": "Apache-2.0",
6 | "authors": [
7 | {
8 | "name": "Pedro Padron",
9 | "email": "ppadron@php.net"
10 | }
11 | ],
12 | "require": {
13 | "php": ">=5.3.0"
14 | },
15 | "require-dev": {
16 | "phpunit/phpunit": "~4.3.0"
17 | },
18 | "autoload": {
19 | "classmap" : ["src/Spamassassin/"]
20 | },
21 | "autoload-dev": {
22 | "classmap" : ["tests/"]
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
15 |
16 |
17 |
18 | tests/
19 |
20 |
21 |
22 |
23 |
24 | SpamAssassin
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/Spamassassin/Client.php:
--------------------------------------------------------------------------------
1 |
11 | * @license http://www.apache.org/licenses/LICENSE-2.0.html Apache License 2.0
12 | */
13 | class Client
14 | {
15 | const LEARN_SPAM = 0;
16 | const LEARN_HAM = 1;
17 | const LEARN_FORGET = 2;
18 |
19 | protected $learnTypes = array(
20 | self::LEARN_SPAM,
21 | self::LEARN_HAM,
22 | self::LEARN_FORGET
23 | );
24 |
25 | protected $hostname = 'localhost';
26 | protected $port = '783';
27 |
28 | protected $socketPath;
29 | protected $socket;
30 | protected $protocolVersion = '1.5';
31 | protected $enableZlib;
32 |
33 | /**
34 | * Class constructor
35 | *
36 | * Accepts an associative array with the following keys:
37 | *
38 | * socketPath - mandatory only if using UNIX sockets to local server
39 | * hostname - mandatory only if using remote SpamAssassin server
40 | * user - optional parameter
41 | * protocolVersion - spamd protocol version (defaults to 1.5)
42 | *
43 | * @param array $params SpamAssassin parameters
44 | */
45 | public function __construct(array $params)
46 | {
47 | foreach ($params as $param => $value) {
48 | $this->$param = $value;
49 | }
50 | }
51 |
52 | /**
53 | * Creates a new socket connection with data provided in the constructor
54 | */
55 | protected function getSocket()
56 | {
57 | if (!empty($this->socketPath)) {
58 | $socket = fsockopen('unix://' . $this->socketPath, NULL, $errno, $errstr);
59 | } else {
60 | $socket = fsockopen($this->hostname, $this->port, $errno, $errstr);
61 | }
62 |
63 | if (!$socket) {
64 | throw new Exception(
65 | "Could not connect to SpamAssassin: {$errstr}", $errno
66 | );
67 | }
68 |
69 | return $socket;
70 | }
71 |
72 | /**
73 | * Sends a command to the server and returns an object with the result
74 | *
75 | * @param string $cmd Protocol command to be executed
76 | * @param string $message Full email message
77 | * @param array $additionalHeaders Associative array with additional headers
78 | *
79 | * @throws Exception
80 | *
81 | * @return Result
82 | */
83 | protected function exec($cmd, $message, array $additionalHeaders = array())
84 | {
85 | $socket = $this->getSocket();
86 | $message .= "\r\n";
87 | $contentLength = strlen($message);
88 |
89 | if (!empty($this->maxSize)) {
90 | if ($contentLength > $this->maxSize) {
91 | throw new Exception(
92 | "Message exceeds the maximum allowed size of {$this->maxSize} kbytes"
93 | );
94 | }
95 | }
96 |
97 | $cmd = $cmd . " SPAMC/" . $this->protocolVersion . "\r\n";
98 | $cmd .= "Content-length: {$contentLength}\r\n";
99 |
100 | if ($this->enableZlib && function_exists('gzcompress')) {
101 | $cmd .= "Compress: zlib\r\n";
102 | $message = gzcompress($message);
103 | }
104 |
105 | if (!empty($this->user)) {
106 | $cmd .= "User: " .$this->user . "\r\n";
107 | }
108 |
109 | if (!empty($additionalHeaders)) {
110 | foreach ($additionalHeaders as $headerName => $val) {
111 | $cmd .= $headerName . ": " . $val . "\r\n";
112 | }
113 | }
114 |
115 | $cmd .= "\r\n";
116 | $cmd .= $message;
117 | $cmd .= "\r\n";
118 |
119 | $this->write($socket, $cmd);
120 |
121 | list($headers, $message) = $this->read($socket);
122 |
123 | return $this->parseOutput($headers, $message);
124 | }
125 |
126 | /**
127 | * Writes data to the socket
128 | *
129 | * @param resource $socket Socket returned by getSocket()
130 | * @param string $data Data to be written
131 | *
132 | * @return void
133 | */
134 | protected function write($socket, $data)
135 | {
136 | fwrite($socket, $data);
137 | }
138 |
139 | /**
140 | * Reads all input from the SpamAssassin server after data was written
141 | *
142 | * @param resource $socket Socket connection created by getSocket()
143 | *
144 | * @return array Array containing output headers and message
145 | */
146 | protected function read($socket)
147 | {
148 | $headers = '';
149 | $message = '';
150 |
151 | while (true) {
152 | $buffer = fgets($socket, 128);
153 | $headers .= $buffer;
154 | if ($buffer == "\r\n" || feof($socket)) {
155 | break;
156 | }
157 | }
158 |
159 | while (!feof($socket)) {
160 | $message .= fgets($socket, 128);
161 | }
162 |
163 | fclose($socket);
164 |
165 | return array(trim($headers), trim($message));
166 | }
167 |
168 | /**
169 | * Parses SpamAssassin output ($header and $message)
170 | *
171 | * @param string $header Output headers
172 | * @param string $message Output message
173 | *
174 | * @return Result Object containing the result
175 | */
176 | protected function parseOutput($header, $message)
177 | {
178 | $result = new Result();
179 |
180 | /*
181 | * Matches the first line in the output. Something like this:
182 | *
183 | * SPAMD/1.5 0 EX_OK
184 | * SPAMD/1.5 68 service unavailable: TELL commands have not been enabled
185 | */
186 | if (preg_match('/SPAMD\/(\d\.\d) (\d+) (.*)/', $header, $matches)) {
187 | $result->protocolVersion = $matches[1];
188 | $result->responseCode = $matches[2];
189 | $result->responseMessage = $matches[3];
190 |
191 | if ($result->responseCode != 0) {
192 | throw new Exception(
193 | $result->responseMessage,
194 | $result->responseCode
195 | );
196 | }
197 |
198 | } else {
199 | throw new Exception('Could not parse response header');
200 | }
201 |
202 | if (preg_match('/Content-length: (\d+)/', $header, $matches)) {
203 | $result->contentLength = $matches[1];
204 | }
205 |
206 | if (preg_match(
207 | '/Spam: (True|False|Yes|No) ; (\S+) \/ (\S+)/',
208 | $header,
209 | $matches
210 | )) {
211 |
212 | ($matches[1] == 'True' || $matches[1] == 'Yes') ?
213 | $result->isSpam = true :
214 | $result->isSpam = false;
215 |
216 | $result->score = (float) $matches[2];
217 | $result->thresold = (float) $matches[3];
218 | } else {
219 |
220 | /**
221 | * In PROCESS method with protocol version before 1.3, SpamAssassin
222 | * won't return the 'Spam:' field in the response header. In this case,
223 | * it is necessary to check for the X-Spam-Status: header in the
224 | * processed message headers.
225 | */
226 | if (preg_match(
227 | '/X-Spam-Status: (Yes|No)\, score=(\d+\.\d) required=(\d+\.\d)/',
228 | $header.$message,
229 | $matches)) {
230 |
231 | ($matches[1] == 'Yes') ?
232 | $result->isSpam = true :
233 | $result->isSpam = false;
234 |
235 | $result->score = (float) $matches[2];
236 | $result->thresold = (float) $matches[3];
237 | }
238 |
239 | }
240 |
241 | /* Used for report/revoke/learn */
242 | if (preg_match('/DidSet: (\S+)/', $header, $matches)) {
243 | $result->didSet = true;
244 | } else {
245 | $result->didSet = false;
246 | }
247 |
248 | /* Used for report/revoke/learn */
249 | if (preg_match('/DidRemove: (\S+)/', $header, $matches)) {
250 | $result->didRemove = true;
251 | } else {
252 | $result->didRemove = false;
253 | }
254 |
255 | $result->headers = $header;
256 | $result->message = $message;
257 |
258 | return $result;
259 |
260 | }
261 |
262 | /**
263 | * Pings the server to check the connection
264 | *
265 | * @return bool
266 | */
267 | public function ping()
268 | {
269 | $socket = $this->getSocket();
270 |
271 | $this->write($socket, "PING SPAMC/{$this->protocolVersion}\r\n\r\n");
272 | list($headers, $message) = $this->read($socket);
273 |
274 | if (strpos($headers, "PONG") === false) {
275 | return false;
276 | }
277 |
278 | return true;
279 | }
280 |
281 | /**
282 | * Returns a detailed report if the message is spam or null if it's ham
283 | *
284 | * @param string $message Email message
285 | *
286 | * @return Result Detailed spam report
287 | */
288 | public function getSpamReport($message)
289 | {
290 | return $this->exec('REPORT', $message);
291 | }
292 |
293 | /**
294 | * Processes the message and returns it's headers
295 | *
296 | * This will check if the message is spam or not and return all headers
297 | * for the modified processed message. Such as X-Spam-Flag and X-Spam-Status.
298 | *
299 | * @param string $message Headers for the modified message
300 | *
301 | * @return Result Object containing the
302 | */
303 | public function headers($message)
304 | {
305 | return $this->exec('HEADERS', $message)->message;
306 | }
307 |
308 | /**
309 | * Checks if a message is spam with the CHECK protocol command
310 | *
311 | * @param string $message Raw email message
312 | *
313 | * @return Result Object containing the result
314 | */
315 | public function check($message)
316 | {
317 | return $this->exec('CHECK', $message);
318 | }
319 |
320 | /**
321 | * Shortcut to check() method that returns a boolean
322 | *
323 | * @param string $message Raw email message
324 | *
325 | * @return boolean Whether message is spam or not
326 | */
327 | public function isSpam($message)
328 | {
329 | return $this->check($message)->isSpam;
330 | }
331 |
332 | /**
333 | * Shortcut to check() method that returns a float score
334 | *
335 | * @param string $message Raw email message
336 | *
337 | * @return float Spam Score of the Message
338 | */
339 | public function getScore($message)
340 | {
341 | return $this->check($message)->score;
342 | }
343 |
344 | /**
345 | * Processes the message, checks it for spam and returning it's modified version
346 | *
347 | * @param string $message Raw email message
348 | *
349 | * @return Result Result details and modified message
350 | */
351 | public function process($message)
352 | {
353 | return $this->exec('PROCESS', $message);
354 | }
355 |
356 | /**
357 | * Returns all rules matched by the message
358 | *
359 | * @param string $message Raw email message
360 | *
361 | * @return array Array containing the names of the rules matched
362 | */
363 | public function symbols($message)
364 | {
365 | $result = $this->exec('SYMBOLS', $message);
366 |
367 | if (empty($result->message)) {
368 | return array();
369 | }
370 |
371 | $symbols = explode(",", $result->message);
372 |
373 | return array_map('trim', $symbols);
374 | }
375 |
376 | /**
377 | * Uses SpamAssassin learning feature with TELL. Must be enabled on the server.
378 | *
379 | * @param string $message Raw email message
380 | * @param int $learnType self::LEARN_SPAM|self::LEARN_FORGET|self::LEARN_HAM
381 | *
382 | * @throws Exception when invalid learnType is passed
383 | *
384 | * @return bool Whether it did learn or not
385 | */
386 | public function learn($message, $learnType = self::LEARN_SPAM)
387 | {
388 | if (!in_array($learnType, $this->learnTypes)) {
389 | throw new Exception("Invalid learn type ($learnType)");
390 | }
391 |
392 | if ($learnType === self::LEARN_SPAM) {
393 | $additionalHeaders = array(
394 | 'Message-class' => 'spam',
395 | 'Set' => 'local',
396 | );
397 | } elseif ($learnType === self::LEARN_HAM) {
398 | $additionalHeaders = array(
399 | 'Message-class' => 'ham',
400 | 'Set' => 'local',
401 | );
402 | } elseif ($learnType === self::LEARN_FORGET) {
403 | $additionalHeaders = array(
404 | 'Remove' => 'local',
405 | );
406 | }
407 |
408 | $result = $this->exec('TELL', $message, $additionalHeaders);
409 |
410 | if ($learnType === self::LEARN_SPAM || $learnType === self::LEARN_HAM) {
411 | return $result->didSet;
412 | } else {
413 | return $result->didRemove;
414 | }
415 | }
416 |
417 | /**
418 | * Report message as spam, both local and remote.
419 | *
420 | * @param string $message Raw email message
421 | *
422 | * @return bool
423 | */
424 | public function report($message)
425 | {
426 | $additionalHeaders = array(
427 | 'Message-class' => 'spam',
428 | 'Set' => 'local,remote',
429 | );
430 |
431 | return $this->exec('TELL', $message, $additionalHeaders)->didSet;
432 | }
433 |
434 | /**
435 | * Revokes a message previously reported as spam.
436 | *
437 | * @param string $message Raw email message
438 | *
439 | * @return bool
440 | */
441 | public function revoke($message)
442 | {
443 | $additionalHeaders = array(
444 | 'Message-class' => 'ham',
445 | 'Set' => 'local,remote',
446 | );
447 |
448 | return $this->exec('TELL', $message, $additionalHeaders)->didSet;
449 | }
450 | }
451 |
--------------------------------------------------------------------------------
/src/Spamassassin/Client/Exception.php:
--------------------------------------------------------------------------------
1 |
9 | * @license http://www.apache.org/licenses/LICENSE-2.0.html Apache License 2.0
10 | */
11 | class Exception extends \Exception
12 | {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/Spamassassin/Client/Result.php:
--------------------------------------------------------------------------------
1 |
11 | * @license http://www.apache.org/licenses/LICENSE-2.0.html Apache License 2.0
12 | */
13 | class Result
14 | {
15 | /**
16 | * The protocol version of the server response
17 | *
18 | * @var string
19 | */
20 | public $protocolVersion;
21 |
22 | /**
23 | * Response code.
24 | *
25 | * @var int
26 | */
27 | public $responseCode;
28 |
29 | /**
30 | * Response message. EX_OK for sucess.
31 | *
32 | * @var string
33 | */
34 | public $responseMessage;
35 |
36 | /**
37 | * Response content length
38 | *
39 | * @var int
40 | */
41 | public $contentLength;
42 |
43 | /**
44 | * SpamAssassin score
45 | *
46 | * @var float
47 | */
48 | public $score;
49 |
50 | /**
51 | * How many points the message must score to be considered spam
52 | *
53 | * @var float
54 | */
55 | public $thresold;
56 |
57 | /**
58 | * Is it spam or not?
59 | *
60 | * @var boolean
61 | */
62 | public $isSpam;
63 |
64 | /**
65 | * Raw output from SpamAssassin server
66 | *
67 | * @var string
68 | */
69 | public $message;
70 |
71 | /**
72 | * Output headers
73 | *
74 | * @var string
75 | */
76 | public $headers;
77 |
78 | /**
79 | * @var bool
80 | */
81 | public $didSet;
82 |
83 | /**
84 | * @var bool
85 | */
86 | public $didRemove;
87 | }
88 |
--------------------------------------------------------------------------------
/tests/BaseTestCase.php:
--------------------------------------------------------------------------------
1 | $GLOBALS["PHPUNIT_SA_SOCKET"],
18 | "user" => $GLOBALS["PHPUNIT_SA_USER"],
19 | );
20 | } else {
21 | $params = array(
22 | "hostname" => $GLOBALS["PHPUNIT_SA_HOST"],
23 | "port" => (int) $GLOBALS["PHPUNIT_SA_PORT"],
24 | "user" => $GLOBALS["PHPUNIT_SA_USER"]
25 | );
26 | }
27 |
28 | $params["protocolVersion"] = $GLOBALS["PHPUNIT_SA_PROTOCOL_VERSION"];
29 | $this->params = $params;
30 | $this->sa = new Client($params);
31 | $this->gtube = $this->getMessage('Spam_GTUBE.txt');
32 | $this->ham = $this->getMessage('Ham_testCheckHamMessage.txt');
33 | }
34 |
35 | protected function getMessage($filename)
36 | {
37 | return file_get_contents(dirname(__FILE__) . '/files/' . $filename);
38 | }
39 |
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/tests/CheckTest.php:
--------------------------------------------------------------------------------
1 | getMessage('Spam_testCheckSpamMessage.txt');
8 | $return = $this->sa->check($message);
9 |
10 | $this->assertTrue($return->isSpam);
11 | $this->assertEquals(5.0, $return->thresold);
12 | $this->assertTrue($return->score >= 1000);
13 | }
14 |
15 | public function testShouldBeAbleToCheckHamMessage()
16 | {
17 | $message = $this->getMessage('Ham_testCheckHamMessage.txt');
18 | $return = $this->sa->check($message);
19 |
20 | $this->assertFalse($return->isSpam);
21 | }
22 |
23 | public function testIsSpamShouldBeAnAliasToCheck()
24 | {
25 | $this->assertTrue($this->sa->isSpam($this->gtube));
26 | $this->assertFalse($this->sa->isSpam($this->ham));
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/tests/ConnectionTest.php:
--------------------------------------------------------------------------------
1 | assertEquals(true, $this->sa->ping());
8 | }
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/tests/HeadersTest.php:
--------------------------------------------------------------------------------
1 | params = array(
12 | "socketPath" => $GLOBALS["PHPUNIT_SA_SOCKET"],
13 | "user" => $GLOBALS["PHPUNIT_SA_USER"],
14 | );
15 | } else {
16 | $this->params = array(
17 | "hostname" => $GLOBALS["PHPUNIT_SA_HOST"],
18 | "port" => (int) $GLOBALS["PHPUNIT_SA_PORT"],
19 | "user" => $GLOBALS["PHPUNIT_SA_USER"]
20 | );
21 | }
22 |
23 | $this->gtube = $this->getMessage('Spam_GTUBE.txt');
24 | $this->ham = $this->getMessage('Ham_testCheckHamMessage.txt');
25 | }
26 |
27 |
28 | public function testShouldReturnProcessedSpamMessageHeaders()
29 | {
30 | $this->params["protocolVersion"] = 1.5;
31 | $sa = new Client($this->params);
32 |
33 | $message = $this->getMessage('Spam_GTUBE.txt');
34 | $headers = $sa->headers($message);
35 |
36 | $this->assertContains("X-Spam-Status: Yes", $headers);
37 | }
38 |
39 | public function testShouldReturnProcessedHamMessageHeaders()
40 | {
41 | $this->params["protocolVersion"] = 1.5;
42 | $sa = new Client($this->params);
43 |
44 | $message = $this->getMessage('HeadersTest_Ham.txt');
45 | $headers = $sa->headers($message);
46 |
47 | $this->assertContains("X-Spam-Status: No", $headers);
48 | }
49 |
50 | public function testShouldAlsoWorkWithProtocol13()
51 | {
52 | $this->params["protocolVersion"] = 1.3;
53 | $sa = new Client($this->params);
54 | $message = $this->getMessage('HeadersTest_Ham.txt');
55 | $headers = $sa->headers($message);
56 |
57 | $this->assertContains("X-Spam-Status: No", $headers);
58 | }
59 |
60 | public function testShouldAlsoWorkWithProtocol12()
61 | {
62 | $this->params["protocolVersion"] = 1.2;
63 | $sa = new Client($this->params);
64 | $message = $this->getMessage('HeadersTest_Ham.txt');
65 | $headers = $sa->headers($message);
66 |
67 | $this->assertContains("X-Spam-Status: No", $headers);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/tests/LearnDisabledTest.php:
--------------------------------------------------------------------------------
1 | markTestSkipped(
13 | 'This test only runs when learning is disabled in SpamAssassin'
14 | );
15 | }
16 |
17 | /* @see phpunit.xml */
18 | if (!empty($GLOBALS["PHPUNIT_SA_SOCKET"])) {
19 | $params = array(
20 | "socketPath" => $GLOBALS["PHPUNIT_SA_SOCKET"],
21 | "user" => $GLOBALS["PHPUNIT_SA_USER"],
22 | );
23 | } else {
24 | $params = array(
25 | "hostname" => $GLOBALS["PHPUNIT_SA_HOST"],
26 | "port" => (int) $GLOBALS["PHPUNIT_SA_PORT"],
27 | "user" => $GLOBALS["PHPUNIT_SA_USER"]
28 | );
29 | }
30 |
31 | $params["protocolVersion"] = $GLOBALS["PHPUNIT_SA_PROTOCOL_VERSION"];
32 |
33 | $this->sa = new Client($params);
34 | }
35 |
36 | public function testShouldThrowExceptionIfLearningIsDisabled()
37 | {
38 | $message = $this->getMessage('Spam_GTUBE.txt');
39 | $this->setExpectedException('Spamassassin\Client\Exception');
40 | $this->sa->learn($message, Client::LEARN_SPAM);
41 | }
42 |
43 | public function testShouldThrowExceptionWhenForgettingIfLearningIsDisabled()
44 | {
45 | $message = $this->getMessage('Spam_GTUBE.txt');
46 | $this->setExpectedException('Spamassassin\Client\Exception');
47 | $this->sa->learn($message, Client::LEARN_FORGET);
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/tests/LearnEnabledTest.php:
--------------------------------------------------------------------------------
1 | markTestSkipped(
14 | 'To test the learning behavior, enable the TELL ' .
15 | 'command in SpamAssassin and update phpunit.xml'
16 | );
17 | }
18 |
19 | /* @see phpunit.xml */
20 | if (!empty($GLOBALS["PHPUNIT_SA_SOCKET"])) {
21 | $params = array(
22 | "socketPath" => $GLOBALS["PHPUNIT_SA_SOCKET"],
23 | "user" => $GLOBALS["PHPUNIT_SA_USER"],
24 | );
25 | } else {
26 | $params = array(
27 | "hostname" => $GLOBALS["PHPUNIT_SA_HOST"],
28 | "port" => (int) $GLOBALS["PHPUNIT_SA_PORT"],
29 | "user" => $GLOBALS["PHPUNIT_SA_USER"]
30 | );
31 | }
32 |
33 | $params["protocolVersion"] = $GLOBALS["PHPUNIT_SA_PROTOCOL_VERSION"];
34 |
35 | $this->sa = new Client($params);
36 |
37 | }
38 |
39 | public function testShouldLearnAndMessageAsSpam()
40 | {
41 | $message = $this->getMessage('Spam_GTUBE.txt');
42 |
43 | $this->assertTrue($this->sa->learn($message, Client::LEARN_SPAM));
44 | $this->assertTrue($this->sa->learn($message, Client::LEARN_FORGET));
45 | }
46 |
47 | public function testShouldLearnMessageAsHam()
48 | {
49 | $message = $this->getMessage('Ham_testLearnMessageAsHam.txt');
50 |
51 | $this->assertTrue($this->sa->learn($message, Client::LEARN_HAM));
52 | $this->assertTrue($this->sa->learn($message, Client::LEARN_FORGET));
53 | }
54 |
55 | public function testShouldNotLearnIfMessageIsAlreadyKnown()
56 | {
57 | $message = $this->getMessage('Ham_testLearnMessageAsHam.txt');
58 |
59 | /* should learn in the first call */
60 | $this->assertTrue($this->sa->learn($message, Client::LEARN_HAM));
61 |
62 | /* should fail in the second call because message is already known */
63 | $this->assertFalse($this->sa->learn($message, Client::LEARN_HAM));
64 |
65 | /* cleanup (forget message) */
66 | $this->assertTrue($this->sa->learn($message, Client::LEARN_FORGET));
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/tests/MaxSizeTest.php:
--------------------------------------------------------------------------------
1 | setExpectedException('Spamassassin\Client\Exception');
10 |
11 | $params = $this->params;
12 |
13 | // setting max size as 10 bytes less than message size
14 | $params['maxSize'] = strlen($this->gtube) - 10;
15 |
16 | $sa = new Client($params);
17 |
18 | $result = $sa->process($this->gtube);
19 | }
20 |
21 | public function testShouldProcessIfMessageSmallerThanMaxSize()
22 | {
23 | $result = $this->sa->process($this->gtube);
24 | $this->assertTrue($result->isSpam);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/tests/ProcessTest.php:
--------------------------------------------------------------------------------
1 | sa->process($this->gtube);
7 |
8 | $this->assertEquals(true, $result->isSpam);
9 | $this->assertTrue(is_double($result->score));
10 | $this->assertTrue(is_double($result->thresold));
11 |
12 | $this->assertContains(
13 | "Content-Description: original message before SpamAssassin",
14 | $result->message
15 | );
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tests/ReportTest.php:
--------------------------------------------------------------------------------
1 | markTestSkipped(
12 | 'To test the learning behavior, enable the TELL ' .
13 | 'command in SpamAssassin and update phpunit.xml'
14 | );
15 | }
16 | }
17 |
18 | public function testShouldReportMessageAsSpam()
19 | {
20 | // the message cannot be older than 2 days
21 | $today = date('j, d M Y');
22 | $message = str_replace('Thu, 29 Apr 2010', $today, $this->gtube);
23 |
24 | $this->assertTrue($this->sa->report($message));
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/tests/RevokeTest.php:
--------------------------------------------------------------------------------
1 | markTestSkipped(
12 | 'To test the learning behavior, enable the TELL ' .
13 | 'command in SpamAssassin and update phpunit.xml'
14 | );
15 | }
16 | }
17 |
18 | public function testShouldRevokeMessageAsHam()
19 | {
20 | // the message cannot be older than 2 days
21 | $today = date('j, d M Y');
22 | $message = str_replace('2 Jan 2010', $today, $this->ham);
23 |
24 | $this->assertTrue($this->sa->revoke($message));
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/tests/SpamReportTest.php:
--------------------------------------------------------------------------------
1 | sa->getSpamReport($this->gtube);
7 |
8 | $this->assertContains("Content preview:", $report->message);
9 | $this->assertContains("1000 GTUBE", $report->message);
10 | $this->assertTrue($report->isSpam);
11 | }
12 |
13 | public function testShouldReturnNullIfMessageIsHam()
14 | {
15 | $message = $this->getMessage('Ham_testReportWithHamMessage.txt');
16 | $report = $this->sa->getSpamReport($message);
17 | $this->assertFalse($report->isSpam);
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/tests/SymbolsTest.php:
--------------------------------------------------------------------------------
1 | sa->symbols($this->gtube);
7 | $this->assertEquals(true, in_array('GTUBE', $result));
8 | }
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/tests/ZlibCompressionTest.php:
--------------------------------------------------------------------------------
1 | params;
9 | $params['enableZlib'] = true;
10 |
11 | $sa = new Client($params);
12 | $result = $sa->process($this->gtube);
13 |
14 | $this->assertTrue($result->isSpam);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/tests/files/Ham_testCheckHamMessage.txt:
--------------------------------------------------------------------------------
1 | From announce-return-26-apmail-spamassassin-announce-archive=spamassassin.apache.org@spamassassin.apache.org Sat Jan 02 09:45:36 2010
2 | Return-Path:
3 | Delivered-To: apmail-spamassassin-announce-archive@www.apache.org
4 | Received: (qmail 27672 invoked from network); 2 Jan 2010 09:45:36 -0000
5 | Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3)
6 | by minotaur.apache.org with SMTP; 2 Jan 2010 09:45:36 -0000
7 | Received: (qmail 92473 invoked by uid 500); 2 Jan 2010 09:45:31 -0000
8 | Delivered-To: apmail-spamassassin-announce-archive@spamassassin.apache.org
9 | Received: (qmail 92451 invoked by uid 500); 2 Jan 2010 09:45:31 -0000
10 | Mailing-List: contact announce-help@spamassassin.apache.org; run by ezmlm
11 | Precedence: bulk
12 | list-help:
13 | list-unsubscribe:
14 | List-Post:
15 | List-Id:
16 | Delivered-To: mailing list announce@spamassassin.apache.org
17 | Delivered-To: moderator for announce@spamassassin.apache.org
18 | Received: (qmail 52899 invoked by uid 99); 2 Jan 2010 07:42:44 -0000
19 | X-ASF-Spam-Status: No, hits=-2000.0 required=10.0
20 | tests=ALL_TRUSTED
21 | X-Spam-Check-By: apache.org
22 | Date: 2 Jan 2010 07:42:23 -0000
23 | Message-ID: <20100102074223.6745.qmail@minotaur.apache.org>
24 | From: dos@apache.org
25 | To: dos@apache.org
26 | Subject: Apache SpamAssassin Y2K10 Rule Bug - Update Your Rules Now!
27 |
28 | I've posted the following note on the Apache SpamAssassin website [1]
29 | about an issue with a rule that may cause wanted email to be classified
30 | as spam by SpamAssassin. If you're running SpamAssassin 3.2.x you are
31 | encouraged to update you rules (updates were released on sa-update
32 | around 1900 UTC Jan 1, 2010).
33 |
34 | Y2K10 Rule Bug - Update Your Rules Now!
35 |
36 | 2010-01-01:
37 |
38 | Versions of the FH_DATE_PAST_20XX [2] rule released with versions of
39 | Apache SpamAssassin 3.2.0 thru 3.2.5 will trigger on most mail with a
40 | Date header that includes the year 2010 or later. The rule will add a
41 | score of up to 3.6 towards the spam classification of all email. You
42 | should take corrective action immediately; there are two easy ways to
43 | correct the problem:
44 |
45 | 1) If your system is configured to use sa-update [3] run sa-update now.
46 | An update is available that will correct the rule. No further action
47 | is necessary (other than restarting spamd or any service that uses
48 | SpamAssassin directly).
49 |
50 | 2) Add "score FH_DATE_PAST_20XX 0" without the quotes to the end of your
51 | local.cf file to disable the rule. If you require help updating your
52 | rules to correct this issue you are encouraged to ask for assistance on
53 | the Apache SpamAssassin Users' list. Users' mailing list info is here. [4]
54 |
55 | On behalf of the Apache SpamAssassin project I apologize for this error
56 | and the grief it may have caused you.
57 |
58 | Regards,
59 |
60 | Daryl C. W. O'Shea
61 |
62 | VP, Apache SpamAssassin
63 |
64 | [1] http://spamassassin.apache.org/
65 | [2] http://wiki.apache.org/spamassassin/Rules/FH_DATE_PAST_20XX
66 | [3] http://wiki.apache.org/spamassassin/RuleUpdates
67 | [4] http://wiki.apache.org/spamassassin/MailingLists
68 |
69 | ---------------------------------------------------------------------
70 | To unsubscribe, e-mail: announce-unsubscribe@spamassassin.apache.org
71 | For additional commands, e-mail: announce-help@spamassassin.apache.org
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/tests/files/Ham_testLearnMessageAsHam.txt:
--------------------------------------------------------------------------------
1 | From announce-return-13-apmail-spamassassin-announce-archive=spamassassin.apache.org@spamassassin.apache.org Tue Jun 06 13:35:24 2006
2 | Return-Path:
3 | Delivered-To: apmail-spamassassin-announce-archive@www.apache.org
4 | Received: (qmail 81966 invoked from network); 6 Jun 2006 13:35:24 -0000
5 | Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199)
6 | by minotaur.apache.org with SMTP; 6 Jun 2006 13:35:24 -0000
7 | Received: (qmail 55092 invoked by uid 500); 6 Jun 2006 13:35:13 -0000
8 | Delivered-To: apmail-spamassassin-announce-archive@spamassassin.apache.org
9 | Received: (qmail 55058 invoked by uid 500); 6 Jun 2006 13:35:13 -0000
10 | Mailing-List: contact announce-help@spamassassin.apache.org; run by ezmlm
11 | Precedence: bulk
12 | list-help:
13 | list-unsubscribe:
14 | List-Post:
15 | List-Id:
16 | Delivered-To: mailing list announce@spamassassin.apache.org
17 | Delivered-To: moderator for announce@spamassassin.apache.org
18 | Received: (qmail 98356 invoked by uid 99); 5 Jun 2006 16:15:38 -0000
19 | X-ASF-Spam-Status: No, hits=0.0 required=10.0
20 | tests=
21 | X-Spam-Check-By: apache.org
22 | Received-SPF: neutral (asf.osuosl.org: local policy)
23 | Date: Mon, 5 Jun 2006 12:15:14 -0400
24 | From: Theo Van Dinter
25 | To: Spamassassin Users List ,
26 | Spamassassin Devel List ,
27 | Spamassassin Announcements List
28 | Subject: ANNOUNCE: Apache SpamAssassin 3.0.6 available!
29 | Message-ID: <20060605161514.GO1612@kluge.net>
30 | Mime-Version: 1.0
31 | Content-Type: multipart/signed; micalg=pgp-sha1;
32 | protocol="application/pgp-signature"; boundary="mvuFargmsA+C2jC8"
33 | Content-Disposition: inline
34 | User-Agent: Mutt/1.4.2.1i
35 | X-Virus-Checked: Checked by ClamAV on apache.org
36 | X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N
37 |
38 | --mvuFargmsA+C2jC8
39 | Content-Type: text/plain; charset=us-ascii
40 | Content-Disposition: inline
41 | Content-Transfer-Encoding: quoted-printable
42 |
43 | Apache SpamAssassin 3.0.6 is now available! This is a maintainance
44 | release of the 3.0.x branch.
45 |
46 | Downloads are available from:
47 | http://spamassassin.apache.org/downloads.cgi?update=3D200606050750
48 |
49 | The release file will also be available via CPAN in the near future.
50 |
51 | md5sum of archive files:
52 | 423eb193db9f7757c6d957f5c04550cb Mail-SpamAssassin-3.0.6.tar.bz2
53 | bf0a1e1a7f6e5dd719deda6293b83e35 Mail-SpamAssassin-3.0.6.tar.gz
54 | 72c012d51f8507c2839a34f900c80412 Mail-SpamAssassin-3.0.6.zip
55 |
56 | sha1sum of archive files:
57 | 10d42d954c421f40fbbd9411a5ff096e29240c6f Mail-SpamAssassin-3.0.6.tar.bz2
58 | 78358df8ea26513a8fbe466f484d19e487e5438f Mail-SpamAssassin-3.0.6.tar.gz
59 | 17031fd2c9b54846d4e41d7ea3945639659fd91e Mail-SpamAssassin-3.0.6.zip
60 |
61 |
62 | The release files also have a .asc accompanying them. The file serves
63 | as an external GPG signature for the given release file. The signing=20
64 | key is available via the wwwkeys.pgp.net key server, as well as
65 | http://spamassassin.apache.org/released/GPG-SIGNING-KEY
66 |
67 | The key information is:
68 |
69 | pub 1024D/265FA05B 2003-06-09 SpamAssassin Signing Key
71 | Key fingerprint =3D 26C9 00A4 6DD4 0CD5 AD24 F6D7 DEE0 1987 265F A05B
72 |
73 | 3.0.6 fixes a remote code execution vulnerability if spamd is run with the
74 | "--vpopmail" and "-P" options. If either/both of those options are not
75 | used, there is no vulnerability.
76 |
77 | Changelog:
78 |
79 | - bug 4926: given a certain set of parameters to spamd and a specially
80 | formatted input message, users could cause spamd to execute arbitrary
81 | commands as the spamd user
82 |
83 | --mvuFargmsA+C2jC8
84 | Content-Type: application/pgp-signature
85 | Content-Disposition: inline
86 |
87 | -----BEGIN PGP SIGNATURE-----
88 | Version: GnuPG v1.4.2.2 (GNU/Linux)
89 |
90 | iD8DBQFEhFiSvTLro+k8grsRAoI9AJ9SjVCxDIJ6z9SlmmZwLn1RaWYaugCfWoZJ
91 | U0bB5y5qX5kj4BbwLFQfIt8=
92 | =An3l
93 | -----END PGP SIGNATURE-----
94 |
95 | --mvuFargmsA+C2jC8--
96 |
--------------------------------------------------------------------------------
/tests/files/Ham_testReportWithHamMessage.txt:
--------------------------------------------------------------------------------
1 | From announce-return-26-apmail-spamassassin-announce-archive=spamassassin.apache.org@spamassassin.apache.org Sat Jan 02 09:45:36 2010
2 | Return-Path:
3 | Delivered-To: apmail-spamassassin-announce-archive@www.apache.org
4 | Received: (qmail 27672 invoked from network); 2 Jan 2010 09:45:36 -0000
5 | Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3)
6 | by minotaur.apache.org with SMTP; 2 Jan 2010 09:45:36 -0000
7 | Received: (qmail 92473 invoked by uid 500); 2 Jan 2010 09:45:31 -0000
8 | Delivered-To: apmail-spamassassin-announce-archive@spamassassin.apache.org
9 | Received: (qmail 92451 invoked by uid 500); 2 Jan 2010 09:45:31 -0000
10 | Mailing-List: contact announce-help@spamassassin.apache.org; run by ezmlm
11 | Precedence: bulk
12 | list-help:
13 | list-unsubscribe:
14 | List-Post:
15 | List-Id:
16 | Delivered-To: mailing list announce@spamassassin.apache.org
17 | Delivered-To: moderator for announce@spamassassin.apache.org
18 | Received: (qmail 52899 invoked by uid 99); 2 Jan 2010 07:42:44 -0000
19 | X-ASF-Spam-Status: No, hits=-2000.0 required=10.0
20 | tests=ALL_TRUSTED
21 | X-Spam-Check-By: apache.org
22 | Date: 2 Jan 2010 07:42:23 -0000
23 | Message-ID: <20100102074223.6745.qmail@minotaur.apache.org>
24 | From: dos@apache.org
25 | To: dos@apache.org
26 | Subject: Apache SpamAssassin Y2K10 Rule Bug - Update Your Rules Now!
27 |
28 | I've posted the following note on the Apache SpamAssassin website [1]
29 | about an issue with a rule that may cause wanted email to be classified
30 | as spam by SpamAssassin. If you're running SpamAssassin 3.2.x you are
31 | encouraged to update you rules (updates were released on sa-update
32 | around 1900 UTC Jan 1, 2010).
33 |
34 | Y2K10 Rule Bug - Update Your Rules Now!
35 |
36 | 2010-01-01:
37 |
38 | Versions of the FH_DATE_PAST_20XX [2] rule released with versions of
39 | Apache SpamAssassin 3.2.0 thru 3.2.5 will trigger on most mail with a
40 | Date header that includes the year 2010 or later. The rule will add a
41 | score of up to 3.6 towards the spam classification of all email. You
42 | should take corrective action immediately; there are two easy ways to
43 | correct the problem:
44 |
45 | 1) If your system is configured to use sa-update [3] run sa-update now.
46 | An update is available that will correct the rule. No further action
47 | is necessary (other than restarting spamd or any service that uses
48 | SpamAssassin directly).
49 |
50 | 2) Add "score FH_DATE_PAST_20XX 0" without the quotes to the end of your
51 | local.cf file to disable the rule. If you require help updating your
52 | rules to correct this issue you are encouraged to ask for assistance on
53 | the Apache SpamAssassin Users' list. Users' mailing list info is here. [4]
54 |
55 | On behalf of the Apache SpamAssassin project I apologize for this error
56 | and the grief it may have caused you.
57 |
58 | Regards,
59 |
60 | Daryl C. W. O'Shea
61 |
62 | VP, Apache SpamAssassin
63 |
64 | [1] http://spamassassin.apache.org/
65 | [2] http://wiki.apache.org/spamassassin/Rules/FH_DATE_PAST_20XX
66 | [3] http://wiki.apache.org/spamassassin/RuleUpdates
67 | [4] http://wiki.apache.org/spamassassin/MailingLists
68 |
69 | ---------------------------------------------------------------------
70 | To unsubscribe, e-mail: announce-unsubscribe@spamassassin.apache.org
71 | For additional commands, e-mail: announce-help@spamassassin.apache.org
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/tests/files/HeadersTest_Ham.txt:
--------------------------------------------------------------------------------
1 | From announce-return-9-apmail-spamassassin-announce-archive=spamassassin.apache.org@spamassassin.apache.org Wed Jun 15 20:12:57 2005
2 | Return-Path:
3 | Delivered-To: apmail-spamassassin-announce-archive@www.apache.org
4 | Received: (qmail 560 invoked from network); 15 Jun 2005 20:11:48 -0000
5 | Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199)
6 | by minotaur.apache.org with SMTP; 15 Jun 2005 20:11:48 -0000
7 | Received: (qmail 48551 invoked by uid 500); 15 Jun 2005 20:11:37 -0000
8 | Delivered-To: apmail-spamassassin-announce-archive@spamassassin.apache.org
9 | Received: (qmail 48455 invoked by uid 500); 15 Jun 2005 20:11:36 -0000
10 | Mailing-List: contact announce-help@spamassassin.apache.org; run by ezmlm
11 | Precedence: bulk
12 | list-help:
13 | list-unsubscribe:
14 | List-Post:
15 | List-Id:
16 | Delivered-To: mailing list announce@spamassassin.apache.org
17 | Delivered-To: moderator for announce@spamassassin.apache.org
18 | Received: (qmail 18095 invoked by uid 99); 15 Jun 2005 20:00:59 -0000
19 | X-ASF-Spam-Status: No, hits=-0.0 required=10.0
20 | tests=SPF_HELO_PASS,SPF_PASS
21 | X-Spam-Check-By: apache.org
22 | Received-SPF: pass (hermes.apache.org: domain of quinlan@pathname.com designates 209.204.178.122 as permitted sender)
23 | From: Daniel Quinlan
24 | MIME-Version: 1.0
25 | Content-Type: text/plain; charset=us-ascii
26 | Content-Transfer-Encoding: 7bit
27 | Message-ID: <17072.35054.586017.822288@proton.pathname.com>
28 | Date: Wed, 15 Jun 2005 13:00:46 -0700
29 | To: announce@spamassassin.apache.org
30 | Cc: users@spamassassin.apache.org, dev@spamassassin.apache.org
31 | Subject: Denial of Service Vulnerability in Apache SpamAssassin 3.0.1-3.0.3
32 | X-Mailer: VM 7.16 under Emacs 20.7.2
33 | Reply-To: users@spamassassin.apache.org
34 | X-Virus-Checked: Checked
35 | X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N
36 |
37 | Apache SpamAssassin 3.0.4 was recently released [0], and fixes a denial
38 | of service vulnerability in versions 3.0.1, 3.0.2, and 3.0.3. The
39 | vulnerability allows certain misformatted long message headers to cause
40 | spam checking to take a very long time.
41 |
42 | While the exploit has yet to be seen in the wild, we are concerned that
43 | there may be attempts to abuse the vulnerability in the future.
44 | Therefore, we strongly recommend all users of these versions upgrade to
45 | Apache SpamAssassin 3.0.4 as soon as possible.
46 |
47 | This issue has been assigned CVE id CAN-2005-1266 [1].
48 |
49 | To contact the Apache SpamAssassin security team, please e-mail
50 | security at spamassassin.apache.org. For more information about Apache
51 | SpamAssassin, visit the http://spamassassin.apache.org/ web site.
52 |
53 | Apache SpamAssassin Security Team
54 |
55 | [0]: http://mail-archives.apache.org/mod_mbox/spamassassin-dev/200506.mbox/%3c20050606223631.GG11538@kluge.net%3e
56 |
57 | [1]: http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-1266
58 |
59 | ---------------------------------------------------------------------
60 | To unsubscribe, e-mail: announce-unsubscribe@spamassassin.apache.org
61 | For additional commands, e-mail: announce-help@spamassassin.apache.org
62 |
63 |
64 |
--------------------------------------------------------------------------------
/tests/files/Spam_GTUBE.txt:
--------------------------------------------------------------------------------
1 | Subject: Test spam mail (GTUBE)
2 | Message-ID:
3 | Date: Thu, 29 Apr 2010 23:30:00 +0200
4 | From: Sender
5 | To: Recipient
6 | Precedence: junk
7 | MIME-Version: 1.0
8 | Content-Type: text/plain; charset=us-ascii
9 | Content-Transfer-Encoding: 7bit
10 |
11 | This is the GTUBE, the
12 | Generic
13 | Test for
14 | Unsolicited
15 | Bulk
16 | Email
17 |
18 | If your spam filter supports it, the GTUBE provides a test by which you
19 | can verify that the filter is installed correctly and is detecting incoming
20 | spam. You can send yourself a test mail containing the following string of
21 | characters (in upper case and with no white spaces and line breaks):
22 |
23 | XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
24 |
25 | You should send this test mail from an account outside of your network.
26 |
27 |
--------------------------------------------------------------------------------
/tests/files/Spam_testCheckSpamMessage.txt:
--------------------------------------------------------------------------------
1 | Subject: Test spam mail (GTUBE)
2 | Message-ID:
3 | Date: Wed, 23 Jul 2003 23:30:00 +0200
4 | From: Sender
5 | To: Recipient
6 | Precedence: junk
7 | MIME-Version: 1.0
8 | Content-Type: text/plain; charset=us-ascii
9 | Content-Transfer-Encoding: 7bit
10 |
11 | This is the GTUBE, the
12 | Generic
13 | Test for
14 | Unsolicited
15 | Bulk
16 | Email
17 |
18 | If your spam filter supports it, the GTUBE provides a test by which you
19 | can verify that the filter is installed correctly and is detecting incoming
20 | spam. You can send yourself a test mail containing the following string of
21 | characters (in upper case and with no white spaces and line breaks):
22 |
23 | XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
24 |
25 | You should send this test mail from an account outside of your network.
26 |
27 |
--------------------------------------------------------------------------------