I have an Outlook Addin that perform really big scanning and often cause Outlook crash. I made a lot of searches and find out I should use Redemption instead.
I have download Redemption 5.17, I am trying to make a search folder in Outlook to start with. I follow the doc here
set Session = CreateObject("Redemption.RDOSession")
Session.Logon
set Searches = Session.Stores.DefaultStore.Searches
for each Search in Searches
Debug.Print "-------------"
Debug.Print Search.Name
Debug.Print Search.SearchCriteria.AsSQL
next
I code this with VS2017 C#. I could not find the properties Searches on Session.Stores.DefaultStore
Anyone could help me on how to make a search folder that copy an existing
SearchCriteria from another search folder.
Firstly, in an addin there is no reason to use RDOSession.Logon - you already have an Outlook session: set RDOSession.MAPIOBJECT property to Application.Session.MAPIOBJECT from OOM.
Secondly, Searches property is exposed by the RDOStore2 interface (see http://www.dimastr.com/redemption/rdosearches.htm) - just cast your RDOStore object to RDOStore2.
Related
I am using late binding to connect to MS Outlook and to open and extract info from outlook emails using the MailItemobject.
I am trying to save attachments to file. This is fairly straightforward in most instances using the Attachment object and its SaveAsFile method.
However, it does not work where the Attachment Type is olOLE. I believe this only relates to documents embedded in emails created in RTF format (hopefully few and far between nowadays).
Via the Attachment object it is possible to access MAPI properties not exposed by the object model using its PropertyAccessor.
The relevant MAPI property for OLE objects is PR_ATTACH_DATA_OBJ, which can be accessed using the PropertyInspector as in the following example:
Function SaveOLEAttachmentToFile(Attachment:Variant; fn:String): boolean;
var
OPA, PropName : Variant;
begin
Result := false;
OPA := Attachment.PropertyAccessor;
PropName := 'http://schemas.microsoft.com/mapi/proptag/0x3701000D '; //PR_ATTACH_DATA_OBJ
?????? := OPA.GetProperty(PropName);
end;
I am stuck at this point as I can't know work out what Delphi type to save the data to and I am not even sure this is possible having read the MS documentation (Click here). PR_ATTACH_DATA_OBJ returns a PT_OBJECT. I am hoping that this object contains the raw data which (if I could work out how to access it in Delphi) can be simply saved to a file. However, the documentation suggests it may not be that simple and it's possible I may have to work with Extended MAPI. I have spent a few hours researching the latter with no concrete result other than a headache. I appreciate I could use Redemption, but I don't want to use a third party tool for something which is fairly minor in the round.
If anyone can advise as to a data type to hold the PT_OBJECT from which it can be simply saved to file that would be my route one.
Failing that, if I need to dig deeper into MAPI, I would be grateful if anyone could clarify/amplify my research so far. I have the following steps:
Initialize MAPI.
Get an IMAPIPROP interface. I think I should be getting the interface from my Attachment object and the following seems to work (ie compiles and executes without problems): MAPIPROP := IUnknown(Attachment.MAPIObject) as IMAPIPROP. Failing that, I would have to cast the parent MailItem to IMAPIPROP interface and work my way down to the attachment via GetAttachmentTable.
Load the attachment data into an IStream: if Succeeded(MAPIPROP.OpenProperty(PR_ATTACH_DATA_OBJ, IStream, STGM_READ, 0, IUnknown(SourceStream)) then
Extract the data from the IStream and save to file
I have failed to get as far as point 3 as something would seem to be wrong with my initial casting to IMAPIPROP albeit it does not cause any violations. I have tried reading a single property from the MailItem cast to IMAPIPROP using the following code:
if (Succeeded(HrGetOneProp(MAPIPROP, PR_SUBJECT, Prop))) then
And I get an access violation. Likewise if I cast the Attachment object and query an attachment property I also get a violation. I don't think the problem lies with the call to HrGetOneProp, I think it has to be the casting to IMAPIPROP.
Any pointers re the above would be greatly appreciated.
Not quite an answer to my question, but I have thought of an alternative solution. What I am ultimately trying to do is convert a msg email as a pdf. To do that I need to extract the body and then somehow insert the embedded images. With an html email this seemed pretty straightforward ((1) extract all the attachments to a folder, (2) parse the html body for references to SRC IMG and update the location of the image to reference the saved files and (3) save the edited html body to file and open it in Word and save as PDF).
RTF emails cannot be handled in this way. However, for my specific problem there is a much easier way to achieve what I need for all email types using Outtlook and Word.
Use the MailItem.SaveAs function and save the email in either html format or mthml. The former format will save all embedded images to a sub-folder (in png and jpg formats) should you need them for any other reason. once you have your html file, open it with Word and save to PDF.
If Office is not a solution then you need to figure Istorage or use one of the Extended MAPI solutions such as Redemption.
For Delphi users there are also the following commercial offerings that I have come across in my recent travels:
IMIBO
Scalabium
Rapware
I did come across one more solution which I can't find at the moment! Will post an update if I do.
PropertyAccessor (and the Outlook Object Model in general) does not handle PT_OBJECT type properties.
What you need to do is open the PR_ATTACH_DATA_OBJ property as IStorage, and then extract the data from there (it depends on the actual type of the attachment). You can see the data in the streams in OutlookSpy (I am its author) - select the message, click IMessage button on the OutlookSpy rubbon, go to the GetAttachmentTable tab, double click on the attachment to open it, select the PR_ATTACH_DATA_OBJ property, right click, select IMAPIProp::OpenProperty, then IStorage.
If using Redemption (I am also its author) is an option, its version of RDOAttachment.SaveAsFile handles OLE attachment for the most popular formats (Word, Excel, bitmap, Power Point, Adobe PDF, etc.) - create an instance of the RDOSession object (using either CrealeOleObject or RedemptionLoader) and use RDOSession.GetRDOObjectFromOutlookObject method (pass either Attachment or MailItem object) to get back RDOMail or RDOAttachment object respectively.
GET mailFolders/archivemsgfolderroot
I use distinguish name to get this in-place mailbox folder
and the response is:
...
"displayName": "Top of Information Store",
...
However, this is not the custom name I modified on office365.
Is it possible to get that custom name?
I also try to get distinguish folder in EWS managed API
<t:DistinguishedFolderId Id="archivemsgfolderroot" />
It returns the same name
...
<t:DisplayName>Top of Information Store</t:DisplayName>
...
--
Add two image ref.
how I add it
how it looks like at outlook
thanks for help
I see that a user can set a property, "ArchiveName", to give their archive mailbox a custom name. In powershell, this would be using a Set-Mailbox cmdlet.
https://learn.microsoft.com/en-us/powershell/module/exchange/mailboxes/set-mailbox?view=exchange-ps
That doc states that it applies to Outlook and OWA and, after a quick look, I can't see a way to get that property other than using Get-Mailbox which is not ideal. So as best I can tell it's not exposed through EWS or REST and thus probably isn't available through Microsoft Graph.
I would encourage you to file a suggestion: https://officespdev.uservoice.com/forums/224641-feature-requests-and-feedback/category/101632-microsoft-graph-o365-rest-apis
You can try the following endpoint
https://graph.microsoft.com/v1.0/me/mailFolders/archivemsgfolderroot/childFolders/AAMkADQ5OWMzMGEwLTg4ZjktNDk1Ny05NzFmLWRhZjg4ODU0YzUwYwAuAAAAAACtqDzk9UzLSpZsdesjndr1AQBNzq1HG8BvRYqBQbPeZSPaAAGdwZCCAAA=
(Replace the id to yours):https://graph.microsoft.com/v1.0/me/mailFolders/archivemsgfolderroot/childFolders/id
I guess it's a simple question, but i still couldn't figure out how can i change the PDATA1/MiscData(0) property of an element via Add-In (and not by SQL Update). The problem is that the documentation says the MiscData is read-only.
Basically i am trying to make a hyper-link on a diagram with the help of an Add-In.
I create a simple Text typed EA.Element, then an EA.DiagramObject, connect them via ElementID and i need this Text typed object to point to an exact diagram.
What i know is that a hyper-link is a Text typed object with PDATA1 filled in with the wanted diagram's ID. The created element's Notes is already filled with a valid hyperlink's value like: packageName : diagramName.
I'm interested in any other ways to make a working hyper-link with the help of an Add-In.
Thanks in advance for the answer!
Tamas
You need to call
Repository.Execute("UPDATE t_object set PDATA1 ...")
Execute is an undocumented but ever since working last resort. Nobody knows why MiscData is r/o.
In oder to make the changes visible on the diagram you need to call
Repository.ReloadDiagram (diagram.DiagramID)
Since EA will eventually pop-up a save-window for modified diagrams you should eventually call
Repository.SaveDiagram (diagram.DiagramID)
prior to the reload.
Important note: You need to remember that the Execute bypasses the API. If you have diagram changes and call Execute on diagram objects they need to be saved before. EA only updates all changed diagram objects in the database when the whole diagram is saved (manually or via SaveDiagram).
I'm trying to set the Visitor ID in Adobe Analytics through DTM.
Above the s_code I have:
var visitor = new Visitor("xxxx")
visitor.trackingServer = "xxx.xx.xx.omtrdc.net"
I've created a data element where the legacy code used to call the
Visitor.getInstance("xxxx");
and set the Visitor ID to %Visitor ID%
That's not working however, and my visitor ID is always just set to %Visitor ID% and obviously not reading any values. I'd really appreciate any input that someone can give me.
Thanks,
Mike
The Visitor ID pops s.visitorID and is in general related to visitor id, but is not the same as s.visitor which is what gets popped for the VisitorAPI integration. DTM does not currently have a built-in field for the s.visitor variable, so you will have to set it yourself within the config, either in the Library Management code editor (assuming you are opting to c/p the core lib and not the "Managed by Adobe" option) or else in the Custom Page Code section.
Since you are popping it in a data layer first, you can reference the data layer like this:
s.visitor = _satellite.getVar('Visitor ID');
NOTE: A separate potential issue you may have is with whether or not the Visitor object is available for your data element. Since data elements are the first thing to be evaluated by DTM, you will need to ensure that the VisitorAPI.js library is output before your top page DTM script include.
If this is a problem for you, or if you are wanting to host VisitorAPI.js within DTM, then you may need to adjust where you are popping that stuff. For example, place the VisitorAPI core code above the custom code as the first stuff within the data element, before:
var visitor = new Visitor("xxxx") visitor.trackingServer = "xxx.xx.xx.omtrdc.net
Or, don't use the data element at all. Instead, put the VisitorAPI code within the Adobe Analytics custom code or core lib section and pop all that stuff (aboove the s.visitor assignment). Or a number of other methods; point is, VisitorAPI stuff must be loaded before the data element can make use of it, same as it must be loaded before Adobe Analytics can make use of it.
So DTM is changing pretty fast and furious right now. They have a "Marketing Cloud Service ID" that works well. Before I used that, however, I did find a way to fix the code. Crayon Violent was right, as usual, that the problem was that the script wasn't available yet. I fixed this by putting the following code in between the VisitorAPI.js and the AppMeasurement stuff in the DTM managed library.
var aA = new AppMeasurement();
aA.visitorNamespace="companyname";
aA.visitor = Visitor.getInstance("companyname");
In addition, there were also some issues using my localhost for testing while trying to see if I had this correct or not. If you are having issues and think you have it correct, it may be worthwhile to elevate it to a different environment.
It seems that using the DocumentQuery where using updatedMin seems to to not be working correctly. This query does find new files and folders that were created since the "when" but fails to return files that were modified, moved, trashed, or anything else since the when.
DocumentQuery myQuery = new DocumentQuery(new URL("https://docs.google.com/feeds/default/private/full/"));
myQuery.setUpdatedMin(when);
DocumentListFeed entries = getDocsService().getFeed(myQuery, DocumentListFeed.class);
I realize that the API might be changing with the upcoming Google Drive, has something changed in the interim?
To retrieve documents that have been edited since a specific date, use the edited-min query parameter.
From a DocumentQuery instance, you can use the addCustomParameter to set such a value.
query.addCustomParameter(
new Query.CustomParameter("edited-min", "<DATE_IN_RFC_3339_FORMAT>");