I'm automating Outlook and I need to control who the email appears to be from. The users will have two or more Accounts set up in Outlook and I need to be able to select which account to send the email from. Any ideas?
Needs to be supported on Outlook 2003 and above. I'm using Delphi 2006 to code this, but that doesn't really matter.
A person named Sue Mosher wrote up a pretty summary on this issue in microsoft.public.office.developer.outlook.vba.
In short, it boils down to either of this:
use MailItem.SentOnBehalfOfName, which only works in Exchange enviromnents (I suppose that is the case for you) - when the user has "Send As" permissions for the other Exchange mailbox, this is pretty much the same thing as switching accounts.
use a small hack that involves fiddling with the CommandBars
use Outlook Redemption
(in OL2007, you would have MailItem.SendUsingAccount)
Expanding a bit on the accepted answer, I needed a Delphi implementation of Sue's set_account function. Couldn't find anything on the internet anywhere for this, so here is a Delphi interpretation of Sue's code.
Function SetAccount(TargetAccount:string; var MailItem:OLEVariant):boolean;
var OLI,CBs,CBP,MC:olevariant;
strAccountBtnName:String;
i,t:Integer;
FoundAccount:Boolean;
Const ID_ACCOUNTS = 31224;
begin
FoundAccount:=false;
OLI:=MailItem.GetInspector;
CBs:=OLI.CommandBars;
CBP:=CBs.FindControl(, ID_ACCOUNTS);
t:=1;
while (not FoundAccount) and (t<=CBP.Controls.Count) do begin
MC:=CBP.Controls[t];
i:=Pos(' ',MC.Caption);
if i > 0 Then strAccountBtnName:=Copy(MC.Caption,i+1,Length(MC.Caption)-i)
else strAccountBtnName:=MC.Caption;
if strAccountBtnName = TargetAccount then begin
MC.Execute;
FoundAccount:=true;
end;
inc(t);
end;
Result:=FoundAccount;
end;
Credit to Sue Mosher, thank you, couldn't have done it without you :)
Related
Problem: we are wanting to use SonarJS but much of our old Javascript code uses functions from the Microsoft ASP.Net framework (and the MS AjaxToolkit). As such we have a couple of hundred occurrences of the error "XXX" does not exist. Change its name or declare it so that its usage doesn't result in a "ReferenceError". (where XXX is Sys, Type, $get etc.).
I appreciate that I could suppress these by specifying them all in the sonar.javascript.globals property (as per the Elena Vilchik's answer to this question ) but it feels like what I really want to do is to add my own bespoke entries in sonar.javascript.environments (called msajax and msajaxtoolkit say). Then I could be more precise about when to include / exclude these globals.
So I guess I would like to know whether defining my own environment is supported or if there is a more elegant solutions overall.
Thanks in advance.
You are more than welcome to open pull request for https://github.com/SonarSource/sonar-javascript. Edit "javascript-frontend/src/main/resources/org/sonar/javascript/tree/symbols/globals.json" by adding new group/groups of names.
I am here with a question about scripting Outlook. Well, let me first start with what I'd like to accomplish:
I would like to write a script that does the following with Outlook:
Get all Names (Users) written under File > Info > Account Settings > Delegate Access, including the Permissions...
Get all Data Files written under File > Info > Account Settings > Account Settings > Data Files
Get currently used Signatures under Home > New E-mail > Signature and there the selection under New messages: and Replies/forwards:
Finally, get all Additional Mailboxes under File > Info > Account Settings > Data Files > Settings... > Advanced > Mailboxes
What's my skill level?
I kind of got this task by accident, so not very high concerning the understanding of the Windows/ Office architecture. My background is R/ Matlab, Maple and some Mathematica and recently VBA. I've just started with VBScripting ;)
What do I have so far?
Almost nothing, but I do not ask for much. I don't need a full solution to the problem. Being creative will help me to build the code around your answers, hopefully! So far, I've managed to restore given *.psts, like this:
Set oOutlook = CreateObject("Outlook.Application")
Set oMAPI = oOutlook.GetNameSpace("MAPI")
WScript.Sleep 3000
and then ...
' Restore *.psts
For Each oFile In oFolder.Files
If UCase(oFSO.GetExtensionName(oFile.Name)) = "PST" Then
oMAPI.AddStore sPath & "\" & oFile.Name
WScript.Sleep 500
End If
Next
But let me step back a little. It is very important to know that I am a rookie with this :), but I can build all the code around. Writing from experience, I think that I would be happy with one line of code for every question (if that is possible), like:
???.Delegates.Names.Item(integer)
oMAPI.GetStore ...
???.MailItem.Signature.NewMessage.ToString() ' or whatever
oMAPI.AdditionalMailbox.Item(integer)
The four examples above are pure guessing, but I really couldn't find anything usable for me in the internet. It would be cool if most of the methods would return a string, so that I could log them into a text file.
I am glad about any answer, regardless of the Outlook version you are using. I've searched the Internet for two days and literally came up with nothing much but the short code above. I need some better starting points to proceed. And also, all things happen locally. I don't search for any AD solutions (like creating fancy automated AD signatures ...).
Thank you very much in advance :)
That information is only accessing through the Exchange Web Services (EWS) API.
Use the Namespace.Stores collection
You can only access that information through the file system
Same as 2, but you will need to check the Store.ExchangeStoreType property to be olAdditionalExchangeMailbox (=4).
I'm writing to ask you a question about NSSpeechSynthesizer. Really it works perfect for me, the only things I saw is strange (to me) is that the available voices are all the premium voices.
NSArray* voices;
voices = [NSpeechSynthesizer availableVoices];
When I print all voices in the array I can see, for instance, Silvia and Paolo, but not Silvia Compact and Paolo Compact.
For the italian language, unfortunately, the premium version have many bugs in their way of speaking that the compact voices haven't. So I'd like to be able to select the Compact version... does anyone of you know how can I make them available?
Thank you very much...
You could use availableVoices, and whenever a voice ends in ".premium" try replacing ".premium" with ".compact". That will only work with voices that the user has installed, but that should be no surprise for the user.
You can set the using the identifier (Alice is the compact Italian voice):
let voiceId : String = "com.apple.ttsbundle.Alice-compact"
speechUtterL1 = AVSpeechUtterance(string: "dì qualcosa in italiano")
speechUtter.voice = AVSpeechSynthesisVoice(identifier: voiceId)
place the voice after the text, for I have seen issues when the voice parameter is set before the utterance.
I am trying to use ime (for hiragana input) in a flex 4 spark combo.
On creation complete I am setting the following.
cbx_text.textInput.imeMode = IMEConversionMode.JAPANESE_HIRAGANA;
And to check, tracing the following:
trace(cbx_text.textInput.enableIME); returns true;
trace(cbx_text.textInput.imeMode); returns JAPANESE_HIRAGANA;
However, when I select the text input and start to type some text I am unable to switch to hiragana.
I can set it to work on a textinput component with no problems.
<s:TextInput imeMode="JAPANESE_HIRAGANA"></s:TextInput>
Has anyone had any experience with this?
Any insights much appreciated.
Although I haven't had any experience with IME, I took a quick look at the documentation : http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/system/IME.html
Can it be that it's not enabled application wise? That, maybe what returns true is only valid for the component you are tracing from?
Obvious questions first:
Are you certain the TextInput is a member of cbx_text? I know this seems silly, but it's best to eliminate the obvious first.
Do you have an IME enabled on your computer? For example, do you regularly type in hiragana on your computer and have the appropriate language pack enabled?
Are you sending the IME the string appropriately? IME.setCompositionString() for windows computers?
Does your OS support the use of IMEs? Linux only supports the following methods:
Capabilities.hasIME
IME.enabled <= Can set or return value.
Try tracing hasIME and see if it's installed. Again, we're shotgunning here – trying to track down any possibility of a problem.
When all else fails, go to the source:
http://livedocs.adobe.com/flex/3/html/help.html?content=18_Client_System_Environment_6.html
I need to get the name of the program currently associated with a file extension for the current user. If you right-click on a file and select properties, then what I need is the program name that is to the right of the "Opens with" line.
e.g. For ".xls", I want to be able to get the answer "Microsoft Office Excel", or whatever program the user has as their default program to open .xls files.
I have determined it's not as easy as just going into HKEY_CLASSES_ROOT and picking it out, since it may also be specified in HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER or HKEY_USERS.
Maybe all I need to know is the pecking order used by Windows to determine this and how to get to each of the locations. Of course, a Windows API call to do this would be ideal.
This is a similar question to:
How to get icon and description from file extension using Delphi? but that question only answered how to get the description of the extension and the icon of the associated program. I couldn't find a way to extend that to also get the name of the associated program.
I'm using Delphi 2009 and need a solution that works on Windows XP, Vista and 7.
Thank you all for your answers.
It appears my belief that the name of the executable is not in the Registry after all. And after looking around extensively for a Windows API that will give the name, I could not find one.
I think Mef's answer then is the best. To get the name of the executable from the information included in the program's executable.
Followup: I found David Hefferman's answer to "How do I open a file with the default text editor?" gives an excellent solution for opening one program using the default program for a different extension.
Don't go spelunking in the registry when there are API functions designed to do what you need.
In your case, you want AssocQueryString. You can give it the file-name extension, and it will tell your the program registered to handle that extension (AssocStr_Executable). If you're planning on running that program to open a document, then you'll really want the command string instead of just the executable; AssocQueryString can give you that, too (AssocStr_Command). It can also tell you the document type like what's displayed in Windows Explorer, like "Text Document" or "Zip Archive" (AssocStr_FriendlyDocName).
That API function is a wrapper for the IQueryAssociations interface. If you're looking for programs from many file types, or lots of strings associated with a single type, you may wish to instantiate that interface and re-use it instead of calling the API function over and over.
Delphi comes with a unit ShellApi.pas that is used in the sample code below. The file has to exist.
Here's how to use it:
function MyShellFindExecutable(const aFileName: string): string;
var
Buffer: array[0..WINDOWS.MAX_PATH] of Char;
begin
Result := '';
FillChar(Buffer, SizeOf(Buffer), #0);
if (SHELLAPI.FindExecutable(PChar(aFileName), nil, Buffer) > 32) then
Result := Buffer;
end;
Step 1
Get the executable which is assigned to a file extension, for instance with the following function:
uses Registry, Windows, SysUtils;
function GetAssociation(const DocFileName: string): string;
var
FileClass: string;
Reg: TRegistry;
begin
Result := '';
Reg := TRegistry.Create(KEY_EXECUTE);
Reg.RootKey := HKEY_CLASSES_ROOT;
FileClass := '';
if Reg.OpenKeyReadOnly(ExtractFileExt(DocFileName)) then
begin
FileClass := Reg.ReadString('');
Reg.CloseKey;
end;
if FileClass <> '' then begin
if Reg.OpenKeyReadOnly(FileClass + '\Shell\Open\Command') then
begin
Result := Reg.ReadString('');
Reg.CloseKey;
end;
end;
Reg.Free;
end;
(See here, or marc_s' anwser to this question :-)
Step 2
Now you can read out the name of the program from the version information of this executable! The easiest way is using the TVersionInfo class you can find via Google, for instance here.
var VersionInfo: TVersionInfo;
VersionInfo := TVersionInfo.Create('PathToExe\name.exe');
s := VersionInfo.KeyValue['Description'];
However, you have to be aware that some programs use the description key therefore (like RAD Studio itself or MS Excel), while others use the product name key...
I think that you need to combine Mef's and Rob Kennedy's answers.
Take Rob Kennedy's answer and take step 2 from Mef's answer. Reading registry directly isn't good thing to do, so you should throw away his part 1.
But I'm not looking for the friendly name of the file type.
AssocQueryString returns not only friendly name for file type (ASSOCSTR_FRIENDLYDOCNAME), but also it can return the name of executable to open file (ASSOCSTR_EXECUTABLE) - that is what you need.
Even more than that: I'm not sure, but may be ASSOCSTR_FRIENDLYAPPNAME will match your needs. In that case, you may use only Rob Kennedy's answer.
The problem with reading registry directly is that it may return wrong info. That's because you read system settings - that is what application registered. But user may override this. For example, he may right click on .xls and select "Open with..." -> "Other app." -> "OpenOffice" -> "Use this app always". Registration info for .xls type will not be altered (user preferences are saved in separate place, so apps can't mess with them), so your code (which reads registry directly) will continue to produce "MS Excel", even though when user double-clicks on file - OpenOffice will be launched.
How about this article here: Determining the associated application
In the concrete case of Excel, you will find the .xls extension under HKEY_CLASSES_ROOT - the default value of that entry is Excel.Sheet.8.
When you go search for Excel.Sheet.8 again in HKEY_CLASSES_ROOT, you'll find an entry with a default value of Microsoft Office Excel 97-2003 Worksheet - that's probably as good as it gets.
If the user says "use this app always" for .xls-files the info ist stored in
HK_CU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.xls
The key has an entry "Application" containing the Application name (e.g. "soffice.exe"). It's correlated to an Applcication key in HK_CR, e.g. HK_CR\Applications\soffice.exe\