Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

Just wondering whats considered safe and not. I'm making a simple script that allows a user to send a email message to several friends on his list.

Should I limit the textfield to a certain amount of characters? Do I allow anything typed? Am I being a bit too paranoid?

Cheers, DJ
  • Comment on How do I go about validating a e-mail message field?

Replies are listed 'Best First'.
Re: How do I go about validating a e-mail message field?
by davorg (Chancellor) on Sep 21, 2006 at 08:06 UTC

    This sounds potentially dangerous. How does it work. If I can use your form to send text that is taken from the web form to a set of email addresses that are also taken from the web form, then I can use that form to send whatever spam I want to whatever addresses I want. And the spam will come from your server.

    I'm guessing that you don't want that to happen.

    --
    <http://dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

Re: How do I go about validating a e-mail message field?
by Skeeve (Parson) on Sep 21, 2006 at 07:43 UTC
    search is your friend

    s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
    +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e
      Hi,

      I have done a little function to try to deal with this but it's hard to deal with everything, but you could add your caracter logic into this function...
      Here is the code...
      # # Check if a email is valid # Tests aplied: there must not be space chars on the mail, there must +be only one @ char, there must be a mail user # there must be a mail domain and a domain prefix # optionally it can also restrict a email into a given l +ist of domain prefixes (com,pt,org,etc) # Will Return 0 ; 1 # 0 email is valid ; 1 email is not valid sub check_email { my $email = $_[0]; # email to test my $global_config_p = $_[1]; # configuration pointer print "Running the check_email() function\n" if ( defined $$global +_config_p{debug_level} and ($$global_config_p{debug_level} eq "half" +or $$global_config_p{debug_level} eq "full") ); # print message if th +e debug level requires it my $alllowed_domain_prefixes = $_[2]; # optional value where you c +an say what email prefixes (.pt .com .org etc) are allowed # the list should be passed +without the . char and separated by the , char example (pt,com,org,es +) my $error_flag = 1; # by default the email is invalid $email =~ s/^\s+//; # Delete leading whitespace ^ is the first ca +racter \s is space then // replace with nothing if there was /a/ the +n replace with a $email =~ s/\s+$//; # Delete trailing whitespace same thing kind +of but $ represents end of line. if ( length($email) >= 5 and ($email =~ tr/@//) == 1 and ($email = +~ tr/ //) == 0 ) { # email must have at least 5 chars ( a@a.c) and on +e @ char and no SPACE CHARS my ( $mail_user, $mail_domain ) = split (/@/, $email ); # find the last occurence of . my $mail_domain_pref_pos = rindex($mail_domain,"."); my $mail_domain_prefix = ""; # .pt .org etc if ( $mail_domain_pref_pos >= 0 ) { $mail_domain_prefix = substr($mail_domain,$mail_domain_pre +f_pos+1,length($mail_domain)); # get the domain prefix } # if mail user exists (exanmple miguel) and if the mail domain + exists (mail.pt) and if the mail domain prefix exists (pt) if ( defined $mail_user and defined $mail_domain and defined $ +mail_domain_prefix and length($mail_user) > 0 and length($mail_domain +) > 0 and length($mail_domain_prefix) > 0 ) { my $allowed_prefix = ""; if ( defined $alllowed_domain_prefixes and length($alllowe +d_domain_prefixes) > 0 ) { # check the allowed prefixed if required ( +pt com org etc) my @alllowed_domain_prefixes = split(/,/, $alllowed_do +main_prefixes); $allowed_prefix = "no"; foreach my $allowed_prefix_record (@alllowed_domain_pr +efixes) { if ( $mail_domain_prefix eq $allowed_prefix_record + ) { $allowed_prefix = "yes"; last; } } } if ( $allowed_prefix ne "no" ) { # check if the prefix is +not allowed $error_flag = 0; # mail is valid } } } print "Function check_email() exit value is [ $error_flag ]\n" if +( defined $$global_config_p{debug_level} and $$global_config_p{debug_ +level} eq "full" ); # print message if the debug level requires it return $error_flag; }

      Hope this helps out
      Migas - Miguel
Re: How do I go about validating a e-mail message field?
by monkfan (Curate) on Sep 21, 2006 at 08:00 UTC
    Your task smells like spamming. However, for validating address I usually use this:
    sub validate_email_address { my $addr_to_check = shift; $addr_to_check =~ s/("(?:[^"\\]|\\.)*"|[^\t "]*)[ \t]*/$1/g; my $esc = '\\\\'; my $space = '\040'; my $ctrl = '\000-\037'; my $dot = '\.'; my $nonASCII = '\x80-\xff'; my $CRlist = '\012\015'; my $letter = 'a-zA-Z'; my $digit = '\d'; my $atom_char = qq{ [^$space<>\@,;:".\\[\\]$esc$ctrl$nonASCII] } +; my $atom = qq{ $atom_char+ }; my $byte = qq{ (?: 1?$digit?$digit | 2[0-4]$digit | 25[0-5] ) }; my $qtext = qq{ [^$esc$nonASCII$CRlist"] }; my $quoted_pair = qq{ $esc [^$nonASCII] }; my $quoted_str = qq{ " (?: $qtext | $quoted_pair )* " }; my $word = qq{ (?: $atom | $quoted_str ) }; my $ip_address = qq{ \\[ $byte (?: $dot $byte ){3} \\] }; my $sub_domain = qq{ [$letter$digit] [$letter$digit-]{0,61} [$letter$digit]}; my $top_level = qq{ (?: $atom_char ){2,4} }; my $domain_name = qq{ (?: $sub_domain $dot )+ $top_level }; my $domain = qq{ (?: $domain_name | $ip_address ) }; my $local_part = qq{ $word (?: $dot $word )* }; my $address = qq{ $local_part \@ $domain }; return $addr_to_check =~ /^$address$/ox ? $addr_to_check : ""; }

    Regards,
    Edward
Re: How do I go about validating a e-mail message field?
by Anonymous Monk on Sep 21, 2006 at 10:26 UTC
    lol, sorry but i may have been a bit vague on my topic / message. This is certainly not for spam and all e-mail addresses are pulled from a database which to enter it uses Email::Valid.

    What my problem is that I need to validate only the "text message" field parameter thats passed to CGI.pm.

    This input field value from the html form will then be put in a email message using NE:T:SMTP to send out (WINDOWS).

    The message may also be stored in a database which is why I'm a bit concerned on how to exactly "taint / validate it"

    Cheers, DJ
      If the data submitted as the text message content is never handled in a way that causes some process to "interpret" it, then taint checking is a moot point. So, you can insert the content into a database field, if the SQL insert is done like this:
      my $sth = $dbh->prepare("insert into my_table (mail_text,sender,recip) + values (?,?,?)"); $sth->execute( $message_text, $from, $to );
      (updated the snippet so it makes a little more sense)

      That's the easy way of avoiding an "SQL injection attack" -- the use of the "?" placeholder will cause DBI to pass the text content to the database safely without further ado.

      As for actually sending the email, there's Mail::Send and others that implement the sending of mail as a matter of printing the text to a file handle, avoiding any possibility that your mail server might misinterpret the text as executable commands or whatever. (Update: I've never used Net::SMTP... it looks pretty low-level, and you might need to watch for things like lines of text that start with "From " -- I don't know.)

      As for what might happen to the email recipient, that's another matter... Maybe you're just dealing with "trusted" users who won't be doing stupid or hazardous things like pasting in arbitrary binary data, viral attachments, etc. If it's suitable to your app, you might consider among choices like: allow only ASCII, or only utf8, maybe disallow things that look like embedded MIME headers... I don't actually know what all would be prudent/appropriate in this regard.

Re: How do I go about validating a e-mail message field?
by stonecolddevin (Parson) on Sep 23, 2006 at 00:55 UTC

    As Skeeve said, search is your friend. There's plenty of content on this site that you can search on before posting that would most likely give you plenty of info to go off on your own with a solution.

    As davorg said, i think the general consensus is Email::Valid for email validation. Whenever dealing with emails, check the Email namespace on CPAN. They're working very hard to standardize and create efficient ways of validating and manipulating email addresses.

    meh.