spf-discuss
[Top] [All Lists]

Re: send money

2004-06-22 21:56:57
On Tue, Jun 22, 2004 at 05:20:36PM -0400, Meng Weng Wong wrote:
| | Also maybe as part of the setup testing, send an email to a 
| | "test" email account (at pobox maybe), after jumping through a 
| | few hoops for security, which then reports on all aspects of 
| | the configuration.
| | 
| | This could warn of potential issues:
| | 
| | * No SPF record
| | * SPF record gives a FAIL
| | * SPF record is outrageous (+ALL, big IP range...)
| | * Lack of PTR records (or IP encoded PTR records).
| | * IP is designated as MTAMark=No
| | * IP is listed as DUL/DHCP in major RBL lists
| | * others based on policies of AOL etc...
| 
| OK, guys, if we collect $1000 in the form of donations
| and/or t-shirt sales, we can fund development of the above
| wizard.  Donate anytime ...

We're up to $200!  Only $800 to go.

Meanwhile, this is the HTML::Mason source code for the
wizard.  I hope it will be helpful in producing the above
robot for those who have the time to work on the project.

<%attr>
title => "SPF Publisher Wizard"
</%attr>

<%doc>
the ilustrator file mechlabel.ai generates the little labels.  transparent pngs 
are antialiased.
the whitesep colour in spf.css should either be white or one of the label 
colours for consistency.

20031212-16:27:43 mengwong(_at_)nutmeg:~/Documents/spf2/website/images% perl 
-le 'my %hash = (qw(09 a 11 mx 13 ptr 25 a: 27 mx: 29 ip4: 41 include: 43 
-all)); while (my ($k, $v) = each %hash) { print "mv mechlabel_$k.png 
label_$v.png" }' | sh; cp *.png /sw/apache/htdocs/spf/images/
</%doc>

<%args>
$use_built_from_args => 0
</%args>

<%once>
my $res = Net::DNS::Resolver->new();
</%once>

<%shared>
my $mydomain;
my $a;
my $mx;
my $a_colon;
my $mx_colon;
my $ip4_colon;
my $include;
my $ptr;
my $all;

my %mxhosts;
my @mx;
my @a;
my $a_ptrdname;
my %a_ptrdnames;
my $Mydomain;
my $built_from_args;
my $built_from_args_length = 40;

my $DEFAULT_INCLUDE   = "myISP.com";
my $DEFAULT_A_COLON   = "regular hostnames";
my $DEFAULT_MX_COLON  = "MX servers";
my $DEFAULT_IP4_COLON = "IP addresses";

my $spfquery;
my $directive_set;

my @record_to_explain;
</%shared>

<%perl>
$mydomain  = $ARGS{mydomain};
$a         = $ARGS{a};
$mx        = $ARGS{mx};
$a_colon   = $ARGS{a_colon};
$mx_colon  = $ARGS{mx_colon};
$ip4_colon = $ARGS{ip4_colon};
$include   = $ARGS{include};
$ptr       = $ARGS{ptr};
$all       = $ARGS{all};


if (! $mydomain) {
  my $client_host = gethostbyaddr(inet_aton($ENV{REMOTE_ADDR}), AF_INET) || 
"mydomain.com";
  my @client_host = split /\./, $client_host;
  my $client_domain = join ".", @client_host[ length($client_host[-1]) == 3 ? 
(-2,-1) : (-3,-2,-1) ];

  $mydomain ||= $client_domain;
}
($mydomain) = $mydomain =~ /(\S+)/;
$Mydomain = $mydomain;

$spfquery = Mail::SPF::Query->new(ipv4=>"208.210.125.24", helo=>$Mydomain, 
sender=>"droid\(_at_)$Mydomain");
my $result = $spfquery->result();
$directive_set = $spfquery->{directive_set};

if (defined $directive_set) { # domain already publishes SPF, so we prefill the 
form values

  my $mechanisms = {};
  foreach my $mech ($directive_set->mechanisms) {
    no warnings 'uninitialized';
    my ($prefix, $mech_name, $value) = @$mech;
    $mechanisms->{$mech_name}->{"$prefix$value"} = $mech;
  }
                
  if (not defined $all) {
    $all = ($mechanisms->{all}->{"-"} ? "yes" : "no");
  }

  if (not defined $a)         { $a   = (delete $mechanisms->{a}  ->{"+"} ? 
"yes" : "no"); }
  if (not defined $mx)        { $mx  = (delete $mechanisms->{mx} ->{"+"} ? 
"yes" : "no"); }
  if (not defined $ptr)       { $ptr = (delete $mechanisms->{ptr}->{"+"} ? 
"yes" : "no"); }
  if (not defined $a_colon)   { $a_colon   = join (" ", grep { s/^\+// } keys 
%{$mechanisms->{a}})       || undef; }
  if (not defined $mx_colon)  { $mx_colon  = join (" ", grep { s/^\+// } keys 
%{$mechanisms->{mx}})      || undef; }
  if (not defined $ip4_colon) { $ip4_colon = join (" ", grep { s/^\+// } keys 
%{$mechanisms->{ip4}})     || undef; }
  if (not defined $include)   { $include   = join (" ", grep { s/^\+// } keys 
%{$mechanisms->{include}}) || undef; }

}

if (my $query = $res->query($mydomain, "MX")) { @mx = map { $_->exchange } grep 
{ $_->type eq "MX" } $query->answer }
if (my $query = $res->query($mydomain, "A"))  { @a  = map { $_->address }  grep 
{ $_->type eq "A"  } $query->answer }
@a = keys %{ { map { lc $_ => 1 } @a } };

foreach my $a (@a) {
  my @a_ptr;
  if (my $query = $res->query(join (".", reverse(split /\./, $a), 
"in-addr.arpa"), "PTR"))  { @a_ptr = map { $_->ptrdname } grep { $_->type eq 
"PTR"  } $query->answer }
  $a_ptrdname = $a_ptr[0] || undef;
  @a_ptrdnames{(_at_)a_ptr}=@a_ptr;
}

foreach my $mx (@mx) {
  my @a_for_mx;
  if (my $query  = $res->query($mx, "A"))  { @a_for_mx = map { $_->address }  
grep { $_->type eq "A"  } $query->answer }
  foreach my $mx_ip (@a_for_mx) {
    my @hostnames;
    if (my $query = $res->query(join(".",(reverse split /\./, $mx_ip), 
"in-addr.arpa"), "PTR")) {
        @hostnames = map { $_->ptrdname } grep { $_->type eq "PTR" } 
$query->answer;
    }
    foreach my $ptrdname ($mx, @hostnames) { push @{$mxhosts{$ptrdname}}, 
$mx_ip; }
  }
}

my @built_from_args = ("v=spf1");

if ($ip4_colon ne $DEFAULT_IP4_COLON) { push @built_from_args, map {     
"ip4:$_" } split ' ', $ip4_colon }
if ($a   eq "yes") { push @built_from_args, "a"  }
if ($mx  eq "yes") { push @built_from_args, "mx" }
if ($ptr eq "yes") { push @built_from_args, "ptr" }
if ($a_colon   ne $DEFAULT_A_COLON)   { push @built_from_args, map {       
"a:$_" } split ' ', $a_colon   }
if ($mx_colon  ne $DEFAULT_MX_COLON)  { push @built_from_args, map {      
"mx:$_" } split ' ', $mx_colon  }
if ($include   ne $DEFAULT_INCLUDE)   { push @built_from_args, map { 
"include:$_" } split ' ', $include   }
if   ($all eq "yes") { push @built_from_args, "-all" }
elsif ($all eq "no") { push @built_from_args, "~all" }

$built_from_args = join " ", @built_from_args;
$built_from_args_length = (length $built_from_args < 40 ? 40 : length 
$built_from_args);

my @existing_txt;
if (my $query = $res->query($Mydomain, "TXT")) {
    @existing_txt = (grep { /^v=spf1(\s|$)/i }
                     map { join "", $_->char_str_list }
                            grep { $_->type eq "TXT" } $query->answer);
                     
                 }
    @record_to_explain = ($use_built_from_args 
                          ? @built_from_args 
                          : split ' ', join " ", @existing_txt);
    
</%perl>

<P>Most domains send outbound mail through a relatively
small number of servers.  Domains should describe that set
of servers in an SPF record in their DNS.  Internet email
receivers can then reject forged messages which don't come
from an envelope sender domain's approved servers.  This
wizard helps domain owners identify all the servers which
could be expected to send mail from their domain.</P>

<script language="JavaScript1.3" type="text/javascript">
<!--

function textarea2colon(prefix, textarea) {
  mywords = textarea.value.split(/\s+/);
  for (i in mywords) {
        if (mywords[i].match(/\S/)) {
            newvalue.push(  prefix + ":" + mywords[i]);
        }
    }
}

function update_rsf(myform) {
    newvalue = new Array("v=spf1");

  if (myform.a         && myform.a[0].checked)                         { 
newvalue.push(   "a");             }
  if (myform.mx        && myform.mx[0].checked)                        { 
newvalue.push(  "mx");             }
  if (myform.ptr       && myform.ptr[0].checked)                       { 
newvalue.push( "ptr");             }
  if (myform.a_colon   && myform.a_colon.value.length   && myform.a_colon.value 
  != "<% $DEFAULT_A_COLON   %>") { textarea2colon("a",      myform.a_colon); }
  if (myform.mx_colon  && myform.mx_colon.value.length  && 
myform.mx_colon.value  != "<% $DEFAULT_MX_COLON  %>") { textarea2colon("mx",    
 myform.mx_colon) }
  if (myform.ip4_colon && myform.ip4_colon.value.length && 
myform.ip4_colon.value != "<% $DEFAULT_IP4_COLON %>") { textarea2colon("ip4",   
 myform.ip4_colon)}
  if (myform.include   && myform.include.value.length   && myform.include.value 
  != "<% $DEFAULT_INCLUDE   %>") { textarea2colon("include",myform.include); }
  if (myform.all[0]    && myform.all[0].checked)                       { 
newvalue.push("-all"); }
  if (myform.all[1]    && myform.all[1].checked)                       { 
newvalue.push("~all"); }

    myform.record_so_far.value = "\"" + newvalue.join(" ") + "\"";
}

//-->
</script>

<TABLE BGCOLOR="#FFFFB0" BORDER=0>
               <& .setdomain &>
<FORM METHOD=GET>
<INPUT TYPE=HIDDEN NAME="mydomain" VALUE="<% $Mydomain %>">
<& .whitesep &><& .mech-a        &>
<& .whitesep &><& .mech-mx       &>
<& .whitesep &><& .mech-ptr      &>
<& .whitesep &><& .mech-others   &>
<& .whitesep &><& .mech-include  &>
<& .whitesep &><& .mech-all      &>
<& .whitesep &><& .record-so-far &>
</TABLE>
</FORM>

% return if ! @record_to_explain;

<H3><% join " ", @record_to_explain |h %></H3>

<TABLE BORDER=0 CELLPADDING=5 CELLSPACING=0 CLASS="orangeblock">
% foreach my $directive (@record_to_explain) {
% 
%   if ($directive eq "v=spf1") {
      <TR><TD ALIGN=CENTER VALIGN=MIDDLE CLASS="orangeblock"><& .mechlabel, 
label => "v=spf1" &></TD>
         <TH><CODE><% $directive |h%></CODE></TH><TD>This identifies the TXT 
record as an SPF string.</TD></TR>
%   }
% 
%   elsif ($directive =~ /^\+?a(\/.*)?$/i) {
      <TR><TD ALIGN=CENTER VALIGN=MIDDLE CLASS="orangeblock"><& .mechlabel, 
label => "a" &></TD>
         <TH><CODE><% $directive |h%></CODE></TH><TD>
%      if (@a == 0) {
                            <% $Mydomain %> has no IP addresses.  This 
declaration has no effect.
%      } elsif (@a == 1) {
                            <% $Mydomain %>'s IP address is <% $a[0] %><% 
($a_ptrdname && lc $a_ptrdname ne $Mydomain) ? " ($a_ptrdname)" : "" %>.
                            <BR>That server is allowed to send mail from <% 
$Mydomain %>.
%      } else {
                            <% $Mydomain %>'s IP addresses are <& comma_and, 
in=>[map { s/.$Mydomain//i; $_ } keys %a_ptrdnames] &>.
                            <BR>Those servers are allowed to send mail from <% 
$Mydomain %>.
%      }
%      if ($directive =~ /\/(\d+)$/) {
                            <BR>So are any other servers in the same /<%$1%> 
subnet.
%      }
       </TD></TR>
%   }
%
%   elsif ($directive =~ /^\+?mx(\/.*)?$/i) {
      <TR><TD ALIGN=CENTER VALIGN=MIDDLE CLASS="orangeblock"><& .mechlabel, 
label => "mx" &></TD>
         <TH><CODE><% $directive |h%></CODE></TH><TD>
%     if (keys %mxhosts == 0) {
                                <% $Mydomain %> has no MX servers.
%     } elsif (keys %mxhosts == 1) {
                                <% $Mydomain %> has one MX server, <& 
comma_and, in=> [ map { s/.$Mydomain//i; $_ } keys %mxhosts] &>.
                                <BR>It is allowed to send mail from <% 
$Mydomain %>.
                                <BR>If you add more MX servers in the future, 
they'll automatically be allowed, too.
%     } else {
                                This wizard found <% scalar(keys %mxhosts) %> 
names for the MX servers for <% $Mydomain %>: <& comma_and, in=>[map { 
s/.$Mydomain//i; $_ } keys %mxhosts] &>.
                                <BR>(A single machine may go by more than one 
hostname.  All of them are shown.)
                                <BR>The servers behind those names are allowed 
to send mail from <% $Mydomain %>.
%     }
%      if ($directive =~ /\/(\d+)$/) {
                            <BR>So are any other servers in the same /<%$1%> <% 
keys %mxhosts > 1 ? "subnets" : "subnet" %>.
%      }
       </TD></TR>
%   }
%
%   elsif ($directive =~ /^\+?ptr$/i) {
      <TR><TD ALIGN=CENTER VALIGN=MIDDLE CLASS="orangeblock"><& .mechlabel, 
label => "ptr" &></TD>
         <TH><CODE><% $directive |h%></CODE></TH><TD>
                                Any server whose name ends in <% $Mydomain %> 
is allowed to send mail from <% $Mydomain %>.
       </TD></TR>
%   }
%
%   elsif ($directive =~ /^\+?ptr:(\S+)/i) {
      <TR><TD ALIGN=CENTER VALIGN=MIDDLE CLASS="orangeblock"><& .mechlabel, 
label => "ptr" &></TD>
         <TH><CODE><% $directive |h%></CODE></TH><TD>
                                Any server whose name ends in <CODE><% 
$spfquery->macro_substitute($1) %></CODE> is allowed to send mail from <% 
$Mydomain %>.
       </TD></TR>
%   }
%
%   elsif ($directive =~ /^\+?ip4:(\S+)/i) {{
      <TR><TD ALIGN=CENTER VALIGN=MIDDLE CLASS="orangeblock"><& .mechlabel, 
label => "ip4:" &></TD>
         <TH><CODE><% $directive |h%></CODE></TH><TD>
% my $network = $1; $network =~ s/\/32$//;
% if ($network =~ /\//) {
%   my $cidr = Net::CIDR::Lite->new($network);
          Every host in the range <% $cidr->list_range |h%> is allowed to send 
mail from <% $Mydomain %>.
% } else {
          <% $network |h%> is allowed to send mail from <% $Mydomain %>.
% }
      </TD></TR>
%   }}
%
%   elsif ($directive =~ /^\+?mx:([^\/]+)/i) {
      <TR><TD ALIGN=CENTER VALIGN=MIDDLE CLASS="orangeblock"><& .mechlabel, 
label => "mx:" &></TD>
         <TH><CODE><% $directive |h%></CODE></TH><TD>
          The MX servers for <% $1 |h%> are allowed to send mail from <% 
$Mydomain %>.
%      if ($directive =~ /\/(\d+)$/) {
                            <BR>So are any other servers in the same /<%$1%> <% 
keys %mxhosts > 1 ? "subnets" : "subnet" %>.
%      }
      </TD></TR>
%   }
%
%   elsif ($directive =~ /^\+?a:([^\/]+)/i) {
      <TR><TD ALIGN=CENTER VALIGN=MIDDLE CLASS="orangeblock"><& .mechlabel, 
label => "a:" &></TD>
         <TH><CODE><% $directive |h%></CODE></TH><TD>
          <% $1 |h%> is also allowed to send mail from <% $Mydomain %>.
%      if ($directive =~ /\/(\d+)$/) {
                            <BR>So are any other servers in the same /<%$1%> 
subnet.
%      }
      </TD></TR>
%   }
%
%   elsif ($directive =~ /^\+?include:(\S+)/i) {
      <TR><TD ALIGN=CENTER VALIGN=MIDDLE CLASS="orangeblock"><& .mechlabel, 
label => "include:" &></TD>
         <TH><CODE><% $directive |h%></CODE></TH><TD>
          Any server allowed to send mail from <CODE><% 
$spfquery->macro_substitute($1) |h%></CODE> is also allowed to send mail from 
<% $Mydomain %>.
      </TD></TR>
%   }
%
%   elsif ($directive =~ /^\+?exists:(\S+)/i) {
      <TR><TD ALIGN=CENTER VALIGN=MIDDLE CLASS="orangeblock"><& .mechlabel, 
label => "exists:" &></TD>
         <TH><CODE><% $directive |h%></CODE></TH><TD>
       <CODE><% $1 |h%></CODE> is <A HREF="macros.html">macro-expanded</A>.
       <BR>If the result has an A record, the transaction is approved.
      </TD></TR>
%   }
%
%   elsif ($directive =~ /^([+~?-])all/) {
      <TR><TD ALIGN=CENTER VALIGN=MIDDLE CLASS="orangeblock"><& .mechlabel, 
label => "all" &></TD>
         <TH><CODE><% $directive |h%></CODE></TH><TD>
%      if ($1 eq "+") {
                                                         The entire Internet is 
allowed to send mail from <% $Mydomain %>.
                                                         <BR>This is <BLINK>not 
recommended</BLINK>.
%      } elsif ($1 eq "-" and @record_to_explain == 2) {
                                                         No servers are allowed 
to send mail from <% $Mydomain %>.
                                                         <BR>This is 
appropriate for web-only sites.
%      } elsif ($1 eq "-") {
                                                         No other servers are 
allowed to send mail from <% $Mydomain %>.
                                                         <BR>This is a good 
default.
%      } elsif ($1 eq "?") {
                                                         SPF queries that do 
not match any other mechanism will return "neutral".
                                                         <BR>Messages that are 
not sent from an approved server should still be accepted as if the SPF record 
did not exist.
%      } elsif ($1 eq "~") {
                                                         SPF queries that do 
not match any other mechanism will return "softfail".
                                                         <BR>Messages that are 
not sent from an approved server should still be accepted but may be subjected 
to greater scrutiny.
%      }
      </TD></TR>
%   }
%
%   elsif ($directive =~ /^redirect=(\S+)/) {
      <TR><TD ALIGN=CENTER VALIGN=MIDDLE CLASS="orangeblock"><& .mechlabel, 
label => "redirect=" &></TD>
         <TH><CODE><% $directive |h%></CODE></TH><TD>
                                          Load the SPF record for <% $1 %> and 
execute it instead.
      </TD></TR>
%   }
%
%   elsif ($directive =~ /^exp=(\S+)/) {
      <TR><TD ALIGN=CENTER VALIGN=MIDDLE CLASS="orangeblock"><& .mechlabel, 
label => "exp=" &></TD>
         <TH><CODE><% $directive |h%></CODE></TH><TD>
%  my @txt_exp = "";
% if (my $query = $res->query($1, "TXT")) { @txt_exp = map { join "", 
$_->char_str_list } grep { $_->type eq "TXT" } $query->answer }
                                          If the message is rejected, the 
explanation string
                                          <BR><% join " ", @txt_exp |h %>
                                          <BR>will be macro-expanded and shown 
to the SMTP client.
      </TD></TR>
%   }
%
%
%   elsif ($directive =~ /^[^:\/]+=/) {
      <TR><TD ALIGN=CENTER VALIGN=MIDDLE CLASS="orangeblock"><& .mechlabel, 
label => "unknown-modifier" &></TD>
         <TH><CODE><% $directive |h%></CODE></TH><TD>
%  my @txt_exp = "";
% if (my $query = $res->query($1, "TXT")) { @txt_exp = map { join "", 
$_->char_str_list } grep { $_->type eq "TXT" } $query->answer }
                                          Unrecognized modifiers are ignored.
      </TD></TR>
%   }
%
%   elsif ($directive =~ /^-/) {
      <TR><TD ALIGN=CENTER VALIGN=MIDDLE CLASS="orangeblock"><& .mechlabel, 
label => "fail" &></TD>
         <TH><CODE><% $directive |h%></CODE></TH><TD>
                                          If this directive matches, SPF will 
return "fail".
      </TD></TR>
%   }
%
%   elsif ($directive =~ /^\?/) {
      <TR><TD ALIGN=CENTER VALIGN=MIDDLE CLASS="orangeblock"><& .mechlabel, 
label => "unknown-mechanism" &></TD>
         <TH><CODE><% $directive |h%></CODE></TH><TD>
                                          If this directive matches, SPF will 
return "unknown".
      </TD></TR>
%   }
%
%   else {
      <TR><TD ALIGN=CENTER VALIGN=MIDDLE CLASS="orangeblock"><& .mechlabel, 
label => "unknown-mechanism" &></TD>
         <TH><CODE><% $directive |h%></CODE></TH><TD>
                                          An SPF client will abort if it 
encounters a mechanism it does not recognize.
      </TD></TR>
%   }
% }
</TABLE>

<HR>

% 
% my @just_a = $mx eq "yes" ? sort grep { lc $_ ne $Mydomain } keys %mxhosts : 
();
% 

<TABLE BORDER=0 CLASS="orangeblock">
 <TR>
  <TD>
   <H3>If you run BIND</H3>
    Paste this into your zone file:

<PRE><% $Mydomain %>. IN TXT "<% join (" ", @record_to_explain) |h %>"</PRE>

% if (@just_a) {

<P>When a mail server sends a bounce message, it uses a null
MAIL FROM: &lt;&gt;, and a HELO address that's supposed to
be its own name.  SPF will still operate, but in "degraded
mode" by using the HELO domain name instead.  Because this
wizard can't tell which name your mail server uses in its
HELO command, it lists all possible names, so there may be
multiple lines shown below.  If you know which hostname your
mail server uses in its HELO command, you should pick out
the appropriate entries and ignore the rest.</P>

So this should also appear in DNS:
<PRE>\
%    foreach my $mxhost (@just_a) {
<% $mxhost %>. IN TXT "v=spf1 a -all"
%    }
</PRE>
% }

  </TD>
 </TR>
</TABLE>
<P></P>
<TABLE BORDER=0 CLASS="orangeblock">
 <TR>
  <TD>
   <H3>If you run tinydns (djbdns)</H3>

<PRE>\
'<% $Mydomain %>:<% map { s/:/\\072/g; $_ } join (" ", @record_to_explain) |h 
%>:3600
% if (@just_a) {
% foreach my $mxhost (@just_a) {
'<% $mxhost %>:v=spf1 a -all:3600
% }
% }
</PRE>

  </TD>
 </TR>
</TABLE>

<P>If your site requires more complex configuration than
this, you should read <A HREF="mechanisms.html">more
about mechanisms</A>.</P>

<P>When you've put these records into your DNS, <A
HREF="http://www.infinitepenguins.net/SPF/register.php";>register
at the SPF registry.</A></P>

<P>You can test some pretend scenarios at one of the <A
HREF="faq.html#tools">DNS tools</A>.  MTAs that reject mail
because SPF tests failed will link to the <A
HREF="why.html">why</A> page.</P>

%# TODO: precompile into ip4 notation

%# ---------------------------------------------------------- setdomain

<%def .setdomain>
<FORM METHOD=GET>
 <&| .orangeblock, args=>"COLSPAN=2, ALIGN=CENTER" &>
      Let's set up SPF records for <& .textbox, 
name=>mydomain=>value=>$Mydomain &>
 </&>
 <&| .orangeblock, args=>"ALIGN=CENTER" &>
  <INPUT TYPE=SUBMIT VALUE="Begin">
 </&>
</FORM>
</%def>

%# ---------------------------------------------------------- record-so-far

<%def .record-so-far>
 <&| .orangeblock, args=>"COLSPAN=2 ALIGN=CENTER VALIGN=TOP" &>
 <% $Mydomain %>. IN TXT  <TEXTAREA NAME="record_so_far" WRAP=virtual ROWS=2 
COLS=50>"<% $built_from_args %>"</TEXTAREA>
 </&>
 <&| .orangeblock, args=>"ALIGN=CENTER" &>
  <INPUT TYPE=HIDDEN NAME="use_built_from_args" VALUE="1">
  <INPUT TYPE=SUBMIT VALUE="Explain">
 </&>
</%def>

%# ---------------------------------------------------------- mech-a

<%def .mech-a><TR>
  <&| .row-left &>
% if (@a == 0) {
    <% $Mydomain %> does not have an IP address.
% }
% elsif (@a == 1) {
    <% $Mydomain %>'s IP address is <% $a[0] %><% ($a_ptrdname && lc 
$a_ptrdname ne $Mydomain) ? " ($a_ptrdname)" : "" %>.
<BR>Does that server send mail from <% $Mydomain %>?
% }
% else {
    <% $Mydomain %>'s IP addresses are <% join ", ", @a %>.
<BR>Do those servers send mail from <% $Mydomain %>?
% }
  </&>

  <&| .row-mid   &><& .mechlabel, label => "a" &></&>
% if (@a) {
  <&| .row-right &><&| .yesno, name=>"a", selected => $a  &></&></&>
% } else {
  <&| .row-right &></&>
% }

</TR></%def>

%# ---------------------------------------------------------- mech-mx
<%def .mech-mx><TR>
  <&| .row-left &>
% if (keys %mxhosts == 0) {
    <% $Mydomain %> has no MX servers.
% }
% elsif (keys %mxhosts == 1) {
%   my ($mx_ips) = values(%mxhosts);
%   if ("@{[sort @$mx_ips]}" eq "@{[sort @a]}") {
    <% $Mydomain %> has no other MX servers.
    <BR>Do you want to add an explicit MX entry anyway?
    <BR>If you might add other MX servers in the future, say yes.
%   }
%   else {
    <% $Mydomain %> has one MX server, <% keys(%mxhosts) %>.
    <BR>It receives mail <I>for</I> <% $Mydomain %>.
    <BR>Does it also send mail <I>from</I> <% $Mydomain %>?
%   }
% }
% else {
    This wizard found <% scalar(keys %mxhosts) %> names for <% $Mydomain %>'s 
MX servers.
    <BR>MX servers receive mail <I>for</I> <% $Mydomain %>.
    <BR>Do they also send mail <I>from</I> <% $Mydomain %>?
% }
  </&>
  <&| .row-mid   &><& .mechlabel, label => "mx" &></&>

% if (@mx) {
  <&| .row-right &><&| .yesno, name=>"mx", selected => $mx &></&></&>
% } else {
  <&| .row-right &></&>
% }

</TR></%def>

%# ---------------------------------------------------------- mech-others
<%def .mech-others><TR>
 <TR>
  <&| .orangeblock, args=>"ROWSPAN=2 VALIGN=TOP" &>
<P>Do any other servers send mail from <% $Mydomain %>?</P>
<P>You can describe them by giving "arguments" to the <B>a:</B>, <B>mx:</B>, 
<B>ip4:</B>, and <B>ptr:</B> mechanisms.
   To keep the wizard short we left out <B>ptr:</B> but it works the same 
way.</P>
</&>
  <&| .row-mid   &><& .mechlabel, label => "a:" &></&>
  <&| .row-right &><&| .textarea, name=>"a_colon" &><% $a_colon || 
$DEFAULT_A_COLON %></&></&>
 </TR>

 <TR>
  <&| .row-mid   &><& .mechlabel, label => "mx:" &></&>
  <&| .row-right &><&| .textarea, name=>"mx_colon" &><% $mx_colon || 
$DEFAULT_MX_COLON %></&></&>
 </TR>

 <TR>
  <&| .orangeblock, args=>"ALIGN=RIGHT" &><BR><FONT SIZE=-1><I>IP networks can 
be entered using CIDR notation, eg. 192.0.2.0/24</I></FONT></&>
  <&| .row-mid   &><& .mechlabel, label => "ip4:" &></&>
  <&| .row-right &><&| .textarea, name=>"ip4_colon" &><% $ip4_colon || 
$DEFAULT_IP4_COLON %></&></&>
 </TR>
</TR></%def>

%# ---------------------------------------------------------- mech-ptr
<%def .mech-ptr><TR>
  <&| .row-left &>
    Do you want to just approve any host
    <BR>whose name ends in <% $Mydomain %>?
  </&>
  <&| .row-mid   &><& .mechlabel, label => "ptr" &></&>
  <&| .row-right &><&| .yesno, name=>"ptr", selected => $ptr     &></&></&>
</TR></%def>

%# ---------------------------------------------------------- mech-include
<%def .mech-include><TR>
  <&| .row-left &>
    Could mail from <% $Mydomain %> originate through
    <BR>servers belonging to some other domain?
    <BR>If you send mail through your ISP's servers, name the ISP here.</P>
  </&>
  <&| .row-mid   &><& .mechlabel, label => "include:" &></&>
  <&| .row-right &><&| .textbox, name=>"include", value=>$include || 
$DEFAULT_INCLUDE &></&></&>
</TR></%def>

%# ---------------------------------------------------------- mech-all
<%def .mech-all><TR>
  <&| .row-left &>
    Do the above lines describe all the hosts
    <BR>that send mail from <% $Mydomain %>?
  </&>
  <&| .row-mid   &><& .mechlabel, label => "-all" &></&>
  <&| .row-right &><&| .yesno, name=>"all", selected => $all  &></&></&>
</TR></%def>

%# ---------------------------------------------------------- mechlabel

<%def .mechlabel>
<%args>
$label
</%args>
<IMG ALT="[<%$label%>]" SRC="/images/label_<%$label%>.png">
</%def>

%# ---------------------------------------------------------- whitesep

<%def .whitesep>
<%args>
$args => ""
</%args>
<TR><TD CLASS="whitesep" COLSPAN=3 HEIGHT=2></TD></TR>
</%def>

%# ---------------------------------------------------------- orangeblock

<%def .orangeblock>
<%args>
$args => ""
</%args>
  <TD CLASS="orangeblock"<% $args ? " $args" : "" %>>
    <% $m->content %>
  </TD>
</%def>

%# ---------------------------------------------------------- row-left, 
row-mid, row-right

<%def .row-left>
<&| .orangeblock, args => "COLSPAN=1" &><% $m->content %></&>
</%def>

<%def .row-mid>
<&| .orangeblock, args=>"ALIGN=CENTER" &><% $m->content %></&>
</%def>

<%def .row-right>
<&| .orangeblock, args=>"ALIGN=CENTER" &><% $m->content %></&>
</%def>

%# ---------------------------------------------------------- yesno

<%def .yesno>
<%args>
$name
$selected => ""
</%args>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0>
  <TR><TD ALIGN=CENTER><INPUT TYPE="radio" NAME="<% $name %>" VALUE="yes"<% 
$selected eq "yes" ? " CHECKED" : "" %> onClick="update_rsf(this.form)"></TD>
      <TD ALIGN=CENTER><INPUT TYPE="radio" NAME="<% $name %>" VALUE="no" <% 
$selected eq "no"  ? " CHECKED" : "" %> onClick="update_rsf(this.form)"></TD>
  </TR>
  <TR><TD ALIGN=CENTER><FONT SIZE="-1">yes</FONT></TD>
      <TD ALIGN=CENTER><FONT SIZE="-1">no</FONT></TD>
  </TR>
</TABLE>
</%def>


%# ---------------------------------------------------------- textbox

<%def .textbox>
<%args>
$name
$value => ""
$onchange => "update_rsf(this.form)"
</%args>
<INPUT TYPE="text" NAME="<% $name %>" VALUE="<% $value %>" <% $onchange ? 
qq(onChange="$onchange") : "" %>>
</%def>


%# ---------------------------------------------------------- textarea

<%def .textarea>
<%args>
$name
</%args>
<TEXTAREA NAME="<% $name %>" onChange="update_rsf(this.form);"><% $m->content 
%></TEXTAREA>
</%def>

%# ---------------------------------------------------------- comma_and



<%def comma_and>
<%args>@in</%args>
<%perl>
  if    (@in >=3) { $in[-1] = " and $in[-1]"; $m->out(join ", ", @in) }
  elsif (@in ==2) { $m->out(join " and ", @in) }
  elsif (@in ==1) { $m->out($in[0]) }
  else            {  }
</%perl>
</%def>


<Prev in Thread] Current Thread [Next in Thread>