Archive

Posts Tagged ‘Zend Framework’

How-To Create a RESt Webservice with Zend Rest

August 13th, 2010 Ivan Villareal No comments

There are many times when we need to get data from a production application, but the application is running on a different server, or has a different db than the one we are currently working.

So a quick way to get the required data, without modifying the app would be to create a webservice to expose the data needed.

There are several ways to do this, RPC, SOAP, RESt, to name a few, we can even use some non standard methods, but the discussion of this is beyond the scope of this post.

Thanks to the Zend Framework, we can easily write an api and have working REST server within minutes, even if you don’t use the Zend Framework in your application you can just grab the needed files, and you’ll have your server up and running.

This is the way I can quickly expose some data of a current system.

First get the Zend Framework from Latest Zend Framework.

If you don’t want to put all the framework in your library, you can just use the following files to create your REST server.

|-- Exception.php
|-- Rest
|   |-- Client
|   |   |-- Exception.php
|   |   |-- Result
|   |   |   `-- Exception.php
|   |   `-- Result.php
|   |-- Client.php
|   |-- Controller.php
|   |-- Exception.php
|   |-- Route.php
|   |-- Server
|   |   `-- Exception.php
|   `-- Server.php
`-- Server
    |-- Abstract.php
    |-- Cache.php
    |-- Definition.php
    |-- Exception.php
    |-- Interface.php
    |-- Method
    |   |-- Callback.php
    |   |-- Definition.php
    |   |-- Parameter.php
    |   `-- Prototype.php
    |-- Reflection
    |   |-- Class.php
    |   |-- Exception.php
    |   |-- Function
    |   |   `-- Abstract.php
    |   |-- Function.php
    |   |-- Method.php
    |   |-- Node.php
    |   |-- Parameter.php
    |   |-- Prototype.php
    |   `-- ReturnValue.php
    `-- Reflection.php
 
8 directories, 29 files

Once you have saved the above files somewhere (I use lib/Zend), start writing your server.

< ?php
set_include_path('./lib' . PATH_SEPARATOR . get_include_path());
 
/**
 * Include the main class that we will use
 * to get the data from.
 */
require_once 'DomainProcessor.php';
require_once 'Zend/Rest/Server.php';
 
 
 
class domainService
{
    private $_domainProcessor;
 
    public function __construct()
    {
         $this->_domainProcessor = new domainProcessor();
    }
 
    /**
     * This method will expose the data
     * so we make the call and return what we want to
     * publish
     */
    public function getDomainData($domain)
    {
        $domain = strtolower($domain);
        $result = $this->_domainProcessor->_getDomainData($domain);
        if ($result['fullDomainName'] != $domain) {
            $result = false;
        }
        return $result;
    }
}
 
/**
 * We instantiate a Zend_Rest_Server
 * and we pass the class name that we 
 * want to expose, Zend_Rest will take
 * care of everything else, all our public
 * methods can be consumed by a RESt client
 */
$server = new Zend_Rest_Server();
$server->setClass('domainService');
$server->handle();

To consume our webservice we call it either using a GET or a POST, we can use Zend_Rest_Client to write a client, but also we can call it manually just to be sure that everything works.

To call the above class would be something like:

http://blog.ivanvillareal.info/api.php?method=getDomainData&domain=ivanvillareal.com

and it should respond something like this:

01
<domainservice generator="zend" version="1.0">
02
 <getdomaindata>
03
 <response>
04
 <name>ivanvillareal.com</name>
05
 <age>1</age>
06
 <owner>me</owner>
07
 </response>
08
 <status>success</status>
09
 </getdomaindata>
10
</domainservice>

Fetching mail from a POP3 server with Zend_Mail

June 9th, 2010 Ivan Villareal 1 comment

I was in a need for a class to get mails from a pop server to process them, so I’ve decided to leverage the Zend_Mail class, what I did was to create a wrapper around the Zend_Mail, to return all the messages from the server in a manageable way.

The first step was to put the needed Zend files in my library folder:

lib/Zend/Mail.php
Mail
|-- Exception.php
|-- Message
|   |-- File.php
|   `-- Interface.php
|-- Message.php
|-- Part
|   |-- File.php
|   `-- Interface.php
|-- Part.php
|-- Protocol
|   |-- Abstract.php
|   |-- Exception.php
|   |-- Imap.php
|   |-- Pop3.php
|   |-- Smtp
|   |   `-- Auth
|   |       |-- Crammd5.php
|   |       |-- Login.php
|   |       `-- Plain.php
|   `-- Smtp.php
|-- Storage
|   |-- Abstract.php
|   |-- Exception.php
|   |-- Folder
|   |   |-- Interface.php
|   |   |-- Maildir.php
|   |   `-- Mbox.php
|   |-- Folder.php
|   |-- Imap.php
|   |-- Maildir.php
|   |-- Mbox.php
|   |-- Pop3.php
|   `-- Writable
|       |-- Interface.php
|       `-- Maildir.php
|-- Storage.php
`-- Transport
    |-- Abstract.php
    |-- Exception.php
    |-- Sendmail.php
    `-- Smtp.php

Then I started writing my class:

< ?php
 
set_include_path('lib' . PATH_SEPARATOR . get_include_path());
 
include_once 'Zend/Mail.php';
include_once 'Zend/Mail/Storage/Pop3.php';
include_once 'Zend/Mail/Transport/Smtp.php';
include_once 'Zend/Mime/Part.php';
 
/**
 * Class to get mails from a server
 */
class mailFetcher
{
    private $_emailHost = 'pop.server.com';
    private $_emailUser = 'ivan@ivanvillareal.com';
    private $_emailPass = 'password';
	/**
	 * Zend_Mail_Storage
	 */
    private $_mail;
	/**
	 * Inbox wrapper
	 */
	private $_inbox = array();
 
	/**
	 * on class instantiation we fire connect
	 * to the pop server and start fetching the mails
	 */
    public function __construct()
    {
        try {
            $this->_mail = new Zend_Mail_Storage_Pop3(array(
                                             'host' => $this->_emailHost,
                                             'user' => $this->_emailUser,
                                             'password' => $this->_emailPass));
        } catch (Exception $e) {
            echo 'Mail Retrieval Failed...' . PHP_EOL;
            die();
        }      
        $this->processMail();
    }
 
 
	private function _contentDecoder($encoding, $content)
	{
		switch ($encoding) {
			case 'quoted-printable':
				$result = quoted_printable_decode($content);
			break;
			case 'base64':
				$result = base64_decode($content);
			break;
			default:
				$result = $content;
			break;
		}
		return $result;
	}
 
	/**
	 * This is where everything is done
	 */
	public function processMail()
	{
		if ($this->_mail instanceof Zend_Mail_Storage_Pop3 && $this->_mail->countMessages() > 0) {
			$messageNum = 0;
			foreach ($this->_mail as $message) {
				$messageNum++;
				$rawMail      = $this->_mail->getRawHeader($messageNum) . $this->_mail->getRawContent($messageNum);
				$received     = $message->received;
				$date         = date('Y-m-d H:i:s', strtotime($message->date));
				$messageId    = $message->headerExists('message-id') ? $message->getHeader('message-id') : null;
				//remove <> from message id
				$messageId    = (preg_match('|< (.*?)>|', $messageId, $regs)) ? $regs[1] : $messageId;
				$inReplyTo    = $message->headerExists('in-reply-to') ? $message->getHeader('in-reply-to') : null;
				//remove <> from in-reply-to
				$inReplyTo    = (preg_match('|< (.*?)>|', $inReplyTo, $regs)) ? $regs[1] : $inReplyTo;
				$references   = $message->headerExists('References')  ? $message->getHeader('References') : null;
				//remove <> from references
				$references   = (preg_match('|< (.*?)>|', $references, $regs)) ? $regs[1] : $references;
				$from         = $message->from;
				$subject      = $message->subject;
				$to           = $message->to;
				$plainContent = null;
				$htmlContent  = null;
				$attachments = array();
 
				/**
				 * Check if the message has multiple parts
				 */
		        if ($message->isMultipart()) {
					/**
					 * We have a multipart message
					 * lets extract the plain content,
					 * html content, and attachments
					 */
					foreach (new RecursiveIteratorIterator($message) as $part) {
						try {
							switch (strtok($part->contentType, ';')) {
								case 'text/plain':
									$plainContent = $this->_contentDecoder($part->getHeader('content-transfer-encoding'), $part->getContent());
								break;
								case 'text/html':
									$htmlContent = $this->_contentDecoder($part->getHeader('content-transfer-encoding'), $part->getContent());
								break;
								default: //attachment handle
									$type       = strtok($part->contentType, ';');
									$fileName   = $part->getHeader('content-description');
									$attachment = $this->_contentDecoder($part->getHeader('content-transfer-encoding'), $part->getContent());
									$attachments[] = array(
													   'file_name' => $fileName,
													   'type'      => $type,
													   'content'	=> $attachment);
								break;
							}
						} catch (Zend_Mail_Exception $e) {
							echo "$e \n";
						}
					}
				} else {
					$plainContent = $message->getContent();
				}
				$this->_inbox[] = array('messageNumber' => $messageNum,
									    'rawMail'       => $rawMail,
										'received'		=> $received,
										'date'			=> $date,
										'messageId'		=> $messageId,
										'inReplyTo'		=> $inReplyTo,
										'references'	=> $references,
										'from'			=> $from,
										'subject'		=> $subject,
										'to'			=> $to,
										'plainContent'	=> $plainContent,
										'htmlContent'	=> $htmlContent,
										'attachments'	=> $attachments);
			}
		} else {
			$this->_inbox = false;
		}
	}
	public function getInbox()
	{
		return $this->_inbox;
	}
}

My fetch class does everything on instantiation, and it will have all the mails retreived, so for example if I need to get all messages I can do this:

< ?php
include_once 'mailFetcher.php';
 
$inbox = new mailFetcher();
print_r($inbox->getInbox());

And this would be the result:

Array
(
    [0] => Array
        (
            [messageNumber] => 1
            [rawMail] => Received: from gate55.gate.iad.mailserver.com (11.1.111.1) by
 IAD2HUB01.mex02.mailserver.com (111.11.11.65) with Microsoft SMTP Server (TLS) id
 8.2.247.2; Wed, 9 Jun 2010 17:56:16 -0400
Received: from mail-yw0-f186.google.com (mail-yw0-f186.google.com
 [111.11.111.186])	by gate55.gate.iad.mailserver.com (SMTP Server) with ESMTP id
 B1F6E31D0171	for <asdfasdf @ivanvillareal.com>; Wed,  9 Jun 2010
 17:56:15 -0400 (EDT)
Received: by ywh16 with SMTP id 16so5309053ywh.32        for
 </asdfasdf><asdfasdf @ivanvillareal.com>; Wed, 09 Jun 2010 14:56:15 -0700 (PDT)
Received: by 10.111.111.111 with SMTP id jz1mr465966qcb.170.1276120573865;
 	Wed, 09 Jun 2010 14:56:13 -0700 (PDT)
Received: by 11.111.111.11 with HTTP; Wed, 9 Jun 2010 14:56:13 -0700 (PDT)
From: Ivan Villareal <ivaano @gmail.com>
To: "asdfasdf@ivanvillareal.com" <asdfasdf @ivanvillareal.com>
Date: Wed, 9 Jun 2010 17:56:13 -0400
Subject: attachment test
Thread-Topic: attachment test
Thread-Index: AcsIHpXuE+vWJJMfTGyqikgD2kYkng==
Message-ID: <aanlktingkmpbkefog5kxxoq8wrib7tj1pt1rsy -1ug-1@mail.gmail.com>
Accept-Language: en-US
Content-Language: en-US
X-MS-Exchange-Organization-AuthAs: Anonymous
X-MS-Exchange-Organization-AuthSource: IAD2HUB01.mex02.mailserver.com
X-MS-Has-Attach: yes
X-MS-TNEF-Correlator:
x-virus-scanned: OK, catchall
x-originating-ip: [111.11.111.186]
dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed;        d=gmail.com;
 s=gamma;
        h=domainkey-signature:mime-version:received:received:date:message-id
         :subject:from:to:content-type;
        bh=IvMOHmKRabcJ2PrUHPHB/NbNpgQubvvgGprC6gtDY9E=;
        b=cA5Pjycedt9Pylic7CTk4HCF6HXV9eEFpr086KwcMepGKJEv4DWU6d4iFt4Gp7R42V
         +4rVmrmwj2j9yj1vbEUqVMI6/m+Kkwt1r+MAtN/0qZsvEaVBBbbjTBxFLO9cQ7xlaSSm
         eGTHv9mR0qCcBZGLOVFeWUNiYDkhY2F0eDUbU=
domainkey-signature: a=rsa-sha1; c=nofws;        d=gmail.com; s=gamma;
        h=mime-version:date:message-id:subject:from:to:content-type;
        b=VKdlRSfBz/Swij0xE0c7Su8TOwcc2YGmw0K8dvVxoS9TJf0p8nIqtR6nQtmKqabSu4
         g2ALFFHXuVOhGpP+JdvI3wQJ1k9N5EZhcWtSRECrikOlLnaDA8/4z3SYckY6hs7Q+KIe
         qG0IbY+QkuZh7yymcyAN5omTaFDFT2GIPs+1c=
x-orig-to: catchall@ivanvillareal.com
Content-Type: multipart/mixed;
	boundary="_004_AANLkTingkMPbKeFog5kxXoq8WRib7tJ1pT1Rsy1ug1mailgmailcom_"
MIME-Version: 1.0
 
--_004_AANLkTingkMPbKeFog5kxXoq8WRib7tJ1pT1Rsy1ug1mailgmailcom_
Content-Type: multipart/alternative;
	boundary="_000_AANLkTingkMPbKeFog5kxXoq8WRib7tJ1pT1Rsy1ug1mailgmailcom_"
 
--_000_AANLkTingkMPbKeFog5kxXoq8WRib7tJ1pT1Rsy1ug1mailgmailcom_
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64
 
amhnamhnamhnDQo=
 
--_000_AANLkTingkMPbKeFog5kxXoq8WRib7tJ1pT1Rsy1ug1mailgmailcom_
Content-Type: text/html; charset="utf-8"
Content-Transfer-Encoding: base64
 
amhnamhnamhnDQo=
 
--_000_AANLkTingkMPbKeFog5kxXoq8WRib7tJ1pT1Rsy1ug1mailgmailcom_--
 
--_004_AANLkTingkMPbKeFog5kxXoq8WRib7tJ1pT1Rsy1ug1mailgmailcom_
Content-Type: image/jpeg; name="2010-05-28-112655.jpg"
Content-Description: 2010-05-28-112655.jpg
Content-Disposition: attachment; filename="2010-05-28-112655.jpg"; size=15004;
	creation-date="Wed, 09 Jun 2010 17:56:16 GMT";
	modification-date="Wed, 09 Jun 2010 17:56:16 GMT"
Content-Transfer-Encoding: base64
 
/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0a
gq4UlFJmmKwtHakzS0DsMNFLikIxQAUmKKM0AFLSUtABRRRQAlFGeaKACiikouAtGaKPrQAmaKDS
4oASgClxRQKwUUUlAxaKKM0AFBNFGM0AGalHzIKiIp6HgigQuKKKKQyZDlaJAcU2I09+VP0qWSRK
R0zTGXBpuec1IDvX3qihqNhhV5WG0Vn9DUocgUMTJpyCpIqsKezZXmoqENDqQ0dqBmmMBS0UmKAF
oFJS0AJ3oIpQKQk0AAp4JxTBTxQwYE0oFNNOU8UhCkDGKaRin0EZoEiLIpcUuzuKMUyrje9FKQet
J2oGf//Z
 
--_004_AANLkTingkMPbKeFog5kxXoq8WRib7tJ1pT1Rsy1ug1mailgmailcom_--
 
            [received] => from gate55.gate.iad.mailserver.com (11.1.111.1) by IAD2HUB01.mex02.mailserver.com (111.11.11.15) with Microsoft SMTP Server (TLS) id 1.1.147.2; Wed, 9 Jun 2010 17:56:16 -0400
from mail-yw0-f186.google.com (mail-yw0-f186.google.com [209.85.211.186])	by gate55.gate.iad.mailserver.com (SMTP Server) with ESMTP id B1F6E31D0171	for <asdfasdf @ivanvillareal.com>; Wed,  9 Jun 2010 17:56:15 -0400 (EDT)
by ywh16 with SMTP id 16so5309053ywh.32        for </asdfasdf><asdfasdf @ivanvillareal.com>; Wed, 09 Jun 2010 14:56:15 -0700 (PDT)
by 10.229.233.193 with SMTP id jz1mr465966qcb.170.1276120573865; Wed, 09 Jun 2010 14:56:13 -0700 (PDT)
by 10.229.192.82 with HTTP; Wed, 9 Jun 2010 14:56:13 -0700 (PDT)
            [date] => 2010-06-09 14:56:13
            [messageId] => AANLkTingkMPbKeFog5kxXoq8WRib7tJ1pT1Rsy-1ug-1@mail.gmail.com
            [inReplyTo] => 
            [references] => 
            [from] => Ivan Villareal <ivaano @gmail.com>
            [subject] => attachment test
            [to] => "asdfasdf@ivanvillareal.com" <asdfasdf @ivanvillareal.com>
            [plainContent] => jhgjhgjhg
 
            [htmlContent] => jhgjhgjhg
 
            [attachments] => Array
                (
                    [0] => Array
                        (
                            [file_name] => 2010-05-28-112655.jpg
                            [type] => image/jpeg
                        )
 
                )
 
        )
 
)</asdfasdf></ivaano></asdfasdf></aanlktingkmpbkefog5kxxoq8wrib7tj1pt1rsy></asdfasdf></ivaano></asdfasdf>

From this point I can iterate the inbox easily saving the email results or applying other logic to it,