I have a program that is using Outlook to send messages with attachments. It is working ok, sending emails with attachments but in outbox there is no attachment in the message. When somebody receive the message the attachment is visible but in outbox not.
Here is some code:
Outlook.MailItem mail = (Outlook.MailItem)outlookApp.CreateItem(Outlook.OlItemType.olMailItem);
mail.BodyFormat = Outlook.OlBodyFormat.olFormatPlain;
int iAttachType = (int)Microsoft.Office.Interop.Outlook.OlAttachmentType.olByValue;
mail.Attachments.Add(Application.StartupPath+"/"+attachment, iAttachType, null, attachment);
mail.To = email;
mail.Subject = "Something";
mail.Body = "Some body";
mail.Send();
Before this I use:
private Outlook.Application outlookApp;
private Outlook._NameSpace outlookNameSpace;
private Outlook.MAPIFolder outbox;
and
outlookApp = new Outlook.Application();
outlookNameSpace = outlookApp.GetNamespace("MAPI");
outlookNameSpace.Logon(null, null, false, false);
outbox = outlookNameSpace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderOutbox);
My outlook program is connected with Microsoft Exchange Serwer. When I was using an application written in C++ it saved attachment in messages in outbox.
Thx for help!
You could be working with an old version of the outlook item.
This can happen if you keep references to your mail items, rec-patterns, inspectors and some other types [that I now forgot] longer than you need them.
Your reference will often point to the old version of the item and keeping it can also prevent you from getting a reference to the updated one (the one with the attachment), even when events (Folder.BeforeItemMove) are triggered.
Also, have you tried if mail.Save() would do anything for you?
This is what I use as soon as I am done with an item.
public static void NullAndRelease(object o)
{
if (o == null) {
return;
}
try {
int releaseResult = 0;
do {
releaseResult = System.Runtime.InteropServices.Marshal.ReleaseComObject(o);
} while (releaseResult >= 0);
} catch {
} finally {
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
The catch has no message and is not important in my case. It is there if someone would pass in a reference that leads to something other than a com object. You can also try FinalReleaseComObject(o).
Related
I'm trying to programmatically click on a link which creates an email with predefined subject,to,cc,bcc and body content of the email.My requirement is, If I select an Outlook mail item and click on “Approve via mail” in my Addin, the code will search for hyperlink “Click here to Approve” in the mail body and Automatically click on the hyperlink.
The hyperlink “Click here to Approve” creates an email with predefined subject,to,cc,bcc and body content of the email.
I'm not sure how to do it with VSTO as all the other solutions suggest using JQuery and Javascript
Object selObject = this.Application.ActiveExplorer().Selection[1];
Outlook._MailItem eMail = (Outlook._MailItem)
this.Application.CreateItem(Outlook.OlItemType.olMailItem);
eMail = ((Outlook._MailItem)selObject);
if(eMail.HTMLBody.Contains("Approve"))
{
}
I'm not sure what I can write in the IF segment of the code.Please Suggest.
Outlook doesn't provide anything for opening hyperlinks. You can use the the following code (Process.Start) for opening them in the default web browser:
Process.Start("your_hyperlink");
Or just create a Mail item progrmmatically in Outlook based on the info where the Approve button was clicked.
Outlook.MailItem mail = null;
Outlook.Recipients mailRecipients = null;
Outlook.Recipient mailRecipient = null;
try
{
mail = OutlookApp.CreateItem(Outlook.OlItemType.olMailItem)
as Outlook.MailItem;
mail.Subject = "A programatically generated e-mail";
mailRecipients = mail.Recipients;
mailRecipient = mailRecipients.Add("Eugene Astafiev");
mailRecipient.Resolve();
if (mailRecipient.Resolved)
{
mail.Send();
}
else
{
System.Windows.Forms.MessageBox.Show(
"There is no such record in your address book.");
}
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message,
"An exception is occured in the code of add-in.");
}
finally
{
if (mailRecipient != null) Marshal.ReleaseComObject(mailRecipient);
if (mailRecipients != null) Marshal.ReleaseComObject(mailRecipients);
if (mail != null) Marshal.ReleaseComObject(mail);
}
Take a look at the following articles for more information and samples:
How to create and show a new Outlook mail item programmatically: C#, VB.NET
How To: Create and send an Outlook message programmatically
How To: Fill TO,CC and BCC fields in Outlook programmatically
How To: Create a new Outlook message based on a template
I just started to dabble into using Microsoft.Office.Interop.Outlook. I was able to successfully send an email using the bit of code below.
public void Send()
{
try
{
Outlook._Application _app = new Outlook.ApplicationClass();
var test = _app.CreateItem(Outlook.OlItemType.olMailItem);
Outlook.MailItem mail = (Outlook.MailItem) _app.CreateItem(Outlook.OlItemType.olMailItem);
mail.To = "testemail#fakeaddress.com";
mail.Subject = "Test Outlook Subject";
mail.Body = "Test Outlook Body";
mail.Importance = Outlook.OlImportance.olImportanceNormal;
((Outlook.MailItem) mail).Send();
}
catch
{
Notification.Notice("Error");
}
}
I would like to have a Validate() function before the try/catch such that it'll check to see if there's a valid outlook account enabled. May I ask does anyone know how I can check if any outlook accounts are setup?
I tried this
public bool validate()
{
Outlook._Application _app = new Outlook.ApplicationClass();
Outlook.Accounts accounts = _app.Session.Accounts;
return accounts.Count > 0;
}
But accounts.Count returned 1 even after I removed my outlook account.
There will always be at least one account - the store. Otherwise Outlook won't run. But even if there are mail accounts, how would you know whether they are configured appropriately? Unless you take over the message submission, there is no way for you to know ahead of time.
UPDATE: Loop through the Namespace.Accounts collection and look for accounts with Account.AccountType == olExchange ,olImap,olPop3, olHttp. Keep in mind that OOM only list mail accounts, not store or address book.
If you were using Extended MAPI (C++ or Delphi), you could use IOlkAccountManager::EnumerateAccounts(CLSID_OlkMail, ...) (you can play with that interface in OutlookSpy (I am its author) - click IOlkAccountManager button). If Extended MAPI is not an option, Redemption (I am also its author) exposes the RDOAccounts object; its GetOrder(acMail) method will return all mail accounts. You'll just need to check if the returned collection has any elements.
I am attempting to program a DataGridHyperlinkColumn which contains user's emails to send a new email through outlook when clicking on the address. For now I am just using a test email instead of getting the contents of the column, but this is what I have so far;
<DataGridHyperlinkColumn Header="Email" Binding="{Binding Email}">
<DataGridHyperlinkColumn.ElementStyle>
<Style>
<EventSetter Event="Hyperlink.Click" Handler="OnEmailHyperlinkClick"/>
</Style>
</DataGridHyperlinkColumn.ElementStyle>
</DataGridHyperlinkColumn>
Then the handler in C#;
private void OnEmailHyperlinkClick(object sender, RoutedEventArgs e)
{
string subject = "My subject";
string emailTag = string.Format("mailto:someone#test.com?subject={0}", subject);
System.Diagnostics.Process.Start(emailTag);
}
At the moment this is providing strange behaviour. First of all it opens a new instance of Google Chrome. Nothing to do with Outlook at at all. It then crashes saying;
Cannot locate resource 'addressbook/someone#test.com'
It's almost as if this event is actually being handled elsewhere, but I am lamost certain it isn't. Has anyone experienced this before?
All that your solution does is tells windows to try to start a new process using the provided string.
You need to specify that you want it to use outlook.
Add the Microsoft.Office.Interop.Outlook reference to your project (make sure it's the correct version)
Then try something like this:
public static void OnEmailHyperlinkClick(object sender, RoutedEventArgs e)
{
try
{
Microsoft.Office.Interop.Outlook.Application oApp = new Microsoft.Office.Interop.Outlook.Application();
MailItem msg = (MailItem)oApp.CreateItem(OlItemType.olMailItem);
msg.Subject = "My subject";
msg.Body = "My Message Body";
Recipients recipients = (Recipients)msg.Recipients;
Recipient recipient = (Recipient)recipients.Add("someone#test.com");
recipient.Resolve();
msg.Display(); // If you want to have the email displayed for the user to send
// Otherwise
msg.Send();
recipient = null;
recipients = null;
msg = null;
oApp = null;
}
catch (Exception ex)
{
}
}
I'm trying to use the attachments included in calendar items pulled progmatically.
I have a list of chosen calendar subject lines from a previous dialog box, and while the subject is transferring properly, the body isn't working well (another question altogether) but the attachments aren't working whatsoever.
Here's my foreach loop where the attachments are being placed into an Attachments array for use later:
string[] subjects = new string[dialog.chosen.Count];
string[] bodies = new string[dialog.chosen.Count];
Attachments[] attach = new Attachments[dialog.chosen.Count];
foreach (Outlook.AppointmentItem appt in rangeAppts)
{
foreach (string text in dialog.chosen)
{
if (text == appt.Subject)
{
subjects[i] = appt.Subject;
bodies[i] = Convert.ToString(appt.Body);
attach[i] = appt.Attachments;
i = i + 1;
}
}
}
And then here's where I actually call the method:
sendEmailTemplate(bodies[i], subject, to, "", attachment: attach[i]);
And then the method itself:
public void sendEmailTemplate(string body, string subject, string to, string cc , Attachments attachment = null)
{
Microsoft.Office.Interop.Outlook.Application oApp = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook._MailItem oMailItem = (Microsoft.Office.Interop.Outlook._MailItem)oApp.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem);
oMailItem.HTMLBody = body;
oMailItem.Subject = subject;
try
{
oMailItem.Attachments.Add(attachment);
}
catch {}
oMailItem.To = to;
oMailItem.CC = cc;
oMailItem.Display(false);
oMailItem.Application.ActiveInspector().WindowState = Microsoft.Office.Interop.Outlook.OlWindowState.olNormalWindow;
}
I've tried several things, however when I actually go to send the e-mail, I end up getting:
Exception: Member not found. HRESULT: 0x80020003
And then I haven't been able to get anything else to work. The try/catch loop on the method is to prevent the above exception as I was getting that exception regardless of whether or not an attachment was present, and now attachments just aren't being added.
I'm using Interop that comes with Office along with C#. Winforms if that makes a difference.
MailItem.Attachments takes either a string (fully qualified file name), or another Outlook item (MailItem, ContactItem, etc.).
You cannot pass Attachments object as an argument. If you need to copy the attachments, loop through all attachments in the Attachments collection, call Attachment.SaveAsFile for each attachment, pass the file name to MailItem.Attachments.Add, delete thee temporary file.
In Outlook, I can set the subject for a new message (when composing a new mail message), but I want to prepend text. So I need to get the subject first, and then set it.
Outlook.Application application = Globals.ThisAddIn.Application;
Outlook.Inspector inspector = application.ActiveInspector();
Outlook.MailItem myMailItem = (Outlook.MailItem)inspector.CurrentItem;
if (myMailItem != null && !string.IsNullOrEmpty(myMailItem.Subject))
{
myMailItem.Subject = "Following up on your order";
}
This code works on replies, but not for new messages, because in that case, myMailItem is null.
This is what I was looking for:
if (thisMailItem != null)
{
thisMailItem.Save();
if (thisMailItem.EntryID != null)
{
thisMailItem.Subject = "prepended text: " + thisMailItem.Subject;
thisMailItem.Send();
}
}
The subject was null until the mail item had been saved, either because it was sent, or as a draft. We can save it programmatically and then get the subject.
One other note: if the subject is blank at the time of saving, it will still show as null.