I have a requirement where I need to get the data from a folder called "Public folder" which contains global information like book rooms for discussions / meetings etc and this folder is in server and I am able to access this through outlook. How do I access the same programmatically, C# ?
If you're solely on the client use COM via Outlook.
Or use WebDav against Exchange 2003, or check out the new webservices for Exchange 2007.
It all depends where your code will execute and/or the version of Exchange running before deciding the way to go.
You just have to make sure the application is running as a user with permissions to Exchange.
I know you said C#, but if you're willing to experiment a bit, here's a Perl solution I've used successfully in the past:
http://rasterweb.net/raster/code/src/vcalxical_pl.txt
You need IMAP enabled on the Exchange server and this will only work with 2003. In Exchange 2007 calendar information is no longer stored in folders, so this will break. You also said you just needed to get the data, not modify it.
This solution will work with Exchange 2007:
http://blogs.msdn.com/exchangedev/archive/2009/02/05/quick-and-dirty-unix-shell-scripting-with-ews.aspx
Ksempac, look here for a way forward:
http://msdn.microsoft.com/en-us/library/ms268893(VS.80).aspx
The Microsoft.Office.Interop.Outlook namespace is horrible to work with, but with a bit of Googling you can do some cool stuff.
In the past we used Outlook Redemption. It works through extended MAPI so it has more features then Outlook provides with Microsoft.Office.Interop.Outlook
There is also another useful tool - Outlook Spy that allow you to discover Outlook object model in run time.
I modified the code to loop through sub folders, sorry for the delayed response
using System;
using OutLook = Microsoft.Office.Interop.Outlook;
class OutlookFolders
{
static void Main(string[] args)
{
OutLook.Application outlookObj = new OutLook.Application();
GetSubFolders(outlookObj.Session.Folders);
}
private static void GetSubFolders(OutLook.Folders folders)
{
foreach (OutLook.MAPIFolder f in folders)
{
Console.WriteLine(f.Name);
GetSubFolders(f.Folders);
}
}
}
Related
I'm warning you, that yhis question will seems to be very strange for a lot of people:) But I have to post it because my project manager is teeling me that a technical solution exist, even if for me it doesn't.
What we have:
A Windows 7 Console Application with no UI, with our C# application running and no Office and Interop on it
a Windows 2012 server, with Ms Office 2010 + Interop installed on it (also with IIS and .NET of course)
What my PM want (and I told him it is not possible) :
From my C# client application
Automate "Ms office" installed on the server
Automate means "Save" or "print" a doc file to a network printer.
Of course the Ms office process had to run on the server
This kind of solution of "remote Ms Office automation is possible" seems to be impossible for me. But maybe I am wrong, it can be possiblbe using DCOM, WCF, or something else?
Anyone can confirm I am right please ;)
As you already learned from the comments, automating the desktop version of any of the Office applications is bad for several reasons. The details can be found in the Knowledge base article KB257757 Considerations for server-side Automation of Office. The main take away from that article is:
Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.
But as you are still insisting, consider the following example as a very simple, naive, not to be used near production proof-of-concept that enables you to quickly run into all problems mentioned in the KB article.
In a fresh solution create a WCF Service application and a Console Application. In the WCF application add the following interface:
[ServiceContract]
public interface IPrintService
{
[OperationContract]
string Print(Stream wordDoc);
}
and have a service implement that. Make sure to add a reference to Microsoft.Office.Interop.Word that you can find in the COM tab of the Add Reference dialog.
public class PrintService : IPrintService
{
public string Print(Stream wordDocStream)
{
// copy our stream to a local file
var tempFile = Path.GetTempFileName();
using(var file = File.Create(tempFile))
{
wordDocStream.CopyTo(file);
}
// start word
var wordApp = new Microsoft.Office.Interop.Word.Application();
// setup printer
wordApp.ActivePrinter = "Canon LBP3010/LBP3018/LBP3050";
// open, collect data, print and close
var doc = wordApp.Documents.Open(tempFile);
doc.PrintOut();
var res = doc.Words.Count;
doc.Close(false);
// quit word
wordApp.Quit(false);
// delete temp file
File.Delete(tempFile);
return String.Format("{0} words", res);
}
}
You can see here a barebone solution to print a document that is sent as a stream to the Service. The service copies the stream to a file, starts Word, Opens the file, prints the document, get some data from the document and tears down and cleans up hen finished.
The client is straight forward:
using(var client = new PrintService.PrintServiceClient())
{
using(var file = File.Open(#"small.docx", FileMode.Open))
{
var response = client.Print(file);
Console.WriteLine(response);
}
}
This is technically all there is that is needed to print a Word document from a service. This runs without much problems on the dev server. If you run this on IIS you'll probably have to make sure that the account used as an identity in the AppPool is a "user" that can start Word, is allowed to access the printers etc. I already ran into one known issue: I used the XPS Print driver which caused a dialog to popup. That is something you can't have on a server and there is no real way to prevent or detect that.
Remember that this service interface only allows for a stream to be sent. If you want to add extra data you'll have to use a message contract as is explained on msdn in Large Data and Streaming. Your contract would have to look like this in that case:
[MessageContract]
public class UploadStreamMessage
{
[MessageHeader]
public string appRef;
[MessageBodyMember]
public Stream data;
}
If you run all this, (stress)test, consider deployment and install I'm sure you'll convince anyone that this isn't a good idea.
I am creating a button in asp.net c# that when clicked will open up Outlook window.
I am referencing to the Microsoft.Office.Interop.Outlook dll, and using this in using statement:
using Outlook = Microsoft.Office.Interop.Outlook;
This the code.
private void CreateMailItem()
{
try
{
var outlookApp = new Outlook.Application();
var mailItem = (Outlook.MailItem)outlookApp.CreateItem(Outlook.OlItemType.olMailItem);
//var mailItem = (Outlook.MailItem)
// Application.CreateItem(Outlook.OlItemType.olMailItem);
mailItem.Subject = "This is the subject";
mailItem.To = "someone#example.com";
mailItem.Body = "This is the message.";
mailItem.Importance = Outlook.OlImportance.olImportanceLow;
mailItem.Display(false);
}
catch (Exception)
{
throw;
}
}
I get error on the very first line, var outlookApp = new Outlook.Application();
The exception says:
{"Retrieving the COM class factory for component with CLSID {0006F03A-0000-0000-C000-000000000046} failed due to the following error: 80070005 Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))."}
The exception you've posted is thrown when a referenced dll or depencies of this dll are not correctly installed.
In this case, it seems outlook or office is not with the correct version which you referenced, on your test machine?
Can't post this as comment.
I would like to know why you prefer the use of Outlook Interop?
I am using the mailto:// protocol if I wanted my program to send email on the user's current email client, though I use this on WinForms.
like http://www.rapidtables.com/web/html/mailto.htm
Outlook, just like any Office app, cannot be used from a service (such as IIS). Even if you did make it work, the new message window will be displayed on the server where the user will not see it anyway.
You can try to run a client-side JavaScritp code, but then you'd be limited IE only, Outlook would need to be locally installed, and your site must be trusted to be able to create COM objects in a script.
Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.
If you are building a solution that runs in a server-side context, you should try to use components that have been made safe for unattended execution. Or, you should try to find alternatives that allow at least part of the code to run client-side. If you use an Office application from a server-side solution, the application will lack many of the necessary capabilities to run successfully. Additionally, you will be taking risks with the stability of your overall solution. Read more about that in the Considerations for server-side Automation of Office article.
Consider using System.Net.Mail namespace for creating and sending emails in ASP.NET.
I am trying to send email from .net windows application using Microsoft.Office.Interop.Outlook. The mail is in html format and has an image embedded to it. Getting the following error when trying to attach the image,
"Cannot create file: XXX.jpg. Right-click the folder you want to create the file in, and then click Properties on the shortcut menu to check your permissions for the folder."
I dont have any issues with folder access. I am running the app on 64 bit computer with 32 bit outlook on it. When i dont embed image, i dont get any errors and it works fine.
string body = string.Empty;
using(StreamReader reader = new StreamReader(Environment.CurrentDirectory + #"/Mail Templates/XXX.txt"))
{
body = reader.ReadToEnd();
}
Outlook.Application oApp = new Outlook.Application();
Outlook._MailItem mailItem = (Outlook._MailItem)oApp.CreateItem(Outlook.OlItemType.olMailItem);
mailItem.To = "XXX";
string filename = Environment.CurrentDirectory + #"/Mail Templates/XXX.jpg";
mailItem.Attachments.Add(filename, (int)Outlook.OlAttachmentType.olEmbeddeditem, 1);
mailItem.HTMLbody = "true"
mailItem.Display(true);
Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.
If you are building a solution that runs in a server-side context, you should try to use components that have been made safe for unattended execution. Or, you should try to find alternatives that allow at least part of the code to run client-side. If you use an Office application from a server-side solution, the application will lack many of the necessary capabilities to run successfully. Additionally, you will be taking risks with the stability of your overall solution.
You can read more about that in the Considerations for server-side Automation of Office article.
You may consider using the EWS (Exchange Web Services) or BCL (Base Class Libraries from the .Net framework). See EWS Managed API, EWS, and web services in Exchange for more information.
Does anybody know how to programmatically enable/disable the actual state of the out-of-office auto-responder in Outlook 2007?
Already searched the object browser in VS 2008 and found the enumeration Microsoft.Office.Interop.Outlook.OlBusyStatus but i didn't find any class or anything else using this.
Any idea is appreciated, thanks and regards
UPDATE: Updated the code below using sample code adapted from this blog post which will work better in a wider variety of Outlook installations (e.g. ones using both Exchange and PST or accessing multiple Exchange mailboxes).
Here's code which worked for me on Outlook 2007, to set the OOF status from an external (to Outlook) EXE:
Microsoft.Office.Interop.Outlook.Application app = new Microsoft.Office.Interop.Outlook.ApplicationClass();
Microsoft.Office.Interop.Outlook.NameSpace ns = app.Session;
foreach (Microsoft.Office.Interop.Outlook.Store store in ns.Stores)
{
if (store.ExchangeStoreType == Microsoft.Office.Interop.Outlook.OlExchangeStoreType.olPrimaryExchangeMailbox)
{
store.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x661D000B", true); // false to turn off OOF
break;
}
}
Make sure you're not running that code as Administrator and outlook as non-Administrator-- otherwise you may get a security-related error on Vista.
Note that it will pop up security dialogs inside Outlook to ensure the user is OK with you accessing the Outlook object model. This is normal when outlook object model is accessed from an external EXE.
If, however, you're accessing the object model from an add-in, the code above isn't fully correct: instead of creating a new Outlook.Application object via the constructor, you you need to get a reference to the trusted Outlook.Application object from inside your add-in, like this:
Microsoft.Office.Interop.Outlook.NameSpace ns = this.Application.Session;
foreach (Microsoft.Office.Interop.Outlook.Store store in ns.Stores)
{
if (store.ExchangeStoreType == Microsoft.Office.Interop.Outlook.OlExchangeStoreType.olPrimaryExchangeMailbox)
{
store.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x661D000B", true); // false to turn off OOF
break;
}
}
BTW, there's a good MSDN article on security for add-ins, which may be useful if you run into security dialogs or errors.
I have a requirement of reading subject, sender address and message body of new message in my Outlook inbox from a C# program. But I am getting security alert 'A Program is trying to access e-mail addresses you have stored in Outlook. Do you want to allow this'.
By some googling I found few third party COM libraries to avoid this. But I am looking for a solution which don't require any third party COM library.
I ran into same issue while accessing sender email address for outlook mail item. To avoid 'security alert' do not create new Application object, instead use Globals.ThisAddIn.Application to create new mailitem.
string GetSenderEmail(Outlook.MailItem item)
{
string emailAddress = "";
if (item.SenderEmailType == "EX")
{
Outlook.MailItem tempItem = (Outlook.MailItem)Globals.ThisAddIn.Application.CreateItem(Outlook.OlItemType.olMailItem);
tempItem.To = item.SenderEmailAddress;
emailAddress = tempItem.Recipients[1].AddressEntry.GetExchangeUser().PrimarySmtpAddress.Trim();
}
else
{
emailAddress = item.SenderEmailAddress.Trim();
}
return emailAddress;
}
Sorry, I have had that annoying issue in both Outlook 2003 and Outlook 2007 add-ins, and the only solution that worked was to purchase a Redemption license. In Outlook 2007 that pesky popup should only show up if your firewall is down or your anti-virus software is outdated as far as I recall.
Try this
Tools-->Macro-->Security-->Programmatic Access
Then choose Never warn me about suspicious activity.
"But I am looking for a solution which don't require any third party COM library."
You won't find it. Kasper already pointed out the only solution that I know of. Redemption has been the only thing that has kept the Outlook plug-ins and code to work. I have done commercial Outlook add-ins for Franklin Covey. We explored a lot things, but Redemption was the only thing that got us over this hurdle.
If your application is not a Outlook plug in you can look at MAPI to read data from the inbox
We use Advanced Security for Outlook from Mapilab for this. It is free, also for commercial use, and still keeps Outlook safe (by only allowing access from approved applications). Just apposed to previously mentioned solutions that cost either money, or may compromise security.
You can disable the security pop-up using Outlook's Trust Center.
Check here.