I'm working on a VSTO project for Outlook. Very simple application with an icon on the ribbon. When user clicks on it, the selected email will be sent to the manager. It is working with the following code. But I want to add the sender as CC in the email. So whenever user clicks on it, the selected email will be sent to the manager and the user will be CC'd on it. So user will get a copy too. How can I CC the sender?
here is the code:
public partial class Ribbon1
{
private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
{
}
private void button1_Click(object sender, RibbonControlEventArgs e)
{
Outlook.Application application = new Outlook.Application();
Outlook.NameSpace ns = application.GetNamespace("MAPI");
try
{
//get selected mail item
Object selectedObject = application.ActiveExplorer().Selection[1];
Outlook.MailItem selectedMail = (Outlook.MailItem)selectedObject;
//create message
Outlook.MailItem newMail = application.CreateItem(Outlook.OlItemType.olMailItem) as Outlook.MailItem;
newMail.To = "email#gmail.com";
newMail.CC = Outlook.Account;
newMail.Subject = "Subject Here";
newMail.Attachments.Add(selectedMail, Microsoft.Office.Interop.Outlook.OlAttachmentType.olEmbeddeditem);
newMail.Send();
selectedMail.Delete();
System.Windows.Forms.MessageBox.Show("Message has been sent! You have been CC'd.");
}
catch
{
System.Windows.Forms.MessageBox.Show("You must select a message to report.");
}
}
}
}
First of all, I've noticed the following line of code in the event handler:
Outlook.Application application = new Outlook.Application();
There is no need to create a new Outlook Application instance in the ribbon event handler if you develop VSTO based add-in for Outlook. Instead, you need to use the ThisAddIn.Application property. You can start writing your VSTO Add-in code in the ThisAddIn class. Visual Studio automatically generates this class in the ThisAddIn.vb (in Visual Basic) or ThisAddIn.cs (in C#) code file in your VSTO Add-in project. The Visual Studio Tools for Office runtime automatically instantiates this class for you when the Microsoft Office application loads your VSTO Add-in. To access the object model of the host application, use the Application field of the ThisAddIn class. This field returns an object that represents the current instance of the host application. See Program VSTO Add-ins for more information.
Use the Recipients.Add method to add new recipients to the email. For example, a raw sketch:
var recipient = Item.Recipients.Add(ThisAddIn.Application.GetNameSpace("MAPI").CurrentUser.Address);
recipient.Type = OlMailRecipientType.olCC;
Related
Looking a bit of advise or direction in regards to VSTO Ribbons with Outlook in C#.
So far I’ve built an Outlook 2010 Ribbon (using TabMail), this Ribbon opens a WinForms window which allows my users to select contacts from a Custom Built Address Book from a SQL database, via a DataGridView.
The users basically select from a datagridview who they want to email, which then gets added to a toLine list.
Application app = new Microsoft.Office.Interop.Outlook.Application();
Mail item item = app.CreateItem((OlItemType.olMailItem));
item.To = toLine;
Item.Display();
This.close();
The downside of using this approach is the user has to build their To List before they actually compose their email.
I’m now trying to make use of TabMailNewMessage. This should allow the user to compose their email, then click the Ribbon icon within the new message and add to their To List from there.
I’ve got the icon showing okay in the TabMailNewMessage, and I’ve got it to open a 2nd Win Form [currently as a test].
I’m a little unsure how to add to the To List of an already open existing mailItem.
At present all I have on the 2nd Win Form is a button, can someone explain how I can click that button and simply add someone to the To List [of this already composed email]. (I don’t have any code behind the button click as I’m not sure what to do)
I also need to make sure that it doesn’t send the email, but simply adds the user to the To List.
Currently using Office 2010, and VS 2013 (with C#).
Hopefully I’m making some sense here.
Thanks
EDIT:
Not sure if its a simple as
Application app = Globals.ThisAddIn.Application;
MailItem mi = (Outlook.MailItem)app.ActiveInspector().CurrentItem;
Mi.Recipients.Add(“joe#email.com”);
This.Close();
The MailItem.Recipients.Add method allows creating a new recipient in the Recipients collection. The name of the recipient can be a string representing the display name, the alias, or the full SMTP email address of the recipient.
using System.Runtime.InteropServices;
// ...
private bool AddRecipients(Outlook.MailItem mail)
{
bool retValue = false;
Outlook.Recipients recipients = null;
Outlook.Recipient recipientTo = null;
Outlook.Recipient recipientCC = null;
Outlook.Recipient recipientBCC = null;
try
{
recipients = mail.Recipients;
// first, we remove all the recipients of the e-mail
while(recipients.Count != 0)
{
recipients.Remove(1);
}
// now we add new recipietns to the e-mail
recipientTo = recipients.Add("Eugene Astafiev");
recipientTo.Type = (int)Outlook.OlMailRecipientType.olTo;
recipientCC = recipients.Add("Somebody");
recipientCC.Type = (int)Outlook.OlMailRecipientType.olCC;
recipientBCC = recipients.Add("eugene.astafiev#somedomain.com");
recipientBCC.Type = (int)Outlook.OlMailRecipientType.olBCC;
retValue = recipients.ResolveAll();
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
finally
{
if (recipientBCC != null) Marshal.ReleaseComObject(recipientBCC);
if (recipientCC != null) Marshal.ReleaseComObject(recipientCC);
if (recipientTo != null) Marshal.ReleaseComObject(recipientTo);
if (recipients != null) Marshal.ReleaseComObject(recipients);
}
return retValue;
}
You may find the following articles helpful:
How To: Fill TO,CC and BCC fields in Outlook programmatically
How To: Create and send an Outlook message programmatically
Also, I'd suggest developing an Outlook form region which can be displayed on the same window instead of using a standalone window, see Create Outlook form regions for more information.
Yes, it is as simple as using Application.ActiveInspector.CurrentItem. But you can do better than that - your ribbon button event handler takes IRibbonControl object as a parameter. Cast the IRibbonControl.Context property to Inspector or Explorer (depending on where the button is hosted).
Also keep in mind that in a COM addin there is no reason to create a new instance of the Outlook.Application object (it will be crippled with the security prompts anyway) - use Globals.ThisAddIn.Application
I have a problem with development of a Office 365 Outlook Addin (Desktop).
I need to modify certain properties on a MailItem opened with a custom form ( Form designed in Outlook, exported as OFS file and imported in to Visual Studio AddIn project) but the call of method 'Save' on MailItem object
doesn't working, "Saved" property remain to "false" and when i close the inspector, Outlook prompt to save current item. No exception or error message raised on 'Save' call.
But if i try to call 'Save' to the same MailItem in the AddIn body, the message is saved.
I tried to write a simple test "addin" and i obtained the same result, but i can't understand this behaviour.
NB: with previous version of Outlook i haven't this issue.
Any idea?
Thanks so much!
Currently using VS2017, C#, .NET Framework 4.5, Interop library version 15.0
// ADD-IN BODY
private Outlook.Inspectors inspectors;
public static MailItem CurrentMailItem;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
inspectors = this.Application.Inspectors;
inspectors.NewInspector += Inspectors_NewInspector;
}
private void Inspectors_NewInspector(Inspector Inspector)
{
if (Inspector.CurrentItem is MailItem)
{
MailItem item = (MailItem)Inspector.CurrentItem;
item.MessageClass = "IPM.Note.MyReader";
item.Save();
bool saved = item.Saved;
Marshal.ReleaseComObject(item);
item = null;
}
}
// CUSTOM FORM:
private void FormRegion2_FormRegionShowing(object sender, System.EventArgs e)
{
// from this.OutlookItem
MailItem item = this.OutlookItem as MailItem;
item.Save();
bool saved = item.Saved; // <== SAVED=FALSE!
// from global variable (static)
ThisAddin.CurrentMailItem.Save();
saved = ThisAddin.CurrentMailItem.Saved; // <=== SAVED=FALSE!!!!
}
It seems you are using wrong event NewInspector to modify the message class. Have a look at this thread
I think it's a problem with the specific custom form that i've created, or a compatibility problem with Outlook 2016 (the same form working with Outlook 2013)
Steps to the resolution:
Create a new form for reader inspector with Outlook 20016.
Import new Form to Visual Studio 2017 project (there are some problem on import: it's necessary to add some registry key to specify Office installation path)
([see]https://social.msdn.microsoft.com/Forums/vstudio/en-US/3688eec8-2215-482c-ba5f-73f516ad26b8/unable-to-import-outlook-2016-form-region-ofs-into-visual-studio-2015-with-error-the?forum=vsto)
The new form is working and now i can modify and save mail item.
It's not the definitive solution, because now i must recreate a form with Outlook 2016 and i'm not sure that it's working with previous version of Office.
Moreover, the designer of Outlook 2016 have some problem with font size… i can't change font size to '8' for any label present in the form.
Similar to this question,
Open Specific MailItem in Outlook from C# , In a C# VSTO application I'm trying to open an email in a new outlook window/inspector using the method GetFolderFromID and passing it's EntryID and StoreID.
Full code below:
Outlook.Application myApp = new Outlook.ApplicationClass();
Outlook.NameSpace mapiNameSpace = myApp.GetNamespace("MAPI");
Outlook.MAPIFolder mySentBox = mapiNameSpace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderSentMail);
Outlook.MailItem myMail = ((Outlook.MailItem)mySentBox.Items[1]);
string guid = myMail.EntryID;
string folderStoreID = mySentBox.StoreID;
Outlook.MailItem getItem = (Outlook.MailItem)mapiNameSpace.GetItemFromID(guid, folderStoreID);
getItem.Display();
The below code only opens up the requested email in a new window when the email is already selected within outlook.
getItem.Display();
If not selected, the following error returns.
System.Runtime.InteropServices.ComException: 'A dialog box is open. Close it and try again'.
I've also attempted adding a new inspector & activating/displaying the email object via it with no success.
Kind regards
The error simply means a dialog box is open. Make sure there are no modal windows displayed and make sure you ever call MailItem.Display(true) to display items modally.
I need to open several Outlook windows previously populated with ticulo and email body for later user to inform the senders. I need to open several windows (I walk a grid to know how many windows).
I'm trying to do this with threads but an error message occurs saying: Outlook can not do this because the dialog box is open. Please close it and try again "
How to open multiple competing windows?
Test Call
private void button2_Click(object sender, EventArgs e)
{
int qtdEventos = dgvDescEvento.RowCount;
Thread[] Threads = new Thread[qtdEventos];
try
{
cEmail testeEmail = new cEmail();
for (int i = 0; i < qtdEventos; i++)
{
Threads[i] = new Thread(new ThreadStart(new cEmail().Monta));
}
foreach (Thread t in Threads)
{
t.Start();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace NavEventos.Class
{
class cEmail
{
private Outlook.Application outlookApp;
public cEmail()
{
outlookApp = new Outlook.Application();
}
public void Monta()
{
string pTitulo = "Title";
string pAssunto = "Body test";
Outlook._MailItem oMailItem = (Outlook._MailItem)outlookApp.CreateItem(Outlook.OlItemType.olMailItem);
Outlook.Inspector oInspector = oMailItem.GetInspector;
Outlook.Recipients oRecips = (Outlook.Recipients)oMailItem.Recipients;
#region MONTA ASSUNTO
oMailItem.Subject = pTitulo;
#endregion
#region MONTA CORPO DO E-MAIL
oMailItem.Body = pAssunto;
#endregion
oMailItem.Display(true);
}
}
}
You may not like this... but you shouldn't try. ;(
As you can see the Outlook COM interface is trying very hard to prevent you from doing this, it is one of the limitations of the outlook automation libraries that displaying a mail item is done in a modal kind of way.
There is good reason for this, your user is in your LOB application, then your code wants them to read an email in outlook, which you have done using the COM automation libraries for outlook. Now their outlook icon in the toolbar is flashing because a new email modal window has opened up, but this dialog may have opened up behind your current LOB app.
Now the user will need to switch context into Outlook to see the dialog and read the email.
If you can review your need to open these emails all at the same time then you and outlook com automation will get along just fine :)
Otherwise consider writing a plugin for Outlook and moving your email management routines into outlook itself. In there you can be very creative, sounds like you really need just a master - detail style of interface, like the main outlook browser, so you have a list of these emails and as the user clicks on them they are displayed in the preview inspector.
Maybe the solution is to use your logic to move these messages into a
specific folder in outlook, then use Outlook automation to make this
folder the current active window in outlook, then the user can decide
which emails they want to action or not.
I am developing an Outlook utility to forward the currently open message to a preset address.
This could be done with a macro but they are not as easily deployed to a user base.
I have created the UI for the add-in through Visual Studio ribbon design. I have a button on the ribbon to use for this process.
I am trying to put in button action similar to what is described here: forwarding MailItem Outlook Addinn issue.
How can I forward the current selection?
namespace OutlookAddIn2
{
public partial class Ribbon1
{
private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
{
}
private void button1_Click(object sender, RibbonControlEventArgs e)
{
sendMail();
}
private void sendMail(Outlook.MailItem mail)
{
Outlook.Application Application = Globals.ThisAddIn.Application;
Outlook.MailItem newmail = Application.CreateItem(Outlook.OlItemType.olMailItem) as Outlook.MailItem;
newmail = mail.Forward();
newmail.Recipients.Add("____#example.com");
newmail.Send();
}
}
}
First of all, there is no need to create a new Outlook Application instance if you develop an add-in. Instead, you need to use the Application property which is available everywhere. See Global Access to Objects in Office Projects for more information.
In case if you deal with inspector windows you can use the following sequence of calls:
Application.ActiveInspector().CurrentItem
where the ActiveInspector method which returns the topmost Inspector object on the desktop. Use this method to access the Inspector object that the user is most likely to be viewing. For example:
Sub CloseItem()
Dim myinspector As Outlook.Inspector
Dim myItem As Outlook.MailItem
Set myinspector = Application.ActiveInspector
Set myItem = myinspector.CurrentItem
myItem.Close olSave
End Sub
But if you need to get the currently selected item in the Explorer window you can use the following sequence:
Application.ActiveExplorer().Selection[1]
where the ActiveExplorer method returns the topmost Explorer object on the desktop. This method is also useful for determining when there is no active explorer, so a new one can be opened.
The above code CloseItem() executed within an excel workbook rendered a run-time error 438, Object does not support this property or method. The reason I suspect is that there is no correct reference to the Outlook object model created.
I found a solution in code published by Wedge: Edit an open email from excel
I implemented the solution for the same purpose as above.
The adjusted code is as follows:
Sub CloseItemEdit()
Dim outlookApp As Outlook.Application
Set outlookApp = New Outlook.Application
Dim outlookInspector As Outlook.Inspector
Dim outlookMail As Outlook.MailItem
Set outlookInspector = outlookApp.ActiveInspector
If Not outlookInspector Is Nothing Then
If TypeOf outlookInspector.CurrentItem Is Outlook.MailItem Then
Set outlookMail = outlookInspector.CurrentItem
outlookMail.Close olSave
End If
End If
'Source: https://stackoverflow.com/questions/52596796/edit-an-open-email-from-excel
End Sub