How can I move mailItem from 1 store to another - c#

I'm trying to move a mail item form 1 store to another, using Outlook 2010 and C#
I'm gotten quite far, but not sure how I perform the 'move'. I'm assuming it's saveas and then delete
My attempt (code greatly reduced)
foreach (var mail in folder.Items)
{
//I am in the correct folder, and all I want to do is move all items to the 'inbox' of the store. I have already gotten the destination store and saved it as a variable called store
Microsoft.Office.Interop.Outlook.MailItem mailItem = (Microsoft.Office.Interop.Outlook.MailItem)mail; //got the item
mailItem.SaveAs(store.FilePath, Microsoft.Office.Interop.Outlook.OlSaveAsType.olMSG); // throws exception
mailItem.Delete();
}
I'm not sure if this is the best approach, but the line mailItem.SaveAs(store.FilePath, Microsoft.Office.Interop.Outlook.OlSaveAsType.olMSG); throws an exception:
The operation failed
I see no more detail other than that

The SaveAs method saves the Microsoft Outlook item to the specified path and in the format of the specified file type. If the file type is not specified, the MSG format (.msg) is used. So, the method is used to save items on the disk, not another store in Outlook.
You can use the Move method of the MailItem class to move a Microsoft Outlook item to a new folder. For example:
Sub MoveItems()
Dim myNameSpace As Outlook.NameSpace
Dim myInbox As Outlook.Folder
Dim myDestFolder As Outlook.Folder
Dim myItems As Outlook.Items
Dim myItem As Object
Set myNameSpace = Application.GetNamespace("MAPI")
Set myInbox = myNameSpace.GetDefaultFolder(olFolderInbox)
Set myItems = myInbox.Items
Set myDestFolder = myInbox.Folders("Personal Mail")
Set myItem = myItems.Find("[SenderName] = 'Eugene'")
While TypeName(myItem) <> "Nothing"
myItem.Move myDestFolder
Set myItem = myItems.FindNext
Wend
End Sub

Related

Microsoft Office Interop Outlook w/ C# - Why does Items.GetNext() return null?

I'm trying to fetch attachments from a particular folder in Outlook 2010 in a C# Windows Forms app. I have a class called MailInbox that contains the Outlook namespace, inbox, and message objects.
Here is the code for that class and its methods:
public class mailInbox
{
//declare needed variables for outlook office interop
public Outlook.Application oApp = new Outlook.Application();
//public Outlook.MAPIFolder oInbox;
public Outlook.MAPIFolder idFolder;
public Outlook.NameSpace oNS;
public Outlook.Items oItems;
public Outlook.MailItem oMsg;
public Outlook.MAPIFolder subFolder;
public string subFolderName;
public mailInbox()
{
//read the subfoldername from a text file
using (StreamReader subFolderNameRead = new StreamReader(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + #"\SuperVerify\config\subfoldername.txt"))
{
subFolderName = subFolderNameRead.ReadLine().Trim();
}
oNS = oApp.GetNamespace("mapi");
//oInbox = oNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
idFolder = oNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox).Folders[subFolderName]; // use the subFolderName string, read from the config text file, to get the folder from outlook
oItems = idFolder.Items;
//oMsg = (Outlook.MailItem)oItems.GetNext();
}
public void FetchEmail() // fetches the next email in the inbox and saves the attachments to the superverify folder
{
oNS.Logon(Missing.Value, Missing.Value, false, true); //login using default profile. This might need to be changed.
oMsg = (Outlook.MailItem) oItems.GetNext(); //fetch the next mail item in the inbox
if(oMsg.Attachments.Count > 0) // make sure message contains attachments **This is where the error occurs**
{
for (int i =0; i< oMsg.Attachments.Count; i++)
{
oMsg.Attachments[i].SaveAsFile(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + #"\SuperVerify\images\" + oMsg.Attachments[i].FileName); //save each attachment to the specified folder
}
} else //if no attachments, display error
{
MessageBox.Show("The inbox folder has no messages.", "TB ID Verification Tool", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
public void changeSubFolderName(string newSubFolderName)
{
subFolderName = newSubFolderName;
}
}
When I click the button that invokes the FetchEmail method, I get the error
System.NullReferenceException: 'Object reference not set to an instance of an object.'
oMsg was null. I thought that
public Outlook.MailItem oMsg;
instantiated the object and that
oMsg = (Outlook.MailItem) oItems.GetNext();
assigned it an Outlook MailItem, but it seems I don't understand what's going on here.
From the documentation which curiously references VB.NET's Nothing instead of null,
It returns Nothing if no next object exists, for example, if already positioned at the end of the collection.To ensure correct operation of the GetFirst, GetLast, GetNext, and GetPrevious methods in a large collection, call GetFirst before calling GetNext on that collection, and call GetLast before calling GetPrevious. To ensure that you are always making the calls on the same collection, create an explicit variable that refers to that collection before entering the loop.
So GetNext will return null if you're at the end of the folder. You'd have to check it for null before attempting to use it.
You can also use oItems.Count to determine that there are no items when you initially access the folder's items. But if Count is one or more you'd still have to check for null, because you're dealing with a collection that can change. Hypothetically someone could remove items from the folder while you're reading it, so you can't get the count up front and then rely on it.

Outlook drag-and-drop: how to get 'Internet Headers' from message

Frequently undesirable messages are received even after any good spam/virus filter.
As a secondary wall, we suggest our user to check the suspicious message properties ('internet headers') to verify the real origin. This action, for the non-tech guys is not easy.
I wrote a simple application to drag the message into it and analyze the headers locating IP addresses and origin: obviously, if the message is from your mother, you know she is not in China...
How can we get the 'internet headers' from the message? Is there any hidden property there?
Private Sub MainForm_DragDrop(sender As Object, e As DragEventArgs) Handles Me.DragDrop
Dim myOlApp As New Outlook.Application
Dim myExp As Outlook.Explorer = myOlApp.ActiveExplorer
Dim myMailItem As Outlook.MailItem = DirectCast(myExp.Selection.Item(1), Outlook.MailItem)
Dim x = myMailItem.Body
myExp = Nothing
myMailItem = Nothing
myOlApp = Nothing
End Sub
This works fine to get the body and other data like To, From etc, however no property expose 'Internet Headers'.
You need to read the PR_TRANSPORT_MESSAGE_HEADERS MAPI property:
Dim headers As String = myMailItem.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x007D001F")

Download outlook emails from specific Folders

I have written code for outllok addon such that when ever email arrives in inbox it should download , but the curret code is such that if it arrives into specific folder also it not getting get downloaded. Can some one guide me on this?
private void ThisApplication_NewMail()
{
const string destinationDirectory = #"C:\TestFileSave";
if (!Directory.Exists(destinationDirectory))
{
Directory.CreateDirectory(destinationDirectory);
}
MAPIFolder sentMail = Application.ActiveExplorer().Session.GetDefaultFolder(OlDefaultFolders.olFolderSentMail);
Items sentMailItems = sentMail.Items;
try
{
foreach (object collectionItem in sentMailItems)
{
MailItem newEmail = collectionItem as MailItem;
if (newEmail == null) continue;
if (newEmail.Attachments.Count > 0)
{
for (int i = 1; i <= newEmail.Attachments.Count; i++)
{
if (newEmail.Attachments[i].FileName.Contains("Logic"))
{
string filePath = Path.Combine(destinationDirectory, newEmail.Attachments[i].FileName);
newEmail.Attachments[i].SaveAsFile(filePath);
}
}
}
}
}
catch (System.Exception ex)
{
Console.WriteLine(ex);
}
You can handle the NewMailEx event to get notified when a new mail arrives. Then you can get an instace of the just arrived item using the EntryID value passed to the NewMailEx event handler. The GetItemFromID method of the Namespace class returns a Microsoft Outlook item identified by the specified entry ID (if valid).
Also you may consider handling the ItemAdd event of the Items class. It is fired when one or more items are added to the specified collection. Be aware, this event does not run when a large number of items are added to the folder at once.
You can read more about that in the series of articles:
Outlook NewMail event unleashed: the challenge (NewMail, NewMailEx, ItemAdd)
Outlook NewMail event: solution options
Outlook NewMail event and Extended MAPI: C# example
Outlook NewMail unleashed: writing a working solution (C# example)
The MarkForDownload property of Outlook items returns an OlRemoteStatus constant that determines the status of an item once it is received by a remote user. For example, the following example searches through the user's Inbox for items that have not yet been fully downloaded. If any items are found that are not fully downloaded, a message is displayed and the item is marked for download.
Sub DownloadItems()
Dim mpfInbox As Outlook.Folder
Dim obj As Object
Dim i As Integer
Set mpfInbox = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)
'Loop all items in the Inbox folder
For i = 1 To mpfInbox.Items.Count
Set obj = mpfInbox.Items.Item(i)
'Verify if the state of the item is olHeaderOnly
If obj.DownloadState = olHeaderOnly Then
MsgBox ("This item has not been fully downloaded.")
'Mark the item to be downloaded.
obj.MarkForDownload = olMarkedForDownload
End If
Next
End Sub
Finally, you can use the Start method of the SyncObject class to begin synchronizing a user's folders using the specified Send\Receive group.
Public Sub Sync()
Dim nsp As Outlook.NameSpace
Dim sycs As Outlook.SyncObjects
Dim syc As Outlook.SyncObject
Dim i As Integer
Dim strPrompt As Integer
Set nsp = Application.GetNamespace("MAPI")
Set sycs = nsp.SyncObjects
For i = 1 To sycs.Count
Set syc = sycs.Item(i)
strPrompt = MsgBox( _
"Do you wish to synchronize " & syc.Name &"?", vbYesNo)
If strPrompt = vbYes Then
syc.Start
End If
Next
End Sub

How to retrieve the Outlook folder of a mail item (Outlook.MailItem)?

I am getting my default inbox folder via inboxFolder = Globals.ThisAddIn.Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox
Elsewhere in my code, I begin doing a foreach loop to extract specific information I want from these MailItems
foreach (var item in this.inboxFolder.Items)
{
Outlook.MailItem mailItem = (Outlook.MailItem)item;
//.... doing stuff here
string SenderEmail = mailItem.SenderEmailAddress;
string SenderName = mailItem.SenderName;
string FolderLocation = mailItem.???; //how to retrieve folder location?
//.... more stuff here
}
For example: A user may have created a subfolder called 'Test' shown below.
Thank you for the pointer guys. However I was having some trouble implementing the same initially. Here is how I solved it, just in case if some one faces the same issue.
Outlook.MAPIFolder parentFolder = mailItemToDelete.Parent as Outlook.MAPIFolder;
string FolderLocation = parentFolder.FolderPath;
The Parent object is dynamic and hence was causing issue.
Do you mean folder path? Use MAPIFolder.FullFolderPath. Or MAPIFoldert.Name if you only need the name.
Also keep in mind that the value will be the same for all items in the folder, so there is no reason to evaluate it on each step of the loop.

Sorting Emails by Received time before processing C# Outlook

I need to sort my emails by Received time before processing them as I am processing emails and entering data from it into a database.
I need it so the newest email to be received gets put into the database to overwrite the older version (If there is an older version).
Microsoft.Office.Interop.Outlook.Items item = (Outlook.Items)source.Items;
Source is the folder with the emails in it that I wanted sorted
I have tried these four ways:
items.Sort("ReceivedTime", false);
items.Sort("[ReceivedTime]", Outlook.OlSortOrder.olAscending);
items.Sort("ReceivedTime", Outlook.OlSortOrder.olSortNone);
items.Sort("[ReceivedTime]");
Which does not seem to sort it as It still puts the oldest into the database second, overwriting the newest submission.
Any Ideas?
it should be
items.Sort("[ReceivedTime]", false);
or true if you want them descending
I spent so much time trying to figure out the same problem.
It appears there is some sort of bug in Microsoft Interop.outlook that if you directly try to sort from folder it does not work at all.
Microsoft.Office.Interop.Outlook.Application app = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook._NameSpace ns = app.GetNamespace("MAPI");
Microsoft.Office.Interop.Outlook.MAPIFolder inboxFolder = null;
inboxFolder = ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
inboxFolder.Items.Sort("[ReceivedTime]", false);
foreach (var item in inboxFolder.Items)
{
// ITEMS ARE NOT SORTED
}
To make it work you must copy them in different list and then sort. The example below will work.
Outlook.Application app = new Outlook.Application();
Outlook.NameSpace outlookNs = app.GetNamespace("MAPI");
Outlook.MAPIFolder emailFolder = outlookNs.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
Outlook.Items myItems = emailFolder.Items;
myItems.Sort("[ReceivedTime]", false);
foreach (var item in myItems)
{
var itemObj = item as MailItem;
if (itemObj != null)
{
// This time it will work
}
}
Now I don't know what class your item-Object is, but maybe the "Sort"-Method does not have return type "void", but it returns a new list itself.
So you should assign your list like so:
items = items.Sort();
You could then try, which of your four approaches fits your needs.
I hope this helps!
Sub SortByDueDate()
Dim myNameSpace As Outlook.NameSpace
Dim myFolder As Outlook.Folder
Dim myItem As Outlook.TaskItem
Dim myItems As Outlook.Items
Set myNameSpace = Application.GetNamespace("MAPI")
Set myFolder = myNameSpace.GetDefaultFolder(olFolderTasks)
Set myItems = myFolder.Items
myItems.Sort "[DueDate]", False
For Each myItem In myItems
MsgBox myItem.Subject &; "-- " &; myItem.DueDate
Next myItem
End Sub
This code is come from MSDN. I am confused as to why at beginning it sets myItmes=myFolder.Items. After trying many times, I know this is a trap. If you use myFolder.Items.sort... directly, the sort function does not work.

Categories

Resources