How to add file attachments to appointment using EWS? - c#

I'm developing application which uses EWS managed API to send appointments to outlook recipients,
Now there are requirement to add attachments to appointment, I'm able to attach attachments to emails, but when I use same technique as attaching item attachments to email ,but attachments are not attaching, my code as below
public string sendCalanderEvntAsReply( EntityLayer.Data_Contracts.AppointmentDTO appointment)
{
Appointment app = new Appointment(service);
app.Subject = appointment.Subject;
app.Body = appointment.Body;
app.Start = Convert.ToDateTime(appointment.Start);
app.End = Convert.ToDateTime(appointment.End);
app.Location = appointment.Location;
foreach (string obj in appointment.Attendees)
{
app.RequiredAttendees.Add(obj);
}
if (appointment.Attachments != null &&
appointment.Attachments.Count > 0)
{
foreach (var att in appointment.Attachments)
{
app.Attachments.AddFileAttachment(att.FileName);
}
}
app.Save(SendInvitationsMode.SendToAllAndSaveCopy);
}
is there any issue in my code?
please help.
thanks

With EWS when you want to send an Attachment with the Meeting invitation you need to save the appointment first before you send the message else you will only get the attachment on the owners copy so with your code you should use something like
Appointment app = new Appointment(service);
app.Subject = appointment.Subject;
app.Body = appointment.Body;
app.Start = Convert.ToDateTime(appointment.Start);
app.End = Convert.ToDateTime(appointment.End);
app.Location = appointment.Location;
if (appointment.Attachments != null &&
appointment.Attachments.Count > 0)
{
foreach (var att in appointment.Attachments)
{
app.Attachments.AddFileAttachment(att.FileName);
}
}
app.Save(SendInvitationsMode.SendToNone);
foreach (string obj in appointment.Attendees)
{
app.RequiredAttendees.Add(obj);
}
app.Update(ConflictResolutionMode.AutoResolve, SendInvitationsOrCancellationsMode.SendToAllAndSaveCopy);

Related

how to find mail that was send by MailItem.Display()

I have following requirement :
Allow the user to drag & drop an email from outlook to a datagrid
Prepare a reply mail, and show it so the user can review and send
After sending, also fetch the send mail and put it into the datagrid
The drag/drop I have working
Preparing the replay email and showing it to the user I also have working, with this code :
MailItem mail = GetMailBySubject(dateReceived, subject);
if (mail != null)
{
MailItem mailReply = mail.ReplyAll();
// add text and stuff to mailReply...
mailReply.Display();
}
This will open a window in outlook, as if the user clicked reply in outlook.
Now I am stuck with the 3th requirement,
after the user send the reply email, I need somehow to find this email in outlook to add it to my datagrid.
But I have no clue on how to do that.
All I have is the original mail that is been used to prepare the reply.
Is there a way to find the reply with only this, or is this maybe a complete wrong approach ?
To make it more difficult is that I have to show the reply email NON Modal, so I have no trigger when the user clicked on send in outlook.
for reference, here is the code for GetMailBySubject
private MailItem GetMailBySubject(DateTime dateReceived, string subject)
{
MailItem Result = null;
Microsoft.Office.Interop.Outlook.Application OutlookIns = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.NameSpace olNamespace = OutlookIns.GetNamespace("MAPI");
MAPIFolder myInbox = olNamespace.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
Items items = myInbox.Items;
int count = items.Count;
MailItem mail = null;
int i = 1; //DO NOT START ON 0
while ((i < count) && (Result == null))
{
if (items[i] is MailItem)
{
mail = (MailItem)items[i];
if ((mail.ReceivedTime.ToString("yyyyMMdd hh:mm:ss") == dateReceived.ToString("yyyyMMdd hh:mm:ss")) && (mail.Subject == subject))
{
Result = mail;
}
}
i++;
}
return Result;
}
EDIT
I tried this code as suggested, but the Items.ItemAdd event is not firing.
So I must still be doing something wrong but I cant see it
this is my code now
MailItem mail = GetMailBySubject((DateTime)sentOn, msg.Subject);
if (mail != null)
{
MailItem mailReply = mail.ReplyAll();
mailReply.HTMLBody = GetDefaultReplyText() + Environment.NewLine + mailReply.HTMLBody;
Guid guid = Guid.NewGuid();
UserProperties mailUserProperties = null;
UserProperty mailUserProperty = null;
mailUserProperties = mailReply.UserProperties;
mailUserProperty = mailUserProperties.Add("myproperty", OlUserPropertyType.olText);
mailUserProperty.Value = guid.ToString(); ;
// the code below gives error "The property cannot be parsed or has an invalid format"
//mailReply.PropertyAccessor.SetProperty("myproperty", guid.ToString());
mailReply.Display();
}
private MailItem GetMailBySubject(DateTime dateReceived, string subject)
{
MailItem Result = null;
Microsoft.Office.Interop.Outlook.Application OutlookIns = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.NameSpace olNamespace = OutlookIns.GetNamespace("MAPI");
MAPIFolder myInbox = olNamespace.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
Items items = myInbox.Items;
int count = items.Count;
MailItem mail = null;
int i = 1; //DO NOT START ON 0
while ((i < count) && (Result == null))
{
if (items[i] is MailItem)
{
mail = (MailItem)items[i];
if ((mail.ReceivedTime.ToString("yyyyMMdd hh:mm:ss") == dateReceived.ToString("yyyyMMdd hh:mm:ss")) && (mail.Subject == subject))
{
Result = mail;
MAPIFolder mySent = olNamespace.GetDefaultFolder(OlDefaultFolders.olFolderSentMail);
mySent.Items.ItemAdd += Items_SentMailItemAdd;
}
}
i++;
}
return Result;
}
and finally
private void Items_SentMailItemAdd(object Item)
{
//throw new NotImplementedException();
; // this event is never fired
}
You can use the Items.ItemAdd event on the Sent Items folder. To check if that is your message, set a custom property on the message that you create and display. You can use MailItem.UserProperties.Add, but that can force the message to be sent in the TNEF format. To prevent that from happening, you can use MailItem.PropertyAccessro.SetProperty to set a named MAPI property without using the UserProperties collection. You can set a test user property and look at its DASL name (to be used by SetProperty) with OutlookSpy (I am its author - select the message, click IMessage button, select your custom property, see the DASL edit box).

Delete Attachments from a EmailMessage with Exchange Web Services

I have the following problem. I would like to delete attachments from emails. As long as it's a normal email with attachments, that's no problem. But if the e-mail is now in an e-mail, then I can not delete the attachments. I always get the message "at least one attachment could not be deleted".
Does somebody has any idea? I am working with version 2 of Exchange Web Services.
private void workEmail(EmailMessage rootMailMessage, EmailMessage subMailMessage, string filePath, int index)
{
EmailMessage eMessageToWork = null;
if (subMailMessage == null)
{
eMessageToWork = rootMailMessage;
}
else
{
eMessageToWork = subMailMessage;
}
for (int i = eMessageToWork.Attachments.Count; i-- > 0; )
{
Microsoft.Exchange.WebServices.Data.Attachment rootAttachment = eMessageToWork.Attachments[i];
if (rootAttachment is FileAttachment)
{
// For now, just .odt files are not supported and it throws an exception if theres any unsupported fileextension
checkFileTypeSupported(rootAttachment.Name);
string strType = Path.GetExtension(rootAttachment.Name);
// check if it is any type of supported image or pdf file
if (checkForImageOrPdfAttachment(strType))
{
// just save the image to temp folder
string subAttRootFileName = saveImageFileAttachment(rootAttachment, index, filePath);
// remove attachment
eMessageToWork.Attachments.Remove(rootAttachment);
// save the updated mail
rootMailMessage.Update(ConflictResolutionMode.AlwaysOverwrite);
}
continue;
}
else // Attachment is an item attachment.
{
// convert attachment to itemattachment
ItemAttachment itmAttach = rootAttachment as ItemAttachment;
// save this item-attachment
// Load Item with additionalProperties of MimeContent
itmAttach.Load(EmailMessageSchema.MimeContent);
// convert the itemattachment to a emailmessage
EmailMessage ebMessage = itmAttach.Item as EmailMessage;
// recursive call for possible attachments in this emailmessage
this.workEmail(rootMailMessage, ebMessage, filePath, index + 1);
// remove the attached mailitem from parent mail
rootMailMessage.Attachments.Remove(rootAttachment);
// update parent mail
rootMailMessage.Update(ConflictResolutionMode.AlwaysOverwrite);
}
}
}
Try this:
EmailMessage message = EmailMessage.Bind(service, Id, new PropertySet(ItemSchema.Attachments));
foreach (Attachment attachment in message.Attachments)
{
message.Attachments.Remove(attachment);
break;
}
message.Update(ConflictResolutionMode.AlwaysOverwrite);

Strip attachments from emails using MailKit / MimeKit

I'm using MailKit library to handle emails, which has been working well. However, I'm trying to split emails into their constituent files a) Main email (no attachments) b) Individual attachment files, to store on the filesystem.
I can save the attachments individually, but can't seem to remove them from the email body code. I.e. they're getting saved along with the main email, so duplicating data. :/
I've tried:
foreach (MimePart part in inMessage.BodyParts)
{
if (part.IsAttachment)
{
// Remove MimePart < This function isn't available on the collection.
}
}
Have also tried:
var builder = new BodyBuilder();
foreach (MimePart part in inMessage.BodyParts)
{
if (!part.IsAttachment)
{
// Add MimeParts to collection < This function isn't available on the collection.
}
}
outMessage.Body = builder.ToMessageBody();
If anyone can help with this, I'd much appreciate it.
Solution implemented FYI:
private string GetMimeMessageOnly(string outDirPath)
{
MimeMessage message = (Master as fsEmail).GetMimeMessage();
if (message.Attachments.Any())
{
var multipart = message.Body as Multipart;
if (multipart != null)
{
while (message.Attachments.Count() > 0)
{
multipart.Remove(message.Attachments.ElementAt(0));
}
}
message.Body = multipart;
}
string filePath = outDirPath + Guid.NewGuid().ToString() + ".eml";
Directory.CreateDirectory(Path.GetDirectoryName(outDirPath));
using (var cancel = new System.Threading.CancellationTokenSource())
{
using (var stream = File.Create(filePath))
{
message.WriteTo(stream, cancel.Token);
}
}
return filePath;
}
And to get the attachments only:
private List<string> GetAttachments(string outDirPath)
{
MimeMessage message = (Master as fsEmail).GetMimeMessage();
List<string> list = new List<string>();
foreach (MimePart attachment in message.Attachments)
{
using (var cancel = new System.Threading.CancellationTokenSource())
{
string filePath = outDirPath + Guid.NewGuid().ToString() + Path.GetExtension(attachment.FileName);
using (var stream = File.Create(filePath))
{
attachment.ContentObject.DecodeTo(stream, cancel.Token);
list.Add(filePath);
}
}
}
return list;
}
You could retrieve all MimeParts that are attachments https://github.com/jstedfast/MimeKit/blob/master/MimeKit/MimeMessage.cs#L734 and then iterate over the all Multiparts and call https://github.com/jstedfast/MimeKit/blob/master/MimeKit/Multipart.cs#L468 for the attachments to remove.
The sample below makes a few assumptions about the mail e.g. there is only one Multipart some email client (Outlook) are very creative how mails are crafted.
static void Main(string[] args)
{
var mimeMessage = MimeMessage.Load(#"x:\sample.eml");
var attachments = mimeMessage.Attachments.ToList();
if (attachments.Any())
{
// Only multipart mails can have attachments
var multipart = mimeMessage.Body as Multipart;
if (multipart != null)
{
foreach(var attachment in attachments)
{
multipart.Remove(attachment);
}
}
mimeMessage.Body = multipart;
}
mimeMessage.WriteTo(new FileStream(#"x:\stripped.eml", FileMode.CreateNew));
}
Starting with MimeKit 0.38.0.0, you'll be able to use a MimeIterator to traverse the MIME tree structure to collect a list of attachments that you'd like to remove (and remove them). To do this, your code would look something like this:
var attachments = new List<MimePart> ();
var multiparts = new List<Multipart> ();
var iter = new MimeIterator (message);
// collect our list of attachments and their parent multiparts
while (iter.MoveNext ()) {
var multipart = iter.Parent as Multipart;
var part = iter.Current as MimePart;
if (multipart != null && part != null && part.IsAttachment) {
// keep track of each attachment's parent multipart
multiparts.Add (multipart);
attachments.Add (part);
}
}
// now remove each attachment from its parent multipart...
for (int i = 0; i < attachments.Count; i++)
multiparts[i].Remove (attachments[i]);
I created an application, that downloads emails and attachments as well using Mailkit.
I faced one problem: E-Mails sent from iOS with attached pictures were not processed correctly. MailKit did not add the images to the Attachments list.
I used this method to get only the text of the message:
private static string GetPlainTextFromMessageBody(MimeMessage message)
{
//content type needs to match text/plain otherwise i would store html into DB
var mimeParts = message.BodyParts.Where(bp => bp.IsAttachment == false && bp.ContentType.Matches("text", "plain"));
foreach (var mimePart in mimeParts)
{
if (mimePart.GetType() == typeof(TextPart))
{
var textPart = (TextPart)mimePart;
return textPart.Text;
}
}
return String.Empty;
}
This is the method I used to download only the .jpg files:
foreach (var attachment in message.BodyParts.Where(bp => !string.IsNullOrEmpty(bp.FileName)))
{
if (attachment.FileName.ToLowerInvariant().EndsWith(".jpg"))
{
//do something with the image here
}
}

Extract/Export attachements from Lotus Notes Email using C#

I need to extract/export the lotus notes email attachment into file system. for that I wrote following method but each time I am receiving an error at line foreach (NotesItem nItem in items).. Can anybody please tell me what I am doing wrong ..
Thanks
Jwalin
public void GetAttachments()
{
NotesSession session = new NotesSession();
//NotesDocument notesDoc = new NotesDocument();
session.Initialize("");
NotesDatabase NotesDb = session.GetDatabase("", "C:\\temps\\lotus\\sss11.nsf", false); //Open Notes Database
NotesView inbox = NotesDb.GetView("By _Author");
NotesDocument docInbox = inbox.GetFirstDocument();
object[] items = (object[])docInbox.Items;
**foreach (NotesItem nItem in items)**
{
//NotesItem nItem = (NotesItem)o1;
if (nItem.Name == "$FILE")
{
NotesItem file = docInbox.GetFirstItem("$File");
string fileName = ((object[])nItem.Values)[0].ToString();
NotesEmbeddedObject attachfile = (NotesEmbeddedObject)docInbox.GetAttachment(fileName);
if (attachfile != null)
{
attachfile.ExtractFile("C:\\temps\\export\\" + fileName);
}
}
}
You don't need to use the $File item to get the attachment name(s). Rather, you can use the HasEmbedded and EmbeddedObject properties of the NotesDocument class.
public void GetAttachments()
{
NotesSession session = new NotesSession();
//NotesDocument notesDoc = new NotesDocument();
session.Initialize("");
NotesDatabase NotesDb = session.GetDatabase("", "C:\\temps\\lotus\\sss11.nsf", false); //Open Notes Database
NotesView inbox = NotesDb.GetView("By _Author");
NotesDocument docInbox = inbox.GetFirstDocument();
// Check if any attachments
if (docInbox.hasEmbedded)
{
NotesEmbeddedObject attachfile = (NotesEmbeddedObject)docInbox.embeddedObjects[0];
if (attachfile != null)
{
attachfile.ExtractFile("C:\\temps\\export\\" + attachfile.name);
}
}
Ed's solution didn't work for me. Something about my Notes db design seems to have left the EmbeddedObjects property null even when the HasEmbedded flag is true. So I sort of combined the Ed's and Jwalin's solutions, modifying them to fetch all attachments from a Notes document.
NotesDocument doc = viewItems.GetNthEntry(rowCount).Document;
if (doc.HasEmbedded)
{
object[] items = (object[])doc.Items;
foreach (NotesItem item in items)
{
if(item.Name.Equals("$FILE"))
{
object[] values = (object[])item.Values;
doc.GetAttachment(values[0].ToString()).ExtractFile(fileSavePath + values[0].ToString());
}
}

How to get Attachment value from "$File" Item? using C# (Lotus Notes)

I am trying to access Attachment names form "$File" (Lotus Notes).
NotesView inbox = _serverDatabase.GetView("($Inbox)");
NotesDocument docInbox = inbox.GetFirstDocument();
NotesItem file = docInbox.GetFirstItem("$File");
String fileType = file.type.ToString();
( getting fileType value "ATTACHMENT" for mail containing attachments)
I am not getting solution given in:
How to Access attachments from Notes mail?
I got solution as:
object[] items = (object[])docInbox.Items;
foreach (NotesItem nItem in items)
{
if (nItem.Name == "$FILE")
{
NotesItem file = docInbox.GetFirstItem("$File");
string fileName = ((object[])nItem.Values) [0].ToString();
NotesEmbeddedObject attachfile = (NotesEmbeddedObject)docInbox.GetAttachment(fileName);
if (attachfile != null)
{
attachfile.ExtractFile("C:\\test\\" + fileName);
}
}
But here I am getting only first attachment value.
Can anyone help me out in this?
Try something like this:
NotesView inbox = _serverDatabase.GetView("($Inbox)");
NotesDocument docInbox = inbox.GetFirstDocument();
if(docInbox.HasEmbedded ) {
foreach (NotesEmbeddedObject o in docInbox.EmbeddedObjects) {
if ( o.Type == 1454 ) {
o.ExtractFile( "c:\samples\" & o.Source )
}
}
}
Here is a link to Lotus Notes Designer Help - Really good as you can search for Classes etc to find out what options you have.
http://publib.boulder.ibm.com/infocenter/domhelp/v8r0/index.jsp?topic=/com.ibm.help.domino.designer85.doc/DOC/H_WHAT_S_NEW_IN_RNEXT_CHAP.html
Show you all the methods and properties of various class.
Hi Preeti,
OK from the other code sample you are returning an array:
string fileName = ((object[])nItem.Values) [0].ToString();
Yet you are only selecting the first value, you need to recurse through the collection.
Try something like this.
foreach (object attachment in (object[])nItem.Values)
{
NotesEmbeddedObject attachfile = (NotesEmbeddedObject)docInbox.GetAttachment(attachment.ToString());
if (attachfile != null)
{
attachfile.ExtractFile("C:\\test\\" + attachment.ToString());
}
}
Josh
Your above code snippet is very helpful to me. So, I tried the to save all attachments and finally found the below solution.
NotesView nInboxDocs = NDb.GetView("$Inbox");
NDoc=nInboxDocs.GetFirstDocument();
while (NDoc != null)
{
if (NDoc.HasEmbedded && NDoc.HasItem("$File"))
{
// To save only first attachment //
//pAttachment = ((object[])NDoc.GetItemValue("$File"))[0].ToString();
//pAttachment = CurItem.ToString();
//NDoc.GetAttachment(pAttachment).ExtractFile(#"C:\Documents and Settings\Administrator\Desktop\" + pAttachment);
// To save all attachment //
object[] AllDocItems = (object[])NDoc.Items;
foreach (object CurItem in AllDocItems)
{
NotesItem nItem = (NotesItem)CurItem;
if (IT_TYPE.ATTACHMENT == nItem.type)
{
pAttachment = ((object[])nItem.Values)[0].ToString();
NDoc.GetAttachment(pAttachment).ExtractFile(#"C:\Documents and Settings\Administrator\Desktop\" + pAttachment);
}
}
}
NDoc = nInboxDocs.GetNextDocument(NDoc);
}

Categories

Resources