use strict; use warnings; use Qpsmtpd::Constants; use Qpsmtpd::DSN; use DBI; sub register { my ($self, $qp) = (shift, shift); # some default values $self->{database} = $qp->config("fedhq_mysql_database") || "mail"; $self->{host} = $qp->config("fedhq_mysql_host") || "localhost"; $self->{port} = $qp->config("fedhq_mysql_port") || "3306"; $self->{user} = $qp->config("fedhq_mysql_user") || "qpsmtpd"; $self->{pass} = $qp->config("fedhq_mysql_password"); $self->createDSN(); } sub createStatements { my $self = shift; $self->{rcpt_sth} = $self->{dbh}->prepare("select username from email_address where alias=? and domain=?"); $self->{fetch_all_sth} = $self->{dbh}->prepare("select username from email_address where domain=? and isFetchAll=1"); } sub connect { my $self = shift; $self->{dbh} = DBI->connect($self->{dsn}, $self->{user}, $self->{pass}, { RaiseError => 0}) || $self->log(LOGERROR, "error connecting to DB " . $DBI::errstr); if ($self->{dbh}->err()) { $self->log(LOGERROR, "error connecting to DB: " . $self->{dbh}->errstr()); $self->{dbh}=undef; } } sub createDSN { my $self = shift; my $dsn = "DBI:MariaDB:database=" . $self->{database} . ";host=" . $self->{host} . ";port=" . $self->{port}; $self->{dsn} = $dsn; # try to parse the dsn to ensure it is valid my @data = DBI->parse_dsn($self->{dsn}); if (@data == 0) { $self->log(LOGERROR, "DSN " . $self->{dsn} . " not valid"); $self->{dsn}=""; } $self->log(LOGDEBUG, "created DSN " . $self->{dsn}); } sub hook_rcpt { my ($self, $transaction, $recipient) = @_; $self->log(LOGNOTICE, "Recipient: " . $recipient->user . "@" . $recipient->host); return DECLINED unless $recipient->host && $recipient->user; $self->connect(); $self->createStatements(); my $result = $self->{rcpt_sth}->execute($recipient->user, $recipient->host); if ($self->{rcpt_sth}->rows > 0) { $self->log(LOGDEBUG, " found recipient in database"); return OK; } $result = $self->{fetch_all_sth}->execute($recipient->host); if ($self->{fetch_all_sth}->rows > 0) { $self->log(LOGDEBUG, " found fetchall for doamin in database"); return OK; } return DECLINED; }