Need to access Outlook contact details from multiple Mail IDs using C# - c#

Using an application, I'm fetching the contact details stored in the Micosoft Office Outlook using C#. I achieved it through the Microsoft.Office.Interop namespace.
The issues I'm facing now is when Outlook has multiple mail IDs configured to the same system I need to fetch contacts of the Individual mail IDs seperately.
How do I do this?
Here is the sample code:
/// <summary>
/// Getting the contacts by passing the folder name.
/// </summary>
/// <param name="folderName"></param>
/// <returns></returns>
private List<MyContact> GetContactsFromFolder(string folderName)
{
List<MyContact> contacts = null;
object missing = System.Reflection.Missing.Value;
//Create instance of Outlook application and Outlook Contacts folder.
try
{
OutLook.MAPIFolder fldContacts = null;
contacts = new List<MyContact>();
OutLook._Application outlookObj = new OutLook.Application();
/* if (folderName == "Default")
{
fldContacts = (OutLook.MAPIFolder)outlookObj.Session.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
}
else
{
OutLook.MAPIFolder contactsFolder = (OutLook.MAPIFolder)
outlookObj.Session.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
//VERIFYING THE CUSTOM FOLDER IN OUT LOOK .
foreach (OutLook.MAPIFolder subFolder in contactsFolder.Folders)
{
if (subFolder.Name == folderName)
{
fldContacts = subFolder;
break;
}
}
}
* */
fldContacts = (OutLook.MAPIFolder)outlookObj.Session.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
//LOOPIN G THROUGH CONTACTS IN THAT FOLDER.
foreach (Microsoft.Office.Interop.Outlook._MailItem contactItem in fldContacts.Items)
{
MyContact contact = new MyContact();
contact.FromAddress = contactItem.SenderEmailAddress;
contact.ToAddress = contactItem.To;
contact.Subject = contactItem.Subject;
contact.MailSize = contactItem.Size.ToString();
contact.Received = contactItem.ReceivedTime.ToString();
System.Data.SqlClient.SqlConnection con;
con = new System.Data.SqlClient.SqlConnection();
con.ConnectionString = "Initial Catalog=sample;Integrated Security=True;Server=Test;Connect Timeout=900";
try
{
con.Open();
string to_address = "";
string Cc = "";
foreach (Microsoft.Office.Interop.Outlook.Recipient olRecipient in contactItem.Recipients)
{
if (contactItem.To.ToLower().Contains(olRecipient.Address.ToLower()) == true ||
contactItem.To.ToLower().Contains(olRecipient.Name.ToLower()) == true)
{
if (to_address != "")
{
to_address = to_address + ";" + olRecipient.Name + " <" + olRecipient.Address + ">";
}
else
{
to_address =olRecipient.Name+" <"+olRecipient.Address+">";
}
}
else
if (contactItem.CC != null && contactItem.CC.ToString() != "")
{
if (contactItem.CC.ToLower().Contains(olRecipient.Address.ToLower()) == true ||
contactItem.CC.ToLower().Contains(olRecipient.Name.ToLower()) == true)
{
if (Cc != "")
{
Cc = Cc + ";" + olRecipient.Name + " <" + olRecipient.Address + ">";
}
else
{
Cc = olRecipient.Name + " <" + olRecipient.Address + ">";
}
}
}
}
//contact.
contacts.Add(contact);
}
}

The point is in this call of your code:
fldContacts = (OutLook.MAPIFolder)outlookObj.Session.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
Here you are always opening the default folder.
You should try to enumerate the available folders and call another method of the Session object to open the one you need to use.
I don't know the answer right now, but this is the direction to go.

Related

How do I find the contents of a specific Outlook Contacts subfolder?

I need to extract the contacts (Employees) listed in a specified (by name) subfolder in Outlook Contacts. I've been at it for days, and tried every scrap of code I can find on the internet, but to no avail. I have seen suggestions about how it could be done, but none of them actually work.
Here's my running code. You can drop it in a console app in Visual Studio as-is. I can find the contents of my "Contacts" folder, and I can find the list of folders, but can't work out how to get the contents of a sub folder.
We're using Outlook 365.
using System;
using System.Collections.Generic;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace OutlookTest
{
public class OutlookDataRetriever
{
public static int Main(string[] args)
{
try
{
Outlook.Application oApp = new Outlook.Application();
Console.WriteLine("\n\nShow Contacts folders:");
Outlook.MAPIFolder folderContacts = oApp.Session.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderContacts);
foreach (Outlook.MAPIFolder subfolder in folderContacts.Folders)
{
Console.WriteLine("folder::: " + subfolder.Name + " ::: " + subfolder.FolderPath);
}
Console.WriteLine("\n\nShow members of Contacts folder:");
Outlook.MAPIFolder fldContacts = (Outlook.MAPIFolder)oApp.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts);
Outlook.Items contactsFolder = fldContacts.Items;
foreach (var contact in contactsFolder)
{
if (contact is Outlook.ContactItem)
{
Outlook.ContactItem thisContact = (Outlook.ContactItem)contact;
Console.WriteLine("contact::: " + thisContact.FullName + " ::: " + thisContact.Email1DisplayName);
}
else
{
Console.WriteLine("I'm guessing this is a folder, but can't figure out how to cast it to access its contents.");
}
}
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
return 0;
}
}
}
My References:
snapshot of the solution explorer showing references
Here's the output I get:
Show Contacts folders:
folder::: {06967759-274D-40B2-A3EB-D7F9E73727D7} ::: \\KNye#myOrganization.com\Contacts\{06967759-274D-40B2-A3EB-D7F9E73727D7}
folder::: {A9E2BC46-B3A0-4243-B315-60D991004455} ::: \\KNye#myOrganization.com\Contacts\{A9E2BC46-B3A0-4243-B315-60D991004455}
folder::: Companies ::: \\KNye#myOrganization.com\Contacts\Companies
folder::: GAL Contacts ::: \\KNye#myOrganization.com\Contacts\GAL Contacts
folder::: Kristy Nye[1] ::: \\KNye#myOrganization.com\Contacts\Kristy Nye[1]
folder::: Kristy Nye ::: \\KNye#myOrganization.com\Contacts\Kristy Nye
folder::: Recipient Cache ::: \\KNye#myOrganization.com\Contacts\Recipient Cache
folder::: PeopleCentricConversation Buddies ::: \\KNye#myOrganization.com\Contacts\PeopleCentricConversation Buddies
folder::: Kristy's Addresses ::: \\KNye#myOrganization.com\Contacts\Kristy's Addresses
folder::: Organizational Contacts ::: \\KNye#myOrganization.com\Contacts\Organizational Contacts
Show members of Contacts folder:
contact::: Matt Smith ::: Matt Smith (ESmith#myOrganization.com)
contact::: Kristy J Nye ::: Kristy J Nye (KNye#myOrganization.com)
I'm guessing this is a folder, but can't figure out how to cast it to access its contents.
Here's a screenshot of my Contacts folder:
Screenshot of Contacts folder
Here's the contents of my folder, "ThisIsATestGroup":Contents of "ThisIsATestGroup" folder
My objective:
I want to query "Find all contacts in "ThisIsATestGroup", and get back:
Edgar B
Kristy J N
Rey G M
Richard D N
How do I get the contacts in this specific subfolder only??? Thank you!
All you really need is
Outlook.MAPIFolder fldContacts = (Outlook.MAPIFolder)oApp.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts);
Outlook.MAPIFolder fldEmployees = fldContacts.Folders["Employees"];
foreach (var item in fldEmployees.Items)
{
Outlook.ContactItem contact = item as Outlook.ContactItem;
if (contact != null)
{
Console.WriteLine("contact::: " + contact .FullName + " ::: " + contact .Email1DisplayName);
}
else
{
Outlook.DistListItem distList = item as Outlook.DistListItem;
if (distList != null)
{
Console.WriteLine("distList ::: " + distList.DLName);
}
}
}
After much pulling of hair and gnashing of teeth, I found my own answer. Here 'tis:
using System;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace OutlookTest
{
public class OutlookDataRetriever
{
public static int Main(string[] args)
{
string myFolder = "ThisIsATestGroup";
try
{
Console.WriteLine("Show members of '" + myFolder + "' list:");
Outlook.Application oApp = new Outlook.Application();
/* Get a list of items in the contactsfolder */
Outlook.MAPIFolder fldContacts = (Outlook.MAPIFolder)oApp.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts);
Outlook.Items contactsFolder = fldContacts.Items;
/* Find the contacts folder with the name I'm looking for. MS documentation calls this a DistListItem. Baffled me for a long time because their UI calls it a contact group. */
string filter = "[Subject] = '" + myFolder + "'";
var targetFolder = contactsFolder.Find(filter);
Outlook.DistListItem myDistList = (Outlook.DistListItem)targetFolder;
Console.WriteLine("myDistList::: " + myDistList.Subject);
/* List all the members in my list */
for (int i = 1; i <= myDistList.MemberCount; i++) // Index starts at 1, not 0 !!!
{
var aMember = myDistList.GetMember(i);
Console.WriteLine(" member::: " + i.ToString() + " " + aMember.Name + " ::: " + aMember.Address);
}
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
return 0;
}
}
}
On my way to the above solution, I found another solution which has the added benefit of allowing you to look through everything in your contacts folder. Both solutions return the correct result, but I suspect the top one runs faster.
namespace OutlookTest
{
public class OutlookDataRetriever
{
public static int Main(string[] args)
{
try
{
Outlook.Application oApp = new Outlook.Application();
Console.WriteLine("Show members of 'ThisIsATestGroup' list:");
Outlook.MAPIFolder fldContactsX = (Outlook.MAPIFolder)oApp.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts);
Outlook.Items contactsFolder = fldContactsX.Items;
foreach (var contact in contactsFolder)
{
if (contact is Outlook.ContactItem)
{
Outlook.ContactItem thisContact = (Outlook.ContactItem)contact;
Console.WriteLine("contact::: " + thisContact.FullName + " ::: " + thisContact.Email1DisplayName);
}
else
{
if (contact is Outlook.DistListItem)
{
Outlook.DistListItem thisDistList = (Outlook.DistListItem)contact;
Console.WriteLine("distList::: " + thisDistList.Subject);
if (thisDistList.Subject == "ThisIsATestGroup")
{
for (int i = 0; i < thisDistList.MemberCount; i++)
{
var aMember = thisDistList.GetMember(i + 1);
Console.WriteLine(" member::: " + i.ToString() + " " + aMember.Name + " ::: " + aMember.Address);
}
}
}
else
{
Console.WriteLine("Should never reach this line.");
}
}
}
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
return 0;
}
}
}
Enjoy!

Exception from HRESULT: 0x80004004 (E_ABORT) at Outlook.Mailitem.getHtmlBody()

I have a custom add-in which gets the body on clicking a button when it got installed. so I am getting this error on a customer machine. code is working fine on my side and for other customers but one customer is facing this problem.
this is my code
private void button1_Click(object sender, RibbonControlEventArgs e)
{
Microsoft.Office.Interop.Outlook.Application olApp = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.NameSpace ns = olApp.GetNamespace("MAPI");
Explorer olExp = olApp.ActiveExplorer();
Selection olSel = olExp.Selection;
string msg = "";
int iterate = 1;
MAPIFolder inbox = null;
if (olSel.Count > 1)
{
MessageBox.Show("Sorry! You can't report more then 1 email at a time", "Report Email");
return;
}
foreach (_MailItem mail in olSel)
{
inbox = ns.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
mail.GetInspector.Display(false);
Thread.Sleep(2100);
string screenShot = getScreenShot(mail);
mail.GetInspector.Close(OlInspectorClose.olDiscard);
String msgToShow = "Are you sure you want to report this email as suspicious?";
if (mail != null && mail.Subject != null)
msgToShow += "\n\nSubject : " + mail.Subject.ToString();
DialogResult dr = MessageBox.Show(msgToShow, "Please Confirm", MessageBoxButtons.YesNo,
MessageBoxIcon.Exclamation);
if (dr == DialogResult.Yes)
{
msg += reportMail(mail, screenShot, e);
}
else {
return;
}
iterate++;
break;
}
if (!msg.Equals(""))
MessageBox.Show(msg, "Report Email");
else
return;
if (!msg.Contains("Success"))
return;
MailItem moveMail = null;
MAPIFolder subfolder = null;
try
{
subfolder = inbox.Folders["Reported Emails"];
}
catch (System.Exception ex) {
subfolder = inbox.Folders.Add("Reported Emails", OlDefaultFolders.olFolderInbox);
}
foreach (MailItem eMail in olSel)
{
try
{
moveMail = eMail;
if (moveMail != null)
{
string titleSubject = (string)moveMail.Subject;
moveMail.Move(subfolder);
}
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
private string reportMail(_MailItem mail, string screenShot, RibbonControlEventArgs e)
{
try
{
var m = Globals.ThisAddIn.Application.GetNamespace("MAPI");
var mailitem = mail;
if (mailitem != null)
{
// Console.WriteLine("Email body ::: " + mailitem.HTMLBody);
String reporterEmail = getReporterEmail(mailitem);
String senderEmailAddress = "";
String senderName = "";
AddressEntry mailsender;
if (reporterEmail.Equals(""))
{
MessageBox.Show("Sorry! This email can't be reported because you are not included in Recipients.", "Report Email");
}
else
{
if (mailitem.SenderEmailType == "EX")
{
mailsender = mailitem.Sender;
if (mailsender != null)
{
if (mailsender.AddressEntryUserType == OlAddressEntryUserType.olExchangeUserAddressEntry || mailsender.AddressEntryUserType == OlAddressEntryUserType.olExchangeRemoteUserAddressEntry)
{
ExchangeUser exchUser = mailsender.GetExchangeUser();
if (exchUser != null)
{
senderEmailAddress = exchUser.PrimarySmtpAddress;
senderName = exchUser.Name;
}
}
}
}
else
{
senderEmailAddress = mailitem.SenderEmailAddress;
senderName = mailitem.SenderName;
}
String emailHeader = mailitem.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x007D001E");
String emailBody = mailitem.Body.Replace("%"," percent").Replace("#","").Replace("|", "");
//String res = HttpPost(Properties.Settings.Default.address, "ReporterEmail=" + reporterEmail + "&suspectedName=" + senderName + "&FromEmail=" + senderEmailAddress
// + "&ToEmail=" + mailitem.To + "&Subject=" + mailitem.Subject + "&EmailBody=" + emailBody + "&AttachmentName=" + GetAttachments(mailitem)
// + "&reporter=" + reporterEmail + "&emailHeader=" + emailHeader + "&mailImage=" + screenShot);
String htmlBody = mail.HTMLBody;
MessageBox.Show(htmlBody);
Dictionary<string, object> postParameters = new Dictionary<string, object>();
postParameters.Add("ReporterEmail", reporterEmail);
postParameters.Add("suspectedName", senderName);
postParameters.Add("FromEmail", senderEmailAddress);
postParameters.Add("ToEmail", mailitem.To);
postParameters.Add("Subject", mailitem.Subject);
postParameters.Add("EmailBody", emailBody);
List<String> attachmentDetails = GetAttachments(mailitem);
postParameters.Add("AttachmentName", attachmentDetails[0]);
postParameters.Add("reporter", reporterEmail);
postParameters.Add("emailHeader", emailHeader);
postParameters.Add("mailImage", screenShot);
string res = HttpPost(Properties.Settings.Default.serverAddress+ "/PhishRod-portlet/reporter", postParameters, htmlBody,attachmentDetails[1]);
return res + "\n";
}
}
}
catch (System.Exception ex)
{
log.Error(ex);
return "Error: " + ex + "-- - " + ex.StackTrace.ToString() + "\n";
}
return "";
}
In the event handler of your button I see the following lines of code:
Microsoft.Office.Interop.Outlook.Application olApp = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.NameSpace ns = olApp.GetNamespace("MAPI");
There is no need to create a new Outlook Application instance in the add-in. Instead, you need to use the Application property which doesn't trigger a security issue when dealing with OOM from external applications:
var app = Globals.ThisAddIn.Application

c# - How to call/link a workflow on a web application from a c# program?

I have a C# (WinForms) application that can scan documents via a printer. After scanning, I will be able to enter document details on it and have a button to finalize the documents. The documents details and info will be stored in my database ABC in certain tables.
Now, I have another web application written in Java(IntelliJ) that has some button functionality to upload documents and then start a workflow and route it to another user to approve the document. I won't go into detail on the specifics. This application also connects to the same database ABC.
So now comes the tougher part, I need to link these two applications in a way that when I finalize my document
on the C# application, it has to auto trigger the workflow on the web application side. Rather than manually starting the workflow on the web application, it would just call or trigger the workflow, so I do not need to access the web application at all for the process to start.
private void FinButton_Click(object sender, EventArgs e)
{
int count = 0;
var txtBoxFields = new List<TextBox>
{
textBox1,
textBox2,
textBox3,
textBox4,
textBox5,
textBox6,
textBox7,
textBox8,
textBox9,
textBox10,
textBox11,
textBox12,
textBox13,
textBox14,
textBox15
};
var templateFields = new List<String>
{
"T1",
"T2",
"T3",
"T4",
"T5",
"T6",
"T7",
"T8",
"T9",
"T10",
"T11",
"T12",
"T13",
"T14",
"T15"
};
//long tid = 0;
//Start insert query into templatebatch table in db
var dbConnection2 = DBConnection.Instance();
dbConnection2.DatabaseName = ConfigurationManager.AppSettings["dbName"];
if (dbConnection2.IsConnect())
{
bool test = true;
for (int i = 1; i <= 15; i++)
{
var input = txtBoxFields[i - 1].Text;
var insertQuery = "INSERT INTO templateinfo(TID, THEADER, " + templateFields[i - 1] + ") VALUES(#tid, #theader,#t" + i + ")";
var insertCmd = new MySqlCommand(insertQuery, dbConnection2.Connection);
insertCmd.Parameters.AddWithValue("#tid", tid);
insertCmd.Parameters.AddWithValue("#theader", "N");
if (String.IsNullOrEmpty(input))
{
count = 1;
insertCmd.Parameters.AddWithValue("#t" + i, String.Empty);
break;
}
else
{
if (test)
{
insertCmd.Parameters.AddWithValue("#t" + i, txtBoxFields[i - 1].Text);
insertCmd.ExecuteNonQuery();
test = false;
var selectQuery = "select TINFOID from templateinfo where TID=" + tid + " and THEADER = 'N'";
var selectCmd = new MySqlCommand(selectQuery, dbConnection2.Connection);
var selectReader = selectCmd.ExecuteReader();
using (MySqlDataReader dr = selectReader)
{
while (dr.Read())
{
tinfoid = Convert.ToInt32(dr["TINFOID"]);
}
}
}
else
{
var updateQuery = "update templateinfo set " + templateFields[i - 1] + "='" + txtBoxFields[i - 1].Text + "' where TINFOID = '" + tinfoid + "' and TID=" + tid + " and THEADER='N'";
var updateCmd = new MySqlCommand(updateQuery, dbConnection2.Connection);
var updateReader = updateCmd.ExecuteReader();
using (var reader = updateReader)
{
}
}
}
}
}
if (count == 1)
{
//MessageBox.Show("Input field(s) cannot be left empty.");
}
//Finalize here
var client = new LTATImagingServiceClient();
client.Finalize(userID, tid, tinfoid, batchID);
Debug.WriteLine(userID + ", " + tid + ", " + tinfoid + ", " + batchID);
var batchName = templateView.SelectedNode.Text;
var folderPath = #"C:\temp\batches\" + mastertemplatename + #"\" + subtemplatename + #"\" + batchName + #"\";
ThumbnailLists.Items.Clear();
// var img = Image.FromFile(#"C:\temp\batch-done.png");
if (ImageBox.Image != null)
{
ImageBox.Image.Dispose();
}
ImageBox.Image = null;
try
{
using (new Impersonation(_remoteDomain, _remoteUser, _remotePassword))
{
// MessageBox.Show(_remoteUser);
// MessageBox.Show(_remotePassword);
var tPath = #"\\126.32.3.178\PantonSys\SAM\Storage\3\" + mastertemplatename + #"\" + subtemplatename + #"\" + batchName + #"\";
bool exists = System.IO.Directory.Exists(tPath);
if (!exists)
{
System.IO.Directory.CreateDirectory(tPath);
}
string[] fileList = Directory.GetFiles(folderPath, "*");
foreach (var file in fileList)
{
File.Copy(file, tPath + Path.GetFileName(file));
}
CurrentPageBox.Text = "";
NumberPageBox.Text = "";
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
MessageBox.Show(ex.Message);
}
var dbConnection = DBConnection.Instance();
dbConnection.DatabaseName = ConfigurationManager.AppSettings["dbName"];
if (dbConnection.IsConnect())
{
var deleteBatchQuery = "DELETE FROM templatebatch WHERE batchname ='" + templateView.SelectedNode.Text + "'";
var deleteBatchCmd = new MySqlCommand(deleteBatchQuery, dbConnection.Connection);
var deleteBatchReader = deleteBatchCmd.ExecuteReader();
using (var reader = deleteBatchReader)
{
while (reader.Read())
{
}
}
templateView.Nodes.Remove(templateView.SelectedNode);
Directory.Delete(folderPath, true);
MessageBox.Show("Successfully Transferred.");
foreach (var txtFields in txtBoxFields)
{
txtFields.Text = "";
txtFields.Enabled = false;
}
finButton.Visible = false;
finButton.Enabled = false;
}
bindButton.Visible = false;
}
Would this be possible to achieve or just being far-fetched?
I would appreciate any suggestions or pointers on this. Do let me know if there is anything unclear in my explanation.
EDIT:
Request URL: http://126.32.3.178:8111/process/taskmanager/start/start.jsp
Request Method: POST
Status Code: 200 OK
Remote Address: 126.32.3.178:8111
Referrer Policy: no-referrer-when-downgrade
Is there a way I could call this from the C# application?
You can send your file directly from your C# app with use of Http client. Here is code sample:
private async Task<bool> Upload(string filePath)
{
const string actionUrl = #"http://126.32.3.178:8111/process/taskmanager/start/start.jsp";
var fileName = Path.GetFileName(filePath);
var fileBytes = File.ReadAllBytes(filePath);
var fileContent = new ByteArrayContent(fileBytes);
using (var client = new HttpClient())
using (var formData = new MultipartFormDataContent())
{
formData.Add(fileContent, fileName);
var response = await client.PostAsync(actionUrl, formData);
return response.IsSuccessStatusCode;
}
}
Also, note that there maybe some sort of authentication should be performed before you can post a request.

How to get the newest contact's picture in outlook 2010?

Here is the problem:
use Attachment.SaveAsFile() to save contact's picture on disk.(successfully)
change the contact's picture in outlook manually.
repeat step 1, but i get the old picture, not the new one in step 2.
EDIT:
I have know how to save contact's picture on disk.
The problem is that the picture which i get is not the newest one.
Here is the code:
//[Outlook] is short for [Microsoft.Office.Interop.Outlook]
Outlook.Application outlook = new Outlook.Application();
Outlook.MAPIFolder folder = outlook.GetNamespace("MAPI").GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts);
foreach (var item in folder.Items) {
if (item is Outlook.ContactItem) {
Outlook.ContactItem contact = null;
Outlook.Attachments atts = null;
Outlook.Attachment att = null;
string path = "";
contact = item as Outlook.ContactItem;
if (!contact.HasPicture) { continue; }
path = #"C:\Temp\" + contact.EntryID + ".jpg";
atts = contact.Attachments;
att = atts["ContactPicture.jpg"];
if(File.Exists(path)){
File.Delete(path);
}
att.SaveAsFile(#"C:\Temp\" + contact.EntryID + ".jpg");
Marshal.ReleaseComObject(att);
att = null;
Marshal.ReleaseComObject(atts);
atts = null;
Marshal.ReleaseComObject(contact);
contact = null;
}
}
thanks!
I find the resolution on Contact picture retrieved via PIA doesn't change when updated in Outlook
I didn't release the folder.Items
Here is the modified codeļ¼š
//[Outlook] is short for [Microsoft.Office.Interop.Outlook]
Outlook.Application outlook = new Outlook.Application();
Outlook.MAPIFolder folder = outlook.GetNamespace("MAPI").GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts);
Outlook.Items items = null;
items = folder.Items;
foreach (var item in items) {
if (item is Outlook.ContactItem) {
Outlook.ContactItem contact = null;
Outlook.Attachments atts = null;
Outlook.Attachment att = null;
string path = "";
contact = item as Outlook.ContactItem;
if (!contact.HasPicture) { continue; }
path = #"C:\Temp\" + contact.EntryID + ".jpg";
atts = contact.Attachments;
att = atts["ContactPicture.jpg"];
if (File.Exists(path)) {
File.Delete(path);
}
att.SaveAsFile(#"C:\Temp\" + contact.EntryID + ".jpg");
Marshal.ReleaseComObject(att);
att = null;
Marshal.ReleaseComObject(atts);
atts = null;
Marshal.ReleaseComObject(contact);
contact = null;
}
}
if (items != null) {
Marshal.ReleaseComObject(items);
items = null;
}
EDIT:
Problem happened with above code. Sometimes it got the old picture.
I added GC.Collect(); at the end,then it worked well.
So i tried the following code. But the problem remained.
//[Outlook] is short for [Microsoft.Office.Interop.Outlook]
Outlook.Application outlook = new Outlook.Application();
Outlook.MAPIFolder folder = outlook.GetNamespace("MAPI").GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts);
Outlook.Items items = folder.Items;
foreach (var item in items) {
if (item is Outlook.ContactItem) {
Outlook.ContactItem contact = item as Outlook.ContactItem;
string path = "";
Outlook.Attachment att = null;
if (!contact.HasPicture) { continue; }
path = #"C:\Temp\" + contact.EntryID + ".jpg";
att = contact.Attachments["ContactPicture.jpg"];
if (File.Exists(path)) {
File.Delete(path);
}
att.SaveAsFile(#"C:\Temp\" + contact.EntryID + ".jpg");
}
}
GC.Collect();
Finally i use the following code. Release all com objects,then call GC.Collect().
//[Outlook] is short for [Microsoft.Office.Interop.Outlook]
Outlook.Application outlook = new Outlook.Application();
Outlook.MAPIFolder folder = outlook.GetNamespace("MAPI").GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts);
Outlook.Items items = folder.Items;
foreach (var item in items) {
if (item is Outlook.ContactItem) {
Outlook.ContactItem contact = null;
Outlook.Attachments atts = null;
Outlook.Attachment att = null;
string path = "";
contact = item as Outlook.ContactItem;
if (!contact.HasPicture) { continue; }
path = #"C:\Temp\" + contact.EntryID + ".jpg";
atts = contact.Attachments;
att = atts["ContactPicture.jpg"];
if (File.Exists(path)) {
File.Delete(path);
}
att.SaveAsFile(#"C:\Temp\" + contact.EntryID + ".jpg");
Marshal.ReleaseComObject(att);
att = null;
Marshal.ReleaseComObject(atts);
atts = null;
Marshal.ReleaseComObject(contact);
contact = null;
}
}
if (items != null) {
Marshal.ReleaseComObject(items);
items = null;
}
Marshal.ReleaseComObject(folder);
folder = null;
Marshal.ReleaseComObject(outlook);
outlook = null;
GC.Collect();

Outlook 2007: Reading Pane is not updated when an encrypted Email is imported

we use Redemptiontools to develop a Addin for Outlook. At first we create Emailstubs from a Metadataset. When the User select a Mail we load a msg file from the Network and import it into the Emailstub. We dont have any problems in Outlook 2010/2013/2016.
But in Outlook 2007 the reading pane doesnt refresh if the mail has a Signature. I have deselect and reselect the Mail and then i can see the new mail.
Creating the Emailstub from an metadataset:
using (ComObjectWrapper<RDOFolder> rdoFolder = RDOSession.Resource.GetFolderFromID(folderEntryID).WithComCleanup())
{
using (ComObjectWrapper<RDOMail> mailstub = rdoFolder.Resource.Items.Add().WithComCleanup())
{
mailstub.Resource.Sent = true;
mailstub.Resource.SenderName = metadatamail.SenderName + " ";
mailstub.Resource.SenderEmailAddress = metadatamail.SenderEmailAddress + " ";
mailstub.Resource.SentOnBehalfOfName = metadatamail.SentOnBehalfOfName + " ";
mailstub.Resource.SentOnBehalfOfEmailAddress = metadatamail.SentOnBehalfOfEmailAddress + " ";
mailstub.Resource.Subject = metadatamail.Subject + " ";
mailstub.Resource.ReceivedTime = metadatamail.ReceivedTime;
mailstub.Resource.Body = metadatamail.Body + " ";
mailstub.Resource.To = metadatamail.To + " ";
mailstub.Resource.ReceivedByName = metadatamail.ReceivedByName + " ";
mailstub.Resource.UnRead = metadatamail.UnRead;
if (metadatamail.ContainsAttachments)
{
var Attach = mailstub.Resource.Attachments.Add(new char[0]);
Attach.FileName = "Attachment.txt";
}
mailstub.Resource.Save();
}
}
Importing the msg file in the selection change Event of the Explorer (expl):
void expl_SelectionChange()
{
using (var selection = expl.Selection.WithComCleanup())
{
foreach (var item in selection.Resource)
{
if (item is Outlook.MailItem)
{
string entryID = (item as Outlook.MailItem).EntryID;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
if (!string.IsNullOrEmpty(entryID))
{
using (var researchEntry = RDOSession.Resource.GetMessageFromID(entryID).WithComCleanup())
{
string mailpath = GetEmailFromNetwork(entryID);
if (!string.IsNullOrEmpty(mailpath))
{
Redemption.SafeMailItem sItem = new Redemption.SafeMailItem();
sItem.Item = researchEntry.Resource;
sItem.Import(mailpath, (int)rdoSaveAsType.olMSG);
sItem.ReleaseComObject<Redemption.SafeMailItem>();
researchEntry.Resource.Save();
}
}
}
}
}
}
}
RDOSession:
private ComObjectWrapper<RDOSession> RDOSession
{
get
{
try
{
var rdoSession = Activator.CreateInstance(Type.GetTypeFromProgID("Redemption.RDOSession")) as RDOSession;
if (rdoSession != null)
{
rdoSession.MAPIOBJECT = this.Application.Session.MAPIOBJECT;
return rdoSession.WithComCleanup();
}
}
catch { }
return null;
}
}
Does anyone have a hint or a solution?

Categories