2025-02-07 11:58:17 +01:00
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
|
2025-02-07 15:57:46 +01:00
|
|
|
use Qpsmtpd::Constants;
|
|
|
|
use Qpsmtpd::DSN;
|
2025-02-07 12:25:57 +01:00
|
|
|
use Net::LMTP;
|
2025-02-07 11:58:17 +01:00
|
|
|
|
|
|
|
|
|
|
|
sub register {
|
|
|
|
my ($self, $qp) = (shift, shift);
|
|
|
|
|
|
|
|
$self->{lmtp_rcpt_based} = $qp->config("lmtp_rcpt_based") || 0;
|
|
|
|
$self->{lmtp_host} = $qp->config("lmtp_host");
|
|
|
|
$self->{lmtp_port} = $qp->config("lmtp_port") || 24;
|
2025-02-07 12:25:57 +01:00
|
|
|
$self->{qp}= $qp;
|
2025-02-07 11:58:17 +01:00
|
|
|
$self->{enabled} = 1;
|
|
|
|
|
2025-02-07 12:25:57 +01:00
|
|
|
|
2025-02-07 11:58:17 +01:00
|
|
|
if (!$self->{lmtp_rcpt_based} && !$self->{lmtp_host}) {
|
|
|
|
$self->{enabled} = 0;
|
2025-02-07 12:04:12 +01:00
|
|
|
$self->log(LOGERROR, "No LMTP host configured, disabling plugin\n");
|
2025-02-07 11:58:17 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
sub lmtp_transfer
|
|
|
|
{
|
2025-02-07 12:25:57 +01:00
|
|
|
my ($self, $transaction, $lmtp_host, $lmtp_port, $lmtp_user) = @_;
|
|
|
|
|
2025-02-07 15:46:07 +01:00
|
|
|
my $lmtp = Net::LMTP->new(
|
|
|
|
$lmtp_host,
|
|
|
|
Port => $lmtp_port,
|
|
|
|
Timeout => 60,
|
|
|
|
Hello => $self->qp->config("me"),
|
|
|
|
) || die $!;
|
|
|
|
|
|
|
|
|
|
|
|
$lmtp->mail($transaction->sender->address || "")
|
2025-02-07 17:52:24 +01:00
|
|
|
or return DECLINED, "Unable to queue message during mail($!)";
|
|
|
|
$lmtp->to($lmtp_user) or return DECLINED, "Unable to queue message during to($!)";
|
|
|
|
$lmtp->data() or return DECLINED, "Unable to queue message during data($!)";
|
|
|
|
$lmtp->datasend($transaction->header->as_string) or return DECLINED, "Unable to queue message during datasend ($!) ";
|
2025-02-07 12:25:57 +01:00
|
|
|
$transaction->body_resetpos;
|
|
|
|
while (my $line = $transaction->body_getline) {
|
|
|
|
$lmtp->datasend($line)
|
2025-02-07 17:52:24 +01:00
|
|
|
or return DECLINED, "Unable to queue message during datasendbody($!)";
|
2025-02-07 12:25:57 +01:00
|
|
|
}
|
2025-02-07 17:52:24 +01:00
|
|
|
$lmtp->dataend() or return DECLINED, "Unable to queue message during dataend($!)";
|
2025-02-07 15:46:07 +01:00
|
|
|
my $qid = $lmtp->message();
|
|
|
|
my @list = split(' ', $qid);
|
|
|
|
$qid = pop(@list);
|
|
|
|
|
2025-02-07 17:52:24 +01:00
|
|
|
$lmtp->quit() or return DECLINED, "Unable to queue message during quit($!)";
|
2025-02-07 15:46:07 +01:00
|
|
|
|
2025-02-07 12:25:57 +01:00
|
|
|
$self->log(LOGINFO, "finished queueing");
|
2025-02-07 15:46:07 +01:00
|
|
|
return OK, "queued as $qid";
|
2025-02-07 11:58:17 +01:00
|
|
|
|
|
|
|
return DECLINED;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub hook_queue {
|
|
|
|
my ($self, $transaction) = @_;
|
|
|
|
|
|
|
|
return DECLINED unless $self->{enabled};
|
|
|
|
|
|
|
|
my $lmtp_host;
|
|
|
|
my $lmtp_port;
|
|
|
|
my $lmtp_user;
|
|
|
|
|
|
|
|
if ($self->{lmtp_rcpt_based})
|
|
|
|
{
|
|
|
|
my $queue = $transaction->notes("queue");
|
|
|
|
$queue =~ /^lmtp:\/\/(.*):(\d+)$/;
|
|
|
|
$lmtp_host=$1;
|
|
|
|
$lmtp_port=$2;
|
2025-02-07 12:13:48 +01:00
|
|
|
$lmtp_user = $transaction->notes("destination-user") || "";
|
2025-02-07 11:58:17 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$lmtp_host = $self->{lmtp_host};
|
|
|
|
$lmtp_port = $self->{lmtp_port};
|
|
|
|
$lmtp_user = $transaction->sender->address || "";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$lmtp_user) {
|
2025-02-07 12:07:24 +01:00
|
|
|
$self->log(LOGERROR, "No sender address found for transaction.\n");
|
2025-02-07 11:58:17 +01:00
|
|
|
return DECLINED;
|
|
|
|
}
|
|
|
|
|
|
|
|
$self->log(LOGNOTICE,"forwarding mail to LMTP host: $lmtp_host:$lmtp_port\n");
|
|
|
|
|
2025-02-07 12:25:57 +01:00
|
|
|
return $self->lmtp_transfer($transaction, $lmtp_host, $lmtp_port, $lmtp_user);
|
2025-02-07 11:58:17 +01:00
|
|
|
}
|