I am forced to implement a sender policy in qmail.
I have a file describing the policies:
[email protected]:*@domain1.com,[email protected],[email protected]
[email protected]:*@*
[email protected]:
This file describes the following situation:
[email protected] can send messages to anyone having the address defined on domain1.com, to [email protected] and to [email protected]
[email protected] can send messages to anyone
[email protected] can not send messages at all
The letter case should be ignored.
I have to implement those restrictions in qmail, using qmailqueue and PERL (Mail::Qmail::Queue::Message) but I have no knowledge of PERL at all.
Any help is sincerely appreciated.
but I have no knowledge of PERL at all.
Then the solution is
(As an aside, the language is called Perl, and the interpreter used to run Perl programs is called perl. Other capitalizations are a bit frowned upon).
Should you decide to try solving this problem on your own, here are a few pointers:
The problem can be decomposed into subproblems:
Parsing the rule file. This is rather easy with the split
function.
The function takes zero to three arguments: regex, string, limit. If the limit is omitted, the number of resulting fragments is arbitrary. If the string is omitted, then the $_
special variable is used. If the regex is omitted, it will be treated as if the special value " "
was given: Splits on all whitespace, and removes leading whitespace.
To parse a line, the following will have to be done:
chomp
,:
into sender and rule string, with at most two fragments,,
into single rules,@
into user and domain part.The rules can then be saved in a database or a Perl data structure.
Matching rules given a pair of sender and receiver addresses. In case of a database, this could be done with a nice SQL query. In case of a Perl data structure, you would:
Matching a rule against an address will first check if the rule part (user/domain) is a *
. Else, the parts are tested for equality. Both the user and domain part have to match for the whole rule to match.
Choosing a good Perl data structure: To make our life easy, all email addresses and rules are only handled in their normalized form. This means e.g. lowercase. For each object in the above algorithm, one could define a seperate class. This is probably undesirable. Instead,
where the line is given in $_
, and a hashref $rules_for_sender
is in scope
chomp;
my ($sender, $rules) = map lc, split /:/, $_, 2;
my @rules = map [split /@/], split /,/, $rules;
$rules_for_sender->{$sender} = \@rules;
for my $rule (@{ $rules->{$sender} } {
my ($rule_user, $rule_domain) = @$rule;
...; # do stuff here
}
…is almost trivial if you remember
use strict; use warnings;
helps you find many errors, andeq
operator.