PHP: Да работим с COM и IMAP

Категория: Интернет
Етикети:
10.2.2004

Приложението на PHP, което е различно от стандартното, е доста широко. Нека сега да се спрем на няколко основни категории по-малко познати приложения на езика.

Работа с COM обекти
Работата с тези обекти може да се окаже костелив орех от гледна точка на самото програмиране. Едва ли сте намирали документация по този въпрос, освен няколко скрипта с много добро описание, които, ако решите да ги подкарате, няма да можете. Това се дължи на факта, че трябва да се направят доста настройки, за да тръгне един такъв скрипт. Ако сте на Windows 2000 или XP, ще трябва да направите чудо, за да тръгнат нещата, защото фирмата прозиводител леко е повишила изискванията за сигурност и с това почти е отрязала пътя на тези приложения, но начин има.
Този скрипт е тестван на Windows NT и работи перфектно, ако се направят следните стъпки.
1. Стартирайте regedit.exe от менюто старт и проверете в:
HKEY_CLASSES_ROOT за следните неща:
- Outlook.Application
- MAPI.Session (MAPI.Session1)
Ако ги нямате обаче, ще се наложи да инсталираме някои неща, които да помогнат в работата ни в тази област. Задължително условие е да имате инсталиран Microsoft Offfice 2000. Като се уверите в неговото съществуване, претърсете компютъра си за следния файл: CDO.dll. Aко го няма обаче, трябва да си го свалите от Internet - от сайта на Майкрософт или от друго място. След това сложете файла в директория system32 и го регистрирайте по следния начин:
Отворете command и пишете
C:> cd windows
C:> cd system32
C:> regsvr32.exe cdo.dll
Ще ви се изпише съобщение на екрана, че процесът е бил успешен. След това проверете отново в регистрите дали има необходимите записи, както споменах по-горе.
Време е да отворите любимия си текстов редактор и да започнете да пишете. Искам да спомена, че резултатът може да се види през браузер и през конзола в зависимост от това как ще направите кода.
function getMessages($folder) { - тук ще използвам директно HTML, което не ви пречи да работите по по-добрия начин ;)
echo”

$folder

”; - създаваме инстанция на двата COM обекта, за които споменах малко по-горе и инсталирахме.
$oOutlook = new COM(“Outlook.
Application”);
$session= new COM(“MAPI.Session”);
- влизане в акаунта (акаунта по подразбиране, няма нужда от име и парола).
$session->Logon(); - избираме работната папка
$inb=$session->$folder; - вземаме броя на всички съобщения в папката която избрахме по-горе.
$messages=$inb->Messages->Count(); - вземаме елементите на съобщението. for($i=1;$i<($messages+1);$i++){ $item=$inb->Messages->item($i); - кога е получено съобщението
$timeres=$item->TimeReceived();
$date_vb=getdate($timeres); - масив - елементите на датата, когато е получено съобщението.
$year=$date_vb[‘year’];
$month=$date_vb[‘mon’];
$day=$date_vb[‘mday’]; - започваме да ги изписваме отново пак с HTML.
echo “”;
}
echo”
N:
Subject

Type
Date
>$i>$item->Subject$item->Type$year/$month/$day
”;
}
Kaкво направихте в тази функция? Много е важно да се разбере самият начин на работа с тези обекти, защото няма документация, както споменах и по-рано. Единственото място, където има информация и тя може да се пригоди някак си за PHP, както и аз съм направил в този скрипт, е MSDN дискът и сайт на Microsoft.
В горната функция създадохме обекти, с които ще работим, след това отворихме inbox-a на Outlоok-а ви, намерихме броя на съобщенията вътре и след това им взехме някои данни. Нека да видим следващата функция:
function ViewMessageFrom
Folder($id,$folder){
- отново създаваме инстанция на обектите.
$oOutlook = new COM(“Outlook
.Application”);
$session= new COM(“MAPI.Session”); - логваме се.
$session->Logon(); - вземаме папката, която сме подали като параметър на функцията (inbox, outbox).
$inb=$session->$folder; - правим проверка дали има ID на съобщението, което искаме да покажем if($id==””){
echo “Message Viewer
No Messages Selected
”;
}
else{
$idint=(int)$id; - започваме да четем.
$items=$inb->Messages->item($idint); - слагаме статус, че съобщението е прочетено.
$items->Unread=”false”; - променяме статуса.
$items->Update(true); - показваме го. echo”Message Viewer”;
echo””;
- $items->Type - показва статуса на съобщението (прочетено/непрочетено) - $items->Text - показва съдържанието му. }
}
Сега следват 2 много важни функции:
function getUnreadinInbox(){
- взема непрочетените съобщения от Inbox
$oOutlook = new COM(“Outlook
.Application”);
$oNs = $oOutlook->GetNamespace
(“MAPI”);
$oFldr = $oNs->GetDefaultFolder
(olFolderInbox);
$UnreadMessagesInFolder = $oFldr->UnReadItemCount;
return $UnreadMessagesInFolder;
} function getUnreadinOutbox(){
- взема непрочетените съобщения от Outbox
$oOutlook = new COM(“Outlook.
Application”);
$oNs = $oOutlook->GetNamespace
(“MAPI”);
$oFldr = $oNs->GetDefault
Folder(olFolderOutbox);
$UnreadMessagesInFolder = $oFldr->UnReadItemCount;
return $UnreadMessagesInFolder; }
Логиката и тук е същата и се следва познатият алгоритъм и на разсъждения, и на писане. Разбира се, този код поема доста голяма част оптимизация и ако искате да си го напишете, ще придобие малко по-друго лице. Едва ли ше ви върши огромна работа, особенно с ограниченията, наложени от оперционната система, но по-важно е да видим как става. А ако го подкарате на друга версия на Windows, ще се радвам да споделите опит.
Ето и последната функция:
function staticFolders(){
- списък на папките, който са достъпни (статичен лист), не успях да намеря начин, за да ги вземам динамично.
$unread=$this->getUnreadinInbox();
$out_unr=$this->getUnreadinOutbox();
echo”Available folders in this version are:
Inbox>Inbox($unread)
and Outbox>Outbox($out_unr)
”;
}
Ако поставим всичко това в един клас за по лесна комуникация с отделните функции, би се получило много добре. Нека класът да бъде class CoutLook.
Следващата стъпка в нашето навлизане в дебрите на тези обекти, уважаеми читателю, е малко скучна работа, но скучното не винаги е безполезно.
Предните функции запишете във файл под името COutLook.php
Създайте нов файл под името command.php и в него напишете следното:
require(“COutLook.php”);
$class= new COutLook;
if ($folder==””){
$class->staticFolders();
}
else {
$class->staticFolders();
$class->getMessages($folder);
} ?>
След това в нов файл под името view.php напишете:
require(“COutLook.php”);
$class= new COutLook;
if ($id==”” || $folder== “”){
echo “Message Viewer


No Messages Selected
”;
}
else{ $class->ViewMessageFrom
Folder($id,$folder);
}
?>
Ето че приключихме с писането, остана само едно нещо - да сглобим всичко:
Outlook Reader<body></body>
Запишете дайла като Index.php и го стартирайте през Apache
http://localhost/outlook/index.php
Ако всичко е наред, трябва да видите съдържанието на Оutlooka в бразузера си. Друго приложение на същата основа е да изпратим e-mail, без да се налага да отваряме outlook-a, ето как става това:
.Application”);
$myItem = $objApp->CreateItem
(olMailItem);
$a=$myItem->Recipients->Add(“admin@spisanie.com”); $myItem->Subject=”Tова е тест”; $myItem->Body=”Искам да направя един тест само”; $myItem->Display(); $myItem->Send(); ?>
Запишете файла като mail.php и го изпълнете. За него обаче важат всички горни забележки и изисквания.
Какво правим тук:
$myItem = $objApp->CreateItem(olMailItem); - създаваме ново съобщение.
$a=$myItem->Recipients->Add(“кой@койдомайн.org”); - определяме кой е получателят. $myItem->Subject=”Това е темата”; - слагаме тема на това съобщение. $myItem->Body=”Това е тялото!”; - тяло $myItem->Display(); - ако искате да се покаже Outlook-ът като програма, трябва да сложите този ред, но това не е задължително. $myItem->Send(); - изпращане.
И отново стартираме:
http://localhost/outlook/mail.php
Aко няма грешка и всичко е както трябва, можете да проверите пощата си. Сигурно досега, ако не знаете, се питате какво е това COM. Оставих го за края на този раздел, за да има по голямо значение, след като сте прочели всичките примери.
COM е технология, която позволява да се използва отново код, ползвайки стандартни конвенции. Разделя се изпълнението от интерфейса.Тоест, имате предварително писан код, който е в библиотека, и вие ползвате методите му посредством тази технология.
С това мисля да приключа с тези обекти и да се прехвърлим на IMAP.

Да работим с IMAP
Сигурно ви се е искало да си направите собствен мейлинг лист, тези, които са правени от някой друг, нямат нужната функционалност. В следващите редове ще ви дам някои примери как сами да си направите такъв лист или респондер или как да обработвате определени съобщения по определен начин.
Нека спрем да говорим и да вземем да пишем. Отворете отново текстовия си редактор и напишете следното:
- oтваряме поток към mail сървър на порт 110 (pop3), с име и парола за пощенската кутия, с която ще работим.
$imap_stream = imap_open (“{mail.
host.bg:110/pop3}INBOX”, “username”, “password”); - взимаме данните за съобщенията в Inbox и ги обработваме.
$inbox=imap_mailboxmsginfo($imap_stream); for($i=1;$i<=$inbox->Nmsgs;$i++){ $header=imap_header($imap_stream,$i,300,300,0); $from = $header->from; foreach ($from as $id => $object){
$fromaddress = $object->mailbox . “@” . $object->host; }
$Subject=$header->Subject; ....... - тук проверките, които ще покажем по надолу. }
Интересното тук е да се обърне внимание не толкова как се влиза в сървъра, а как се обработват съобщенията. Нека да си поставим следната задача, ако потребителят изпрати е-mail с тема subscribe, да го запишем в базата данни и да му изпратим обратно е-mail, за да го уведомим. За целта имаме нужда от неща, който трябва да получим:
e-mail на подателя, име на подателя и темата на съобщението. - e-mail на подателя
$from = $header->from; - име на подателя
$fromaddress = $object->mailbox . “@” . $object->host; - темата на съобщението.
$Subject=$header->Subject;
Тези променливи се вземат за всяко съобщение от кутията. След като вече ги имаме, можем да започнем работа с тях. Да си направим първо един клас, който ще се грижи за регистрацията на потребителите и да ги уведомява. Нека да го кръстим
Сregister.php
,’$email’)”; mysql_query(
$insert_data); } } ?>
Тук мисля, че няма нищо неясно, подава се email-ът на потребителя на функция в този клас и той го добавя в базата данни. Този клас може да се разшири, разбира се, като примерно се добави функционалността да проверява за вече регистриран e-mail, както и да проверява за нежелани или невалидни такива. В config.php се намират настройките за базата данни.
Нека сега се върнем на кода и да видим как да филтирираме това, което ни се подава:
if ($Subject ==”subscribe”)
{
$b=new CRegister;
$b->add($fromaddress);
$mail_desc=”
Благодарим Ви, че се записахме за нашия бюлетин
”; NewMailer::execute($fromaddress,
”Success”,$mail_desc);
imap_delete($imap_stream,$i);
}
От преди получените данни проверявяаме дали темата е subscribe, ако е такава, вкарваме e-mail-а на изпращача в базата данни и го уведомяваме с обратен e-mail.
class NewMailer {
function execute($to,$subject,$text) {
$params[‘host’] = ‘mail.webgate.bg’; $params[‘port’] = 25; $params[‘auth’] = FALSE; $params[‘user’] = ‘’; $params[‘pass’] = ‘’; $send_params[‘recipients’] = array($to); $send_params[‘headers’] = array( ‘Content-type: text/html; charset=windows-1251’,
‘From:Webgate JSC ’,
‘Subject:’. $subject.’’,
‘To:’.$to.’’); $send_params[‘from’] = ‘Webgate JSC ’; $send_params[‘body’] = ‘’.$text.’’; $smtp = smtp::connect($params); echo $proc=$smtp->send($send
_params); if(is_object($smtp) AND $proc){ echo “OK”; }else{ echo “Failed”;
}
}
}
Функцията за изпращане на e-mail, която използваме малко по-горе.Тя е на основата на един SMTP клас. Това е направено с цел, дори и да нямате mail сървър при вас, да можете да ползвате този скрипт. Той се настройва много лесно и е написан много добре, като може да работи и с различни сървъри. Може би от целия клас ще са ви интересни някои моменти само и те са следните:
function &connect($params = array()){
if(!isset($this->status)){
$obj = new smtp($params); if($obj->connect()){
$obj->status = SMTP_STATUS_CONNECTED; }
return $obj; }else{
$this->connection = fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout); if(function_exists(‘socket_set_timeout’)){ @socket_set_timeout($this->connection, 5, 0); } $greeting = $this->get_data(); if(is_resource($this->connection)){
return $this->auth ? $this->ehlo() : $this->helo();
}else{
$this->errors[] = ‘Failed to connect to server: ‘.$errstr;
return FALSE; }
}
}
И
function send($params = array()){ foreach($params as $key => $value){
$this->set($key, $value); }
if($this->is_connected()){ if($this->auth AND !$this->authenticated){ if(!$this->auth()) return FALSE; }
- oттук започва приложението на SMTP протокола; ако имате желание, можете да разгледате как протича, а след този код можете да видите една кратка сесия. $this->mail($this->from); if(is_array($this->recipients)) foreach($this->recipients as $value) $this->rcpt($value);
else $this->rcpt($this->recipients);
if(!$this->data()) return FALSE; $headers = str_replace(CRLF.’.’, CRLF.’..’, trim(implode(CRLF, $this->headers)));
$body = str_replace(CRLF.’.’, CRLF.’..’, $this->body); $body = $body[0] == ‘.’ ? ‘.’.$body : $body; $this->send_data($headers); $this->send_data(‘’); $this->send_data($body); $this->send_data(‘.’); $result = (substr(trim($this->get_data()), 0, 3) === ‘250’); return $result; }else{
$this->errors[] = ‘Not connected!’;
return FALSE; }
}
Които ние използваме пряко в горния скрипт. Самия клас можете да си свалите от клутовия сайт phpclasses.org. Eто и обещаната схема на една сесия на SMTP, по който е направен и скриптът.
HELO server.bg
250 mail.server.bg
MAIL FROM: 250 ok
DATA
354 go ahead
Subject: test
Towa e tesr
.
250 ok 902549473 qp 24035
QUIT
221 mail.server.bg
Малко отбих встрани от темата, за да обясня и тази материя, защото все повече се пита за алтернативни методи за изпращане на поща или за някакви други услуги, като IRC например, извън стандартните библиотеки на PHP, с цел да се избегнат ограниченията на операционната среда или на различните версии на езика.
>$i
$items->Subject
$items->Type
$items->Text