Outlook event function triggers multiple times when used on shared mailbox - C# - outlook

I've function which checks every new coming email inbox and if it is reply, it would move it to "Reply" folder.
It runs on shared mailbox in multiple people's PC. The problem is, it moves the email file but creates multiple copies of the same email into "Reply" folder. How can I fix it?
Here is my code, any help will be appreciated.
Thank you.
Outlook.NameSpace outlookNameSpace;
Outlook.MAPIFolder inbox;
private Outlook.Items items;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
Outlook.NameSpace ns = Globals.ThisAddIn.Application.Session;
Outlook.MAPIFolder inbox = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
outlookNameSpace = this.Application.GetNamespace("MAPI");
string recipientName = "abc#abcd.com";
Outlook.Recipient recip = outlookNameSpace.CreateRecipient(recipientName);
recip.Resolve();
if (recip.Resolved)
{
inbox = outlookNameSpace.GetSharedDefaultFolder(recip, Outlook.OlDefaultFolders.olFolderInbox);
items = inbox.Items;
items.ItemAdd += new Outlook.ItemsEvents_ItemAddEventHandler(items_ItemAdd);
}
}
void items_ItemAdd(object Item)
{
if (Item != null)
{
Outlook.MailItem mail = Item as Outlook.MailItem;
if (mail.MessageClass == "IPM.Note")
{
try
{
Outlook.Application app = Globals.ThisAddIn.Application;
if (Item is Outlook.MailItem)
{
if (mailItem.ConversationIndex.Length >= 64)
{
Outlook.Folder nonInbox = folder.Parent as Outlook.Folder;
string FolderName = "Reply";
Outlook.MAPIFolder DestFolder = null;
try
{
DestFolder = nonInbox.Folders[FolderName];
}
catch
{
}
try
{
mailItem.Move(DestFolder);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}

The way I dealt with it is when our user reply to email, it will save custom user property along with original email from customer. User property is our user's name. When they get reply from customer, add-in checks if current user is same as user property saved in original email, if they are same; then add-in will move the email to folder. Like this, condition on every reply will be true only once.

Related

ActiveExplorer().Selection returns previously selected mail in Outlook C#

I've following code. When user clicks on Reply or Reply button, it will pass the original email which will be process on SendAndComplete button.
public partial class ThisAddIn
{
public object selectedObject = null;
Outlook.MailItem mailItem = null;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
Outlook.Application application = this.Application;
Outlook.Explorer currentExplorer = application.ActiveExplorer();
//Get this event fire when selection changes
currentExplorer.SelectionChange += new Outlook.ExplorerEvents_10_SelectionChangeEventHandler(CurrentExplorer_Event);
}
public void CurrentExplorer_Event()
{
if (this.Application.ActiveExplorer().Selection.Count == 1
&& this.Application.ActiveExplorer().Selection[1] is Outlook.MailItem)
{
selectedObject = this.Application.ActiveExplorer().Selection[1];
mailItem = selectedObject as Outlook.MailItem;
((Outlook.ItemEvents_10_Event)mailItem).Reply += new Outlook.ItemEvents_10_ReplyEventHandler(MailItem_Reply);
((Outlook.ItemEvents_10_Event)mailItem).ReplyAll += new Outlook.ItemEvents_10_ReplyAllEventHandler(MailItem_ReplyAll);
}
}
void MailItem_Reply(object response, ref bool cancel)
{
//No code here
}
void MailItem_ReplyAll(object response, ref bool cancel)
{
//No code here
}
}
Now the selectedObject will be used on Ribbon.cs on button click.
public void SendnCompleteButton_Click(Office.IRibbonControl control)
{
Outlook.Application application = new Outlook.Application();
var addIn = Globals.ThisAddIn;
Outlook.MailItem mailItem = addIn.selectedObject as Outlook.MailItem;
MessageBox.Show(mailItem.Subject + " " + mailItem.ReceivedTime + " " + mailItem.Sender.Name)
}
Message box is showing previously selected email, how do I release the previously selected object?
Thank you.
First of all, there is no need to create a new Outlook Application instance in the ribbon button's event handler:
Outlook.Application application = new Outlook.Application();
Instead, you need to use the Globals.ThisAddIn.Application property or just the add-in class which provides the Application property out of the box.
Second, you must declare the event source object at the global scope, for example:
Outlook.Explorer currentExplorer;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
currentExplorer = Application.ActiveExplorer();
//Get this event fire when selection changes
currentExplorer.SelectionChange += new Outlook.ExplorerEvents_10_SelectionChangeEventHandler(CurrentExplorer_Event);
}
Third, checking whether a single item is selected in Outlook UI is not correct. Instead, you should check whether any item is selected:
if (this.Application.ActiveExplorer().Selection.Count > 0)

How can I share an event handler?

private void ExitAndSave(object sender, EventArgs e)
{
foreach (Form form in MdiChildren)
{
if (form is TextForm tf)
{
tf.BringToFront();
DialogResult dr = MessageBox.Show("Do you want to save your document?", "Save document?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (dr == DialogResult.Yes)
{
//counter++;
var textBoxValue = tf.FetchTextBoxValue();
//string filePath = $"{DateTime.Now.Ticks.ToString()}.txt";
string filePath = $"composition{DateTime.Now.Ticks.ToString()}.txt";
File.WriteAllText(filePath, textBoxValue);
}
if (dr == DialogResult.No)
{
continue;
}
}
else if (form is ImageDocumentForm)
{
MessageBox.Show("Please note that only text documents can be saved.", "Advisory:", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
Close();
}
This code works fine. I need it to be called when the user exits the program. I'm not able to assign this event to the form closing event in the design view.
Your event argument needs to be of the form FormClosingEventArgs e
Change that and try again.

How to update outlook Search folder result for a new search programmaticaly without changing the folder name

I created Outlook search folder using add-in express for a outlook plugin as below. it is based on this article.
is there similar way to update search folder name for a new result ?
private void adxOutlookEvents_AdvancedSearchComplete(object sender, object hostObj) {
Outlook.Search advancedSearch = null;
Outlook.Results advancedSearchResults = null;
Outlook.MailItem resultItem = null;
System.Text.StringBuilder strBuilder = null;
try {
advancedSearch = hostObj as Outlook.Search;
if (advancedSearch.Tag == advancedSearchTag) {
System.Diagnostics.Debug.WriteLine("!!! adxOutlookEvents_AdvancedSearchComplete");
advancedSearchResults = advancedSearch.Results;
if (advancedSearchResults.Count > 0) {
if (HostMajorVersion > 10) {
object folder = advancedSearch.GetType().InvokeMember("Save",
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.InvokeMethod |
System.Reflection.BindingFlags.Public,
null, advancedSearch,
new object[] { advancedSearchTag });
}
} else {
System.Diagnostics.Debug.WriteLine("!!!" + "There are no items found.");
}
}
} catch (Exception ex) {
MessageBox.Show(ex.Message, "An exception is occured");
} finally {
if (resultItem != null) Marshal.ReleaseComObject(resultItem);
if (advancedSearchResults != null)
Marshal.ReleaseComObject(advancedSearchResults);
}
}
Application.AdvancedSearch returns Search object. You can call Search.Save passing the name (string) - it will return MAPIFolder object. You can modify the MAPIFolder.Name property at any time.

How to share contact data of my app with whtsapp in .vcf /vcard format using xamarin forms

I have an application that creates a .vcf file after you input data. it stores storage provided by the phone, I want to click on a list view item and get the vcf file and share it via Email, SMS, WhatsApp, Skype etc how do I implement this in IOS and Android.
Thank you
I have got the answer of creating .vcf file which is given below. and for share that file follow this link : https://github.com/adamped/ShareDialog
private void Share_Clicked(object sender, EventArgs e)
{
try
{
var _btn = sender as Button;
var record = _btn.BindingContext as Contact;
int tempcontactID = record.ContactID;
if (record.CardFrontImage == null)
{
record.CardImage = record.CardBackImage;
}
else
{
record.CardImage = record.CardFrontImage;
}
string baseimage = Convert.ToBase64String(record.CardImage);
var vcf = new StringBuilder(); //vcf code start
vcf.AppendLine("BEGIN:VCARD");
vcf.AppendLine("VERSION:3.0");
vcf.AppendLine($"N:{record.ContactName};{string.Empty}; ;;");
vcf.AppendLine($"FN:{record.ContactName}");
vcf.AppendLine($"ORG:{record.CompanyName}");
vcf.AppendLine($"TITLE:{record.Designation}");
vcf.AppendLine($"PHOTO;ENCODING=BASE64;TYPE=PNG:{baseimage}");
vcf.AppendLine($"TEL;TYPE=work,voice;VALUE=uri:tel:{record.PhoneNumber}");
vcf.AppendLine("END:VCARD");
string fileName = Path.Combine("/storage/emulated/0/Android/data/com.Gamma.GammaNetworkingApp/files/", record.ContactID + record.ContactName + ".vcf");
using (var writer = new StreamWriter(fileName))
{
writer.Write(vcf.ToString());
}
string text = File.ReadAllText(fileName);
bool doesExist = File.Exists(fileName);
if (doesExist == true)
{
var share = DependencyService.Get<IShare>();
share.Show("Contact share", record.ContactName, fileName);
}
}
catch (Exception ex)
{
string test = ex.ToString();
Navigation.PushAsync(new HomePage());
}
}

How to get all contacts and write into file for Windows phone 7

The problem I want to solve:
Get all the contacts info like name and Mobile phone and write it into file and save in ISO.
How to use SearchAsync if I want to search available contacts in the phone?
How to iterate the return-results and write to file one by one of the contact into a file?
Here's the code I have:
private void btnSearch_Click(object sender, RoutedEventArgs e)
{
Contacts contacts = new Contacts();
contacts.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(contacts_SearchCompleted);
contacts.SearchAsync(displayName,FilterKind.DisplayName,null);
//search for all contacts
contacts.SearchAsync(string.Empty, FilterKind.None, null);
}
Update:
The below code throw NullException error if the PhoneNumber is Empty. Why?
How to get all the possibile phone number other than result.PhoneNumbers.FirstOrDefault().ToString();
Same question for EmailAddresses
Using this to search all contacts in the phone:
contacts.SearchAsync(searchterm, FilterKind.None, null);
void contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
{
int intTTL = e.Results.Count();
if (intTTL != 0)
{
MessageBox.Show(intTTL.ToString());
foreach (var result in e.Results)
{
string strTTL;
string strName = result.DisplayName;
string MobileNo = result.PhoneNumbers.FirstOrDefault().ToString();
strTTL = strName + "," + MobileNo;
MessageBox.Show(strTTL);
}
else
{
MessageBox.Show("You have not entered any contact info at all.");
}
}
Have a look at this article to see how to get the Contacts:
To iterate:
void contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
{
foreach(var contact in e.Results)
{
// write to Isolated storage
}
}
See this MSDN page for writing files in isolated storage

Resources