#!/usr/bin/env perl # # Copyright (c) 2022 Mischa Peters # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # use 5.024; use strict; use warnings; use autodie; use Getopt::Std; use DBI; my $db_type = 'MariaDB'; my $db_host = ''; my $db_user = ''; my $db_pass = ''; my $db_name = ''; getopts('dv'); our($opt_d, $opt_v); my $email = ""; my $from = ""; my %ooo; my $dbh = DBI->connect("DBI:$db_type:$db_name:$db_host", "$db_user", "$db_pass", {RaiseError => 1}); sub do_query { my ($query) = @_; my $sth = $dbh->prepare($query); $sth->execute; return $sth; } open (my $fh, '>', "/tmp/virtualvacation.log") if ($opt_d); select(STDOUT); $|++; select($fh); $|++; print STDOUT "register|filter|smtp-in|rcpt-to\n"; print STDOUT "register|filter|smtp-in|mail-from\n"; print STDOUT "register|filter|smtp-in|data-line\n"; print STDOUT "register|ready\n"; while (my $line = <>) { next if ($line =~ m/^config/); chomp $line; print $fh "$line\n" if ($opt_v); if ($line =~ m/filter/) { my ($stream, $version, $timestamp, $subsystem, $event, $sid, $token, $data) = split /\|/, $line; if ($line =~ m/mail-from/) { $from = $data; print STDOUT "filter-result|$sid|$token|proceed\n"; } if ($line =~ m/rcpt-to/) { $email = $data; $ooo{$sid} = 1; print $fh "Virtual Vacation: created session $sid\n"; print STDOUT "filter-result|$sid|$token|proceed\n"; } if ($line =~ m/data-line/) { if (!$data) { $data = ""; } if ($data =~ m/^precedence:\s+(bulk|list|junk)/i) { $ooo{$sid} = 0; } if ($data =~ m/^x-loop:\s+opensmtpd\ admin\ virtual\ vacation/i) { $ooo{$sid} = 0; } print STDOUT "filter-dataline|$sid|$token|$data\n"; } if ($line =~ m/data-line/ && $data eq '.' && $ooo{$sid} == 1) { print $fh "Virtual Vacation: To: $email, From: $from\n" if ($opt_d); my $query = qq{SELECT subject,body FROM vacation WHERE email='$email' and active=1}; my $sth = do_query($query); my $rv = $sth->rows; if ($rv == 1) { my @row = $sth->fetchrow_array; print $fh "Virtual Vacation: Found OOO for $email\n" if ($opt_d); $query = qq{SELECT cache FROM vacation WHERE email='$email' AND FIND_IN_SET('$from',cache)}; $sth = do_query ($query); $rv = $sth->rows; if ($rv == 0) { $query = qq{UPDATE vacation SET cache=CONCAT(cache,',','$from') WHERE email='$email'}; $sth = do_query($query); print $fh "Virtual Vacation: Sending OOO to $from\n" if ($opt_d); open my $fh_email, "|-", "/usr/sbin/sendmail -t"; print $fh_email "From: $email\n"; print $fh_email "To: $from\n";; print $fh_email "Subject: $row[0]\n"; print $fh_email "X-Loop: OpenSMTPD Admin Virtual Vacation\n"; print $fh_email "Content-Type: text/plain; charset=utf-8\n\n"; print $fh_email "$row[1]\n"; close $fh_email; } delete $ooo{$sid}; print $fh "Virtual Vacation: removed session $sid\n" if ($opt_d); } } elsif ($line =~ m/data-line/ && $data eq '.' && $ooo{$sid} == 0) { delete $ooo{$sid}; print $fh "Virtual Vacation: removed session $sid\n" if ($opt_d); } } } close $fh; 0;