Using Visual Studio 2022
outlook 365 with IMAP account
VSTO addin.
c#
Event : newmaileX to capture every incoming email. If certain subject, then I enter text into the body. If body is html, I find the tag and insert after. I have create a button on ribbon to test, and the email subject is altered and new text is in the body.
fine so far.
When the newmailex is fired, it runs my code, but sometimes it does not save the changes, and sometimes it does.
Why ?
if I add "mailItem.Save()" this works, but I then get duplicates of the same email. Sometimes upto 10 duplicates. Is this an IMAP thing ? Below is my code.
void NewMail_Event(String entryIDCollection)
{
Outlook.NameSpace outlookNS = this.Application.GetNamespace("MAPI");
Outlook.MailItem mailItem = null;
try
{
string sTag;
string sBody;
int nPos;
sTag = "<table border=\"1\" cellspacing=\"0\"><tr bgcolor=\"#f5e942\"><td><font color=\"#FF0000\" size=\"4\">";
sTag += "This email originated from outside and was not listed in our safe senders list.<br>";
sTag += "DO NOT action, click on any links or open attachments unless you recognise the sender and know the content is safe.";
sTag += "</font></td></tr></table><br>";
string sSubject = null;
string filter = "[EXTERNAL]";
string[] sEmails = entryIDCollection.Split(',');
foreach (string sEmail in sEmails)
{
mailItem = (Outlook.MailItem)outlookNS.GetItemFromID(sEmail, Type.Missing);
if (mailItem.Subject != null)
{
File.AppendAllText("c:\\1data\\desktop\\vstolog.txt", mailItem.Subject + "\r\n");
if (mailItem.Subject.Length >= 10)
{
if (mailItem.Subject.ToUpper().StartsWith(filter))
{
sSubject = mailItem.Subject.Substring(filter.Length, mailItem.Subject.Length - filter.Length);
mailItem.Subject = sSubject;
sBody = mailItem.HTMLBody;
if (sBody.Contains("<body>") || sBody.Contains("<BODY>"))
{
if (sBody.Contains("<BODY>"))
{
sBody = sBody.Replace("<BODY>", "<body>" + sTag);
}
else
{
sBody = sBody.Replace("<body>", "<body>" + sTag);
}
}
else
{
if (sBody.Contains("<body") || sBody.Contains("<BODY"))
{
if (sBody.Contains("<body"))
{
nPos = sBody.IndexOf("<body", 0);
}
else
{
nPos = sBody.IndexOf("<BODY", 0);
}
nPos = sBody.IndexOf(">", nPos);
sBody = sBody.Insert(nPos + 1, sTag);
}
else
{
sBody = sTag + sBody;
}
}
if (mailItem.BodyFormat == OlBodyFormat.olFormatHTML)
{
mailItem.HTMLBody = sBody;
}
else
{
mailItem.Body = sBody;
}
//mailItem.Close(OlInspectorClose.olSave);
}
}
}
Marshal.ReleaseComObject(mailItem);
mailItem = null;
}
}
catch (Exception eX)
{
MessageBox.Show(eX.Message);
}
finally
{
if (mailItem != null) Marshal.ReleaseComObject(mailItem);
mailItem = null;
if (outlookNS != null) Marshal.ReleaseComObject(outlookNS);
outlookNS = null;
}
}
You can find similar issues described in case of IMAP profiles configured in Outlook, see IMAP Sent Messages are duplicated and unread in Sent Items folder for more information.
I suppose you are handling the NewMailEx event of the Application class, not the NewMail one. There are several aspects in the code:
string[] sEmails = entryIDCollection.Split(',');
The EntryIDsCollection string contains the Entry ID that corresponds to that item. Note that this behavior has changed from earlier versions of the event when the EntryIDCollection contained a list of comma-delimited Entry IDs of all the items received in the Inbox since the last time the event was fired.
However, depending on the setup on the client computer, after a new message arrives in the Inbox, processes like spam filtering and client rules that move the new message from the Inbox to another folder can occur asynchronously. You should not assume that after these events fire, you'll always get a one-item increase in the number of items in the Inbox.
As a possible workaround you may try to handle the ItemAdd event on the target folder instead.
Related
using Outlook = Microsoft.Office.Interop.Outlook;
I'm able to sending the mail using above Outlook dll but I want to send a mail which I configured in the the logic "FROM' MailID only
I'm trying to sending the mail which I configured mail only "FROM", but while I'm sending the mail I'm getting error
Outlook does not recognize one or more names
where did I make the mistake and how to send the logically written FROM MailID only?
public int sendMFSwitchMail(MAEEmail mAEEmail , string data)
{
try
{
// Create the Outlook application.
Outlook.Application oApp = new Outlook.Application();
// Create a new mail item.
Outlook.MailItem oMsg = (Outlook.MailItem)oApp.CreateItem(Outlook.OlItemType.olMailItem);
//string pathfilecontent = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + #"\payment_failed_mail.html";
string pathfilecontent = Server.MapPath(#"\payment_failed_mail.html");
string contentmailstr = "";
//if (string.IsNullOrEmpty(mAEEmail.Body))
// contentmailstr = File.ReadAllText(pathfilecontent);
//else
// contentmailstr = mAEEmail.Body;
contentmailstr = File.ReadAllText(pathfilecontent);
contentmailstr = contentmailstr.Replace("Full_Name", data);
//contentmailstr = contentmailstr.Replace("Existing_Baskets_Constituents", oldfund);
//contentmailstr = contentmailstr.Replace("New_Baskets_Constituents", newfund);
oMsg.HTMLBody = contentmailstr;// sb.ToString();
//oMsg.HTMLBody = mAEEmail.Body;
//Subject line
oMsg.Subject = mAEEmail.Subject;
//if (!string.IsNullOrEmpty(mAEEmail.BCC))
// oMsg.BCC = mAEEmail.BCC;
Outlook.Recipients oRecips = (Outlook.Recipients)oMsg.Recipients;
// {"Outlook does not recognize one or more names. "}
oRecips.Add(mAEEmail.From);//from mail:abc#cyient.com[outlook, programmatically configured mailid]
oRecips.Add(mAEEmail.Password);
//Change the recipient in the next line if necessary.
Outlook.Recipient oRecip = (Outlook.Recipient)oRecips.Add(mAEEmail.To); // to mail : a#gmail.com
oRecip.Resolve();
// Send.
//Console.WriteLine("Sending email...");
oMsg.Send();
// Clean up.
oRecip = null;
oRecips = null;
oMsg = null;
oApp = null;
//return 1;
}
catch(Exception ex)
{
//MessageBox.Show("Error is :" + ex.Message.ToString());
//throw;
Response.Write("Error is :" + ex.Message.ToString());
//loggingService.Log("Error is:" + ex.Message.ToString());
}
return 1;
}
You are adding the sender as one of the recipients, that does not make much sense. The error you are getting means the name cannot be resolved, which means it is not an SMTP address or a name in your contacts. Are you sure you the value if just an SMTP address?
To specify the sender, you need to either set the MailItem.SendUsingAccount property to one of the Account objects from the Application.Session.Accounts collection, or, in case of Exchange, set the MailItem.SentOnBehalfOfName property to the name (not address) of another Exchange user on whose behalf you are allowed to send.
I'm trying to get outlook Email using Microsoft.Office.Interop.Outlook but in cases where the folder has a lot of emails (for example 1904 Emails) I'm getting only 571 emails.
here's my code:
Application oApp = new Application();
_NameSpace oNS = (_NameSpace)oApp.GetNamespace("MAPI");
MAPIFolder inbox = oNS.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
var emails = inbox.Items;
int emailsCount = emails.Count;
when I open outlook I see the number 1904 next to the Inbox folder, but when I scroll down I see the line "there are more items in this folder on the sever"
dose anyone know how can I download all my Emails using outlook interop?
this is my code from a working app:
A lot of it seems cracking a nut with a sledge hammer however, this hasnt failed me in many years.
MAPIFolder f;
int retries = 0;
while (!connected && retries < 2)
{
doUpdateStatus("Connecting");
try
{
app = new Application();
NameSpace ns = app.GetNamespace("MAPI");
f = ns.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
doUpdateStatus("Connected to outlook");
doUpdateStatus("Walking Outlook Folders .. Please wait");
try
{
doUpdateStatus("");
if (DoSync)
{
try
{
doUpdateStatus("Syncing");
SyncObject _syncObj = null;
_syncObj = ns.SyncObjects.AppFolders;
_syncObj.SyncEnd += _syncObj_SyncEnd;
ns.SendAndReceive(false);
syncing = true;
_syncObj.Start();
while (syncing)
{
Thread.Sleep(10);
}
connected = true;
}
catch
{
doUpdateStatus("Sync failed");
}
finally
{
syncing = false;
}
}
else
{
doUpdateStatus("Outlook sync disabled");
connected = true;
}
}
catch
{
doUpdateStatus("Unable to connect to Outlook and Load folders");
app.Quit();
retries++;
Thread.Sleep(5000);
}
}
catch
{
doUpdateStatus("Unable to connect to Outlook");
if (app!=null) app.Quit();
retries++;
Thread.Sleep(5000);
}
}
private static void _syncObj_SyncEnd()
{
syncing = false;
}
You can either force Outlook to download all items (make sure the slider in the Exchange account properties is set to "All' rather than something like "12 months") or you can reopen the folder in the online mode - in Extended MAPI (C++ or Delphi), you can do that by using the MAPI_NO_CACHE flag when calling IMAPISession::OpenEntry or IMsgStore::OpenEntry. If Extended MAPI is not an option, you can use Redemption (I am its author):
MAPI_NO_CACHE = &H200
MAPI_BEST_ACCESS = &H10
set OutlookFolder = Application.ActiveExplorer.CurrentFolder
set Session = CreateObject("Redemption.RDOSession")
Session.MAPIOBJECT = Application.Session.MAPIOBJECT
set OnlineFolder = Session.GetFolderFromID(OutlookFolder.EntryID, OutlookFolder.StoreID, MAPI_NO_CACHE + MAPI_BEST_ACCESS)
MsgBox OnlineFolder.Items.Count
I'm having a problem with email sending in C#.
I'm working on an add-in and everything is going well. I can send my mails, like i want, but not "two times in a row".
For example, my add-in open a Form and after the user action an email is sent.
When the mail is sent, the form is closed and that's okay.
But some time, i need to send two separate emails and the body of second email is always empty. By the way, i fill the "body" of my mails with Word (Microsoft.Office.Interop.Word) to have some formatted text.
If I use the .Body property there is no problem.
Now, I'm wondering if it's not the fault of "Word" because the email part is working but only the body is empty.
I tried to send my mails in the inverse order to see if it's occurs always with the second mail and i was right. It's not about the email or his content but more about being the second sent.
It may be some things which haven't been released yet(not properly released objects) or something like that but i'm doing already it.
That's how i'm doing..
Outlook.MailItem mailItem = (Outlook.MailItem)new Outlook.Application().CreateItem(Outlook.OlItemType.olMailItem);
try
{
mailItem.CC = currentUserExchange.PrimarySmtpAddress;
mailItem.Importance = Outlook.OlImportance.olImportanceHigh;
mailItem.Subject = "XXX";
mailItem.To = finalRecipients;
fillBody(mailItem, mailBody);
mailItem.Send();
}
catch (Exception ex) { }
finally
{
releaseObject(mailItem);
}
if (moderatorPin != String.Empty)
{
Outlook.MailItem mailItemSecurity = (Outlook.MailItem)new Outlook.Application().CreateItem(Outlook.OlItemType.olMailItem);
try
{
mailItemSecurity.Importance = Outlook.OlImportance.olImportanceHigh;
mailItemSecurity.Subject = "XXX";
mailItemSecurity.To = currentUserExchange.PrimarySmtpAddress;
fillBody(mailItemSecurity, mailBodySecure);
mailItemSecurity.Send();
}
catch (Exception ex) { MessageBox.Show("error : " + ex.Message); }
finally
{
releaseObject(mailItemSecurity);
}
}
and :
private void fillBody(Outlook.MailItem mailItem, String bodyMail)
{
Word.Document document = mailItem.GetInspector.WordEditor;
Word.Range rng = document.Paragraphs[1].Range;
try
{
document.Paragraphs[1].LineSpacingRule = Word.WdLineSpacing.wdLineSpaceSingle;
rng.set_Style(Word.WdBuiltinStyle.wdStyleHtmlKbd);
rng.Font.Color = (Word.WdColor)(fontColor.R + 0x100 * fontColor.G + 0x10000 * fontColor.B);
rng.Text = bodyMail;
rng.Select();
}
catch (Exception ex)
{
MessageBox.Show("XXX");
}
finally
{
releaseObject(rng);
releaseObject(document);
}
}
In Form1 in the backgroundworkerdowork event I did:
se.SendPhotos(photofilesDir + "\\" + "photofiles.zip");
se.SendPhotos(photofilesDir1 + "\\" + "photofiles.zip");
se.SendPhotos(photofilesDir2 + "\\" + "photofiles.zip");
se.SendPhotos(photofilesDir3 + "\\" + "photofiles.zip");
In the se class SendEmail I did:
public void SendPhotos(string fileNameToSend)
{
try
{
MailAddress from = new MailAddress("test#gmail.com", "User " + (char)0xD8 + " Name",
System.Text.Encoding.UTF8);
MailAddress to = new MailAddress("test#test");
photosmessage = new MailMessage(from, to);
photosmessage.Body = "Please check the log file attachment I have some bugs.";
string someArrows = new string(new char[] { '\u2190', '\u2191', '\u2192', '\u2193' });
photosmessage.Body += Environment.NewLine + someArrows;
photosmessage.BodyEncoding = System.Text.Encoding.UTF8;
photosmessage.Subject = "Log File For Checking Bugs" + someArrows;
photosmessage.SubjectEncoding = System.Text.Encoding.UTF8;
Attachment myAttachment = new Attachment(fileNameToSend, MediaTypeNames.Application.Octet);
photosmessage.Attachments.Add(myAttachment);
SmtpClient photossend = new SmtpClient("smtp.gmail.com", 587);
photossend.SendCompleted += new SendCompletedEventHandler(photossend_SendCompleted);
photossend.EnableSsl = true;
photossend.Timeout = 10000;
photossend.DeliveryMethod = SmtpDeliveryMethod.Network;
photossend.UseDefaultCredentials = false;
photossend.Credentials = new NetworkCredential("usern", "userpass");
string userState = "test message1";
photossend.SendAsync(photosmessage, userState);
SendLogFile.Enabled = false;
fname = fileNameToSend;
}
catch (Exception errors)
{
Logger.Write("Error sending message :" + errors);
}
}
private void photossend_SendCompleted(object sender, AsyncCompletedEventArgs e)
{
photosmessage.Dispose();
if (fname == #"C:\Users\Simbalip\AppData\Local\outputphotos\photosfiles3" + "\\" + "photofiles.zip")
{
photossendended = true;
}
}
The problem in the backgroundworkerdowork it never send the last one photofilesDir3.
I used a breakpoint and its getting to : photossendended = true;
But in my email im getting only 3 files sent for me and not 4.
When I used a breakpoint on the backgroundworker and did F11 I saw that its doing the 4 sendings one after one without waiting .
Each time the photofiles.zip have different files inside.
Now I check did a breakpoint on the line:
if (fname == #"C:\Users\Simbalip\AppData\Local\outputphotos\photosfiles3" + "\\" + "photofiles.zip")
And when it get there its all the time true it does ==
fname never C:\Users\Simbalip\AppData\Local\outputphotos\photosfiles2 or 1 or photosfiles
But in the end im getting 3 different photofiles.zip files each contain different files but one of the files never sent.
Myabe I need to make somehow that when it send email it will somehow untill the first one is sent then send the next one like in Process there is WaitForExit() so maybe something like that with the emails ?
The documentation for SmtpClient alludes to the fact that it doesn't support parallel operations.
If there is an e-mail transmission in progress and you call SendAsync or Send again, you will receive an InvalidOperationException.
http://msdn.microsoft.com/en-us/library/system.net.mail.smtpclient.aspx
I would recommend not sending the next email until the SendCompleted event has been raised. This means a drastic change in your code (where each call to SendPhotos really just adds something to a collection of pending send mail operations that your process in the background)
I am creating a program that sends a text message and then depending on the reply I want to perform a specific action. Anyways here is my code:
using Microsoft.Office.Interop.Outlook;
using Outlook = Microsoft.Office.Interop.Outlook;
static void Main()
{
var outlook = new Microsoft.Office.Interop.Outlook.Application();
// fire event when a new email arives
outlook.NewMailEx += new ApplicationEvents_11_NewMailExEventHandler(oApp_NewMailEx);
// etc
}
static void oApp_NewMailEx(string EntryIDCollection)
{
var outlook = new Microsoft.Office.Interop.Outlook.Application();
MailItem temp = (MailItem)outlook.Session.GetItemFromID(EntryIDCollection, Missing.Value);
var body = temp.Body; // the body of the email is null! I tried waiting and it is null until I open it...
Console.WriteLine(body);
}
This part is not important but I send the "text message" with this function:
// send text message "att.txt.net only works with at&t phones"
public static int SendEmail(string recipeint = "9546543930#att.txt.net")
{
try
{
// Create the Outlook application by using inline initialization.
Outlook.Application oApp = new Outlook.Application();
//Create the new message by using the simplest approach.
Outlook.MailItem oMsg = (Outlook.MailItem)oApp.CreateItem(Outlook.OlItemType.olMailItem);
Outlook.Accounts accounts = oMsg.Session.Accounts;
foreach (Outlook.Account account in accounts)
{
// When the e-mail address matches, send the mail.
if ( account.SmtpAddress.Contains("gmail") )
{
oMsg.SendUsingAccount = account;
break;
}
}
// If you want to, display the message.
oMsg.Display(true); //modal
//Add a recipient.
Outlook.Recipient oRecip = (Outlook.Recipient)oMsg.Recipients.Add(recipeint);
oRecip.Resolve();
//Set the basic properties.
oMsg.Subject = "This is the subject of the test message";
oMsg.Body = "This is the text in the message.";
//Add an attachment.
// TODO: change file path where appropriate
//String sSource = "C:\\setupxlg.txt";
//String sDisplayName = "MyFirstAttachment";
//int iPosition = (int)oMsg.Body.Length + 1;
//int iAttachType = (int)Outlook.OlAttachmentType.olByValue;
//Outlook.Attachment oAttach = oMsg.Attachments.Add(sSource, iAttachType, iPosition, sDisplayName);
//Send the message.
oMsg.Save();
oMsg.Send();
//Explicitly release objects.
oRecip = null;
//oAttach = null;
oMsg = null;
oApp = null;
}
// Simple error handler.
catch (System.Exception e)
{
Console.WriteLine("{0} Exception caught: ", e);
}
//Default return value.
return 0;
}
So I am able to send an email with my gmail account and when I reply to the text message the function oApp_NewMailEx gets executed with the id of the new email. I am able to get the subject but the body does not get downloaded until I hover my mouse over the email or open the email. I already waitied 2 minutes on another thread and then tried to see the body and it was still null.
Edit note to make this work I have:
It looks gray out because I did not run outlook as an administrator. If You run outlook as an admin you will be able to update the security settings.
I also imported the Microsoft Outlook 14.0 Object library as a reference.
Once I received the email I called the send and receive method. wait a little and then I was able to read the body.
outlook.Session.SendAndReceive(false);