Here I am trying to get all the part of an email separately like body, attachments, address part also So I have the below code . So can I get the attachment files also by using same technique( Using PropertySet class or define RequestedBodyType to something)???
Is there any way to get the contents of Attachment files of any type and I don't need to change the code too much??
// Get the Unread mails from the server
SearchFilter itemFilter = new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false);
// get the emails from Inbox folder
FindItemsResults<Item> emails = service.FindItems(WellKnownFolderName.Inbox, itemFilter, view);
foreach (EmailMessage em in emails)
{
itempropertyset.RequestedBodyType = BodyType.HTML;
em.Load(itempropertyset);
em.IsRead = true;
em.Update(ConflictResolutionMode.AlwaysOverwrite);
EmailProList.HTMLBody = em.Body.Text;
itempropertyset.RequestedBodyType = BodyType.Text;
em.Load(itempropertyset);
EmailProList.Body = em.Body.Text;
itempropertyset.RequestedBodyType =
EmailProList.ToEmailAddr = em.Sender.Address.ToString(); //JG Changed
EmailProList.Subject = em.Subject.ToString();
EmailProList.Type = "Feedback";
}
You can get the attachments like this:
EmailMessage email = item as EmailMessage;
foreach(FileAttachment file in email.FileAttachments)
{
// Process the attachment
}
You can process the attachments by this way.
if (message.HasAttachments && message.Attachments[0] is FileAttachment)
{
FileAttachment fileAttachment = message.Attachments[0] as FileAttachment;
Console.WriteLine("email" + fileAttachment.Name);
fileAttachment.Load(#"D:\\" + fileAttachment.Name);
}
Related
If we have the UniqueId to the mail we wish to move the attachment to via the usage of an ImapClient, how exactly can we achieve this?
Thank you!
UniqueId? AddAttachmentToMessage (ImapClient client, ImapFolder folder, UniqueId uid, MimeEntity attachment)
{
var message = folder.GetMessage (uid);
var body = message.Body;
Multipart multipart;
if (message.Body is Multipart && message.Body.ContentType.IsMimeType ("multipart", "mixed")) {
multipart = (Multipart) message.Body;
} else {
multipart = new Multipart ("mixed");
multipart.Add (message.Body);
message.Body = multipart;
}
multipart.Add (attachment);
var newUid = folder.Append (message);
folder.AddFlags (uid, MessageFlags.Deleted, true);
if (client.Capabilities.HasFlag (ImapCapabilities.UidPlus))
folder.Expunge (new UniqueId[] { uid });
return newUid;
}
If the server doesn't support UIDPLUS and you need the newUid value, then you can probably do something like this:
if (!client.Capabilities.HasFlag (ImapCapabilities.UidPlus)) {
var initialUids = folder.Search (SearchQuery.All);
folder.Append (message);
var updatedUids = folder.Search (SearchQuery.All);
// find the new uids
var newUids = new UniqueIdSet (SortOrder.Ascending);
for (int i = updatedUids.Count - 1; i >= 0; i--) {
if (!initialUids.Contains (updatedUids[i]))
newUids.Add (updatedUids[i]);
}
// get envelope info for each of the new messages
var newItems = folder.Fetch (newUids, MessageSummaryItems.UniqueId | MessageSummaryItems.Envelope);
foreach (var item in newItems) {
var msgid = MimeUtils.ParseMessageId (item.Envelope.MessageId);
if (message.MessageId.Equals (msgid))
return item.UniuqeId;
// Note: if you want to be more pedantic, you can compare the From/To/Cc/ReplyTo and Subject fields as well.
}
}
I have a mail containing only a signature as an image and an attachment like the screenshot below.
I save this email as C:\mail.msg, I try then to read it by the code below:
var oApp = new Microsoft.Office.Interop.Outlook.Application();
MailItem outlookMsg = (Microsoft.Office.Interop.Outlook.MailItem)oApp.CreateItemFromTemplate(#"C:\mail.msg");
//there are 2 attachments inside
foreach(var att in outlookMsg.Attachments)
{
att.SaveAsFile($#"C:\{att.FileName}");
}
The problem
There are 2 attachments inside the MailItem named :
-empty.xlsx
-lot4.xlsx
If I change the extension of lot4.xlsx to lot4.png, it can be opened as the image in the signature.
Someone has seen this strange situation when an attachment is added with name incorrect?
You could download attachments using the below code:
private void ThisApplication_NewMail()
{
Outlook.MAPIFolder inBox = this.Application.ActiveExplorer()
.Session.GetDefaultFolder(Outlook
.OlDefaultFolders.olFolderInbox);
Outlook.Items inBoxItems = inBox.Items;
Outlook.MailItem newEmail = null;
inBoxItems = inBoxItems.Restrict("[Unread] = true");
try
{
foreach (object collectionItem in inBoxItems)
{
newEmail = collectionItem as Outlook.MailItem;
if (newEmail != null)
{
if (newEmail.Attachments.Count > 0)
{
for (int i = 1; i <= newEmail
.Attachments.Count; i++)
{
newEmail.Attachments[i].SaveAsFile
(#"C:\TestFileSave\" +
newEmail.Attachments[i].FileName);
}
}
}
}
}
catch (Exception ex)
{
string errorInfo = (string)ex.Message
.Substring(0, 11);
if (errorInfo == "Cannot save")
{
MessageBox.Show(#"Create Folder C:\TestFileSave");
}
}
}
For more information, please refer to this link:
How to: Programmatically save attachments from Outlook email items
With Microsoft EWS, its very easy to do:
reference: http://johnlabtest.blogspot.com/2014/01/save-attachments-from-exchange-mail-box.html
static void Main(string[] args)
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.Credentials = new WebCredentials("user1#contoso.com", "password");
service.TraceEnabled = true;
service.TraceFlags = TraceFlags.All;
service.AutodiscoverUrl("user1#contoso.com", RedirectionUrlValidationCallback);
var messages = new List<EmailMessage>();
// only get unread emails
SearchFilter folderSearchFilter = new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false);
// we just need the id in our results
var itemView = new ItemView(10) {PropertySet = new PropertySet(BasePropertySet.IdOnly)};
FindItemsResults<Item> findResults = service.FindItems(folder.Id, folderSearchFilter, itemView);
foreach (Item item in findResults.Items.Where(i => i is EmailMessage))
{
EmailMessage message = EmailMessage.Bind(service, item.Id, new PropertySet(BasePropertySet.IdOnly, ItemSchema.Attachments, ItemSchema.HasAttachments));
messages.Add(message);
}
// loop through messages and call processemail here.
}
public static void ProcessEmail(EmailMessage message)
{
string saveDir = ConfigurationManager.AppSettings["AttachmentSaveDirectory"];
if (message.HasAttachments)
{
foreach (Attachment attachment in message.Attachments.Where(a=> a is FileAttachment))
{
FileAttachment fileAttachment = attachment as FileAttachment;
fileAttachment.Load(); // populate the content property of the attachment
using (FileStream fs = new FileStream(saveDir + attachment.Name, FileMode.Create))
{
using (BinaryWriter w = new BinaryWriter(fs))
{
w.Write(fileAttachment.Content);
}
}
}
}
message.IsRead = true;
message.Update(ConflictResolutionMode.AutoResolve); // push changes back to server
}
private static bool RedirectionUrlValidationCallback(string redirectionUrl)
{
// The default for the validation callback is to reject the URL.
bool result = false;
Uri redirectionUri = new Uri(redirectionUrl);
// Validate the contents of the redirection URL. In this simple validation
// callback, the redirection URL is considered valid if it is using HTTPS
// to encrypt the authentication credentials.
if (redirectionUri.Scheme == "https")
{
result = true;
}
return result;
}
I am trying to add a FileAttachment to a message. Unfortunately message.Attachments.AddFileAttachment() asks for a path, which I don't have. I have the FileAttachment straight from another mail.
Here I get the attachment:
EmailMessage oldEmailMessage = EmailMessage.Bind(service, olderSoxMail.Id);
// load attachments
FileAttachment fileAttachment = newEmailMessage.Attachments[0] as FileAttachment;
fileAttachment.Load();
Here I try to attach the attachment to a mail
public static void ComposeEmail(string recipient, string subject, string body, FileAttachment[] attachment = null)
{
var map = new Dictionary<char, string>() {
{ 'ä', "ae" },
{ 'ö', "oe" },
{ 'ü', "ue" },
{ 'Ä', "Ae" },
{ 'Ö', "Oe" },
{ 'Ü', "Ue" },
{ 'ß', "ss" }
};
recipient = recipient.Aggregate(
new StringBuilder(),
(sb, c) =>
{
string r;
if (map.TryGetValue(c, out r))
return sb.Append(r);
else
return sb.Append(c);
}).ToString();
EmailMessage message = new EmailMessage(service);
message.Subject = subject;
message.Body = body;
message.ToRecipients.Add(recipient);
foreach (FileAttachment attach in attachment)
{
// COMPILER ERROR HERE: Cannot Convert from FileAttachment to Path (string)
message.Attachments.AddFileAttachment(attach);
// END ERROR
}
message.SendAndSaveCopy();
}
Do you know how I can add the FileAttachment?
Now your fileattachments that you are receiving exist on the Exchange server. You can download those attachments and store the path and attach those paths to your new email.
A better solution is reading the attachments as streams and attach them directly to the mail without saving them to disk first.
foreach (var fileAttachment in fileAttachments)
{
var stream = new System.IO.MemoryStream(fileAttachment.Content);
message.Attachments.AddFileAttachment(fileAttachment.Name, stream);
}
I have looked at other examples online, but I am unable to figure out how to download and store ALL the attachments from a MimeMessage object.
I did look into the WriteTo(), but I could not get it to work.
Also wondering whether attachments will be saved according to the original file name, and type inside the email.
Here is what I have so far:
using (var client = new ImapClient())
{
client.Connect(Constant.GoogleImapHost, Constant.ImapPort, SecureSocketOptions.SslOnConnect);
client.AuthenticationMechanisms.Remove(Constant.GoogleOAuth);
client.Authenticate(Constant.GoogleUserName, Constant.GenericPassword);
if (client.IsConnected == true)
{
FolderAccess inboxAccess = client.Inbox.Open(FolderAccess.ReadWrite);
IMailFolder inboxFolder = client.GetFolder(Constant.InboxFolder);
IList<UniqueId> uids = client.Inbox.Search(SearchQuery.All);
if (inboxFolder != null & inboxFolder.Unread > 0)
{
foreach (UniqueId msgId in uids)
{
MimeMessage message = inboxFolder.GetMessage(msgId);
foreach (MimeEntity attachment in message.Attachments)
{
//need to save all the attachments locally
}
}
}
}
}
This is all explained in the FAQ in the "How do I save attachments?" section.
Here is a fixed version of the code you posted in your question:
using (var client = new ImapClient ()) {
client.Connect (Constant.GoogleImapHost, Constant.ImapPort, SecureSocketOptions.SslOnConnect);
client.AuthenticationMechanisms.Remove (Constant.GoogleOAuth);
client.Authenticate (Constant.GoogleUserName, Constant.GenericPassword);
client.Inbox.Open (FolderAccess.ReadWrite);
IList<UniqueId> uids = client.Inbox.Search (SearchQuery.All);
foreach (UniqueId uid in uids) {
MimeMessage message = client.Inbox.GetMessage (uid);
foreach (MimeEntity attachment in message.Attachments) {
var fileName = attachment.ContentDisposition?.FileName ?? attachment.ContentType.Name;
using (var stream = File.Create (fileName)) {
if (attachment is MessagePart) {
var rfc822 = (MessagePart) attachment;
rfc822.Message.WriteTo (stream);
} else {
var part = (MimePart) attachment;
part.Content.DecodeTo (stream);
}
}
}
}
}
A few notes:
There's no need to check if client.IsConnected after authenticating. If it wasn't connected, it would have thrown an exception in the Authenticate() method. It would have thrown an exception in the Connect() method as well if it didn't succeed. There is no need to check the IsConnected state if you literally just called Connect() 2 lines up.
Why are you checking inboxFolder.Unread if you don't even use it anywhere? If you just want to download unread messages, change your search to be SearchQuery.NotSeen which will give you only the message UIDs that have not been read.
I removed your IMailFolder inboxFolder = client.GetFolder(Constant.InboxFolder); logic because you don't need it. If you are going to do the SEARCH using client.Inbox, then don't iterate over the results with a different folder object.
I'm using Outlook.Interop in order to to get the Html Body from email recieved.
I'm trying to get the recipients' email address, but only getting a name of the recipients and not the full email address.
Application myApp = new ApplicationClass();
NameSpace mapiNameSpace = myApp.GetNamespace("MAPI");
MAPIFolder myInbox = mapiNameSpace.GetDefaultFolder(OlDefaultFolders.olFolderInbox).Folders["digitel"];
List<MailItem> ReceivedEmails = new List<MailItem>();
foreach (MailItem mail in myInbox.Items)
{ ReceivedEmails.Add(mail); }
var Recipients = ReceivedEmails[0].Recipients.ToString();
Checkout the following snippet:
foreach (Outlook.Recipient recip in ReceivedEmails[0].Recipients)
{
Debug.WriteLine(recip.AddressEntry.GetExchangeUser().PrimarySmtpAddress.ToString());
}
Let me know if you have any problem :)!