<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<div class="moz-text-plain" wrap="true" style="font-family:
-moz-fixed; font-size: 12px;" lang="x-western">
<pre class="moz-quote-pre" wrap=""># HG changeset patch
# User Sander Hoentjen <a class="moz-txt-link-rfc2396E" href="mailto:shoentjen@antagonist.nl"><shoentjen@antagonist.nl></a>
# Date 1586370310 -7200
# Wed Apr 08 20:25:10 2020 +0200
# Node ID 3d35b19abfa72d1d09e23d02917df7fbdee0970c
# Parent 9e5d38da765152a20098642e37b0afe56312f794
Tests: added sieve tests
diff -r 9e5d38da7651 -r 3d35b19abfa7 lib/Test/Nginx.pm
--- a/lib/Test/Nginx.pm Fri Mar 20 16:32:06 2020 +0300
+++ b/lib/Test/Nginx.pm Wed Apr 08 20:25:10 2020 +0200
@@ -165,6 +165,7 @@
cache => '(?s)^(?!.*--without-http-cache)',
pop3 => '(?s)^(?!.*--without-mail_pop3_module)',
imap => '(?s)^(?!.*--without-mail_imap_module)',
+ sieve => '(?s)^(?!.*--without-mail_sieve_module)',
smtp => '(?s)^(?!.*--without-mail_smtp_module)',
pcre => '(?s)^(?!.*--without-pcre)',
split_clients
diff -r 9e5d38da7651 -r 3d35b19abfa7 lib/Test/Nginx/SIEVE.pm
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/Test/Nginx/SIEVE.pm Wed Apr 08 20:25:10 2020 +0200
@@ -0,0 +1,156 @@
+package <a class="moz-txt-link-freetext" href="Test::Nginx::SIEVE">Test::Nginx::SIEVE</a>;
+
+# (C) Maxim Dounin
+
+# Module for nginx sieve tests.
+
+###############################################################################
+
+use warnings;
+use strict;
+
+use <a class="moz-txt-link-freetext" href="Test::More">Test::More</a> qw//;
+use <a class="moz-txt-link-freetext" href="IO::Select">IO::Select</a>;
+use <a class="moz-txt-link-freetext" href="IO::Socket">IO::Socket</a>;
+use Socket qw/ CRLF /;
+
+use <a class="moz-txt-link-freetext" href="Test::Nginx">Test::Nginx</a>;
+
+sub new {
+ my $self = {};
+ bless $self, shift @_;
+
+ $self->{_socket} = <a class="moz-txt-link-freetext" href="IO::Socket::INET">IO::Socket::INET</a>->new(
+ Proto => "tcp",
+ PeerAddr => "127.0.0.1:" . port(8200),
+ @_
+ )
+ or die "Can't connect to nginx: $!\n";
+
+ if ({@_}->{'SSL'}) {
+ require <a class="moz-txt-link-freetext" href="IO::Socket::SSL">IO::Socket::SSL</a>;
+ <a class="moz-txt-link-freetext" href="IO::Socket::SSL">IO::Socket::SSL</a>->start_SSL($self->{_socket}, @_)
+ or die $<a class="moz-txt-link-freetext" href="IO::Socket::SSL::SSL_ERROR">IO::Socket::SSL::SSL_ERROR</a> . "\n";
+ }
+
+ $self->{_socket}->autoflush(1);
+
+ return $self;
+}
+
+sub eof {
+ my $self = shift;
+ return $self->{_socket}->eof();
+}
+
+sub print {
+ my ($self, $cmd) = @_;
+ log_out($cmd);
+ $self->{_socket}->print($cmd);
+}
+
+sub send {
+ my ($self, $cmd) = @_;
+ #warn "\n>>>$cmd\n";
+ log_out($cmd);
+ $self->{_socket}->print($cmd . CRLF);
+}
+
+sub read {
+ my ($self) = @_;
+ my $socket = $self->{_socket};
+ eval {
+ local $SIG{ALRM} = sub { die "timeout\n" };
+ alarm(8);
+ while (<$socket>) {
+ #warn "\n====\n<<<$_\n===\n";
+ log_in($_);
+ # XXX
+ last;
+ }
+ alarm(0);
+ };
+ alarm(0);
+ if ($@) {
+ log_in("died: $@");
+ return undef;
+ }
+ return $_;
+}
+
+sub read_ok {
+ my ($self) = @_;
+ my $socket = $self->{_socket};
+ eval {
+ local $SIG{ALRM} = sub { die "timeout\n" };
+ alarm(8);
+ while (<$socket>) {
+ #warn "\n====\n<<<$_\n===\n";
+ log_in($_);
+ # XXX
+ next if m/^"/;
+ last;
+ }
+ alarm(0);
+ };
+ alarm(0);
+ if ($@) {
+ log_in("died: $@");
+ return undef;
+ }
+ return $_;
+}
+
+sub check {
+ my ($self, $regex, $name) = @_;
+ <a class="moz-txt-link-freetext" href="Test::More">Test::More</a>->builder->like($self->read(), $regex, $name);
+}
+
+sub ok {
+ my $self = shift;
+ <a class="moz-txt-link-freetext" href="Test::More">Test::More</a>->builder->like($self->read_ok(), qr/^OK/, @_);
+}
+
+sub can_read {
+ my ($self, $timo) = @_;
+ <a class="moz-txt-link-freetext" href="IO::Select">IO::Select</a>->new($self->{_socket})->can_read($timo || 3);
+}
+
+###############################################################################
+
+sub sieve_test_daemon {
+ my ($port) = @_;
+
+ my $server = <a class="moz-txt-link-freetext" href="IO::Socket::INET">IO::Socket::INET</a>->new(
+ Proto => 'tcp',
+ LocalAddr => '127.0.0.1:' . ($port || port(8201)),
+ Listen => 5,
+ Reuse => 1
+ )
+ or die "Can't create listening socket: $!\n";
+
+ while (my $client = $server->accept()) {
+ $client->autoflush(1);
+ print $client "OK fake sieve server ready" . CRLF;
+
+ while (<$client>) {
+ if (/^logout/i) {
+ print $client 'OK logout ok' . CRLF;
+ } elsif (/^AUTHENTICATE /i) {
+ print $client 'OK login ok' . CRLF;
+ } elsif (/^CAPABILITY/i) {
+ print $client 'OK capabilty ok' . CRLF;
+ } else {
+ print $client 'NO unknown command ' . $_ . CRLF;
+ }
+ }
+
+ close $client;
+ }
+}
+
+###############################################################################
+
+1;
+
+###############################################################################
diff -r 9e5d38da7651 -r 3d35b19abfa7 mail_capability.t
--- a/mail_capability.t Fri Mar 20 16:32:06 2020 +0300
+++ b/mail_capability.t Wed Apr 08 20:25:10 2020 +0200
@@ -3,7 +3,7 @@
# (C) Sergey Kandaurov
# (C) Nginx, Inc.
-# Tests for imap/pop3/smtp capabilities.
+# Tests for imap/pop3/sieve/smtp capabilities.
###############################################################################
@@ -18,6 +18,7 @@
use <a class="moz-txt-link-freetext" href="Test::Nginx">Test::Nginx</a>;
use <a class="moz-txt-link-freetext" href="Test::Nginx::IMAP">Test::Nginx::IMAP</a>;
use <a class="moz-txt-link-freetext" href="Test::Nginx::POP3">Test::Nginx::POP3</a>;
+use <a class="moz-txt-link-freetext" href="Test::Nginx::SIEVE">Test::Nginx::SIEVE</a>;
use <a class="moz-txt-link-freetext" href="Test::Nginx::SMTP">Test::Nginx::SMTP</a>;
###############################################################################
@@ -25,8 +26,8 @@
select STDERR; $| = 1;
select STDOUT; $| = 1;
-my $t = <a class="moz-txt-link-freetext" href="Test::Nginx">Test::Nginx</a>->new()->has(qw/mail mail_ssl imap pop3 smtp/)
- ->has_daemon('openssl')->plan(17);
+my $t = <a class="moz-txt-link-freetext" href="Test::Nginx">Test::Nginx</a>->new()->has(qw/mail mail_ssl imap pop3 sieve smtp/)
+ ->has_daemon('openssl')->plan(25);
$t->write_file_expand('nginx.conf', <<'EOF');
@@ -81,6 +82,24 @@
}
server {
+ listen 127.0.0.1:8200;
+ protocol sieve;
+ sieve_capabilities '"SEE-THIS"';
+ }
+
+ server {
+ listen 127.0.0.1:8201;
+ protocol sieve;
+ starttls on;
+ }
+
+ server {
+ listen 127.0.0.1:8202;
+ protocol sieve;
+ starttls only;
+ }
+
+ server {
listen 127.0.0.1:8025;
protocol smtp;
starttls off;
@@ -188,6 +207,38 @@
unlike($caps, qr/SASL/, 'pop3 starttls only - no methods');
like($caps, qr/STLS/, 'pop3 startls only - stls');
+# sieve, custom capabilities
+
+$s = <a class="moz-txt-link-freetext" href="Test::Nginx::SIEVE">Test::Nginx::SIEVE</a>->new(PeerAddr => '127.0.0.1:' . port(8200));
+$s->ok('sieve connection completed');
+
+$s->send('CAPABILITY');
+$s->check(qr/^"SEE-THIS"/, 'sieve capability custom');
+$s->check(qr/^"SASL" "PLAIN"/, 'sieve capability sasl');
+$s->ok('sieve capability completed');
+
+# sieve starttls
+
+$s = <a class="moz-txt-link-freetext" href="Test::Nginx::SIEVE">Test::Nginx::SIEVE</a>->new(PeerAddr => '127.0.0.1:' . port(8201));
+$s->read();
+$s->read();
+$s->read();
+$s->check(qr/^"SASL" "PLAIN"/,
+ 'sieve capability starttls has plain');
+$s->check(qr/^"STARTTLS"/,
+ 'sieve capability starttls');
+
+# sieve starttls only
+
+$s = <a class="moz-txt-link-freetext" href="Test::Nginx::SIEVE">Test::Nginx::SIEVE</a>->new(PeerAddr => '127.0.0.1:' . port(8202));
+$s->read();
+$s->read();
+$s->read();
+$s->check(qr/^"SASL" ""/,
+ 'sieve capability starttls only not has plain');
+$s->check(qr/^"STARTTLS"/,
+ 'sieve capability starttls only');
+
# smtp
$s = <a class="moz-txt-link-freetext" href="Test::Nginx::SMTP">Test::Nginx::SMTP</a>->new(PeerAddr => '127.0.0.1:' . port(8025));
diff -r 9e5d38da7651 -r 3d35b19abfa7 mail_sieve.t
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mail_sieve.t Wed Apr 08 20:25:10 2020 +0200
@@ -0,0 +1,176 @@
+#!/usr/bin/perl
+
+# (C) Sander Hoentjen
+# (C) Antagonist B.V.
+
+# Tests for nginx mail sieve module.
+
+###############################################################################
+
+use warnings;
+use strict;
+
+use <a class="moz-txt-link-freetext" href="Test::More">Test::More</a>;
+
+use <a class="moz-txt-link-freetext" href="MIME::Base64">MIME::Base64</a>;
+
+BEGIN { use FindBin; chdir($<a class="moz-txt-link-freetext" href="FindBin::Bin">FindBin::Bin</a>); }
+
+use lib 'lib';
+use <a class="moz-txt-link-freetext" href="Test::Nginx">Test::Nginx</a>;
+use <a class="moz-txt-link-freetext" href="Test::Nginx::SIEVE">Test::Nginx::SIEVE</a>;
+
+###############################################################################
+
+select STDERR; $| = 1;
+select STDOUT; $| = 1;
+
+local $SIG{PIPE} = 'IGNORE';
+
+my $t = <a class="moz-txt-link-freetext" href="Test::Nginx">Test::Nginx</a>->new()->has(qw/mail sieve http rewrite/)
+ ->write_file_expand('nginx.conf', <<'EOF');
+
+%%TEST_GLOBALS%%
+
+daemon off;
+
+events {
+}
+
+mail {
+ proxy_pass_error_message on;
+ auth_http <a class="moz-txt-link-freetext" href="http://127.0.0.1:8080/mail/auth">http://127.0.0.1:8080/mail/auth</a>;
+
+ server {
+ listen 127.0.0.1:8200;
+ protocol sieve;
+ sieve_auth plain cram-md5 external;
+ }
+}
+
+http {
+ %%TEST_GLOBALS_HTTP%%
+
+ server {
+ listen 127.0.0.1:8080;
+ server_name localhost;
+
+ location = /mail/auth {
+ set $reply ERROR;
+ set $passw "";
+
+ if ($http_auth_smtp_to ~ example.com) {
+ set $reply OK;
+ }
+
+ set $userpass "$http_auth_<a class="moz-txt-link-freetext" href="user:$http_auth_pass">user:$http_auth_pass</a>";
+ if ($userpass ~ '^test@<a class="moz-txt-link-freetext" href="example.com:secret$">example.com:secret$</a>') {
+ set $reply OK;
+ }
+
+ set $userpass "$http_auth_<a class="moz-txt-link-freetext" href="user:$http_auth_salt:$http_auth_pass">user:$http_auth_salt:$http_auth_pass</a>";
+ if ($userpass ~ '^test@example.com:<a class="moz-txt-link-rfc2396E" href="mailto:.*@.*"><.*@.*></a>:0{32}$') {
+ set $reply OK;
+ set $passw secret;
+ }
+
+ set $userpass "$http_auth_<a class="moz-txt-link-freetext" href="method:$http_auth_user:$http_auth_pass">method:$http_auth_user:$http_auth_pass</a>";
+ if ($userpass ~ '^<a class="moz-txt-link-freetext" href="external:test@example.com:$">external:test@example.com:$</a>') {
+ set $reply OK;
+ set $passw secret;
+ }
+
+ add_header Auth-Status $reply;
+ add_header Auth-Server 127.0.0.1;
+ add_header Auth-Port %%PORT_8201%%;
+ add_header Auth-Pass $passw;
+ add_header Auth-Wait 1;
+ return 204;
+ }
+ }
+}
+
+EOF
+
+$t->run_daemon(\&<a class="moz-txt-link-freetext" href="Test::Nginx::SIEVE::sieve_test_daemon">Test::Nginx::SIEVE::sieve_test_daemon</a>);
+$t->run()->plan(15);
+
+$t->waitforsocket('127.0.0.1:' . port(8201));
+
+###############################################################################
+
+my $s = <a class="moz-txt-link-freetext" href="Test::Nginx::SIEVE">Test::Nginx::SIEVE</a>->new();
+$s->ok('greeting');
+
+# bad auth
+
+$s->send('AUTHENTICATE');
+$s->check(qr/^NO/, 'auth without arguments');
+
+# auth plain
+
+$s->send('AUTHENTICATE "PLAIN" "' . encode_base64(<a class="moz-txt-link-rfc2396E" href="mailto:\0test\@example.com\0bad">"\0test\@example.com\0bad"</a>, '') . '"');
+$s->check(qr/^BYE/, 'auth plain with bad password');
+
+$s = <a class="moz-txt-link-freetext" href="Test::Nginx::SIEVE">Test::Nginx::SIEVE</a>->new();
+$s->ok('greeting');
+$s->send('AUTHENTICATE "PLAIN" "' . encode_base64(<a class="moz-txt-link-rfc2396E" href="mailto:\0test\@example.com\0secret">"\0test\@example.com\0secret"</a>, '') . '"');
+#$s->check(qr/auth plain/, 'blaat');
+$s->ok('auth plain');
+
+# auth login simple
+
+$s = <a class="moz-txt-link-freetext" href="Test::Nginx::SIEVE">Test::Nginx::SIEVE</a>->new();
+$s->read_ok();
+
+$s->send('AUTHENTICATE "LOGIN"');
+$s->check(qr/"VXNlcm5hbWU6"/, 'auth login username challenge');
+
+$s->send('"' . encode_base64('<a class="moz-txt-link-abbreviated" href="mailto:test@example.com">test@example.com</a>', '') . '"');
+$s->check(qr/"UGFzc3dvcmQ6"/, 'auth login password challenge');
+
+$s->send('"' . encode_base64('secret', '') . '"');
+$s->ok('auth login simple');
+
+# auth login with username
+
+$s = <a class="moz-txt-link-freetext" href="Test::Nginx::SIEVE">Test::Nginx::SIEVE</a>->new();
+$s->read_ok();
+
+$s->send('AUTHENTICATE "LOGIN" "' . encode_base64('<a class="moz-txt-link-abbreviated" href="mailto:test@example.com">test@example.com</a>', '') . '"');
+$s->check(qr/"UGFzc3dvcmQ6"/, 'auth login with username password challenge');
+
+$s->send('"' . encode_base64('secret', '') . '"');
+$s->ok('auth login with username');
+
+# auth cram-md5
+
+$s = <a class="moz-txt-link-freetext" href="Test::Nginx::SIEVE">Test::Nginx::SIEVE</a>->new();
+$s->read_ok();
+
+$s->send('AUTHENTICATE "CRAM-MD5"');
+$s->check(qr/"/, 'auth cram-md5 challenge');
+
+$s->send('"' . encode_base64('<a class="moz-txt-link-abbreviated" href="mailto:test@example.com">test@example.com</a> ' . ('0' x 32), '') . '"');
+$s->ok('auth cram-md5');
+
+# auth external
+
+$s = <a class="moz-txt-link-freetext" href="Test::Nginx::SIEVE">Test::Nginx::SIEVE</a>->new();
+$s->read_ok();
+
+$s->send('AUTHENTICATE "EXTERNAL"');
+$s->check(qr/"VXNlcm5hbWU6"/, 'auth external challenge');
+
+$s->send('"' . encode_base64('<a class="moz-txt-link-abbreviated" href="mailto:test@example.com">test@example.com</a>', '') . '"');
+$s->ok('auth external');
+
+# auth external with username
+
+$s = <a class="moz-txt-link-freetext" href="Test::Nginx::SIEVE">Test::Nginx::SIEVE</a>->new();
+$s->read_ok();
+
+$s->send('AUTHENTICATE "EXTERNAL" "' . encode_base64('<a class="moz-txt-link-abbreviated" href="mailto:test@example.com">test@example.com</a>', '') . '"');
+$s->ok('auth external with username');
+
+###############################################################################
</pre>
</div>
</body>
</html>