I am using php-ews to read mailbox items, in order to process emails as support tickets.
As some are/could be part of conversations, I want to use the UniqueBody property, to get the latest/unique part of the message.
Example request:
$request = new GetItemType();
$request->ItemShape = new ItemResponseShapeType();
$request->ItemShape->BaseShape = DefaultShapeNamesType::ALL_PROPERTIES;
$request->ItemType = new ItemType();
$request->ItemType->UniqueBody = true;
$request->ItemIds = new NonEmptyArrayOfBaseItemIdsType();
$item = new ItemIdType();
$item->Id = 'MessageId';
$request->ItemIds->ItemId[] = $item;
$response = $client->GetItem($request);
However, this results in the UniqueBody response being empty.
I have a feeling that the request value of UniqueBody is incorrect, but I cannot find any documentation, examples or other PHP solutions that help.
Has anyone know how to get this to work?
Thanks in advance,
Baz
OK, with a clearer head I've done a bit of digging around in the classes and found the solution.
Add this reference:
use \jamesiarmes\PhpEws\ArrayType\NonEmptyArrayOfPathsToElementType;
Then added the ItemShape->AdditionalProperties
$request->ItemShape->AdditionalProperties = new NonEmptyArrayOfPathsToElementType();
$request->ItemShape->AdditionalProperties->FieldURI = new PathToUnindexedFieldType();
$request->ItemShape->AdditionalProperties->FieldURI->FieldURI = UnindexedFieldURIType::ITEM_UNIQUE_BODY;
To make this:
$request = new GetItemType();
$request->ItemShape = new ItemResponseShapeType();
$request->ItemShape->BaseShape = DefaultShapeNamesType::ALL_PROPERTIES;
$request->ItemShape->AdditionalProperties = new NonEmptyArrayOfPathsToElementType();
$request->ItemShape->AdditionalProperties->FieldURI = new PathToUnindexedFieldType();
$request->ItemShape->AdditionalProperties->FieldURI->FieldURI = UnindexedFieldURIType::ITEM_UNIQUE_BODY;
$request->ItemIds = new NonEmptyArrayOfBaseItemIdsType();
$item = new ItemIdType();
$item->Id = 'MessageId';
$request->ItemIds->ItemId[] = $item;
$response = $client->GetItem($request);
The response now contains the UniqueBody in HTML format
$response->ResponseMessages->GetItemResponseMessage[0]->Items->Message[0]->UniqueBody
Results in:
<html><body><div>
<div>
<div>
<div>
<div dir="ltr">
<div dir="ltr">Second message.</div>
<div dir="ltr">Kind regards</div>
<div dir="ltr">Me </div></div></div></div></div></div>
</body></html>
Related
I am using this SDK - https://github.com/evernote/evernote-cloud-sdk-php
I can find notes in the my own notebooks, something like this:
$client = new \Evernote\Client($token, false);
$search = new \Evernote\Model\Search('*');
$notebook = $client->getNotebook('notebook_id');
$scope = \Evernote\Client::SEARCH_SCOPE_ALL;
$order = \Evernote\Client::SORT_ORDER_REVERSE | \Evernote\Client::SORT_ORDER_RECENTLY_CREATED;
$results = $client->findNotesWithSearch($search, $notebook, $scope, $order, 20);
It works, but if I try get notes from linked notebooks, it get empty result all time.
Tried implement this - https://dev.evernote.com/doc/articles/sharing.php
$adClient = new \Evernote\AdvancedClient($token ,false);
$store = $adClient->getSharedNoteStore('linked_notbook_id');
$client = new \Evernote\Client($store->getToken(), false);
$search = new \Evernote\Model\Search('*');
$notebook = $carrier->getLinkedNotebooks()[0];
$scope = \Evernote\Client::SEARCH_SCOPE_ALL;
$order = \Evernote\Client::SORT_ORDER_REVERSE | \Evernote\Client::SORT_ORDER_RECENTLY_CREATED;
$results = $client->findNotesWithSearch($search, $notebook, $scope, $order, 20);
The same, empty result.
Where did this $carrier come from?
$notebook = $carrier->getLinkedNotebooks()[0];
Assuming it's $client, LinkedNotebook from the SharedNoteStore is assigned to $notebook and it is passed to findNotesWithSearch, which doesn't seem right.
The LinkedNotebook object is for the user who is shared a notebook with. So calling that API with SharedNoteStore is probably not what you want. See https://dev.evernote.com/doc/articles/sharing.php
The type of second argument of findNotesWithSearch is Notebook. notebookGuid can be found in SharedNotebook.
I am writing a php script to read emails from an Exchange Server 2010. Currently, I am able to retrieve all unread emails, but I would like to mark the emails that I have retrieved as read, so I don't retrieve messages I have already retrieved again. I am using php-ews from github. I created a script to do this, but every time it runs I get this error when I call UpdateItem.
PHP Fatal error: SOAP-ERROR: Encoding: object has no 'Path' property
Stack Trace:
#0 ExchangeClient.php(355): SoapClient->__call('UpdateItem', Array)
#1 ExchangeClient.php(355): NTLMSoapClient->UpdateItem(Object(UpdateItemType))
#2 markReadTest.php(20): ExchangeClient->mark_as_read(Object(stdClass))
#3 ExchangeClient.php on line 355
I'm note sure what is causing this error because I think all of my SOAP nesting is correct because I have been referring to Microsoft's EWS SOAP reference for the UpdateItem function. Here is the code for the script that I am using to mark messages as read.
public function mark_as_read($ReadMessage)
{
$request = new EWSType_UpdateItemType();
$request->MessageDisposition = 'SaveOnly';
$request->ConflictResolution = 'AlwaysOverwrite';
$request->ItemChanges = array();
$change = new EWSType_ItemChangeType();
$change->ItemId = new EWSType_ItemIdType();
$change->ItemId->Id = $ReadMessage->ItemId->Id;
$change->ItemId->ChangeKey = $ReadMessage->ItemId->ChangeKey;
$field = new EWSType_SetItemFieldType();
$field->FieldURI = new EWSType_PathToUnindexedFieldType();
$field->FieldURI->FieldURI = 'message:IsRead';
$field->Message = new EWSType_MessageType();
$field->Message->IsRead = True;
$change->Updates->SetItemField[] = $field;
$request->ItemChanges[] = $change;
$response = $this->client->UpdateItem($request);
return $response;
}
After some research I found a comment that provided the solution on a howtoforge post about connecting to EWS through the PHP SOAPclient. The solution was to replace the path element with FieldURI elements in the types.xsd file.
Original XML Tag:
<xs:element ref="t:Path"/>
Replaced By:
<xs:element ref="t:FieldURI"/>
<xs:element ref="t:IndexedFieldURI"/>
<xs:element ref="t:ExtendedFieldURI"/>
This path element occurred 8 times in my version of types.xsd which I got from an Exchange-2013 SP1 server and I replaced all instances of it with the FieldURI elements. After, I did this I was able to mark emails as read without modifying the code I used in my question
Two things that maybe doing it first you should be setting the IsReadSpecified property to true eg
$request = new EWSType_UpdateItemType();
$request->MessageDisposition = 'SaveOnly';
$request->ConflictResolution = 'AlwaysOverwrite';
$request->ItemChanges = array();
$change = new EWSType_ItemChangeType();
$change->ItemId = new EWSType_ItemIdType();
$change->ItemId->Id = $ReadMessage->ItemId->Id;
$change->ItemId->ChangeKey = $ReadMessage->ItemId->ChangeKey;
$field = new EWSType_SetItemFieldType();
$field->FieldURI = new EWSType_PathToUnindexedFieldType();
$field->FieldURI->FieldURI = 'message:IsRead';
$field->Message = new EWSType_MessageType();
$field->Message->IsReadSpecified = true;
$field->Message->IsRead = true;
$change->Updates->SetItemField[] = $field;
$request->ItemChanges[] = $change;
$response = $this->client->UpdateItem($request);
return $response;
Also you might want to look at what the request SOAP is your code is submitting to the server and post that. Its generally a lot clearer from the SOAP what you are doing incorrectly.
I use James Armes's PHP-EWS library.
The following code works fine with single attachments, but fails with multiply files.
<?php
$msgRequest->MessageDisposition = 'SaveOnly';
$msgResponse = $ews->CreateItem($msgRequest);
$msgResponseItems = $msgResponse->ResponseMessages->CreateItemResponseMessage->Items;
// Create attachment(s)
$attachments = array();
$i = 0;
foreach ($message_details['attachment'] as $attachment) {
$attachments[$i] = new EWSType_FileAttachmentType();
$attachments[$i]->Content = file_get_contents($attachment['path'] . '/' . $attachment['file']);
$attachments[$i]->Name = $attachment['file'];
$i++;
}
//
// Attach files to message
$attRequest = new EWSType_CreateAttachmentType();
$attRequest->ParentItemId = $msgResponseItems->Message->ItemId;
$attRequest->Attachments = new EWSType_NonEmptyArrayOfAttachmentsType();
$attRequest->Attachments->FileAttachment = $attachments;
$attResponse = $ews->CreateAttachment($attRequest);
$attResponseId = $attResponse->ResponseMessages->CreateAttachmentResponseMessage->Attachments->FileAttachment->AttachmentId;
// Save message id from create attachment response
$msgItemId = new EWSType_ItemIdType();
$msgItemId->ChangeKey = $attResponseId->RootItemChangeKey;
$msgItemId->Id = $attResponseId->RootItemId;
// Send and save message
$msgSendRequest = new EWSType_SendItemType();
$msgSendRequest->ItemIds = new EWSType_NonEmptyArrayOfBaseItemIdsType();
$msgSendRequest->ItemIds->ItemId = $msgItemId;
$msgSendRequest->SaveItemToFolder = true;
$msgSendResponse = $ews->SendItem($msgSendRequest);
$response = $msgSendResponse->ResponseMessages->SendItemResponseMessage;
?>
$ews->SendItem() returns this error:
Uncaught SoapFault exception: [a:ErrorSchemaValidation] The request
failed schema validation: The required attribute 'Id' is missing.
What do I miss here?
Found the answer here:
https://github.com/jamesiarmes/php-ews/issues/132
Basically Exchange does not use an array if there is only one attachment, so an additional check is required to determine where to get the ID from.
if(!is_array($attResponse->ResponseMessages->CreateAttachmentResponseMessage))
$attResponseId = $attResponse->ResponseMessages->CreateAttachmentResponseMessage->Attachments->FileAttachment->AttachmentId;
else {
$attResponseId = $attResponse->ResponseMessages->CreateAttachmentResponseMessage[0]->Attachments->FileAttachment->AttachmentId;
}
Exchange uses the same structure with recipients. I find this inconsistent, however I am sure there is a reason behind it.
I hope someone will benefit from raising this.
When querying for contacts I use the code below to retrieve all my contacts
$gdata = new Zend_Gdata($client);
$gdata->setMajorProtocolVersion(3);
$query = new Zend_Gdata_Query(
"http://www.google.com/m8/feeds/contacts/default/full");
$feed = $gdata->getFeed($query);
As I look through each entry of the $feed I can get access to the contactId and according to the Contacts API I should be able to retrieve the picture by doing a GET on the following URL:
http://www.google.com/m8/feeds/photos/media/default/contactId
So I use the same mechanism to retrieve contacts and try to get a photo after setting $id:
$query = new Zend_Gdata_Query(
"http://www.google.com/m8/feeds/photos/media/default/$id");
$entryFeed = $gdata->getFeed($query);
But I get an error "DOMDocument cannot parse XML". Am I doing something wrong? Are there any example docs?
To get the photo use DOMXpath and search for the "//atom:link" tag, then use $gdata->get(href) to grab the photo. Check for the etag attribute for each link, this tells you whether or not there is a profile photo associated with this contact.
$doc = new DOMDocument;
$doc->recover = true;
$doc->loadXML($entry->getXML());
$xpath = new DOMXPath($doc);
$links = $xpath->query('//atom:link');
foreach($links as $link) {
if($link->getAttribute('etag') != "") {
$http_response = $gdata->get($link->getAttribute('href'));
$rawImage = $http_response->getBody();
$fp = fopen("/var/www/profile/$id.jpg", "w");
fwrite($fp, $rawImage);
fclose($fp);
break;
}
}
I am trying to develop a script (using the PHP example app as a basis) that will post a note to Evernote based on GET values.
When I insert this to the end of functions.php's listNotebooks()
$note_obj = new Note(array(
'contents' => $note_contents,
'title' => $title
));
It throws a 500 error. (In my code, $title & $note_contents are defined earlier. I have spent a lot of time trying to find proper documentation for the PHP API but it just seems non-existent. Any information on this topic would be greatly appreciated
Update: I did not realize the API was using PHP Namespaces: This fixed the issue:
//import Note class
use EDAM\Types\Note;
use EDAM\Types\NoteAttributes;
use EDAM\NoteStore\NoteStoreClient;
My code to add a note still does not work but I'll post it here once I figure it out.
These classes need to be imported:
//import Note class
use EDAM\Types\Note;
use EDAM\Types\NoteAttributes;
use EDAM\NoteStore\NoteStoreClient;
This will define our new note:
$noteAttr = new NoteAttributes();
$noteAttr->sourceURL = "http://www.example.com";
$note = new Note();
$note->guid = null;
$note->title = "My Title";
$note->content = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml.dtd"><en-note>My Content</en-note>';
$note->contentHash = null;
$note->contentLength = null;
$note->created = time()*1000;
$note->updated = time()*1000;
$note->deleted = null;
$note->active = null;
$note->updateSequenceNum = null;
$note->notebookGuid = null;
$note->tagGuids = null;
$note->resources = null;
$note->attributes = $noteAttr;
$note->tagNames = null;
addNote($note);
This function will add a new note:
function addNote($newnote) {
global $noteRet;
if (empty($noteRet)) {
define("noteStoreHost", "sandbox.evernote.com");
define("noteStorePort", "80");
define("noteStoreProto", "https");
define("noteStoreUrl", "edam/note/");
$noteStoreTrans = new THttpClient(noteStoreHost, noteStorePort, noteStoreUrl . $_SESSION['shardId'], noteStoreProto);
$noteStoreProt = new TBinaryProtocol($noteStoreTrans);
$noteStore = new NoteStoreClient($noteStoreProt, $noteStoreProt);
$noteRet = $noteStore->createNote($_SESSION['accessToken'], $newnote);
return $noteRet;
}
}