Converting attachment to image - c#

Up to know i can load the attachments to memory and i know its right cause i can print the name of the file. What i need is to convert this attachment to an image object which i will later add to a sharepoint picture library. But forget about the sharepoint part i know how to do that, am stuck in the part that after loading the attachments how do i conver this into images. I dont want to save the images in disk cause thats not the point i already load them in memory.
foreach (Item item in findResults.Items)
{
if (item is EmailMessage && item.HasAttachments)
{
EmailMessage message = EmailMessage.Bind(service, item.Id, new PropertySet(BasePropertySet.IdOnly, ItemSchema.Attachments));
foreach (Attachment attachment in message.Attachments)
{
if (attachment is FileAttachment)
{
FileAttachment fileAttachment = attachment as FileAttachment;
// Load the file attachment into memory and print out its file name.
fileAttachment.Load();
Console.WriteLine("Attachment name: " + fileAttachment.Name);
//this is where i would create the image of object but dont know how
}
}
}
}

You already have the FileAttachment object, and you even access one of its properties. You only need to take the next step, and access not only the Name but also the Content.
if (attachment is FileAttachment)
{
FileAttachment fileAttachment = attachment as FileAttachment;
fileAttachment.Load();
byte[] fileContent = fileAttachment.Content;
}
This will give you the contents on the attachemnts, as an array of bytes. I don't remember what the Sharepoint API wants to receive, but it's either this byte array or something you can easily build out of it.

Related

Stream was not readable with Using

I am getting an error
File is being used by another process
trying to implement using for a FileStream. However, I encountered the error of Stream was not readable.
This is my code:
Before: working, but encounters 'file being used by another process' error periodically
EmailMessage responseMessageWithAttachment = responseMessage.Save();
foreach (var attachment in email.Attachments)
{
if (attachment is FileAttachment)
{
FileAttachment fileAttachment = attachment as FileAttachment;
fileAttachment.Load();
fileAttachment.Load(AppConfig.EmailSaveFilePath + fileAttachment.Name);
FileStream fs = new FileStream(AppConfig.EmailSaveFilePath + fileAttachment.Name, FileMode.OpenOrCreate);
responseMessageWithAttachment.Attachments.AddFileAttachment(attachment.Name, fs);
}
}
responseMessageWithAttachment.SendAndSaveCopy();
After: encounters 'stream was not readable' error
EmailMessage responseMessageWithAttachment = responseMessage.Save();
foreach (var attachment in email.Attachments)
{
if (attachment is FileAttachment)
{
FileAttachment fileAttachment = attachment as FileAttachment;
fileAttachment.Load();
fileAttachment.Load(AppConfig.EmailSaveFilePath + fileAttachment.Name);
using (FileStream fs = new FileStream(AppConfig.EmailSaveFilePath + fileAttachment.Name, FileMode.OpenOrCreate))
{
responseMessageWithAttachment.Attachments.AddFileAttachment(attachment.Name, fs);
};
}
}
responseMessageWithAttachment.SendAndSaveCopy();
working, but encounter 'file being used by another process' error periodically
This means what it says: some other process is touching the file. If you want to solve this, you need to figure out what's using the file. This will happen whether you use using or not.
If this code is running multiple times in parallel, it could be your own code interfering. Either way, you could avoid it by open for reading only, but specifically allowing other processes to open it for writing. You would do that like this:
var fs = new FileStream(Path.Combine(AppConfig.EmailSaveFilePath, fileAttachment.Name),
FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
encounter 'stream was not readable' error
This depends on how AddFileAttachment is implemented. You don't show the stack trace, so it's possible that it doesn't read the stream until you call SendAndSaveCopy(), which is outside the using and the stream is closed.
An easy way to work around this is to just use the overload of AddFileAttachment that just takes the path to the file as a string, so you don't need to manage the FileStream yourself:
responseMessageWithAttachment.Attachments.AddFileAttachment(attachment.Name,
Path.Combine(AppConfig.EmailSaveFilePath, fileAttachment.Name));
I use Path.Combine since it avoids problems where there may or may not be a trailing \ in your EmailSaveFilePath setting.
I wonder if you can avoid saving the files and just use Content and AddFileAttachment(String, Byte[])
foreach (var attachment in email.Attachments)
{
if (attachment is FileAttachment)
{
FileAttachment fileAttachment = attachment as FileAttachment;
fileAttachment.Load();
responseMessageWithAttachment.Attachments.AddFileAttachment(attachment.Name, fileAttachment.Content);
}
}
responseMessageWithAttachment.SendAndSaveCopy();

Is there a way to Extract attachment from Email Message Mime Content without using Exchange Service?

I am having a client application which will save eml files to the local disk. Need to get the attachment inside the eml file which is saved without using the exchange service because the Mailbox keeps changing of its capacity.Please help if anyone have come across similar issue
I have tried the reverse process of getting the eml file and load it again to get the details.
You could use something like MimeKit for this. The GitHub page has examples on how to parse MIME messages and how to get attachments.
Here is an example of how to get the attachments in an array of bytes:
var mimeMessage = MimeMessage.Load(#"test.eml");
var attachments = mimeMessage.Attachments.ToList();
foreach (var attachment in attachments)
{
using (var memory = new MemoryStream())
{
if (attachment is MimePart)
((MimePart)attachment).Content.DecodeTo(memory);
else
((MessagePart)attachment).Message.WriteTo(memory);
var bytes = memory.ToArray();
}
}
First of all Big Thanks to MadDev for helping out !!!
Here is the Code which I used:
Note: Here in case, the stored email will always have another eml file attached to it and this is based on the business logic.
protected static void MimeProcessor(MemoryStream stream)
{
try
{
var parser = new MimeParser(stream, MimeFormat.Default);
var message = parser.ParseMessage();
var multipart = message.Body as Multipart;
//Found the Attachment as Message Part
var OriginalMessage = multipart.ToList().LastOrDefault();
if (OriginalMessage is MessagePart)
{
using (var memory = new MemoryStream())
{
((MessagePart)OriginalMessage).Message.WriteTo(memory);
var bytes = memory.ToArray();
File.WriteAllBytes("C:\\Test\\TestMessage.eml", bytes);
}
}
}
catch (Exception)
{
throw;
}
}

MailKit save Attachments

I'm try save attachments from message
foreach(MimeKit.MimeEntity at message.Attachments)
{
at.WriteTo("nameFile");
}
File saved, but when I open I get the error
the file is corrupted or too large
The size of this file is 88 kb, but size of the file should be equal to 55 kb.
I think that in all recorded message file.
How do I only record the attachment?
MailKit v1.2.0.0 MimeKit 1.2.0.0
You are saving the entire MIME object (including the headers). What you need to do is save the content.
foreach (var attachment in message.Attachments) {
using (var stream = File.Create ("fileName")) {
if (attachment is MessagePart) {
var part = (MessagePart) attachment;
part.Message.WriteTo (stream);
} else {
var part = (MimePart) attachment;
part.Content.DecodeTo (stream);
}
}
}

Saving only the REAL attachments of an Outlook MailItem

I'm currently developing an Outlook Addin which saves MailItems and Attachments in my MSSQL Database.
I got a method where I save the MailItem with all it's attachments. But if I save all attachments the embedded images in the MailItem are also saved.
Does anyone know how to save all real attachments?? I mean like the attachments in the picture below:
and not the embbeded images that are in the mail body.
Here is the code that I use to loop through all attachments of a MailItem and then save it:
foreach (Outlook.Attachment att in mailItem.Attachments)
{
try
{
att.SaveAsFile(Path.GetTempPath() + att.FileName);
var fi = new FileInfo(Path.GetTempPath() + att.FileName);
//Saving attachment to DB
var attachment = Attachment.NieuwAttachment(att.FileName, SelectedMap.DossierNr.ToString( CultureInfo.InvariantCulture), -1, Convert.ToInt32(SelectedMap.Tag), fi);
if (!Attachment.InlezenAttachment(attachment)) continue;
OutlookCategories.AddAttachmentCategory(mailItem);
}
catch (Exception ex)
{
var dmsEx = new DmsException("Er is een fout opgetreden bij het opslaan van een bijlage.", ex.Message, ex);
ExceptionLogger.LogError(dmsEx);
}
}
Thanks!
----------- EDIT ------------
I also posted this question on the Microsoft TechNet and I just received an answer to the question (See link below)
Outlook 2007 & 2010: Save all attachments except the embedded attachments C#
----------- EDIT ------------
My problem is still not fixed, the help I got from Microsoft is useless.. So Please I really need this to be fixed!
Use this code answered here :
if (mailItem.Attachments.Count > 0)
{
// get attachments
foreach (Attachment attachment in mailItem.Attachments)
{
var flags = attachment.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x37140003");
//To ignore embedded attachments -
if (flags != 4)
{
// As per present understanding - If rtF mail attachment comes here - and the embeded image is treated as attachment then Type value is 6 and ignore it
if ((int)attachment.Type != 6)
{
MailAttachment mailAttachment = new MailAttachment { Name = attachment.FileName };
mail.Attachments.Add(mailAttachment);
}
}
}
}
Depends on how you define 'real' or 'proper' attachments. I'm going to assume you want to disregard all images that are embedded in the email. These are also attachments but are referenced in the actual body of the html email.
See this answer for an explanation on how attachments are embedded. The key is to disregard attachments that have a Content-ID value that is referenced by an image tag within the body of the email itself.
This worked for me:
var test = attachments[i].PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001E");
if (string.IsNullOrEmpty((string)test))
{
//attachment
}
else
{
//embedded image
}

display image retrieved as ravendb attachment

Simple question: how to display retrieved ravendb attachment image in winforms pictureBox.
Attachment is retrieved as
Raven.Abstractions.Data.Attachment attachment =
_store.DatabaseCommands.GetAttachment("upload/"+ 9999);
update
Image is save with put attachment like this
_Store.DatabaseCommands.PutAttachment("upload/" + attachId, null, ms,
new RavenJObject
{
{ "Content-Type", "image/jpeg" }
});
ms is memory stream
You need to retrieve the attachment memory stream from the Attachment object:
pictureBox1.Image = Image.FromStream(attachment.Data());
See more in the docs

Categories