I've been trying for THREE DAYS to email SOMEBODY at PERL.COM about taking
out a damn ad in their Perl.Com newsletter.
EVERY EMAIL ADDRESS LISTED IN THE NEWSLETTER AND WEBSITE BOUNCES.
It's not like they bounce with the same cause, either! That's the FUNNY
part. It looks like Songline's sever (magic.songline.com) simply refuses
ALL mail.. Nice touch, guy!
The backup MX for Perl.com (lists.oreillynet.com) bounces with another
error. A result of songline's F*CKED UP server.
The BEST OF ALL is Top Christiansen's snot-nosed mail rejection scheme.
NICE WORK TOM! I am including the ENTIRE DAMN REPLY I got from it. You can
see my TINY MESSAGE quoted at the bottom. Tom -- your reply is WAY out of
line. Get a grip, man! Rude, rude, RUDE!
FRUSTRATED AS HELL,
-Jesse-
-----Original Message-----
From: Mail Delivery Subsystem [mailto:[EMAIL PROTECTED]]
Sent: Thursday, May 03, 2001 7:58 PM
To: [EMAIL PROTECTED]
Subject: Returned mail: see transcript for details
The original message was received at Thu, 3 May 2001 17:57:27 -0600 (MDT)
from kyle.vm.com [209.73.238.18]
----- The following addresses had permanent fatal errors -----
"|/home/tchrist/.audit_mail tchrist"
(reason: service unavailable)
(expanded from: <[EMAIL PROTECTED]>)
----- Transcript of session follows -----
***********************************************
**** EMT (Email Abuse Toolkit) Intercept ****
***********************************************
Your message appears to be in violation of 1855 due to
overquoting or forwarding the complete messages, probably following
rather than preceding your reply. These are improper.
Please reconfigure your User Mail Agent to act more responsibly,
and resend your message after reading the following explanation.
Following you will find some code that mind be of use in diagnosing
other netiqutte issues that your User Mail Agent may be violating.
EXECUTIVE SUMMARY:
To send better messages, please trim and summarize what you're
replying to, and integrate your quoted text with the body of your
message. Don't just put everything at the end. This isn't Jeopardy.
People expect question-and-answer, not answer-and-question responses.
LONG STORY:
Wouldn't you like to make your messages easier for others to read and
understand? If so, I have some news posting tips for you. If not,
just ignore this. (Of course, if you don't want your messages
easier to read and understand, it's not clear why you bother to
send them in the first place. :-) I'm going to take a bit of
time to explain this, because newcomers to Usenet often lack the
cultural background were I to send a superbrief message.
Here's the issue: you appear to have quoted the entire message to which
you were replying. Worst of all, you have done so by merely appending
the complete message at the bottom. Folks are used to reading the
original material first, then the follow-up. That's why it's called a
"follow-up", you know. :-)
If all you want to do is forward a copy of the message, that's one thing,
but here you seem to have just blindly pasted the complete old message at
the end without providing any content. This is neither a proper public
followup nor even a decent private reply. Here's why.
First of all, this is massive overkill -- you're supposed to trim your
quoted text to only what you're replying to. Otherwise you'll probably
violate the netiquette target quoting percentage of 50%. See below.
This isn't really an issue of space (I know that a few bytes here and
there mean less today than 20 years go), so much as it is of integrating
your comments with the old material for continuity.
Second, putting everything at the bottom does little good. It doesn't
provide the proper context. It's far too late. When you reply to
someone's content, the reason you quote the previous message is so that
you can provide some degree of contextual continuity. The best way to
do this is to interleave what you're quoting with your responses to that
particular piece. That means that you should provide a quoted portion,
then address what the points therein, then another quoted section, etc.
For example, here's how followup replies *should* look if you'd
like them to be more effective.
> Joe said we should eat noodles.
But I don't like noodles. They are a pain to prepare -- remember
that what started this thread was how to cook using only a microwave,
not real cooking -- and they provide you with very little sustenance
in the long run. It's like eating cardboard, nutritionally speaking.
> He also suggests adding anchovies.
What is this fish fetish? Not all of us like the little minnows
with the lingering briny taste swimming around our mouths for the
next few hours or days. Can you imagine this on a date? Iccccch!
Notice how in the text above, alternate quoted passages are interleaved
with new response text. Notice also that the new text far exceeds the
old text. This is the way it should be.
Here's an excerpt from RFC 1855, which explains why this is bad.
You can read the whole RCS at http://www.faqs.org/rfcs/rfc1855.html
- If you are sending a reply to a message or a posting be sure you
summarize the original at the top of the message, or include just
enough text of the original to give a context. This will make
sure readers understand when they start to read your response.
Since NetNews, especially, is proliferated by distributing the
postings from one host to another, it is possible to see a
response to a message before seeing the original. Giving context
helps everyone. But do not include the entire original!
If you are receiving this message in response to a news posting, please
understand that all modern newsreaders provide a mechanism to fetch
the parent article, so it is seldom necessary to quote the whole thing.
Sometimes even mail readers provide this, depending on the mail headers
and the list archival mechanism on your own system.
Here's a section from the essential netiquette guide, "A Primer
on How to Work With the Usenet Community", which is available in
news.announce.newusers. Perhaps your service provider neglected to point
you at this newsgroup before you got swallowed up by all of Usenet.
It's not only a good read; it's critical to understanding the culture
you're now moving in.
Summarize What You are Following Up.
When you are following up someone's article, please summarize the
parts of the article to which you are responding. This allows readers
to appreciate your comments rather than trying to remember what the
original article said. It is also possible for your response to get
to some sites before the original article.
Summarization is best done by including appropriate quotes from
the original article. Do not include the entire article since it
will irritate the people who have already seen it. Even if you are
responding to the entire article, summarize only the major points you
are discussing.
It's even more annoying when people needlessly quote the original's
automatic trailing matter, like signatures, adverts, or disclaimers.
Please don't do that.
NETIQUETTE CONFORMANCE CODE FOLLOWS:
#!/usr/bin/perl -w
# msgchk - check news and mail messages for netiquette violations
use strict;
my $Msg = get_message();
missing_headers();
bogus_address();
allcap_subject();
annoying_subject();
mimes();
lines_too_long();
control_characters();
miswrapped();
jeopardy_quoted();
overquoted();
good_signature();
exit(0);
#######################
sub AUTOLOAD {
use vars '$AUTOLOAD';
my $field;
($field = uc($AUTOLOAD)) =~ s/.*:://;
if (!defined wantarray) {
require Carp;
Carp::confess("Undefined function call: $AUTOLOAD");
}
$Msg->$field();
}
sub bogus_address {
my $address = from();
if ($address !~ /\@\w.*\.\w/) {
print "From address must contain an at sign, etc.\n";
return;
}
if ($address =~ /(remove|spam)/i) {
print "Munged return address suspected, found `$1' in from.\n";
}
ck822($address); # inscrutable
my($host) = $address =~ /\@([a-zA-Z0-9_.-]+)/;
dns_check($host); # very slow!
}
sub control_characters {
my $lineno = 0;
my $MAX_CONTROL = 5;
for (lines()) {
$lineno++;
if (/(?=[^\s\b])([\000-\037])/) {
printf "Control character (char %#o) appears at line %d of
body.\n",
ord $1, $lineno;
}
if (/([\202-\237])/) {
printf "MS-ASCII character (char %#o) appears at line %d of
body.\n",
ord $1, $lineno;
}
last if --$MAX_CONTROL < 0;
}
}
sub lines_too_long {
my $MAX_LINE_LEN = 80;
my $line_count = scalar @{ [ lines() ] };
my ($long_lines, $longest_line_data, $longest_line_number) = (0,'',0);
my $lineno = 0;
for (lines()) {
$lineno++;
next if /^[>+-]/; # skip quotes and patch diffs
if (length() > $MAX_LINE_LEN) {
$long_lines++;
if (length() > length($longest_line_data)) {
$longest_line_data = $_;
$longest_line_number = $lineno;
}
}
}
if ($long_lines) {
printf "%d of %d lines exceed maxlen %d, ",
$long_lines, $line_count, $MAX_LINE_LEN;
printf "longest is #%d at %d bytes\n",
$longest_line_number, length($longest_line_data);
}
}
sub missing_headers {
if (subject() !~ /\S/) {
print "Missing required subject header.\n";
}
if (newsgroups() && subject() =~ /^\s*Re:/i && !references()) {
print "Followup posting missing required references header.\n";
}
}
sub allcap_subject {
my $subject = subject();
$subject =~ s/^(\s*Re:\s*)+//i;
if ($subject !~ /[a-z]/) {
print "No lower-case letters in subject header.\n";
}
}
sub miswrapped {
my($bq1, $bq2);
for (paragraphs()) {
next unless /\A(^\S.*){2,}\Z/ms; # no indented code
if (!$bq1 && /^>\S.*\n\s*[a-zA-Z]/) {
print "Incorrectly wrapped quoted text.\n";
$bq1++;
}
next if $bq2;
my $count = 0;
while (/^[^>].{60,}\n[^>].{1,20}\n(?=[^>].{60,}\n)/gm) {
$count++;
}
if ($count > 1) {
print "Incorrectly wrapped regular text.\n";
$bq2++;
### print "OOPS count = $count:\n$_\n\n";
}
}
}
sub jeopardy_quoted {
local $_ = body();
$_ = unquote_wrap($_);
$_ = strip_signature($_);
$_ = strip_attribution($_);
# check quotation at bottom but nowhere else
# XXX: these can go superlong superlong! i've added
# some more anchors and constraints to try to avoid this,
# but I still mistrust it
if (/ ((^\s*>.*){2,}) \s* \Z/mx
&&
!/ (\n>.*?)+ (\n[^>].*?)+ (\n>.*?)+ /x )
{
print "Quote follows response, Jeopardy style #1\n";
}
# completely at bottom
elsif (/^.* wr(?:ote|ites):\n(>.*\n)+\s*\Z/m) {
print "Quote follows response, Jeopardy style #2\n";
}
# another way of saying the same
elsif (/^(?:>+\s*)?-[_+]\s*Original Message\s*-[_+]\s.*\Z/ms) {
print "Quote follows response, Jeopardy style #3\n";
}
# another way of saying the same
elsif (/^(?:>+\s*)?[_-]+\s*Reply Separator\s*[_-]+\s.*\Z/ms) {
print "Quote follows response, Jeopardy style #4\n";
}
}
sub overquoted {
# cfoq: check fascistly overquoted by [EMAIL PROTECTED]
# (wants perl 5.0 or better; developed under 5.002)
my (
$total, # total number of lines, minus sig and attribution
$quoted_lines, # how many lines were quoted
$percent, # what percentage this in
$pcount, # how many in this paragraph were counted
$match_part, # holding space for current match
$gotsig, # is this the sig paragraph?
);
$total = $quoted_lines = $pcount = $percent = 0;
my $MINLINES = 20;
my $TOLERANCE = 50;
my $VERBOSE = 0;
if (body() =~ /^-+\s*Original Message\s*-+$/m) {
my $body = strip_signature(body());
my($text,$quote) = body() =~ /(.*)(^-+\s*Original
Message\s*-+.*\Z)/ms;
$total = ((my $x = body()) =~ y/\n//);
$quoted_lines = ($quote =~ y/\n//);
}
else {
for (paragraphs()) {
# strip sig line, remember we found it
$gotsig = s/^-- \n.*//ms;
# strip attribution, possibly multiline
if ($. == 2) { s/\A.*?(<.*?>|\@).*?:\n//s }
# toss trailing blank lines into one single line
s/\n+\Z/\n/;
# now reduce miswrapped lines from idiotic broken PC newsreaders
# into what they should have been
s/(>.*)\n\s*([a-zA-Z])/$1 $2/g;
# count lines in this paragraph
$total++ while /^./mg;
# is it a single line, quoted in the customary fashion?
if ( /^(>+).*\n\Z/ ) {
$quoted_lines++;
print " 1 line quoted with $1\n" if $VERBOSE;
next;
}
# otherwise, it's a multiline block, which may be quoted
# with any leading repeated string that's neither alphanumeric
# nor string
while (/^(([^\w\s]+).*\n)(\2.*\n)+/mg) { # YANETUT
$quoted_lines += $pcount = ($match_part = $&) =~ tr/\n//;
printf "%2d lines quoted with $2\n", $pcount if $VERBOSE;
}
last if $gotsig;
}
}
$percent = int($quoted_lines / $total * 100);
if ($total == $quoted_lines) {
print "All $total lines were quoted lines!\n";
# not ok
}
elsif ($percent > $TOLERANCE && $total > $MINLINES) {
print "Overquoted: $quoted_lines lines quoted out of $total:
$percent%\n";
}
}
sub unquote_wrap {
my $chunk = shift;
# reduce miswrapped lines from idiotic broken PC newsreaders
# into what they should have been
$chunk =~ s/(>.*)\n\s*([a-zA-Z])/$1 $2/g;
return $chunk;
}
sub good_signature {
my $MAX_SIGLINES = 4;
my $sig = '';
my($is_canon, $separator);
my $body = body();
# sometimes the ms idiotware quotes at the bottom this way
$body =~ s/^-+\s*Original Message\s*-+\s.*\Z//ms;
# first check regular signature
if ($body =~ /\n-- \n(.*)/s) {
$sig = $1;
$is_canon = 1;
}
elsif ($body =~ /\n([_-]{2,}\s*)\n(.*?)$/s) {
$separator = $1;
$sig = $2;
}
for ($separator, $sig) { s/\n\Z// if defined }
my $siglines = $sig =~ tr/\n//;
if ($separator && ($siglines && $siglines < 20)) {
if ($separator eq '--') {
print "Double-dash in signature missing trailing space.\n";
} else {
print "Non-canonical signature separator: `$separator'\n";
}
}
if ($siglines > $MAX_SIGLINES && $siglines < 20) {
printf "Signature too long: %d lines\n", $siglines;
}
}
sub strip_signature {
local $_ = shift;
s/\n-- \n(.*)//s
||
s/\n([_-]{2,}\s*)\n(.*?)$//s;
return $_;
}
sub attribution {
local $_ = body();
s/^\s*\[.*\]\s*//; # remove [courtesy cc]
if (/\A(.*wr(?:ote|ites):?)\n/) {
return $1;
} elsif (/\A(.*?(<.*?>|\@).*?:)\n/s) {
return $1;
} else {
return '';
}
}
sub strip_attribution {
local $_ = shift;
s/^\s*\[.*\]\s*//; # remove [courtesy cc]
# XXX: duplicate code with previous function
s/\A(.*wr(?:ote|ites):?)\n//
||
s/\A(.*?(<.*?>|\@).*?:)\n//s;
return $_;
}
sub annoying_subject {
local $_ = subject();
if ( / ( [?!]{3,} ) /x ||
/ ( HELP ) /x ||
/ ( PLEASE ) /x
)
{
print "Subject line contains annoying `$1' in it.\n";
}
}
sub mimes {
my $mime_crap = 0;
for (content_type()) {
last unless defined;
$mime_crap++;
if (/multipart/i) {
print "Multipart MIME detected.\n";
}
elsif (/html/i) {
print "HTML encrypting detected.\n";
}
elsif (! (/^text$/i || m#^text/plain#i)) {
print "Strange content type detected: $_\n";
}
}
for (content_transfer_encoding()) {
last unless defined;
if (/quoted-printable/i) {
print "Gratuitously quoted-illegible MIMEing detected.\n";
}
}
unless ($mime_crap) {
for (body()) {
if (/\A\s*This message is in MIME format/i) {
print "Gratuitous but unadvertised MIME detected.\n";
}
elsif ( /\A\s*This is a multi-part message in MIME format/i) {
print "Unadvertised multipart MIME detected.\n";
}
}
}
}
sub dns_check {
my $NSLOOKUP = '/usr/bin/nslookup'; # or /usr/ucb?
# first try an MX record, then an A rec (for badly configged hosts)
my $host = shift;
local $/ = undef;
local *NS;
local $_;
# the following is commented out for security reasons:
# if ( `nslookup -query=mx $host` =~ /mail exchanger/
# otherwise there could be naughty bits in $host
# we'll bypass system() and get right at execvp()
my $pid;
if ($pid = open(NS, "-|")) {
$_ = <NS>;
kill 'TERM', $pid if $pid; # just in case
close NS;
return if /mail exchanger/;
# else fall trohugh to next test
} else {
die "cannot fork: $!" unless defined $pid;
open(SE, ">&STDERR");
open(STDERR, ">/dev/null");
{ exec $NSLOOKUP, '-query=mx', $host; } # braces for -w
open(STDERR, ">&SE");
die "can't exec nslookup: $!";
}
if ($pid = open(NS, "-|")) {
$_ = <NS>;
kill 'TERM', $pid if $pid; # just in case
close NS;
unless (/answer:.*Address/s || /Name:.*$host.*Address:/si) {
print "No DNS for \@$host in return address.\n";
}
} else {
die "cannot fork: $!" unless defined $pid;
open(SE, ">&STDERR");
open(STDERR, ">/dev/null");
{ exec $NSLOOKUP, '-query=a', $host; } # braces for -w
open(STDERR, ">&SE");
die "can't exec nslookup: $!";
}
}
sub ck822 {
# ck822 -- check whether address is valid rfc 822 address
# [EMAIL PROTECTED]
#
# pattern developed in program by jfriedl;
# see "Mastering Regular Expressions" from ORA for details
# this will error on something like "ftp.perl.com." because
# even though dns wants it, rREJECT overquoted message
fc822 hates it. shucks.
my $what = 'address';
my $address = shift;
local $_;
my $is_a_valid_rfc_822_addr;
($is_a_valid_rfc_822_addr = <<'EOSCARY') =~ s/\n//g;
(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n
\015()]|\\[^\x80-\xff])*\))*\))*(?:(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\
xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"(?:[^\\\x80-\xff\n\015"
]|\\[^\x80-\xff])*")(?:(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xf
f]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*\.(?:[\040\t]|\((?:[
^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\
xff])*\))*\))*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;
:".\\\[\]\000-\037\x80-\xff])|"(?:[^\\\x80-\xff\n\015"]|\\[^\x80-\xff])*"))
*(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\
n\015()]|\\[^\x80-\xff])*\))*\))*@(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\
\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*(?:[^(\04
0)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-
\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])(?:(?:[\040\t]|\((?
:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80
-\xff])*\))*\))*\.(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\(
(?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*(?:[^(\040)<>@,;:".\\\[\]
\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\
\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\]))*|(?:[^(\040)<>@,;:".\\\[\]\000-\0
37\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"(?:[^\\\x80-\xf
f\n\015"]|\\[^\x80-\xff])*")(?:[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\03
7]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\
\[^\x80-\xff])*\))*\)|"(?:[^\\\x80-\xff\n\015"]|\\[^\x80-\xff])*")*<(?:[\04
0\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]
|\\[^\x80-\xff])*\))*\))*(?:@(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x
80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*(?:[^(\040)<>@
,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]
)|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])(?:(?:[\040\t]|\((?:[^\\
\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff
])*\))*\))*\.(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^
\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*(?:[^(\040)<>@,;:".\\\[\]\000-
\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-
\xff\n\015\[\]]|\\[^\x80-\xff])*\]))*(?:(?:[\040\t]|\((?:[^\\\x80-\xff\n\01
5()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*,(?
:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\0
15()]|\\[^\x80-\xff])*\))*\))*@(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^
\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*(?:[^(\040)<
>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xf
f])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])(?:(?:[\040\t]|\((?:[^
\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\x
ff])*\))*\))*\.(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:
[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*(?:[^(\040)<>@,;:".\\\[\]\00
0-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x8
0-\xff\n\015\[\]]|\\[^\x80-\xff])*\]))*)*:(?:[\040\t]|\((?:[^\\\x80-\xff\n\
015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*)
?(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000
-\037\x80-\xff])|"(?:[^\\\x80-\xff\n\015"]|\\[^\x80-\xff])*")(?:(?:[\040\t]
|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[
^\x80-\xff])*\))*\))*\.(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xf
f]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*(?:[^(\040)<>@,;:".\
\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"(?:
[^\\\x80-\xff\n\015"]|\\[^\x80-\xff])*"))*(?:[\040\t]|\((?:[^\\\x80-\xff\n\
015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*@
(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n
\015()]|\\[^\x80-\xff])*\))*\))*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff
]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\
]]|\\[^\x80-\xff])*\])(?:(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\
xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*\.(?:[\040\t]|\((?
:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80
-\xff])*\))*\))*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@
,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff
])*\]))*(?:[\040\t]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff]|\((?:[^\\\x8
0-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*>)(?:[\040\t]|\((?:[^\\\x80-\xff\n\
015()]|\\[^\x80-\xff]|\((?:[^\\\x80-\xff\n\015()]|\\[^\x80-\xff])*\))*\))*
EOSCARY
if ($address !~ /^${is_a_valid_rfc_822_addr}$/o) {
print "rfc822 failure on $address";
}
}
##############################
package Mail_Message;
use Carp;
use vars qw/$AUTOLOAD/;
# process <ARGV> for a message header and body
# currently this assumes one message per file!
sub main::get_message {
my $msg = bless {}, __PACKAGE__;
local $/ = '';
$msg->{HEADER_STRING} = <>;
chomp $msg->{HEADER_STRING};
for (split /\n(?!\s)/, $msg->{HEADER_STRING}) {
my($tag, $value) = /^([^\s:]+):\s*(.*)\s*\Z/s;
push @{ $msg->{HEADERS}{$tag} }, $value;
$tag =~ tr/-/_/;
$tag = uc($tag);
push @{ $msg->{$tag} }, $value;
}
local $/ = undef;
for ($msg->{BODY} = <>) {
$msg->{PARAGRAPHS} = [ split /\n\n+/ ];
$msg->{LINES} = [ split /\n/ ];
}
return $msg;
}
sub AUTOLOAD {
use vars '$AUTOLOAD';
my $self = shift;
my $field;
($field = uc($AUTOLOAD)) =~ s/.*:://;
my $xfield = "x_" . $field;
if (!exists $self->{$field} && exists $self->{$xfield}) {
$field = $xfield;
}
unless (exists $self->{$field}) {
return undef;
# NOT REACHED
confess "No field $field in message";
}
my $data = $self->{$field};
my @data = ref $data ? @$data : $data;
if (wantarray) {
return @data;
}
else {
return join("\n", @data);
}
}
554 5.0.0 "|/home/tchrist/.audit_mail tchrist"... Service unavailable
----- Original message follows -----
Return-Path: <[EMAIL PROTECTED]>
Received: from kyle.vm.com (kyle.vm.com [209.73.238.18])
by chthon.perl.com (8.10.0/8.10.0) with SMTP id f43NvLT05184
for <[EMAIL PROTECTED]>; Thu, 3 May 2001 17:57:27 -0600 (MDT)
Received: (qmail 24050 invoked from network); 3 May 2001 23:56:51 -0000
Received: from exchange.vm.com (209.73.238.141)
by kyle.vm.com with SMTP; 3 May 2001 23:56:51 -0000
Received: by exchange.vm.com with Internet Mail Service (5.5.2650.21)
id <J96RTQLD>; Thu, 3 May 2001 19:58:44 -0400
Message-ID: <[EMAIL PROTECTED]>
From: Jesse Erlbaum <[EMAIL PROTECTED]>
To: "'[EMAIL PROTECTED]'" <[EMAIL PROTECTED]>
Cc: "'[EMAIL PROTECTED]'" <[EMAIL PROTECTED]>,
"'[EMAIL PROTECTED]'" <[EMAIL PROTECTED]>,
"'[EMAIL PROTECTED]'"
<[EMAIL PROTECTED]>,
"'[EMAIL PROTECTED]'" <[EMAIL PROTECTED]>,
"'[EMAIL PROTECTED]'" <[EMAIL PROTECTED]>
Subject: Your mail server is completely f*cked! (WAS: Undelivered Mail Re
turned to Sender)
Date: Thu, 3 May 2001 19:58:40 -0400
MIME-Version: 1.0
X-Mailer: Internet Mail Service (5.5.2650.21)
Content-Type: text/plain;
charset="iso-8859-1"
Is there anyone competent working at ORA or Songline?
Why (oh, why!) is the Sendmail server at magic.songline.com (204.148.40.71)
refusing to accept mail? Was everybody fired? Is the company shutting
down? Did the guy who wrote your sendmail.cf take a job at Microsoft?
May I recommend a book to you? Try reading "Sendmail" by Bryan Costales.
It's published by this little old company -- maybe you've heard of them:
O'REILLY & ASSOCIATES!
Seriously, guys. You have email addresses in the newsletter which bounce.
Your "CONTACT US" page on the website lists addresses which bounce. WHAT
THE HELL IS GOING ON?
Geeze....
-----Original Message-----
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED]]
Sent: Thursday, May 03, 2001 7:47 PM
To: [EMAIL PROTECTED]
Subject: Undelivered Mail Returned to Sender
This is the Postfix program at host lists.oreillynet.com.
I'm sorry to have to inform you that the message returned
below could not be delivered to one or more destinations.
For further assistance, please contact <[EMAIL PROTECTED]>
If you do so, please include this problem report. You can
delete your own text from the message returned below.
The Postfix program
<[EMAIL PROTECTED]>: host magic.songline.com[204.148.40.71] said: 550
<[EMAIL PROTECTED]>... Access denied