getting image from email - c#

I've noticed that when someone copy paste an email and then sends it the "src" value of the images changes. For example if the original email has an image which is an attachment and its contentId is: cid:companlyLogo. And then someone copy paste this email into a new draft and sends it this src value changes to: src="cid:image001.jpg#01CCF6B1.A4CA2FE0".
I have no clue whatsoever on how to get this image and save it in an image object in c#. Am currently using EWS api for doing this. Problem is that since its a copy paste it no longer has attachments as the original email.
Does anyone has any idea on how to retrieve the images of this types of emails?

Embedded images are treated as email attachments by Exchange. That means you can retrieve the images from the Item.Attachments property. The following example shows you how to do this using the EWS Managed API. Notice that EWS will not load the attachments unless you explicitly tell it to by calling LoadPropertiesForItems.
You can tell that an attachment is embedded by checking the Attachment.IsInline property. EWS lets you load the attachment and save it to disk by calling the FileAttachment.Load method.
ExchangeService service = GetService();
var view = new ItemView(1);
var searchFilter = new SearchFilter.IsEqualTo(EmailMessageSchema.Subject, "Some subject text");
var items = service.FindItems(WellKnownFolderName.Inbox, searchFilter, view);
service.LoadPropertiesForItems(items, new PropertySet(BasePropertySet.FirstClassProperties, EmailMessageSchema.Attachments));
var item = items.ElementAt(0) as EmailMessage;
for (int i = 0; i < item.Attachments.Count; i++)
{
var att = item.Attachments[i] as FileAttachment;
if (att.IsInline && att.ContentType.Contains("image"))
{
att.Load(String.Format(#"c:\temp\attachedimage_{0}.jpg", i));
}
}

Related

MimeKit add attachments to a message loaded from mht file

Hi We are trying to develop a mail sending system using MailKit. We have a set of Email Templates which are created using WORD and saved as MHTML files. The whole thing is working fine, when we use MailKit to create a MimeMessage from the MHT file.
But post creating this message, I am not able to see a way of adding attachments to this.
Currently we are trying the following.
private void SendEmail(string templatePath, List<string> attachments)
{
// Load the MHT Template
var mimeMessage = MimeMessage.Load(templatePath);
mimeMessage.From.Add(new MailBoxAddress("test#Test.com"));
mimeMessage.To.Add(new MailBoxAddress("test#Test.com"));
foreach (var attachment in attachments)
{
var fileAttachment = new MimePart()
{
ContentObject = new ContentObject(File.OpenRead(Path.Combine(attachment), ContentEncoding.Default),
ContentDisposition = new ContentDisposition(ContentDisposition.Attachment),
ContentTransferEncoding = ContentEncoding.Binary,
FileName = Path.GetFileName(attachment)
};
// Attachments is a read only Enumerable here.
mimeMessage.Attachments.Add
}
}
I add the attachment by the BodyBuilder:
BodyBuilder _body = new BodyBuilder
{
HtmlBody = message
};
_body.Attachments.Add(_fileName, _stream);
_email.Body = _body.ToMessageBody();
See this post stackoverflow
You will need to traverse the MIME tree structure of the message until you find the Multipart that you would like to add the "attachment" to and then use the Multipart.Add() method.
Keep in mind that a message is a nested tree structure and not a well-defined structure which has only 1 message body (or even just 2) and a list of attachments. It's a whole lot more complicated than that, so there's literally no way for MimeMessage.Attachments to "do the right thing".
For the general case, you can probably get away with something like this:
var message = MimeMessage.Load(fileName);
var attachment = new MimePart("application", "octet-stream") {
FileName = attachmentName,
ContentTransferEncoding = ContentEncoding.Base64,
Content = new MimeContent(attachmentStream)
};
if (!(message.Body is Multipart multipart &&
multipart.ContentType.Matches("multipart", "mixed"))) {
// The top-level MIME part is not a multipart/mixed.
//
// Attachments are typically added to a multipart/mixed
// container which tends to be the top-level MIME part
// of the message (unless it is signed or encrypted).
//
// If the message is signed or encrypted, though, we do
// do not want to mess with the structure, so the correct
// thing to do there is to encapsulate the top-level part
// in a multipart/mixed just like we are going to do anyway.
multipart = new Multipart("mixed");
// Replace the message body with the multipart/mixed and
// add the old message body to it.
multipart.Add(message.Body);
message.Body = multipart;
}
// Add the attachment.
multipart.Add(attachment);
// Save the message back out to disk.
message.WriteTo(newFileName);

Sparkpost C# API add attachments to templates

I've been going thumbing through the documentation and searching the internet to find documenation on how to add attachments to created templates. I'm using darrencauthon's CSharp-Sparkpost to handle the API calls. So far what I have is not working. Does anyone have a working solution (possible?) or a better solution for C#? I'm not opposed to using a different library. This is the link to CSharp-Sparkpost
Here's what I've got so far:
var t = new Transmission();
t.Content.From.Email = "from#thisperson.com";
t.Content.TemplateId = "my-template-email";
new Recipient
{
Address = new Address { Email = recipient }
}
.Apply(t.Recipients.Add);
new Attachment
{
Data = //CSVDATA,
Name = "Table.csv",
Type = "text/csv"
}.Apply(t.Content.Attachments.Add);
var client = new SparkPost.Client(Util.GetPassword("sparkpostapikey"));
client.Transmissions.Send(t).Wait();
I've verified that I can send this attachment without a template and also verified that I can send this template without the attachment. So... the Email is getting sent; however, the content received is only the template and substitution data. No attachment with the template email.
Using Darren's library, and combining the requirements for my project, this is the solution I've come up with. I'm just making an additional API call to grab the template Html so I can build the transmission without having to send the template_id. Still using the CSharp-Sparkpost library to make all of the calls. I modified Darren's example SendInline program as such:
static async Task ExecuteEmailer()
{
var settings = ConfigurationManager.AppSettings;
var fromAddr = settings["fromaddr"];
var toAddr = settings["toaddr"];
var trans = new Transmission();
var to = new Recipient
{
Address = new Address
{
Email = toAddr
},
SubstitutionData = new Dictionary<string, object>
{
{"firstName", "Stranger"}
}
};
trans.Recipients.Add(to);
trans.SubstitutionData["firstName"] = "Sir or Madam";
trans.Content.From.Email = fromAddr;
trans.Content.Subject = "SparkPost sending attachment using template";
trans.Content.Text = "Greetings {{firstName or 'recipient'}}\nHello from C# land.";
//Add attachments to transmission object
trans.Content.Attachments.Add(new Attachment()
{
Data = Convert.ToBase64String(System.IO.File.ReadAllBytes(#"C:\PathToFile\ExcelFile.xlsx")),
Name = "ExcelFile.xlsx",
Type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
});
Console.Write("Sending mail...");
var client = new Client(settings["apikey"]);
client.CustomSettings.SendingMode = SendingModes.Sync;
//retrieve template html and set Content.Html
var templateResponse = await client.Templates.Retrieve("template-email-test");
trans.Content.Html = templateResponse.TemplateContent.Html;
//Send transmission
var response = client.Transmissions.Send(trans);
Console.WriteLine("done");
}
Oh actually, I see now -- you are talking about adding attachments to templates, not attachments.
My answer to that is that back when I developed this library, attachment on templates was not supported by SparkPost itself.
My library allows you to try it, but that's because every template and non-template emails are considered "transmissions." So if you create a transmission, it has the option of adding attachments... but if you send the transmission with a template id, the attachment is ignored.
I could throw an error, or somehow design the API around this limitation, but what if they stopped ignoring the attachment but my library threw an error? I designed the library for flexibility as the SparkPost web API grew, and I didn't want my library to get in the way.
If you want to test if you're sending the attachment right, send your transmission without a transmission id, and instead with a subject and email body. If the email goes through and you get an attachment, then you know it's because of this template/attachment restriction from SparkPost.
NOTE: I'm putting this answer on Stack Overflow, and it's possible that this dated message will no longer be valid in the future.
I'm Darren Cauthon, the primary author of this library.
I have attachment support in my acceptance tests, which are run before each release. The link is below, but the code should be as simple as:
// C#
var attachment = File.Create<Attachment>("testtextfile.txt");
transmission.Content.Attachments.Add(attachment);
https://github.com/darrencauthon/csharp-sparkpost/blob/3a8cb1efbb8c9a0448c71c126ce7f88759867fb0/src/SparkPost.Acceptance/TransmissionSteps.cs#L56

Exchange web services - Forward Email as Attachment

I'm currently using Exchange Web Services in C#. I basically have a small application that reads emails from an inbox and process them.
I would like to forward those emails I receive as an attachment of an email. This attachment will be an outlook email that will include the original email (including its own attachments if any).
Any ideas?
Thanks!
EDIT:
Not sure why I'm getting the down votes but it seems this is not possible as the EWS API does not provide such functionality
You can create an ItemAttachment with EWS but you can't replicate fully what is possible in Outlook with MAPI. Eg with EWS you can create an ItemAttachment and then use the MIMEContent to create an attachment based on a current message as a workaround eg
FolderId Inboxid = new FolderId(WellKnownFolderName.Inbox, "target#domain.com");
ItemView InboxItemView = new ItemView(1);
FindItemsResults<Item> inFiResuls = service.FindItems(Inboxid,InboxItemView);
if(inFiResuls.Items.Count == 1){
EmailMessage fwdMail = new EmailMessage(service);
EmailMessage orgMail = (EmailMessage)inFiResuls.Items[0];
PropertySet psPropSet = new PropertySet(BasePropertySet.FirstClassProperties);
psPropSet.Add(ItemSchema.MimeContent);
orgMail.Load(psPropSet);
ItemAttachment emAttach = fwdMail.Attachments.AddItemAttachment<EmailMessage>();
emAttach.Item.MimeContent = orgMail.MimeContent;
ExtendedPropertyDefinition pr_flags = new ExtendedPropertyDefinition(3591,MapiPropertyType.Integer);
emAttach.Item.SetExtendedProperty(pr_flags,"1");
emAttach.Name = orgMail.Subject;
fwdMail.Subject = "see Attached";
fwdMail.ToRecipients.Add("user#domain.com");
fwdMail.Send();
}
This however doesn't give full fidelity of all the mapi properties associated with a particular message as the MIMEContent is just that, for most normal email messages this isn't an issue however for a message with an attached Outlook Task or other TNEF attachment then you would loose these of attachments or for other properties like categories,flags you would loose these also (you could copy these manually if needed).
Cheers
Glen
you can forward your email using this way. It first loads and reads the each emails with attachment who has "msg" extension. then forwards it to given address. see the below code
FindItemsResults<Item> findResults = exchange.FindItems(WellKnownFolderName.Inbox, newItemView(50,50));
Item[] msgItems = findResults.Where(msgItem => msgItem.HasAttachments).ToArray();
EmailMessage msgInfo = null;
var fileExtensions = new List<string> { "msg", "MSG", "Msg" };
foreach (MSEWS.Item msgItem in msgItems )
{
msgInfo = EmailMessage.Bind(exchange, msgItem.Id);
FileAttachment fa = msgInfo.Attachments[0] asFileAttachment;
if (fileExtensions.Any(ext => ext.Contains(fa.Name.Substring(fa.Name.Length - 3))))
{
fa.Load();
ResponseMessage responseMessage = msgInfo.CreateForward();
responseMessage.BodyPrefix = "messageBody";
responseMessage.ToRecipients.Add("toAddress");
responseMessage.Subject = "subject";
responseMessage.SendAndSaveCopy();
}
}

MailChimp (Mandrill) for .NET why email includes Image?

I'm using MailChimp for .NET from this nuget https://www.nuget.org/packages/mcapi.net/1.3.1.3 and tried sending emails. But the email I received include image (unseen image) even if I'm just sending simple html. Has anyone encountered it? How to get rid of this unseen image? Please help.
Below is my sample email message.
var api = new MandrillApi("XXXXXXXXXXX");
var recipients = new List<Mandrill.Messages.Recipient>();
var name = string.Format("{0} {1}", "Jobert", "Enamno");
recipients.Add(new Mandrill.Messages.Recipient("recipient#gmail.com", name));
var message = new Mandrill.Messages.Message()
{
To = recipients.ToArray(),
FromEmail = "admin#mysite.com",
Subject = "Test Email",
Html = "<div>Test</div>"
};
MVList<Mandrill.Messages.SendResult> result;
result = api.Send(message);
Received Email
When clicked No image shown
You're seeing this because Mandrill uses a small invisible graphic for open tracking. You'd want to either disable open tracking in the API call you're making or on the Sending Options page in your Mandrill account.

Retrieving Some Email Information

I'm trying to obtain some information from emails sent to an Outlook email. I've successfully connected to the Exchange Server and have been able to retrieve some information from emails with attachments (I am skipping emails without attachments).
What I Have: I can retrieve the attachment file name, the email date, and the email subject.
What I Need: I need to retrieve the sender name and email also. From what I've done, I can retreive the body of the email (in HTML), but not the body text only (requires Exchange 2013 - Hello MS advertising).
I'm new to C# and today is my first time to connect to the Exchange Server. I noticed from reading around that "find" is limited in what it can obtain, and that I'll need to bind the message in order to get more information from the email.
Code thus far:
foreach (Item item in findResults.Items)
if (item.HasAttachments) // && item.Attachments[0] is FileAttachment)
{
item.Load();
FileAttachment fileAttachment = item.Attachments[0] as FileAttachment;
date = Convert.ToString(item.DateTimeCreated);
name = Convert.ToString(fileAttachment.Name);
fileAttachment.Load("C:\\test\\" + fileAttachment.Name);
Console.WriteLine(name);
Console.WriteLine(item.Subject);
Console.WriteLine(date);
}
My question from here is if I do EmailMessage msg = EmailMessage.Bind ... what information will I need in order to grab more information?
Solved - for getting sender email and name as well as loading an attachment.
I used the EmailMessage class (just added it in the above loop, and added the variables to the beginning):
EmailMessage msg = (EmailMessage)item;
senderemail = Convert.ToString(msg.Sender.Address);
sendername = Convert.ToString(msg.Sender.Name);
I can then reproduce these on the console:
Console.WriteLine(senderemail);
Console.WriteLine(sendername);
Also, for loading an email's attaachment, I declared a byte[] variable at the beginning, loaded the attachment, converted it, and wrote its content to the console:
fileAttachment.Load();
filecontent = fileAttachment.Content;
System.Text.Encoding enc = System.Text.Encoding.ASCII;
string strFileContent = enc.GetString(filecontent);
Console.WriteLine(strFileContent);

Categories

Resources