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

Hi all,

I am trying to make a script which reads an email and puts it into a mysql database, it is my first attempt at doing this and I'm a little lost, below is what I have got so far, which I think reads the From email address, but I'm unsure how to get the actual main part of the email?
while (<STDIN>) { push @submission, $_; } foreach $line (@submission) { push $line, @header; if ($line =~ /^$/) { last; } } foreach(@header) { if ($_ =~ /from/i) { ($from, $email) = split(/:/, $_); } }

Any help would be appreciated on how I can read the rest of the email, or any better approaches to doing this

Thank You

John

Replies are listed 'Best First'.
Re: Email STDIN
by projekt21 (Friar) on Oct 09, 2001 at 14:30 UTC

    BEFORE you go on, please check CPAN for the MIME-tools package, and read the documentation of MIME::Entity, MIME::Head, MIME::Body and MIME::Parser if you really want to parse emails correctly.

    Else you are reinventing the wheel and yours won't be that round ...

    Please be free to contact me if you need some demo code to show how the MIME-tools operate on your special task.

    Update (some code snippets added)

    use MIME::Parser; # some code here .... my $message = $pop->get($msg); # I get it from POP3 # parse email my $parser = new MIME::Parser; $parser->output_under($Conf::msg_dir); my $entity = $parser->parse_data($message); split_entity($entity); # example header my $from = $entity->head->decode->get("From"); ############################################################ sub split_entity { ############################################################ local $entity = shift; my $num_parts = $entity->parts; # how many mime parts? if ($num_parts) { # we have a multipart mime message foreach (1..$num_parts) { split_entity( $entity->parts($_ - 1) ); } } else { # we have a single mime message/part # we only want text if ($entity->effective_type =~ /^text\/(?!(html|enriched))/) { my $path = $entity->bodyhandle->path; ### do something here } else { my $path = $entity->bodyhandle->path; ### do something other here; } } }

    This snippet is just for demonstration, it won't run.

    alex pleiner <alex@zeitform.de>
    zeitform Internet Dienste

Re: Email STDIN
by tachyon (Chancellor) on Oct 09, 2001 at 15:34 UTC

    Here is a MIME::Parser example. The datastructure it generates is quite complex but it is all there. In nice neat chunks.

    use MIME::Parser; use Data::Dumper; my $message = join '', <DATA>; # Create a new parser object: my $parser = new MIME::Parser; # Parse a message: $entity = $parser->parse_data($message); # Get results my $results = $parser->results; print Dumper( $results ); __DATA__ Return-Path: <vicki@moyes.com.au> Received: from mta05ps.bigpond.com (mta05ps.bigpond.com [144.135.25.13 +7] (may be forged)) by zeus.tassie.net.au (8.8.8/8.8.8) with ESMTP id QAA28679 for <jfreeman@tassie.net.au>; Mon, 8 Oct 2001 16:02:04 +1100 ( +EST) Received: from moyes.com.au ([144.135.25.81]) by mta05ps.bigpond.com (Netscape Messaging Server 4.15) with SM +TP id GKVFL800.57H for <jfreeman@tassie.net.au>; Mon, 8 Oct 200 +1 15:07:56 +1000 Received: from 144.137.126.1 ([144.137.126.1]) by psmam05.mailsvc.emai +l.bigpond.com(MailRouter V2.9j 8410/9896696); 08 Oct 2001 15:07:52 Received: from VICKI ([10.0.0.1]) by moyes.com.au ( IA Mail Server Ver +sion: 3.2.4. Build: 1100 ) ) ; Mon, 08 Oct 2001 15:01:51 +1000 From: "Vicki Cain" <vicki@moyes.com.au> To: "James Freeman \(E-mail\)" <jfreeman@tassie.net.au> Subject: New Order Date: Mon, 8 Oct 2001 15:01:51 +1000 Message-ID: <004301c14fb6$57b89000$0100000a@VICKI> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook CWS, Build 9.0.2416 (9.0.2910.0) X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4807.1700 Importance: Normal Status: U X-Mozilla-Status: 8001 X-Mozilla-Status2: 00000000 X-UIDL: XSa"!WYn"!AWf!!OTl"! Hi James, I would like to place a new order of 50 Fast bars all annodised. Thanks. Let me know if you are interested in us taking over the manufacturing +cause we are. Best Regards Vicki Cain Moyes Delta Gliders Pty. Ltd. 1144 Botany Road Botany NSW 2019 Australia Ph: +61 (02) 9316 4644 Fax: + 61 (02) 9316 8488 Web: www.moyes.com.au

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: Email STDIN
by busunsl (Vicar) on Oct 09, 2001 at 14:36 UTC
Re: Email STDIN
by the_slycer (Chaplain) on Oct 09, 2001 at 18:29 UTC
    While I agree with the people above, using Mime::Something will save you in the long run, here is another answer to your question.

    The main problem with your code above is that you are shoving the message into an array first. What you really want to do is break out of the first while loop when you hit the blank line (denoting the end of the header).
    while (<DATA>) { last if /^$/; #Header is done! print "From: $1\n\n" if /^From:(.+)$/; #Print the from address } while (<DATA>) #This while loop starts from where the other left off {print} __DATA__; To: blah@blahblahFrom: From:green.ecgs@ham.org Subject:test Do you like green ecgs and ham? Would you eat them in a house? Would you eat them with a mouse?
Re: Email STDIN
by strredwolf (Chaplain) on Oct 12, 2001 at 11:07 UTC
    Now, even though I haven't used MIME::*, here's my thoughts which can help:

    First, read RFC 2822. (It used to be 822, but they updated the spec). You'll realize that each header can wrap around to another line, and it causes havoc!!!!

    Second, use procmail to do some unmunging. Procmail can fix those headers so Perl can make it eazier for you. Here's what I have in a .procmailrc:

    PIDFILE=bt-rbl.$$ :0 * ? e-mail_script.pl $PIDFILE { MESS=`cat $PIDFILE` JUNK=`rm $PIDFILE` :0 /dev/null } JUNK=`rm $PIDFILE`

    And for the Perl:

    $flag=0; open(OUT,">$ARGV[0]") || die "Can't open conduit: $!"; while(<STDIN>) { $l=$_; chomp; $flag++ if(/^$/); # Header/Body seperation $header[$hi++]=$_ unless($flag); $body[$bi++]=$_ if($flag); }
    for example.

    --
    $Stalag99{"URL"}="http://stalag99.keenspace.com";