I need to get and save the attachments(s) from a mail item, but using the code below returns all attachments - meaning it also returns the embedded images like the sender's signature with logo which is an image. How can I differentiate a true attachment vs. embedded images? I have seen a lot from forums but it is still unclear to me.
public static void SaveData(MailItem currentMailItem)
{
if (currentMailItem != null)
{
if (currentMailItem.Attachments.Count > 0)
{
for (int i = 1; i <= currentMailItem.Attachments.Count; i++)
{
currentMailItem.Attachments[i].SaveAsFile(#"C:\TestFileSave\" + currentMailItem.Attachments[i].FileName);
}
}
}
}
You can check whether an attachment is inline or not by using the following pseudo-code from MS Technet Forums.
if body format is plain text then
no attachment is inline
else if body format is RTF then
if PR_ATTACH_METHOD value is 6 (ATTACH_OLE) then
attachment is inline
else
attachment is normal
else if body format is HTML then
if PR_ATTACH_FLAGS value has the 4 bit set (ATT_MHTML_REF) then
attachment is inline
else
attachment is normal
You can access the message body format using MailItem.BodyFormat and the MIME attachment properties using Attachment.PropertyAccessor.
string PR_ATTACH_METHOD = 'http://schemas.microsoft.com/mapi/proptag/0x37050003';
var attachMethod = attachment.PropertyAccessor.Get(PR_ATTACH_METHOD);
string PR_ATTACH_FLAGS = 'http://schemas.microsoft.com/mapi/proptag/0x37140003';
var attachFlags = attachment.PropertyAccessor.Get(PR_ATTACH_FLAGS);
Related
We have requirement to read pdf file and need to convert it as html elements( i,e. text, date field, textarea etc). is there any plugin available...or any other method.
Maybe this Information can help you
nuget
PM> Install-Package sautinsoft.pdffocus
example
string pathToPdf = #"d:\Tempos\table.pdf";
string pathToHtml = Path.ChangeExtension(pathToPdf, ".htm");
// Convert PDF file to HTML file
SautinSoft.PdfFocus f = new SautinSoft.PdfFocus();
// You may download the latest version of SDK here:
// www.sautinsoft.com/products/pdf-focus/download.php
// Let's force the component to store images inside HTML document
// using base-64 encoding
f.HtmlOptions.IncludeImageInHtml = true;
f.HtmlOptions.Title = "Simple text";
// This property is necessary only for registered version
f.OpenPdf(pathToPdf);
if (f.PageCount > 0)
{
int result = f.ToHtml(pathToHtml);
//Show HTML document in browser
if (result == 0)
{
System.Diagnostics.Process.Start(pathToHtml);
}
}
I want to save embedded images from outlook. After my analysis i found that user can embed images, and also PDF files etc. But in case of embedding PDF or other than image files(In outlook by using Insert menu and then Object option) the mail item attachment object also contains a .mso file(An MSO file is sent with email attachments and contains information that allows the attachment to be rendered within the email message) which i am not sure like i need to save it or not.
1)So is there any need to save or process the mso file or can i just ignore it and save all other file types?
2)Based on my observation even if user embed pdf file it will be attached as image file with .png extension in outlook inbox. So can i convert all those images to .gif as shown below? Will it failure in any scenario?
if (item.Attachments.Count > 0)
{
for (int j = 1; j <= item.Attachments.Count; j++)
{
string value = item.Attachments[j].PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001E");
if (!String.IsNullOrEmpty(value))
{
index++;
string tempFilename = "C:\\TestFileSave\\" + "inlineimg_" + index.ToString() + System.IO.Path.GetExtension(item.Attachments[j].FileName);
if (System.IO.Path.GetExtension(item.Attachments[j].FileName) == "mso")
{
continue;
}
item.Attachments[j].SaveAsFile(tempFilename);
string mimeType = MimeMapping.GetMimeMapping(tempFilename);
if (mimeType.Contains("image/"))
{
System.Drawing.Image Image1 = System.Drawing.Image.FromFile(tempFilename);
Image1.Save("C:\\TestFileSave\\" + "inlineimg_" + index.ToString() + ".gif", System.Drawing.Imaging.ImageFormat.Gif);
Image1.Dispose();
System.IO.File.Delete(tempFilename);
}
}
}
}
So, I want to be able to get an XML file attachment from an email and store it in the database for later use.
I can retrieve the emails and store the SenderEmailAdress, sentOn and the body in the database. Now I want to add the XML file attachment to the database too, so I can use it later.
How can I get the attachment file (or the content) from the email and to a variable so I can add it to the DB?
Here's the code for the attachment I have now (so after I get the Mail Item):
//Check for attachments.
int AttachCnt = oMsg.Attachments.Count;
// Check if there are any attachments
if (AttachCnt > 0)
{
for (int i = 1; i <= AttachCnt; i++)
{
System.Diagnostics.Debug.WriteLine(i.ToString() + " - FileName: " + oMsg.Attachments[i].FileName);
String ext = Path.GetExtension(oMsg.Attachments[i].FileName);
// check if the file extention is .xml
if (ext == ".xml")
{
// Get the file ready to store in the DB. This is what I want to know!
return;
}
}
}
Save the attachment as a file (Attachment.SaveAsFile), then read the file data into a variable.
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
}
I've had some success encoding the RTFbody from a MailItem using UTF8Encoding. I'm able to compose a new email, do all the new-email stuff and click send. Upon hitting send, I append the email with a tag that is also added to the categories. This all works and all through the RTFBbody.
The problem comes when I reply to RTF emails, which, for testing purposes, are just the emails I sent to my lonesome self. When I send the reply email and new tags were added, I remove the old tags first and then add the new tags. When I set the RTFBody in the reply email with the edited string that contains the new tags, I get a "not enough memory or disk space" error. This doesn't happen when I just remove the tags with the same function.
Bellow is the code I'm using:
private void ChangeRTFBody(string replaceThis, string replaceWith)
{
byte[] rtfBytes = Globals.ThisAddIn.email.RTFBody as byte[];
System.Text.Encoding encoding = new System.Text.UTF8Encoding();
string rtfString = encoding.GetString(rtfBytes);
rtfString = rtfString.Replace(replaceThis, replaceWith);
rtfBytes = encoding.GetBytes(rtfString);
Globals.ThisAddIn.email.RTFBody = rtfBytes; < // The error is here only on
// reply and only when I replace
// with new tags
}
These are the calls I make:
Delete old tag: ChangeRTFBody(lastTag, "");
Add new tag: ChangeRTFBody("}}\0", newTag + "}}\0");
Like I said, This works when I create a new email and send it, but not when I try to reply to the same email. It also seems that the size of the byte[] almost doubles after the delete. When I check it during the Delete it's at about 15k bytes and when I check during the Add it jumps to over 30k bytes. When I try to add the newly inflated byte[] to the rtfBody is when I get the error.
Thanks for any help and tips and sorry about all the reading.
I had the same problem and came across what I think is an easier way to replace text in a outlook rtf body by using the Word.Document object model. You will need to add reference of Microsoft.Office.Interop.Word to your project first.
then add using
using Word = Microsoft.Office.Interop.Word;
then your code would look like
Word.Document doc = Inspector.WordEditor as Word.Document;
//body text
string text = doc.Content.Text;
//find text location
int textLocation = text.IndexOf(replaceThis);
if(textLocation > -1){
//get range
int textLocationEnd = textLocation + replaceThis.Length;
//init range
Word.Range myRange = doc.Range(textLocation , textLocationEnd);
//replace text
myRange.Text = replaceWith
}