Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Using Net::POP3 to retrieve a the subject line from a pop3 mailbox 2

Status
Not open for further replies.

Sqeezebox

MIS
Apr 9, 2007
8
CA
Hello there,

I am a newbie when it comes to Perl. I need to retrieve message subject lines from a POP3 mailbox. I have started out using Net::pOP3 to authenticate and get the number of messages in the POP3 mailbox. I used the following code to accomplish this:

Code:
#!/usr/local/bin/perl
#
use Net::POP3;
#################POP Mail Settings########################
# $srcemail = Source Email Address for alerts to be sourced from
# $dstemail = Destination Email Address for alerts to be sent to
# $mailsrvr = SMTP Server to be used to send the mail through
# $rplyto = Address to which any reply for the alert will be sent
############################################################
$host = '[mail server]';
$user = "[email address]";
$pass = '[account password]';
# Retrieve Mail.
# initiate connection
# default timeout = 120 sec
$conn = Net::POP3->new($host) or die("ERROR: Unable to connect.\n");
# login
$numMsg = $conn->login($user, $pass) or die("ERROR: Unable to login.\n");
# display number of messages
if ($numMsg > 0) {
print "Mailbox has $numMsg message(s).\n";
} 
else {
print "Mailbox is empty.\n";
}
		
# close connection
$conn->quit();

What I want to do is to parse out the subject lines from all messages in the inbox, then be able to use the data contained within them to use in my script. The subject lines are comma separated so it should be pretty easy to extract the data I want once I get the data. Please help!!
 
what makes you think the subject lines are comma seperated? Here is one way you could do it:

Code:
[url=http://perldoc.perl.org/functions/use.html][black][b]use[/b][/black][/url] [green]Net::POP3[/green][red];[/red]

[blue]$host[/blue] = [red]'[/red][purple][host][/purple][red]'[/red][red];[/red]
[blue]$user[/blue] = [red]'[/red][purple][user][/purple][red]'[/red][red];[/red]
[blue]$pass[/blue] = [red]'[/red][purple][password][/purple][red]'[/red][red];[/red]
[url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [blue]@subjects[/blue] = [red]([/red][red])[/red][red];[/red]

[blue]$conn[/blue] = Net::POP3->[maroon]new[/maroon][red]([/red][blue]$host[/blue],[purple]Debug[/purple] => [fuchsia]0[/fuchsia][red])[/red] or [url=http://perldoc.perl.org/functions/die.html][black][b]die[/b][/black][/url][red]([/red][red]"[/red][purple]ERROR: Unable to connect.[purple][b]\n[/b][/purple][/purple][red]"[/red][red])[/red][red];[/red]
[blue]$numMsg[/blue] = [blue]$conn[/blue]->[maroon]login[/maroon][red]([/red][blue]$user[/blue], [blue]$pass[/blue][red])[/red] or [black][b]die[/b][/black][red]([/red][red]"[/red][purple]ERROR: Unable to login.[purple][b]\n[/b][/purple][/purple][red]"[/red][red])[/red][red];[/red]

[url=http://perldoc.perl.org/functions/open.html][black][b]open[/b][/black][/url][red]([/red]FH,[red]"[/red][purple]>[/purple][red]"[/red], [red]"[/red][purple]all_my_mail.txt[/purple][red]"[/red][red])[/red] or [black][b]die[/b][/black] [red]"[/red][purple][blue]$![/blue][/purple][red]"[/red][red];[/red]
[olive][b]for[/b][/olive] [red]([/red][fuchsia]1..[/fuchsia][blue]$numMsg[/blue][red])[/red] [red]{[/red]
   [black][b]my[/b][/black] [blue]$mail[/blue] = [blue]$conn[/blue]->[maroon]get[/maroon][red]([/red][blue]$_[/blue][red])[/red][red];[/red]
   [url=http://perldoc.perl.org/functions/print.html][black][b]print[/b][/black][/url] FH [blue]@[/blue][red]{[/red][blue]$mail[/blue][red]}[/red][red];[/red]
[red]}[/red]
[url=http://perldoc.perl.org/functions/close.html][black][b]close[/b][/black][/url] FH[red];[/red]
[blue]$conn[/blue]->[maroon]quit[/maroon][red]([/red][red])[/red][red];[/red]

[black][b]open[/b][/black][red]([/red]FH, [red]"[/red][purple]all_my_mail.txt[/purple][red]"[/red][red])[/red] or [black][b]die[/b][/black] [red]"[/red][purple][blue]$![/blue][/purple][red]"[/red][red];[/red]
[olive][b]while[/b][/olive] [red]([/red]<FH>[red])[/red] [red]{[/red]
   [olive][b]if[/b][/olive][red]([/red][red]/[/red][purple]^Subject:[/purple][red]/[/red][red])[/red][red]{[/red]
      [url=http://perldoc.perl.org/functions/chomp.html][black][b]chomp[/b][/black][/url][red];[/red] 
      [url=http://perldoc.perl.org/functions/push.html][black][b]push[/b][/black][/url] [blue]@subjects[/blue],[blue]$_[/blue]
   [red]}[/red]
[red]}[/red]
[black][b]print[/b][/black] [red]"[/red][purple][blue]$_[/blue][purple][b]\n[/b][/purple][/purple][red]"[/red] [olive][b]for[/b][/olive] [blue]@subjects[/blue][red];[/red]

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Kevin,

I am sending out messages with a pre defined subject line to a ticketing system that sends back the same subject line along with a ticket number. Since I know what the structure is I have already made a parsing routine to extract the data from the subject line. The only thing I was stuck on was actually getting the subject line out in the first place. I'll try this code out and see what happens. So does this script ultimately return all subject lines to the @subjects array? Thanks!
 
So does this script ultimately return all subject lines to the @subjects array? Thanks!

What it really does is finds lines that begin with "Subject;" and puts those in the @subjects array. So it is possible that it could get lines that begin with "Subject:" elsewhere in the email ad puts those in the array too. But just try running the script and see how it works. It can be adjusted to eliminate the fales matches if there are any.

You also don't have to print to a file and parse the file like the code does, it was just conveninet for me to test it that way. You could directly parse the array reference the get() method returns.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Kevin,
If I'm reading the Net::pop3 CPAN documentation correctly,
you could change the
Code:
   my $mail = $conn->get($_);
line to be
Code:
   my $mail = $conn->top($_);

With only one argument, top() returns only header lines which would eliminate the scenario you mentioned.
 
oh, cool. The OP can try that, sounds like it will be perfect for his situation. [smile]

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Couldn't stop myself:
Code:
[url=http://perldoc.perl.org/functions/use.html][black][b]use[/b][/black][/url] [green]Net::Pop3[/green][red];[/red]
[url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [blue]$host[/blue] = [red]'[/red][purple]mail.myhost.com[/purple][red]'[/red][red];[/red]
[black][b]my[/b][/black] [blue]$user[/blue] = [red]'[/red][purple]me[/purple][red]'[/red][red];[/red]
[black][b]my[/b][/black] [blue]$pass[/blue] = [red]'[/red][purple]mysecretpassword[/purple][red]'[/red][red];[/red]
[black][b]my[/b][/black] [blue]@subjects[/blue] = [red]([/red][red])[/red][red];[/red]
[black][b]my[/b][/black] [blue]$conn[/blue] = Net::POP3->[maroon]new[/maroon][red]([/red][blue]$host[/blue],[purple]Debug[/purple] => [fuchsia]0[/fuchsia][red])[/red] or [url=http://perldoc.perl.org/functions/die.html][black][b]die[/b][/black][/url][red]([/red][red]"[/red][purple]ERROR: Unable to connect.[purple][b]\n[/b][/purple][/purple][red]"[/red][red])[/red][red];[/red]
[black][b]my[/b][/black] [blue]$num_msgs[/blue] = [blue]$conn[/blue]->[maroon]login[/maroon][red]([/red][blue]$user[/blue], [blue]$pass[/blue][red])[/red] or [black][b]die[/b][/black][red]([/red][red]"[/red][purple]ERROR: Unable to login.[purple][b]\n[/b][/purple][/purple][red]"[/red][red])[/red][red];[/red]
[olive][b]for[/b][/olive][red]([/red][fuchsia]1..[/fuchsia][blue]$num_msgs[/blue][red])[/red] [red]{[/red]
   [olive][b]for[/b][/olive][red]([/red] [blue]@[/blue][red]{[/red][blue]$conn[/blue]->[maroon]top[/maroon][red]([/red][blue]$_[/blue][red])[/red][red]}[/red] [red])[/red] [red]{[/red]
     [url=http://perldoc.perl.org/functions/push.html][black][b]push[/b][/black][/url] [blue]@subjects[/blue], [blue]$1[/blue] [olive][b]if[/b][/olive] [red]/[/red][purple]^Subject: (.*)[/purple][red]/[/red][red];[/red]
   [red]}[/red]
[red]}[/red]
[blue]$conn[/blue]->[maroon]quit[/maroon][red]([/red][red])[/red][red];[/red]
[url=http://perldoc.perl.org/functions/print.html][black][b]print[/b][/black][/url] [url=http://perldoc.perl.org/functions/join.html][black][b]join[/b][/black][/url] [red]"[/red][purple][purple][b]\n[/b][/purple][/purple][red]"[/red], [blue]@subjects[/blue][red];[/red]
[tt]------------------------------------------------------------
Other Modules used :
[ul]
[li]Net::pop3[/li]
[/ul]
[/tt]
@subject now contains the subjects minus the "Subject: " prefix.
 
Woah Brigmar, that is beautiful, I was using kevin's code along with some earlier code to get this:
Code:
# Retrieve Mail.
sub retrieveit {
		# initiate connection
		# default timeout = 120 sec
		$conn = Net::POP3->new($host) or die("ERROR: Unable to connect.\n");
		# login
		$numMsg = $conn->login($user, $pass) or die("ERROR: Unable to login.\n");
		# display number of messages
		#if ($numMsg > 0) {
		#    print "Mailbox has $numMsg message(s).\n";
		#} 
		#else {
		#    print "Mailbox is empty.\n";
		#}
		open(FH,">", "all_my_mail.txt") or die "$!";
		for (1..$numMsg) {
   		my $mail = $conn->top($_);
   		print FH @{$mail};
		}
		close FH;
		
		# close connection
		$conn->quit();
		
		$y=0;
		
		open(FH, "all_my_mail.txt") or die "$!";
		open(MSG, ">> $subjects");
		while (<FH>) {
   		if(/^Subject:/){
      	chomp;
      	#$subjectline = $_;
      	push @subjects,$_;
						print MSG "@subjects[$y]";
							if($y > 0) {
								print MSG "\n";
							}
						$y++;
   		}
		}
		close(FH);
		close(MSG);
		&parseit;
}
		
sub parseit {
		#print "we are in parseit";
		our %msghash = ();
		
		# Open our log file for input
		open ( MSG, "< $subjects" );
		# Shift off header line
		my $msgheader = <MSG>;
		
		# Read one line at a time
		while ( <MSG> ) {
			# Remove trailing newline from current line
			chomp ( $_ );
						
			# Split commas on current line and store the field values
			# into the variables on the lefthand side
			# Split will not handle embedded commas properly unless
			# you use a complicated regular expression
			my ( $msgsource, $msgpriority, $msgtype, $msgservername, $msgfriendlyname, $msgtickettime ) = split ( /,/, $_ ); 
				$msghash{$msgtickettime}{MSGSOURCE}		 			= $msgsource;
				$msghash{$msgtickettime}{MSGPRIORITY}      	= $msgpriority;
				$msghash{$msgtickettime}{MSGTYPE}     			= $msgtype;
				$msghash{$msgtickettime}{MSGSERVERNAME}   	= $msgservername;
				$msghash{$msgtickettime}{MSGFRIENDLYNAME} 	= $msgfriendlyname;
				$msghash{$msgtickettime}{MSGTICKETTIME}   	= $msgtickettime;
		}
		close ( MSG );
		
		$i = 0; 
		
		# Loop through all the stored times in the hash and print out the contents
		foreach my $t ( sort keys %msghash ) {
				#print "$msghash{$t}{MSGSOURCE}";
				#print "$msghash{$t}{MSGPRIORITY}";
				#print "$msghash{$t}{MSGTYPE}";
				#print "$msghash{$t}{MSGSERVERNAME}";
				#print "$msghash{$t}{MSGFRIENDLYNAME}";
				#print "$msghash{$t}{MSGTICKETTIME}";
				@msgnames[$i] = "$msghash{$t}{MSGSERVERNAME}";
				@msgitems[$i] = "$msghash{$t}{MSGFRIENDLYNAME}";
				@msgtimes[$i] = "$msghash{$t}{MSGTICKETTIME}";
				# Now we have the raw Ticket source with ticket number, however it is in this format
				# [SourceAddress #ticketnumber]: Lets Extract the ticket number...
				$msgtemp = "$msghash{$t}{MSGSOURCE}";
				if($msgtemp =~ m/(\d+)/) {
					@msgticketnum[$i] = $1;
				}
				if($msgtemp =~ m/(\D+)/) {
					@msgsource[$i] = substr($1,10,-2);
				}
		}
		# Before we get carried away lets figure out how many subject lines are present in the file.
		$z = 0;
		open(LOGF,"< $subjects" );
		seek (LOGF,0,0);
		while ($line = <LOGF>) {
			$z++;
		}
		
		# We will set some counter variables here. $count is used to search through all the subject lines in the array loaded earlier
		# $count2 is used to load variable names with elements from the array
		$count = 1;
		$count2 = 0;
		close (LOGF);
		# So $z is the number of lines in the lines in the subjects mail file. Therefore $z - 1 is the actual subject lines contained
		# within the file not including the header line. So if we start $count at 1 and compare it to $z we should only go through the 
		# array a legal number of times looking for a ticket number. If we can't find a match after going through the array completely
		# then we will delete the MRTG created threshold file and try again next time... 
		while($count <= $z) {
			$eventsname = $msgnames[$count2];
			$eventcname = $msgitems[$count2];
			$eventtimes = $msgtimes[$count2];
			$eventsource = $msgsource[$count2];
			$eventticketnum = $eventticketnum[$count2];
			if (($sname[2] == $eventsnames) and ($cname[2] == $eventcnames) and ($times[2] == $eventtimes)) {
				print "We have a match!";
				$eventsource = $eventsource . "@mosthome.com";
				print "\n $eventsource";
				open(LOGF, "> $filefound");
				print LOGF "$eventsource,$eventticketnum";
				close(LOGF);
				$count = $count + $z;
				$match = 1;
			}
			$count++;
			$count2++;
		}
		if ($match != 1) {
				open(LOGF, "> $filelook");
				close(LOGF);
		}
}
The parse it function is supposed to pull out the subject line elements into their component parts, but it only seems to pull a single element.. Any ideas? The subject line file looks something like this...:
Code:
MSGSOURCE,MSGTYPE,MSGSERVERNAME,MSGFRIENDLYNAME,MSGTICKETTIME
Subject: [SysSupport #104]: P2,(Warning),MULTI1,C:,1176244505
Subject: [SysSupport #114]: P2,(Warning),MULTI1,C:,1176244805
Subject: [SysSupport #124]: P2,(Warning),MULTI1,C:,1176245105
Subject: [SysSupport #134]: P2,(Warning),MULTI1,C:,1176245405
Subject: [SysSupport #144]: P2,(Warning),MULTI1,C:,1176245705
I need to be able to pull each subject line into an array of its component parts so I can compare events easily. Also I want to delete the line that matches my query. For example, I wish to match the last field (msgtickettime) to another variable, we would work through the file and if a match is found we can do some actions, and ultimately delete that subject line from the file. Thanks for all your help guys I am definatly making progress...
 
I figured it out, I wasn't incrementing my Increment variable so the first item of the array was just getting overwritten over and over again.
 
glad you figured it out, all that code was making me dizzy [wink]

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Yes, this project that I undertook as a first time perl programmer is making me dizzy at times. Hopefully it will all be worth it in the end. Thanks for all your help guys!

 
there are some things to note in the code you posted:

Code:
$eventsource = $eventsource . "@mosthome.com";


@mosthome is being interpolated as an array because of the double-quotes and will return the value of that array stringified or no value at all if there is no @mosthome array, which there probably isn't. Use single-quotes.

Code:
$eventsource = $eventsource . '@mosthome.com';

stuff like this:

Code:
print MSG "@subjects[$y]";

is better written as a scalar:

Code:
print MSG "$subjects[$y]";

but scalars should almost never be quoted unless used to form a new scalar/string, so write it as:

Code:
print MSG $subjects[$y];

same for lines like these:

Code:
@msgnames[$i] = "$msghash{$t}{MSGSERVERNAME}";
@msgitems[$i] = "$msghash{$t}{MSGFRIENDLYNAME}";
@msgtimes[$i] = "$msghash{$t}{MSGTICKETTIME}";

should be:

Code:
$msgnames[$i] = $msghash{$t}{MSGSERVERNAME};
$msgitems[$i] = $msghash{$t}{MSGFRIENDLYNAME};
$msgtimes[$i] = $msghash{$t}{MSGTICKETTIME};



------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top