I have some older code connecting to Outlook through OLE that no longer works running on Win10 where Outlook is set up to connect to Exchange online: It raises an exception with message (Dutch) "De bewerking is afgebroken", probably translated as "The operation was aborted" *, when I try to get properties in two different places indicated by !!!:
const
scxOutlookApp = 'outlook.application';
scxNameSpace = 'MAPI';
type
TDataModuleSyncOutlook = class(TTimeTellDataModule)
private
FOutlookApp,
FNameSpace,
FCalendarFolder: OleVariant;
function TDataModuleSyncOutlook.ConnectToOutlook(AUserSMTP: String = ''): Boolean;
var
lRecipient,
lVar : OleVariant;
lLog,
lLoginSMTP: String;
begin
Result := false;
FWasCreated := False;
try
FOutlookApp := GetActiveOleObject(scxOutlookApp);
Result := True;
except
try
FOutlookApp := CreateOleObject(scxOutlookApp);
FWasCreated := True;
Result := True;
except
on E:Exception do
TSyncLogger.LogError('Inner exception 1: ' + E.Message); // Just some logging
end;
end;
if Result then
begin
try
FNameSpace := FOutlookApp.GetNamespace(scxNameSpace);
// From https://stackoverflow.com/questions/18053110/retrieve-outlook-logged-in-user-smtp-address-after-connecting-through-ole/
lLog := Format('Connected to Outlook; Application.DefaultProfilename: %s, Application.Name: %s, Application.Version: %s, NameSpace.CurrentProfileName: %s, NameSpace.ExchangeMailboxServerName: %s, NameSpace.Type: %s',
[FOutlookApp.DefaultProfileName,
FOutlookApp.Name,
FOutlookApp.Version,
FNameSpace.CurrentProfileName,
FNameSpace.ExchangeMailboxServerName,
FNameSpace.Type]);
TSyncLogger.LogDebug(lLog);
// Output here is:
// Connected to Outlook; Application.DefaultProfilename: Office365, Application.Name: Outlook, Application.Version: 16.0.0.13801, NameSpace.CurrentProfileName: Office365, NameSpace.ExchangeMailboxServerName: https://outlook.office365.com/mapi/emsmdb/?MailboxId=23[snip]1de@timetell.nl, NameSpace.Type: Mapi
lVar := FOutlookApp.Session; // NameSpace object for the current session
// VarIsClear(lVar) is FALSE here, then this goes wrong: !!!1
if not VarIsClear(lVar) then lVar := lVar.CurrentUser; // Recipient object for the currently logged-on user
if not VarIsClear(lVar) then lVar := lVar.AddressEntry; // AddressEntry object for the recipient
if not VarIsClear(lVar) then lVar := lVar.GetExchangeUser; // Returns an ExchangeUser object that represents the AddressEntry
if not VarIsClear(lVar) then lVar := lVar.PrimarySmtpAddress; // String representing the SMTP address for the ExchangeUser
if not VarIsClear(lVar) then
begin
lLoginSMTP := FOutlookApp.Session.CurrentUser.AddressEntry.GetExchangeUser.PrimarySmtpAddress;
TSyncLogger.LogDebug('Primary Exchange SMTP address detected as: ' + lLoginSMTP);
end
else
begin
TSyncLogger.LogError(sErrNoExchangeAccount);
DisConnectFromOutlook;
Exit;
end;
except
on E:Exception do
begin
TSyncLogger.LogError('Inner exception 2: ' + E.Message); // This is where we come after the CurrentUser error
DisConnectFromOutlook;
Exit;
end;
end;
If I comment out the above section playing with the lVar
to avoid the exception, the following code gets executed, but it then shows the same problem when retrieving lRecipient.Address
:
if LowerCase(AUserSMTP) <> Lowercase(lLoginSMTP) then
begin // Open shared calendar if it's a different user
try
lRecipient := FNameSpace.CreateRecipient(AUserSMTP);
if not VarIsClear(lRecipient) then // Also FALSE at this moment !!! 2
begin
lLog := Format('Logging in as different user (%s), created recipient for %s, calling GetSharedDefaultFolder',[AUserSMTP,lRecipient.Address]);
TSyncLogger.LogDebug(lLog);
end
else
OutputDebugString('lRecipient unassigned');
FCalendarFolder := FNameSpace.GetSharedDefaultFolder(lRecipient, olFolderCalendar);
if not VarIsClear(FCalendarFolder) then
begin
lLog := Format('GetSharedDefaultFolder folder path = %s',[FCalendarFolder.FolderPath]);
TSyncLogger.LogDebug(lLog);
end
else
OutputDebugString('FCalendarFolder unassigned');
except
on E:Exception do
begin
Result := false; // This is where we come after the lRecipient.Address error
TSyncLogger.LogError(Format(sErrOpenGedeeldeAgenda,[AUserSMTP]));
end;
end;
end
else // ... otherwise open default calendar folder
begin
FCalendarFolder := FNameSpace.GetDefaultFolder(olFolderCalendar);
TSyncLogger.LogDebug('Opened default calendar folder, folder path = ' + FCalendarFolder.FolderPath);
end;
end; // if Result
if Result then TSyncLogger.LogDebug('Connected to Outlook') else TSyncLogger.LogAlways('Connection to Outlook failed');
end;
? Application.Session.CurrentUser.Name
I get my nameWhat can be going on? Why does accessing these two properties NameSpace.CurrentUser
and Recipient.Address
cause an exception or what can I try to resolve this (e.g. get more error info than "The operation was aborted")?
* It's probably the 0x80004004 Operation aborted error
Looks like you are faced with an Outlook security issue. It can also be a prompt issued by Outlook if you try to access any protected property or method. But in your case that is an exception. You get the security prompts/exceptions because Outlook is configured on the client computer in one of the following ways:
You can create a group policy to prevent security prompts from displaying if any up-to-date antivirus software is installed on the system or just turn these warning off (which is not really recommended).
Read more about that in the Security Behavior of the Outlook Object Model article.
Also you may consider using a low-level code on which Outlook is built and which doesn't give security issues - Extended MAPI. Consider using any third-party wrappers around that API such as Redemption.
Another option would be the Outlook Security Manager which allows suppressing Outlook security issues at runtime on the fly.
Eugene's answer pointed me in the right direction: it is indeed a 'security issue' in the sense that the 3 disabled 'Programmatic access' radio buttons caused this.
After our sysadmin had removed me from the Office 2016 group policy, the first button was suddenly checked (although I still could not change them):
Now the code ran without issues.
The admin also tried to tweak all kinds of Office 2016 settings under Microsoft Outlook 2016/Security/Security Form Settings/Programmatic Security
, but those did did not resolve the issue. Either this specific setting cannot be influenced or there is a bug somewhere when applying the policy.
Relevant links may be:
How to disable Programmatic Access in Group Policy for a user
Change Outlook's Programmatic Access Options
Outlook 2010 programmatic security settings for Simple MAPI cannot be configured by using the Group Policy Object
User contributions licensed under CC BY-SA 3.0