سؤال

I am forced to implement a sender policy in qmail.

I have a file describing the policies:

User1@domain1.com:*@domain1.com,x@Domain2.COM,y@DOMAIN.com
user2@domain1.com:*@*
USER3@domain1.com:

This file describes the following situation:

user1@domain1.com can send messages to anyone having the address defined on domain1.com, to x@domain2.com and to y@domain.com
user2@domain1.com can send messages to anyone
user3@domain1.com 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

  • to hire someone who does, or
  • to start learning. See tag wiki.

(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:

    • Removing the trailing newline with chomp,
    • Splitting the line on : into sender and rule string, with at most two fragments,
    • Splitting the rule string on , into single rules,
    • Splitting each rule at @ 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:

    • retrieve all rules for the sender's address
    • Iterate through all rules: Match the user and domain parts and return true once both match.
    • Else, return false

    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,

    • Each rule can be represented as a 2-valued array reference
    • The rule list for a sender could be represented as an array reference of rules.
    • The association between the sender address and receiver rules can be made through a hash.

Code examples

Parsing a line

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;

Iterating through all rules for a sender

for my $rule (@{ $rules->{$sender} } {
  my ($rule_user, $rule_domain) = @$rule;
  ...; # do stuff here
}

The rest…

…is almost trivial if you remember

  • to normalize correctly,
  • that use strict; use warnings; helps you find many errors, and
  • that string comparision is done with the eq operator.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top