can't get the body/attachments of new mails in outlook - c#

I've developed an Outlook plugin using C# where for each new mail received, i get(and save) the sender/subject/the body of email & the attachments. Well, the last 2 gave me a headache. I can see the sender and the subject of the new mail but for the body&attachments it seems that is a problem. I've used NewMailEx for getting the new mails in Inbox. The function looks like this:
private void Application_NewMailEx(string EntryIDCollection)
{
string[] entryIdArray = EntryIDCollection.Split(',');
foreach (string entryId in entryIdArray)
{
try
{
Outlook.MailItem item = (Outlook.MailItem)Application.Session.GetItemFromID(EntryIDCollection, null);
string subj = item.Subject; //works
string to = item.To; //works
string bec = item.BCC; //does not work but dont care
string body = item.Body; //DOES NOT SAVE THE BODY OF THE NEW MAIL RECEIVED
string final = "Sender: " + item.SenderEmailAddress + "\r\n" + "Subject: " + subj + "\r\n" + "BCC: " + bec + "\r\n" + "TO: " + to + "\r\n\n" + "Body: " + body + "\r\n\n";
System.IO.File.AppendAllText(#"D:\tmp\atr.txt", final);
//the result of item.attachments.count is always 0 , even though I've
//sent mails with a different number of attachments. So the if
//statement is false
if (item.Attachments.Count > 0)
{
for (int i = 1; i <= item.Attachments.Count; i++)
{
item.Attachments[i].SaveAsFile(#"D:\tmp\" + item.Attachments[i].FileName);
}
}
Marshal.ReleaseComObject(item);
}
catch (System.Exception e)
{
MessageBox.Show(e.Message);
}
}
}

Where does the Item variable come from? You need to initialize it using Application.Session.getItemfromID().

I'm writing in VBA, so I feel like posting my code here would be a faux pas, but I have come to a solution using similar Object Libraries from the Outlook application that I think transfer well to your C++ intentions.
First of all, switching to POP3 certainly fixes this problem, but you're stuck using POP3, which is only ideal from a programming standpoint.
The solution I have found follows this algorithm:
//Generate Outlook MailItem Object, "item"
//If item.DownloadState is not 1,
//item.Display
//item.Close(1)
//Perform end of code operations
//Call Function that is identical to Application_NewMailEx but is not Application_NewMailEx because Application_NewMailEx is a function that is thrown during the incoming mail event.
//Else,
//Perform Intended Code
You see how calling a function identical to Application_NewMailEx creates a kind of loop because if item.DownloadState is not 1, you'll be calling that function again? I get that this isn't the most ideal coding practice, but I have scoured the internet and Outlook Application and Outlook Object Library experts have no idea how to solve this problem any other way (in fact, no one even proposes THIS solution)
For my full VBA Solution Check out:
https://superuser.com/questions/894972/outlook-strange-item-attachments-error/990968#990968

Related

How to get mail informations from its local path and ReplyAll to it using Outlook application

So i need to get informations such as :
Sender mail address (to later get his Domain profile informations)
Mail subject (which should be the "filepath" minus the "msg" extension anyway).
And then, replying to it just like i would push "ReplyAll" button in Outlook. So the reply needs to get the usual Headers such as "From : ....", "To : ...", "Cc : ..." and so on.
All i need is to change its subject, and delete the address depending on the "FromAddress" of the user that will push the button
I've read a bit here and there, and people are talking about a MailItem, but there's no informations about HOW to get this item or how to build it from a .msg file.
What i have to do comes after a specific user action.
The user is supposed to Drag&Drop the mail into a panel, from there i get its local path.
Thanks for your time !
Edit#1
I managed to find out to get informations and to set a .msg file to a MailItem :
Outlook.Application appOutlook = new Outlook.Application();
var email = (Outlook.MailItem)appOutlook.Session.OpenSharedItem(filepath);
string getCC = "";
string getFrom = ""; // From is never null
string getTo = "";
string getSubject = "";
bool lengthCC = email.CC.HasValue();
bool lengthTo = email.To.HasValue();
bool lengthSubject = email.Subject.HasValue();
if (lengthCC)
{
getCC = email.CC.ToString();
}
// and so on...
//
// Display it in MessageBox to confirm test succeeded :
MessageBox.Show("CC : " + getCC +
"\nFrom : " + getFrom +
"\nTo : " + getTo +
"\nSubject : " + getSubject);
email.Close(Outlook.OlInspectorClose.olDiscard);
Now i just need to build the ReplyAll Body and add headers manually myself i guess...
Edit#2
No need to rewrite Headers apparently, doing so :
Outlook._MailItem reply = email.ReplyAll();
reply.To = getFrom;
reply.CC = getCC;
reply.Body = "SomeReplyMessage" + reply.Body;
reply.Send();
Marshal.ReleaseComObject(appOutlook);
Marshal.ReleaseComObject(email);
Marshal.ReleaseComObject(reply);
But it erased the separator above the original message, i'll find a way to re-add it !!!
Edit#3
And there it is, the so-called "separator" wasn't displaying, because i wasn't re-stating an HTML Body !
So, to keep it you can do this :
reply.BodyFormat = Outlook.OlBodyFormat.olFormatHTML;
string ReplyMessageBody = String.Format("AddSome<br>HTMLCode<br>ThereAndHere<br>ButFinishWith : BodyTag</body>");
reply.HTMLBody = ReplyMessageBody + reply.HTMLBody;
Or simpler if you don't need your reply to be an HTML one :
reply.BodyFormat = Outlook.OlBodyFormat.olFormatHTML;
reply.HTMLBody = "AddSomeReplyMessage" + reply.HTMLBody;
Outlook does not work directly wit MSG files - when you call CreateFromTemplate or even OpenSharedItem, Outlook creates a new item in its default store and imports the MSG or OFT file. It does not expose anything that would you let you figure out that the message came from a file; the item is indistinguishable from an item created directly using CreateItem or MAPIFolder.Items.Add.
See edits on original question for answer !

REST API Consecutive Call is not working

SOLVED
The problem was sending the number with double quotes like "40".
So I replaced quotes with empty space and It worked.
This is the code.
HRMID = HRMID.Replace('"', ' ').Trim();
I am trying to call my REST service consecutively but only one of them is working when I do that.
If I call only one of them in one block it works but two of them in one function block is causing problems I think,I don't know why.
Maybe it is something about restriction in the service.
There is no Error just it is not updating the Database.
If I use it alone it works so call is correct.
This is my code , I am waiting for suggestions.
Thanks!
private void GameClosed(object sender, EventArgs e)
{
// Do your stuff when the game closed.
try
{
var client = new WebClient();
var result = client.DownloadString(wsUrl + "/rest/gethrmid/" + UserValues[4]);// Only the first REST API call is working.This one works.
MessageBox.Show("Result is :" + result);
string HRMID = result;
StreamReader SR = new StreamReader("D:/HRMSession.txt");
string hrmValues = SR.ReadToEnd();
client.DownloadString(wsUrl + "/rest/inserthrmsession/" + HRMID + "/" + hrmValues);//This one is not working if i put here.
}
catch (Exception a)
{
MessageBox.Show(a.ToString());
}
}
EDIT:
If I write it as hardcoded it works but if I use the value that is coming from first call it doesn't work.
client.DownloadString(wsUrl + "/rest/inserthrmsession/" + 40 + "/" + hrmValues);//Works.
But I can not convert the value of HRMID to Int because operation contract is string...

Mail Merge sendgrid c#

Using the SendGrid C# API. I have spent several hours looking through the documentation here and more frustratingly here. I have searched through several SO posts and messed around with the code but to no avail.
Basically I have an email template that begins like so:
--------------------------
{RecipientName},
here is the rest of the email body...
--------------------------------
I simply want every instance of {RecipientName} to be the first name of the person receiving the email. I see there is a Personalization class but there doesn't seem to be any documentation or actual examples of how to use it for this purpose.
Here is the code which works great for actually sending the email to the recipients:
List<EmailAddress> allRecipients = new List<EmailAddress>();
for (int i = 0; i < notice.AllRecipients.Count; i++)
{
_Logger.Info("processing recipient number " + i);
Employee e = _companyLogic.GetEmployeeByEmployeeId(notice.AllRecipients[i].EmployeeId);
EmailAddress email = new EmailAddress(e.EmailAddress, e.FirstName + " " + e.LastName);
allRecipients.Add(email);
}
msg.AddTos(allRecipients);
It would seem the perfect place to add the Substitution would be in the for loop. But I am not seeing how this can be accomplished.
I believe this is the documentation you need: https://github.com/sendgrid/sendgrid-csharp/blob/master/USE_CASES.md#transactional_templates

MailItem.Display(true|false) exception when used in WinForms

I'm creating an Outlook Add In, which has a subform. The form has a button on it, through which I would like to generate a mailitem, if the user clicks it. I'd like to auto-populate some info in the email, and then leave it for the user to send at their leisure.
My code looks like the following:
private void btnMailDocNotice_Click(object sender, EventArgs e)
{
string clientInfo = string.Empty;
string matInfo = string.Empty;
string author = string.Empty;
string dType = string.Empty;
string fLocation = string.Empty;
string keyWords = string.Empty;
string docName = string.Empty;
clientInfo = this.mCboClient.Text + " " + lblClient;
matInfo = this.mCboMatter.Text + " " + lblMatter;
author = this.txtAuthor.Text;
dType = this.mCboDocType.Text.ToUpper();
fLocation = this.txtSavePath.Text;
keyWords = this.txtKeyWords.Text;
docName = this.txtDocName.Text;
this.sendDocNotice = true;
this.Hide();
CreateMailItem(clientInfo, matInfo, author, dType, this.operatorCode.ToUpper(), fLocation, keyWords, docName);
this.Show();
}
private void CreateMailItem(string clientInfo, string matInfo, string author, string dType, string profiledBy, string fLocation, string keyWords, string docName)
{
this.DNoticeItem = (Outlook.MailItem)ThisAddIn.myApp.CreateItem(Outlook.OlItemType.olMailItem);
this.DNoticeItem.Subject = "Document: " + docName;
this.DNoticeItem.HTMLBody = "<span style=\"font-family:Calibri; font-size: 11pt;\">KeyWords: " + keyWords + "</span>";
this.DNoticeItem.HTMLBody += "<br />Client: " + clientInfo;
this.DNoticeItem.HTMLBody += "<br />Matter: " + matInfo;
this.DNoticeItem.HTMLBody += "<br />Author: " + author;
this.DNoticeItem.HTMLBody += "<br />Doc Type: " + dtClient;
this.DNoticeItem.HTMLBody += "<br />Profiled by: " + profiledBy;
this.DNoticeItem.HTMLBody += "<br />File://" + fLocation;
this.DNoticeItem.Importance = Outlook.OlImportance.olImportanceNormal;
this.DNoticeItem.Display(false);
}
The problem that I'm running into, is it fires an exception on the mailitem.display function, whether I use true or false (doing a bit of research says that determines if the user can access the main Outlook window or not while the mailitem is open). The exception is a COM Exception of "A dialog box is open. Close it and try again". I've tried hiding the WinForm prior to the function call that creates the mail item, then show it again after the function is exited, but it didn't work. I've tried a version of the code where I use System.Diagnostics.Process.Start() to try and open the file after saving it to disk, and while it doesn't fire an exception from the add in, Outlook prompts the user with a message box of the same message from the ComException. I even tried creating a field to see if the doc notice email should be drafted, and thought to have the code take care of that after a form.close() call, thinking the close call would at least dispose of the dialog box that was locking Outlook, and I still got the same exception.
Is there a way to achieve what I want? Does anyone have any suggestions? I'm kind of stuck at the moment, and would appreciate any help/pointers/suggestions anyone has to offer in this issue. My sincere apologies if this is a duplicative question - I couldn't find a good answer to the question. Thank you in advance for your time.
Firstly, why not display yoru own form modelessly?
Secondly (and this is pretty important) do not use code like the following
this.DNoticeItem.HTMLBody += "<br />Client: " + clientInfo;
Every time you run a line like that, you retrieve HTMLBody, add some stuff to it (making the HTML malformed), then set HTMLBody again and force Outlook to make sense of your (malformed) HTML. This (assuming Outlook can parse and fix your HTML) will result in HTML being returned to be different from what you set it to.
Build the HTML body once using a regular string, and set HTMLBody property only once.

JScript runtime error in Sharepoint Webpart

I'm trying to design a webpart that looks at a list of news items, and initially prints all the rows in order by date. If the user selects a type of news item, then only those news items will be displayed (again, in order by date). The problem is that my webpart keeps throwing up this error when I try to debug it:
Microsoft JScript runtime error: Unknown runtime error
And this mess pops up behind it:
RTE.RteUtility.$1n = function($p0, $p1) {
if (RTE.RteUtility.isInternetExplorer() && $p0.tagName === 'TABLE') {
var $v_0 = document.createElement('DIV');
$v_0.innerHTML = '<table>' + $p1 + '</table>';
while ($p0.childNodes.length > 0) {
$p0.removeChild($p0.childNodes[0]);
}
RTE.RteUtility.$1E($v_0.firstChild, $p0);
}
else {
$p0.innerHTML = '<div>RTE</div>' + $p1;
$p0.removeChild($p0.firstChild);
}
}
The line: "$p0.innerHTML = 'RTE' + $p1" seems to be causing the problem. Well, otherwise, that's a really specific error message, thanks Microsoft. :/
The error seems to happen after CreateChildControls is called by NewsFeed.cs. My best theory right now is maybe something in NewsFeedUserControl.ascx.cs is causing an error, but as I'm a total neophyte at SharePoint I have no idea what that could possibly be. Is it because of this code in Page_Load?
protected void Page_Load(object sender, EventArgs e)
{
list = web.Lists["NewsFeedLI"];
query.Query = "<Where><IsNotNull><FieldRef Name='Headline' /></IsNotNull></Where></Query>" +
"<OrderBy<FieldRef Name='Article_x0020_Date' Ascending='True' /></OrderBy>";
SPListItemCollection result = list.GetItems(query);
foreach (SPListItem item in result)
{
newsList.Text = newsList.Text + item["Headline"].ToString() + Environment.NewLine;
newsList.Text = newsList.Text + item["Summary"].ToString() + Environment.NewLine + Environment.NewLine;
}
}
See, I don't know.
Try predefining the text that you return in your loop. If the web part looks OK with basic text (e.g. "Hello World") but not with more advanced values then that it where your problem lies.
You will want to ensure that you apply the appropriate encoding to any output you are rendering to the screen as this may be causing you issues.

Categories