I wanted to save Outlook mails in to msg format along with the attachment through C#.
I tried the following code
using Outlook = Microsoft.Office.Interop.Outlook;
private void button1_Click(object sender, EventArgs e)
{
Outlook.Application app = new Microsoft.Office.Interop.Outlook.Application();
Outlook.NameSpace ns = app.GetNamespace("MAPI");
Outlook.MAPIFolder inbox = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
foreach (Outlook.MailItem item in inbox.Items)
{
item.SaveAs(finename, Outlook.OlSaveAsType.olMSG);
}
}
It could save the mail as msg but the attachment part was removed. SaveAs method had no other overloads alos... :(
If i try to save a message from outlook it saves the message along with the attachment embedded in it. Any idea how this can be achieved..?
I am using .Net Framework 3.5 and Outolook 2007
What are you using as a filename? does it end with .msg?
I do something like this and it works as you describe you want it too:
Outlook.MailItem msg;
foreach (object obj in f.Mapi.Items)
{
try
{
msg = obj as Outlook.MailItem;
// ... set file name using message attributes
// string fullPath = "something" + ".msg"
msg.SaveAs(fullPath, Outlook.OlSaveAsType.olMSG);
}
}
The reason I'm so curious in your case is that I am wondering how I can reproduce what you are doing: saving the mail item with out saving the attachments?
I believe that you will have to save them separately.
Use the Attachments property on the MailItem to get all the attachments. then loop through them and call SaveAsFile() for each of the attachments.
examples in below link are for basic, but it should work in C# as well
MailItem::Attachments
http://msdn.microsoft.com/en-us/library/bb207129.aspx
Attachment::SaveAsFile
http://msdn.microsoft.com/en-us/library/bb219926.aspx
Related
I have made an Outlook Add-In (Outlook 2013 and 2016 VSTO Add-In) for business purposes to save the email details to our database. The add-in is launched when a new email is composed, but closes when the email is sent.
The sent date of the email is only added after the email is moved to the Sent mailbox. Is there a way to use my current add-in (or another add-in) can be used to get that sent date after it has been closed without letting the user wait for it to be moved to the sent mailbox?
I know it can easily be done in VBA, but I want to preferably use an Add-in so that it can be easily loaded to all users with exchange server.
Wouldn't that date be today's date/time (Now) or something close to it?
Everything you can do in VBA you can do in a COM addin - subscribe to the Items.ItemAdd event on the Sent Items folder and retrieve the date when the event fires.
Thank you Dmitry for the reply. It set me on the right path. I used my existing VSTO add in to fire when a new item is added to the Sent mailbox. I did not know that when inserting this in the "ThisAddIn_Startup" method re-activates the add-in, which now makes sense.
I followed this example.
Here is my code:
Outlook.NameSpace outlookNameSpace;
Outlook.MAPIFolder Sent_items;
Outlook.Items items;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
outlookNameSpace = this.Application.GetNamespace("MAPI");
Sent_items = outlookNameSpace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderSentMail);
items = Sent_items.Items;
items.ItemAdd += new Outlook.ItemsEvents_ItemAddEventHandler(items_ItemAdd);
}
void items_ItemAdd(object Item)
{
Outlook.MailItem mail = (Outlook.MailItem)Item;
string strMailItemNumber_filter = mail.UserProperties["MailItemNumber"].Value;
if ((Item != null) && (!string.IsNullOrWhiteSpace(strMailItemNumber_filter)))
{
if (mail.MessageClass == "IPM.Note" &&
mail.UserProperties["MailItemNumber"].Value.ToUpper().Contains(strMailItemNumber_filter.ToUpper())) //Instead of subject use other mail property
{
//Write 'Sent date' to DB
System.Windows.Forms.MessageBox.Show("Sent date is: "+ mail.SentOn.ToString()+ " MailNr = "+strMailItemNumber_filter);
}
}
}
I had to create a new mail user defined property to match the email I sent to find the correct email in the sent mailbox:
private void AddUserProperty(Outlook.MailItem mail)
{
Outlook.UserProperties mailUserProperties = null;
Outlook.UserProperty mailUserProperty = null;
try
{
mailUserProperties = mail.UserProperties;
mailUserProperty = mailUserProperties.Add("MailItemNrProperty", Outlook.OlUserPropertyType.olText, false, 1);
// Where 1 is OlFormatText (introduced in Outlook 2007)
mail.UserProperties["MailItemNumber"].Value = "Any value as string...";
mail.Save();
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
finally
{
if (mailUserProperty != null) Marshal.ReleaseComObject(mailUserProperty);
if (mailUserProperties != null) Marshal.ReleaseComObject(mailUserProperties);
}
}
string email ="sample#gmail.com";
attachment = path + "/" + filename;
Application.OpenURL ("mailto:" +
email+"
?subject=EmailSubject&body=EmailBody"+"&attachment="+attachment);
In the above code, attachment isn't working. Is there any other alternative to add attachments using a mailto: link in C#?
mailto: doesn't officially support attachments. I've heard Outlook 2003 will work with this syntax:
<a href='mailto:name#domain.com?Subject=SubjTxt&Body=Bod_Txt&Attachment=""C:\file.txt"" '>
Your problem has already been answered:
c-sharp-mailto-with-attachment
You can use the System.Net.Mail which has the MailMessage.Attachments Property. Something like:
message.Attachments.Add(new Attachment(yourAttachmentPath));
OR
You can try like this:
using SendFileTo;
namespace TestSendTo
{
public partial class Form1 : Form
{
private void btnSend_Click(object sender, EventArgs e)
{
MAPI mapi = new MAPI();
mapi.AddAttachment("c:\\temp\\file1.txt");
mapi.AddAttachment("c:\\temp\\file2.txt");
mapi.AddRecipientTo("person1#somewhere.com");
mapi.AddRecipientTo("person2#somewhere.com");
mapi.SendMailPopup("testing", "body text");
// Or if you want try and do a direct send without displaying the
// mail dialog mapi.SendMailDirect("testing", "body text");
}
}
}
The above code uses the MAPI32.dll.
Source
It probably won't attach the document because you are at the liberty
of the email client to implement the mailto protocol and include
parsing for the attachment clause. You may not know what mail client
is installed on the PC, so it may not always work - Outlook certainly
doesn't support attachments using mailto.
A better way to handle this is to send the mail on the server using System.Net.Mail.Attachment.
public static void CreateMessageWithAttachment(string server)
{
// Specify the file to be attached and sent.
// This example assumes that a file named Data.xls exists in the
// current working directory.
string file = "data.xls";
// Create a message and set up the recipients.
MailMessage message = new MailMessage(
"jane#contoso.com",
"ben#contoso.com",
"Quarterly data report.",
"See the attached spreadsheet.");
// Create the file attachment for this e-mail message.
Attachment data = new Attachment(file, MediaTypeNames.Application.Octet);
// Add time stamp information for the file.
ContentDisposition disposition = data.ContentDisposition;
disposition.CreationDate = System.IO.File.GetCreationTime(file);
disposition.ModificationDate = System.IO.File.GetLastWriteTime(file);
disposition.ReadDate = System.IO.File.GetLastAccessTime(file);
// Add the file attachment to this e-mail message.
message.Attachments.Add(data);
//Send the message.
SmtpClient client = new SmtpClient(server);
// Add credentials if the SMTP server requires them.
client.Credentials = CredentialCache.DefaultNetworkCredentials;
try
{
client.Send(message);
}
catch (Exception ex)
{
Console.WriteLine("Exception caught in CreateMessageWithAttachment(): {0}", ex.ToString());
}
data.Dispose();
}
How I can to move emails from inbox to some folder, for example folder "test"
Pop3Client client = new Pop3Client()
client contains method to get email in html, xml, etc. also delete email or delete all emails, but I need to move some email to another folder, it is possible ?
OpenPop implements the POP3 protocol. This protocol is old, and does not know about such things as folders. Therefore, the OpenPop implementation cannot handle folders as well.
If you need to use folders, consider using some IMAP client instead. IMAP is a newer and more modern protocol.
As J. Steen has pointed out. No, you can't with OpenPop.
Just encase you still want to do it and it wasn't a purely academic question. Taken from MSDN
How to: Programmatically Move Items in Outlook
This example moves unread e-mail messages from the Inbox to a folder named Test. The example only moves messages that have the word Test in the Subject field.
Applies to: The information in this topic applies to application-level projects for Outlook 2013 and Outlook 2010. For more information, see Features Available by Office Application and Project Type.
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
this.Application.NewMail += new Microsoft.Office.Interop.Outlook.
ApplicationEvents_11_NewMailEventHandler
(ThisAddIn_NewMail);
}
private void ThisAddIn_NewMail()
{
Outlook.MAPIFolder inBox = (Outlook.MAPIFolder)this.Application.
ActiveExplorer().Session.GetDefaultFolder
(Outlook.OlDefaultFolders.olFolderInbox);
Outlook.Items items = (Outlook.Items)inBox.Items;
Outlook.MailItem moveMail = null;
items.Restrict("[UnRead] = true");
Outlook.MAPIFolder destFolder = inBox.Folders["Test"];
foreach (object eMail in items)
{
try
{
moveMail = eMail as Outlook.MailItem;
if (moveMail != null)
{
string titleSubject = (string)moveMail.Subject;
if (titleSubject.IndexOf("Test") > 0)
{
moveMail.Move(destFolder);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
i have written a code that will read all unread mails from Outlook 2010 and write them in a file. After that i want to change the status of the mails as Read in outlook.
How do i do it?
I am using Interop for accessing the mails.
Microsoft.Office.Interop.Outlook.Application app = null;
Microsoft.Office.Interop.Outlook._NameSpace ns = null;
Microsoft.Office.Interop.Outlook.MailItem item = null;
Microsoft.Office.Interop.Outlook.MAPIFolder inboxFolder = null;
Microsoft.Office.Interop.Outlook.Items unreadItems = null;
app = new Microsoft.Office.Interop.Outlook.Application();//.CreateItem(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
ns = app.GetNamespace("MAPI");
inboxFolder = ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
unreadItems = inboxFolder.Items.Restrict("[Unread]=true");
Here are some link that could help you:
http://msdn.microsoft.com/en-us/library/aa289167%28VS.71%29.aspx (it is for Outlook 2003 but it still contains very usefull info)
http://msdn.microsoft.com/en-us/library/ms268731%28VS.80%29.aspx
I've a code sample that could help you:
OutLook.Application oApp;
OutLook._NameSpace oNS;
OutLook.MAPIFolder oFolder;
OutLook._Explorer oExp;
oApp = new OutLook.Application();
oNS = (OutLook._NameSpace)oApp.GetNamespace("MAPI");
oFolder = oNS.GetDefaultFolder(OutLook.OlDefaultFolders.olFolderInbox);
oExp = oFolder.GetExplorer(false);
oNS.Logon(Missing.Value, Missing.Value, false, true);
OutLook.Items items = oFolder.Items;
foreach (OutLook.MailItem mail in items)
{
if (mail.UnRead)
{
mail.UnRead = false;
mail.Save();
}
Marshal.ReleaseCOMObject(mail);
}
Marshal.ReleaseCOMObject(items);
// Dont forget to free all other object, using Marshal.ReleaseCOMObject then close oApp
Please note I've not tested if it works or even compile.
On of general rule with outlook dev is that you need to release ALL com object otherwise you can have strange behavior (save popup when closing outlook app, or even the outlook never close etc.)
EDIT:
I would advice to you indeed use the Restrict method to get only unred mail, because my snippet above will loop in all emails which could be unnecessary and not performant.
Set the OutLook.MailItem's UnRead property to false
Is there any way to get all mail from an specific Folder into my Application?
Check this link. Introduction to Outlook Programming will explain things more clearly.
You could loop through the mailitems. Sample code
using System.Runtime.InteropServices;
using OutLook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;
OutLook.Application oApp;
OutLook._NameSpace oNS;
OutLook.MAPIFolder oFolder;
OutLook._Explorer oExp;
oApp = new OutLook.Application();
oNS = (OutLook._NameSpace)oApp.GetNamespace("MAPI");
oFolder = oNS.GetDefaultFolder(OutLook.OlDefaultFolders.olFolderInbox);
oExp = oFolder.GetExplorer(false);
oNS.Logon(Missing.Value, Missing.Value, false, true);
OutLook.Items items = oFolder.Items;
foreach (OutLook.MailItem mail in items)
{
if (mail.UnRead == true)
{
}
}
Edit:
Reference other folders
oFolder.Folders["Foldername"]
OutLook Code
Common Outlook tasks
Looping through all items in a folder is a terrible idea, especially if you are working against an online Exchange store. Items.Find/FindNext or Items.Restrict is the way to go.
Find/FindNext:
OutLook.Items items = oFolder.Items;
OutLook.MailItem mail = items.Find("[Unread] = true");
while (mail != null)
{
MessageBox.Show(mail.Subject);
mail = items.FindNext();
}
Items.Restrict:
OutLook.Items items = oFolder.Items.Restict("[Unread] = true")
foreach (OutLook.MailItem mail in items)
{
MessageBox.Show(mail.Subject);
}
There's some examples of accessing Outlook folders here, one of which deals specifically with unread mail.
Edit: There's a KB article specifically about accessing folders from C#, Programming samples that can reference items and folders in Outlook by using Visual C# .NET
To open another user's folder, use GetSharedDefaultFolder
foreach (Object Unreadmail in folderItems)
{
if ((Unreadmail as Outlook.MailItem) != null && (Unreadmail as Outlook.MailItem).UnRead == true)
{
//DO Your action Here
}
}
I have experienced "COM_object" exception error with above solutions, More info please refer here