PDA

View Full Version : [PHP]Read POP3 Email Account



doof92
July 25th, 2008, 07:01
Hey,

I'm looking for a script that is able to log into my POP3 email account, and download all the unread mails (or any that are already there, doesn't matter). I'll then ammend the script so it puts the details into a database (eg from address, subject, body etc)

Found a couple of scripts, but one was overly complicated, and the other didn't work.

Any help would be appreciated.

Thanks

krakjoe
July 25th, 2008, 12:50
<?php
/**
* @author J Watkins
* @website http://interviolet.com
* A simple POP3 class to allow people to login to, read and delete email from most POP3 servers
**/
final class POP
{
/**
* @var $socket
* @access protected
* Physical socket to POP3 server
**/
protected $socket ;
/**
* @var $ready
* @access protected
* Boolean indication of socket readiness
**/
protected $ready ;
protected $connecting ;
/**
* @var $errno
* @access public
* Socket errno, as stored by fsockopen
**/
public $errno ;
/**
* @var $errstr
* @access public
* Socket errstr, as stored by fsockopen
**/
public $errstr ;
/**
* @var $error
* @access public
* Error message, formatted by object
**/
public $error ;
/**
* @var $welcome
* @access public
* Welcome message stored here, on login and logout
**/
public $welcome ;
/**
* @param string $server
* @param integer $port
* @param integer $timeout
* @return Object
**/
public function __construct( $server, $port = 110, $timeout = 5 )
{
$this->connecting = true ;

if( ( $this->socket = fsockopen( $server, $port, $this->errno, $this->errstr, $timeout ) ) )
{
if( $this->response( true, $buffer ) )
{
$this->welcome = trim( $buffer );
$this->connecting = false ;
$this->ready = true ;
}
else $this->error = sprintf( "failed to connect to &#37;s:%d, server responded with '%s'", $server, $port, $buffer );
}
elseif( $this->errstr )
$this->error = sprintf( "failed to connect to %s:%d, socket responded with '%s'", $server, $port, $this->errstr );
else
$this->error = sprintf( "failed to connect to %s:%d, socket did not respond", $server, $port );
}
/**
* @return boolean
* Check to see if socket is ready
**/
public function ready( )
{
return $this->ready ? true : false ;
}
/**
* @return boolean
* Check to see if socket is connecting
**/
public function connecting( )
{
return $this->connecting ? true : false ;
}
/**
* @param boolean $plus
* @param string $buffer
* @access private
* Read response from server, without garbage
**/
private function response( $plus, &$buffer = null )
{
if( $this->ready( ) or $this->connecting( ) )
{
$buffer = null ;

switch( $plus )
{
case true: if( ( $line = fgets( $this->socket ) ) )
{
$buffer = trim( substr( $line, strpos( $line, ' ' ) ) );

switch( substr( $line, 0, 1 ) )
{
case '-': return false; break;
case '+': return true; break;
}
}
break;

case false: while( $line = fgets( $this->socket ) )
{
if( trim( $line ) == '.' ) break;
if( trim( $line ) ) $buffer .= $line ;
}
break;
}

$buffer = trim( $buffer );

return true ;
}
}
/**
* @param string $email
* @param string $password
* @return boolean
* Login to POP3 server, !PASSWORD IS SENT PLAINTEXT!
**/
public function login( $email, $password )
{
if( $this->ready )
{
if( fprintf( $this->socket, "USER %s\r\n", $email, $password ) )
{
if( $this->response( true, $buffer ) )
{
if( fprintf( $this->socket, "PASS %s\r\n", $password ) )
{
if( $this->response( true, $buffer ) )
{
return true;
}
else $this->error = sprintf( "failed to send PASS command to server, server responded with '%s'", $buffer );
}
else $this->error = sprintf( "failed to send PASS command to server" );
}
else $this->error = sprintf( "failed to send USER command to server, server responded with '%s'", $buffer );
}
else $this->error = sprintf( "failed to send USER command to server" );
}
}
/**
* @return array
* Return array of information from server regarding messages waiting
**/
public function waiting( )
{
if( $this->ready )
{
if( fprintf( $this->socket, "LIST\r\n" ) )
{
if( $this->response( true, $buffer ) )
{
if( $this->response( false, $buffer ) )
{
if( $buffer )
{
$waiting = array( );

foreach( explode( "\n", $buffer ) as $line )
{
if( list( $key, $value ) = explode( " ", trim( $line ) ) )
{
$waiting[$key] = $value ;
}
}
return $waiting;
}
else return array( );
}
else $this->error = sprintf( "failed to send LIST command to server, failed reading data" );
}
else $this->error = sprintf( "failed to send LIST command to server, server responded with '%s'", $buffer );
}
else $this->error = sprintf( "failed to send LIST command to server" );
}
}
/**
* @param integer $id
* @return boolean
* Retrieve message with the identifier $id ( identifiers are keys in $this->waiting( ) response )
**/
public function retrieve( $id )
{
if( $this->ready )
{
if( fprintf( $this->socket, "RETR %d\r\n", $id ) )
{
if( $this->response( true, $buffer ) )
{
if( $this->response( false, $buffer ) )
{
return $buffer ;
}
else $this->error = sprintf( "failed to send RETR command to server, server responded with '%s'", $buffer );
}
else $this->error = sprintf( "failed to send RETR command to server, server responded with '%s'", $buffer );
}
else $this->error = sprintf( "failed to send RETR command to server" );
}
}
/**
* @param integer $id
* @return boolean
* Delete message with the identifier $id ( identifiers are keys in $this->waiting( ) response )
**/
public function delete( $id )
{
if( $this->ready )
{
if( fprintf( $this->socket, "DELE %d\r\n", $id ) )
{
if( $this->response( true, $buffer ) )
{
return true;
}
else $this->error = sprintf( "failed to send DELE command to server, server responded with '%s'", $buffer );
}
else $this->error = sprintf( "failed to send DELE command to server" );
}
}
/**
* @return boolean
* Logout of POP3 server, and close the connection
**/
public function logout( )
{
if( $this->ready )
{
if( fprintf( $this->socket, "QUIT\r\n" ) )
{
if( $this->response( true, $buffer ) )
{
fclose( $this->socket );
$this->ready = false ;
$this->welcome = trim( $buffer );
return true;
}
else $this->error = sprintf( "failed to send QUIT command to server, server responded with '%s'", $buffer );
}
else $this->error = sprintf( "failed to send QUIT command to server" );
}
}
}
/**
* Create a new pop object and connect to mail.interviolet.com on port 110
**/
$pop = new POP( "mail.interviolet.com", 110 );
/**
* Check to see if POP server is ready for commands
**/
if( $pop->ready( ) )
{
/**
* Print welcome message
**/
printf( "\$pop->login( ): %s\r\n", $pop->welcome );
/**
* Login to the server
**/
if( $pop->login( "joe@interviolet.com", "**********" ) )
{
/**
* Check for new messages
**/
if( ( $waiting = $pop->waiting( ) ) )
{
/**
* Print out waiting message count
**/
printf( "\$pop->waiting( ): %d messages waiting\r\n", count( $waiting ) );
/**
* Print out waiting identifiers
**/
if( count( $waiting ) ) foreach( $waiting as $id => $octets )
{
printf( "\$pop->waiting( ): %d %d\r\n", $id, $octets );
}
/**
* Get all messages in queue
**/
/**
if( count( $waiting ) ) foreach( $waiting as $id => $octets )
{
echo $pop->retrieve( $id );
}
**/
/**
* Delete all messages in queue
**/
/**
if( count( $waiting ) ) foreach( $waiting as $id => $octets )
{
echo $pop->delete( $id );
}
**/
}
else print( "\$pop->waiting( ): No messages waiting in inbox\r\n" );
/**
* Logout of POP server and close connection
**/
if( $pop->logout( ) )
{
printf( "\$pop->logout( ): %s\r\n", $pop->welcome );
}
else printf( "\$pop->logout( ): %s\r\n", $pop->error );
}
else printf( "\$pop->login( ): %s\r\n", $pop->error );
}
else printf( "new POP( ): failed to connect to requested server\r\n" );
?>


This is a ten minute script, you'll need to find an email parser, there are plenty about, but that'll give you a basic connection and functions to work with emails on server ... this is not heavily tested, but I believe it conforms to standards ...

doof92
July 25th, 2008, 14:28
Thanks very much. It works, logging in and checking mail correctly, which is the important thing. Haven't had a chance yet to check other stuff out, but it looks brilliant. Thanks very much, you've been a great help.

One other thing, having a quick read through the output (not having been parsed) I can't see anywhere where the From email address is. There is one bit which says "From: "BSKIrc"" for example, which isn't an email address. Any other way of getting sender's email address?

krakjoe
July 25th, 2008, 15:17
What you get when you call retrieve( ) is the raw email, it has all the information a normal client like outlook would have, and should include the From: email header ...

I just tested with an email and it looks like

From: "Name" <email>

and it is definitely there ...



Return-path: <joe@interviolet.com>
Envelope-to: joe@interviolet.com
Delivery-date: Fri, 25 Jul 2008 15:15:45 -0400
Received: from host86-164-172-54.range86-164.btcentralplus.com ([86.164.172.54] helo=JoePC)
by server.spacesocket.com with esmtp (Exim 4.69)
(envelope-from <joe@interviolet.com>)
id 1KMSlU-0001jP-6h
for joe@interviolet.com; Fri, 25 Jul 2008 15:15:45 -0400
From: "Joe Watkins" <joe@interviolet.com>
To: <joe@interviolet.com>
Subject: subject
Date: Fri, 25 Jul 2008 20:14:14 +0100
Message-ID: <000001c8ee8a$ae961cb0$0bc25610$@com>
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="----=_NextPart_000_0001_01C8EE93.105A84B0"
X-Mailer: Microsoft Office Outlook 12.0
Thread-Index: Acjuip/1RiRcowYoSV2ES7fDMFuQhw==
Content-Language: en-us
This is a multipart message in MIME format.
------=_NextPart_000_0001_01C8EE93.105A84B0
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit
test
------=_NextPart_000_0001_01C8EE93.105A84B0
Content-Type: text/html;
charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
<html xmlns:v=3D"urn:schemas-microsoft-com:vml" =
xmlns:o=3D"urn:schemas-microsoft-com:office:office" =
xmlns:w=3D"urn:schemas-microsoft-com:office:word" =
xmlns:m=3D"http://schemas.microsoft.com/office/2004/12/omml" =
xmlns=3D"http://www.w3.org/TR/REC-html40">
<head>
<META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; =
charset=3Dus-ascii">
<meta name=3DGenerator content=3D"Microsoft Word 12 (filtered medium)">
<style>
<!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:purple;
text-decoration:underline;}
span.EmailStyle17
{mso-style-type:personal-compose;
font-family:"Calibri","sans-serif";
color:windowtext;}
..MsoChpDefault
{mso-style-type:export-only;}
@page Section1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.Section1
{page:Section1;}
-->
</style>
<!--[if gte mso 9]><xml>
<o:shapedefaults v:ext=3D"edit" spidmax=3D"1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext=3D"edit">
<o:idmap v:ext=3D"edit" data=3D"1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang=3DEN-US link=3Dblue vlink=3Dpurple>
<div class=3DSection1>
<p class=3DMsoNormal>test<o:p></o:p></p>
</div>
</body>
</html>
------=_NextPart_000_0001_01C8EE93.105A84B0--

doof92
July 25th, 2008, 15:34
Oh right. Mine looked like this (sent from a Gmail account):

Return-Path: Delivered-To: root@linux.doof92.co.uk Received: from Postfix filter 42a77884ce2a0a03efc6bb50a6dcdb21 (localhost.localdomain [127.0.0.1]) by smtp-in-163.livemail.co.uk (Postfix) with SMTP id 9FFFD8480D1 for ; Fri, 25 Jul 2008 19:25:32 +0100 (BST) Received: from nf-out-0910.google.com (nf-out-0910.google.com [64.233.182.185]) by smtp-in-163.livemail.co.uk (Postfix) with ESMTP id 7DFB98480D7 for ; Fri, 25 Jul 2008 19:25:32 +0100 (BST) Received: by nf-out-0910.google.com with SMTP id b2so1129765nfb.12 for ; Fri, 25 Jul 2008 11:25:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=domainkey-signature:received:received:mime-version:message-id:date :content-type:x-mailer:from:x-fid:content-transfer-encoding :x-priority:to:subject; bh=LsNrbMaHXYgucvFF6B5AeAO9asEFjWuWEuUn/LUZU2A=; b=olq/6zPDbJuy45eE9BYhmU6i7i5mJmeq6n8r4icfMCQ8MA1KxeVn4gJsTT3QD4uZ uk 3LURjA/7uvfRV6FV5L1ASWIGImAYdTxnVakNXwCimyeKd9leXWMHdbzH8Sju38WuLar q UReb2nFbOwYrET21GQ8NoHkTp7uxu2Rf7jr5w= DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlemail.com; s=gamma; h=mime-version:message-id:date:content-type:x-mailer:from:x-fid :content-transfer-encoding:x-priority:to:subject; b=XvwYxDFv7xHRmdHzbvfrIwaJtq+zE4E/sS+lyx0+xun85UB3NU+gS1aiSpqcskWX7G MrIjXCfZODlCCYgt2LJsFikih2o2HgCHKXbFA4Hmur9js6qeK6m66MKj8mF+ AobaCOAm 5krzFCq0RI8qYzvcDCl7PcBFidGF2ZKFeJ5SM= Received: by 10.210.51.10 with SMTP id y10mr2344464eby.57.1217010332086; Fri, 25 Jul 2008 11:25:32 -0700 (PDT) Received: from Dan ( [195.137.53.201]) by mx.google.com with ESMTPS id i6sm15411904gve.4.2008.07.25.11.25.30 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 25 Jul 2008 11:25:31 -0700 (PDT) MIME-Version: 1.0 Message-Id: <488A1A9E.000003.02724@DAN> Date: Fri, 25 Jul 2008 19:25:34 +0100 (GMT Standard Time) Content-Type: Text/Plain; charset="iso-8859-1" X-Mailer: IncrediMail (5252670) From: "BSKIrc" X-FID: PLAINTXT-NONE-0000-0000-000000000000 Content-Transfer-Encoding: 7bit X-Priority: 3 To: Subject: sdfdf X-Original-To: root@linux.doof92.co.uk dfdfsdf

Dynash
July 25th, 2008, 15:43
Are you forwarding the email account's emails through GMails SMTP service?
Also, try it with a normal email account, like gMail to Yahoo, without using personal emails.

doof92
July 25th, 2008, 15:59
Just tried a number of different combinations, and the only successful result was sending from my ISP email to my BTinternet/Yahoo email address. Strange that it's doing this.

krakjoe
July 25th, 2008, 19:12
Oh right. Mine looked like this (sent from a Gmail account):

I don't get it, I have a gmail account but no energy left for today. I will look tomorrow when I get a few minutes ...

doof92
July 26th, 2008, 03:32
Thanks very much for your help.
Also, I can't find a decent email parser. Searched around and only came across 2, neither of which work that well. If anyone has come across a parser that works, do let me know. Thanks

Vincenzo
August 16th, 2008, 19:07
Would something like this be good enough to compare with this:

www.mail2web.com

Thanks,

- Vince