I am trying to make a function that fetches the body of an email with a given search criteria. When I fetch items from the mailbox and try to get the body, it only writes part of the body. I want ALL text from the body instead. How can I do this? This is what I have so far:
Outlook.Application myApp = new Outlook.Application();
const string PR_HAS_ATTACH = "http://schemas.microsoft.com/mapi/proptag/0x0E1B000B";
// Obtain Inbox
Outlook.Folder folder = myApp.Session.GetDefaultFolder(OlDefaultFolders.olFolderInbox) as Microsoft.Office.Interop.Outlook.Folder;
Outlook.Table table = folder.GetTable(Microsoft.Office.Interop.Outlook.OlTableContents.olUserItems);
// Remove default columns
table.Columns.RemoveAll();
// Add using built-in name
table.Columns.Add("Subject");
table.Columns.Add("ReceivedTime");
table.Sort("ReceivedTime", Microsoft.Office.Interop.Outlook.OlSortOrder.olDescending);
// Add using namespace
// Date received
table.Columns.Add("urn:schemas:httpmail:textdescription");
while (!table.EndOfTable)
{
Outlook.Row row = table.GetNextRow();
if (row["Subject"].ToString().ToLower().Contains(subject.Text.ToLower()) && row["ReceivedTime"].ToString().Contains(cellCreationDate))
{
body.Text = row["urn:schemas:httpmail:textdescription"].ToString();
}
}
You can't use Outlook.Table and then urn:shcemas:httpmail.textdescription to get the entire body. textdescription only returns the first 255 characters of the body as noted here http://msdn.microsoft.com/en-us/library/office/ff861580.aspx.
here is an alternative.
// change this in your code
body.Text = row["urn:schemas:httpmail:textdescription"].ToString();
// To this
Microsoft.Office.Interop.Outlook.MailItem mailItem =
myApp.Session.GetItemFromID(row["EntryID"]);
body.Text = mailItem.Body;
Related
I am currently making an Outlook Add In and I successfully got the attachments from an email.
Here is the attachment:
And here is the method:
public static List<AttachmentResponse> GetAttachments(
AttachmentSampleServiceRequest request)
{
// Create an ExchangeService object, set the credentials and the EWS URL.
var service = new ExchangeService
{
Credentials = new OAuthCredentials(request.AttachmentToken),
Url = new Uri(request.EwsUrl)
};
var result = new List<AttachmentResponse>();
var getAttachmentsResponse =
service.GetAttachments(request.Attachments.Select(attachment => attachment.id).ToArray(),
null,
new PropertySet(BasePropertySet.FirstClassProperties,
ItemSchema.MimeContent));
var getAttachmentResponsesFiltered = getAttachmentsResponse.Where(file =>
file.Result == ServiceResult.Success && file.Attachment.ContentType == "application/pdf");
{
result.AddRange(from attachmentResponse in getAttachmentResponsesFiltered
let fileAttachment = attachmentResponse.Attachment as FileAttachment
let base64String =
Convert.ToBase64String(fileAttachment?.Content, 0, (int) fileAttachment?.Content.Length)
select new AttachmentResponse
{
Id = attachmentResponse.Attachment.Id, Name = attachmentResponse.Attachment.Name,
Type = attachmentResponse.Attachment.ContentType, FileBase64 = base64String
});
}
return result;
}
The Open XML SDK which you could use on the server-side doesn't provide anything for generating PDF files. You may try to use something like iText or iTextSharp or any other third-party components designed for the server-side execution.
In case of COM add-ins there is no need to use EWS at all. Use the Attachments property of Outlook items to deal with attached files and items. The MailItem.Attachments property returns an Attachments object that represents all the attachments for the specified item. You can access attachments in the collection by using the either the index number of the object, or a value used to match the default property of an object in the collection. For example, here is a sample VBA code which illustrates how you could use the Outlook object model from your add-in:
Sub SaveAttachment()
Dim myInspector As Outlook.Inspector
Dim myItem As Outlook.MailItem
Dim myAttachments As Outlook.Attachments
Set myInspector = Application.ActiveInspector
If Not TypeName(myInspector) = "Nothing" Then
If TypeName(myInspector.CurrentItem) = "MailItem" Then
Set myItem = myInspector.CurrentItem
Set myAttachments = myItem.Attachments
'Prompt the user for confirmation
Dim strPrompt As String
strPrompt = "Are you sure you want to save the first attachment in the current item to the Documents folder? If a file with the same name already exists in the destination folder, it will be overwritten with this copy of the file."
If MsgBox(strPrompt, vbYesNo + vbQuestion) = vbYes Then
myAttachments.Item(1).SaveAsFile Environ("HOMEPATH") & "\My Documents\" & myAttachments.Item(1).DisplayName
End If
Else
MsgBox "The item is of the wrong type."
End If
End If
End Sub
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 !
I'm using ExchangeWebServices C#.
I'm trying to send an email to distributio list, so
I'm created a group as follow:
private void CreateGroup(ExchangeService service)
{
// Create a new contact group object.
ContactGroup myContactGroup = new ContactGroup(service);
// Give the group a name.
myContactGroup.DisplayName = "TestContactGroup";
// Add some members to the group.
myContactGroup.Members.Add(new GroupMember("Euser#mydomain.com"));
myContactGroup.Members.Add(new GroupMember("Euser1#mydomain.com"));
myContactGroup.Members.Add(new GroupMember("Euser2#mydomain.com"));
// Save the group.
myContactGroup.Save();
}
Now I'm trying to send email to this group, how can i do that?
What i'm tried:
EmailMessage email = new EmailMessage(service);
email.ToRecipients.Add("TestContactGroup");//Throw an exception "At least one recipient isn't valid."
//email.ToRecipients.Add("TestContactGroup#mydomain.com");//"Return" the mail that "The email address you entered couldn't be found."
email.Subject = "MySubject";
email.Body = new MessageBody("MyBody");
// Send the mail
email.Send();
If I'm trying to send to TestContactGroup i'm got an exception:
"At least one recipient isn't valid."
And if I'm trying to send to TestContactGroup#mydomain.com I'm got an email that the mail isn't found.
So, how can i send an email to group list that I'm crated? Or another way to create distribution list with EWS?
Thanks
Problem solved.
I'm just need to add the group id as follow:
myContactGroup.Id = grpId;
I'm get my group id as follow:
// Instantiate the item view with the number of items to retrieve from the Contacts folder.
ItemView view = new ItemView(9999);
// Request the items in the Contacts folder that have the properties that you selected.
FindItemsResults<Item> contactItems = service.FindItems(WellKnownFolderName.Contacts, view);
string groupId = string.Empty;
List<ItemId> groupItemIds = new List<ItemId>();
// Loop through all contacts
foreach (Item item in contactItems)
{
//Check to see if ContactGroup
if (item is ContactGroup)
{
//Get the contact group
ContactGroup contactGroup = item as ContactGroup;
groupItemIds.Add(item.Id);//Using to send an email by item id, can classify by DisplayName etc..
}
}
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.