I'm trying to add folder to inbox as follows:
var _client = new ImapClient();
_client.Connect(hostName, portNumber, useSsl);
_client.Authenticate(username, password);
_client.Inbox.Open(FolderAccess.ReadWrite);
_client.Inbox.Create("Name", true);
Everything goes fine, the Create function returns created folder, the _client.Inbox.GetSubfolders() returns list that contains new created folder as well, however I can't see this folder in e-mail client application (such as Thunderbird).
What am I doing wrong?
Thunderbird may only be showing you subscribed folders. If that is the case, then you will also want to do newFolder.Subscribe ();
I should also point out that there's no reason to Open() the inbox before creating a child folder.
You only need to Open() a folder in order to read messages from it.
Related
I'm using Outlook Redemption library (http://www.dimastr.com/redemption/home.htm) for my Outlook AddIn. I want to move multiple mails from an exchange account to a PST store.
onlineAccountFolder.Items.MoveMultiple(onlineEntryIds, targetFolderInPstStore);
The source folder mails were cut from the Exchange account, but not pasted in the target folder. They are gone.
I tried the same operation on an Exchange account folder in the same store and the move operation was successful. The items were moved to the target folder.
There's no overload of the 'MoveMultiple' method where I can define a StoreID.
I had no problem with the following script executed from OutlookSpy (I am its author - click “Script Editor” button on the OutlookSpy toolbar, paste the script, click Run.
The script moves the messages selected in Outlook to a folder returned by the PickFolder method. Works as expected with both PST and Exchange target folders.
set Session = CreateObject("Redemption.RDOSession")
Session.MAPIOBJECT = Application.Session.MAPIOBJECT
dim messages()
set sel = Application.ActiveExplorer.Selection
redim messages(sel.Count-1)
for i = 1 to sel.Count
messages(i-1) = sel.Item(i).EntryID
next
set targetFolder = Session.PickFolder
set sourceFolder = Session.GetFolderFromID(Application.ActiveExplorer.CurrentFolder.EntryID)
sourceFolder.Items.MoveMultiple messages, targetFolder
Use the Move method of the RDOMail class to move items between stores in Outlook.
I receive an email with an excel file every week. I know there are probably better ways to accomplish my goal, but would it be possible to have a script task in SSIS that can open email, look for a specific file name as an attachment and then copy that file to another location?
Here is the scenario. This excel file is important for my team to have in a SQL database, and the provider of the excel source is only willing to email this excel file to us once per week. I then check my email, copy the file to a location where an SSIS dataflow task can then pick it up and insert it into a SQL table. I would like to automate this. So if my original approach is not doable, how else could this be automated? Aside from using a shared network location. Assume the excel file can ONLY come from the email. Using outlook/office 365, SSIS, SSMS, I have DBO access, and can use c#.
I'll admit that I'm ignorant on the email. If there is a procedure that the email client can actually execute to accomplish this, then I'd be all ears!
EDIT: I also have access to a network drive as I realize saving to my local machine may be impossible.
Simple Answer Yes it is Possible.
I had written a console program to process email on Office365 that I was also interfacing with SQL, so it definitely can be done. It isn't necessarily the easiest thing in the world but it is not too hard either.
You can use the Exchange Web Services (EWS) Managed API
Article on stating it is possible and the API documentation
https://msdn.microsoft.com/en-us/library/office/dd877012(v=exchg.150).aspx
Github location where you can find the API (note this link is directly form Microsoft's Site)
https://github.com/officedev/ews-managed-api
Link on how to reference the assembly which contains the second link above:
https://msdn.microsoft.com/en-us/library/office/dn528373(v=exchg.150).aspx
Create and Connect to Service
string emailAddress = 'YourEmail#Domain.com';
ExchangeService exService = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
exService.Credentials = new WebCredentials(emailAddress,"password");
you can autodiscover or if you know the URL just set it so 1 of these lines
exService.AutodiscoverUrl(_emailAddress, delegate { return true; });
exService.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
Find your Inbox & a Folder to Move the File To After Being Processed:
FolderView folderView = new FolderView(1);
folderView.PropertySet = new PropertySet(BasePropertySet.IdOnly);
folderView.PropertySet.Add(FolderSchema.DisplayName);
folderView.Traversal = FolderTraversal.Deep;
SearchFilter searchFilter = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "ProcessedFolderName");
Folder Inbox = Folder.Bind(exService, WellKnownFolderName.Inbox);
FindFoldersResults folderResults = Inbox.FindFolders(searchFilter, folderView);
FolderId processedFolderId = folderResults.Folders[0].Id;
Find Messages That meet your criteria:
List<SearchFilter> searchFilterCollection = new List<SearchFilter();
searchFilterCollection.Add(new SearchFilter.ContainsSubstring(ItemSchema.Subject,"Words in Subject"));
searchFilterCollection.Add(new SearchFilter.IsEqualTo(ItemSchema.HasAttachments,true));
searchFilterCollection.Add(new SearchFilter.IsEqualTo(EmailMessageSchema.From,new EmailAddress("From#SendersDomain.com")));
SearchFilter searchFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.And,searchFilterCollection);
ItemView view = new ItemView(50, 0, OffsetBasePoint.Beginning);
view.OrderBy.Add(ItemSchema.DateTimeReceived, SortDirection.Descending);
view.PropertySet = new PropertySet(BasePropertySet.IdOnly, ItemSchema.DateTimeReceived, ItemSchema.Attachments);
view.Traversal = ItemTraversal.Shallow;
FindItemsResults<Item> findResults = exService.FindItems(WellKnownFolderName.Inbox,searchFilter,view);
Process the results and save the attachments when done move the message to another folder so you don't keep importing the same one.
foreach (Item i in findResults.Items)
{
foreach(FileAttachment attachment in i.Attachments)
{
attachment.Load(#"\\FilePathDirectory\" + attachment.FileName);
}
i.Move(processedFolderId);
}
you can expand the solution by testing if you get no results sending yourself an error message or throwing an error for SSIS to pickup and fail the job. It is likely that you will overwrite the file multiple times if you have multiple messages to process so you may consider adding something unique in the file name instead of just using the same one but that will present other challenges in SSIS as well.
anyway, its a start hope it helps.
I am using the following code to open the signed/unsigned
Outlook messages and I display the content in WebBrowser control.
Microsoft.Office.Interop.Outlook.Application app = new Microsoft.Office.Interop.Outlook.Application();
var item = app.Session.OpenSharedItem(msgfile) as Microsoft.Office.Interop.Outlook.MailItem;
string message = item.HTMLBody;
app.Session.Logoff();
It is working fine for the first time the file is opening, but after
closing the Outlook file trying to reopen the file it showing the
following error:
"Cannot open file: C:\tion.msg. The file may not exist, you may not
have permission to open it, or it may be open in another program.
Right-click the folder that contains the file, and then click
Properties to check your permissions for the folder."
After some time later it is opening fine. For this strange behavior
what could be the reason and how to rectify the the error message?
Outlook manages its own cache of items when you are opening and closing messages. Your best bet would be to use a randomly generated filename (i.e. Path.GetRandomFilename) when opening via OpenSharedItem so that you don't get issues. I would also use a temporary path instead of root c:\ (i.e. Path.GetTempPath).
You can try and free the MailItem reference (i.e. setting it to null), but there is no guarantee when Outlook will release the item from its cache.
Would any combination of the Quit[1], Close[2] or ReleaseComObject[3] methods work for you? My code worked better but not perfect after I used them.[4]
using Outlook = Microsoft.Office.Interop.Outlook;
.
.
.
var app = new Outlook.Application();
var item = app.Session.OpenSharedItem(msgfile) as Outlook.MailItem;
//Do stuff with the mail.
item.Close(OlInspectorClose.olDiscard);
app.Quit();
Marshal.ReleaseComObject(item);
Another solution, according to Microsoft - Help and Support[5], is to delay the opening of the file. However, it doesn't sound like a good solution to me since, like #SliverNinja also said, you'll never know when Outlook releases its lock of the file.
Notes and references
http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook._application.quit.aspx, read 2014-10-14, 16:19.
http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook._mailitem.close%28v=office.15%29.aspx, read 2014-10-14, 16:19.
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.releasecomobject.aspx, read 2014-10-14, 16:19.
For example, if I had opened Outlook for som regular work, the Quit-method would close that window as well.
http://support2.microsoft.com/kb/2633737, read 2014-10-08, 16:19.
Hello you have two options .
set the Read-only attribute to the msg file
or
disable the following permissions for the users or usergroups to the parent folder:
Write Attributes
Write Extended Attributes
the msg file can now open multiple times but is write protect
I had this problem, in my case it was the space in the file name
import win32com.client
import os
path = 'C:/testes/mail'
files = [f for f in os.listdir(path) if '.msg' in f]
for file in files:
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
msg = outlook.OpenSharedItem(os.path.join(path, file))
att=msg.Attachments
for i in att:
i.SaveAsFile(os.path.join('C:/testes/email_download', i.FileName))
I don't know if in your case the OpenSharedItem method can help ...
Firstly, try to release the message as soon as you are done with it using Marshal.ReleaseComObject(). This may or may not help since Outlook likes to cache its last opened item.
Secondly, you are logging off from Outlook while it might still be running and visible to the user - Outlook is a singleton, so you will end up with the existing instance if it was already running. Either don't call Logoff at all, or check that there are no open inspectors and explorers (Application.Explorers.Count == 0 && Application.Inspectors.Count == 0).
Thirdly, reading HTMLBody alone won't work properly if there are embedded images - they are stored as regular attachments. You can save the message as an MHTML file (which most browsers would be happy to show) using MailItem.SaveAs(..., olMHTML).
You can also use Redemption (I am its author) for that - call RDOSession.GetMessageFromMsgFile.
If you need to release the message immediately after you are done, call Marshal.ReleaseComObject()
In case of Redemption, you can also cast RDOMail object to the IDisposable interface and call IDisposable.Dispose(). In addition to the MHTML format, Redemption can also save in the HTML format with image attachments converted into embedded images- use RDOMail.SaveAs(..., olHTMLEmbeddedImages) (olHTMLEmbeddedImages == 1033).
I've made program which one of the purposes is to open OutLook client where user can write his email, add attachments etc. After sending I want to get all attachments which were added to email, as well as all email in my program.
I tried to handle close event
((Microsoft.Office.Interop.Outlook.ItemEvents_10_Event)email.oMsg).Close += new Microsoft.Office.Interop.Outlook.ItemEvents_10_CloseEventHandler(GetAttachmentsInfo);
and then
if (email.oMsg.Attachments.Count > 0)
{
foreach (Microsoft.Office.Interop.Outlook.Attachment at in email.oMsg.Attachments )
{ attachments.Add(at); }
}
email is OutlookEMail
oMsg is Email Item
attachments is List<Attachment>
but when I close client Attachment throws exception that cannot find object. as well as these in List.
I know that Microsoft.Office.Interop.Outlook.Attachment is not a file, but only something like path to this file containing it name and size.
So question : is it possible to save attachments after client is closed in my program?
(Without using Email.SaveAttachments os SaveEmail methods, because it uses time and computer space)?
Here are two other options you could try:
1. You could listen for MailItem additions to the SentItems Folder via Folder.ItemAdd.
Outlook.Folder sentItems = Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderSentMail) as Outlook.Folder;
sentItems.ItemAdd += new Outlook.ItemsEvents_ItemAddEventHandler(GetAttachmentsInfo);
2. You could attach to the MailItem.Send event.
((Outlook.ItemEvents_10_Event)MailItem).Send += new Outlook.ItemEvents_10_SendEventHandler(GetAttachmentsInfo);
I'm creating a program to automatically generate reports from incoming email attachments and it is almost complete save for one area. The incoming emails are automatically filtered into folders which differentiate which client and server they originate from. I can't figure out how to get the path of the folder from the email Item.
I'm using the NewMailEx event to call the method below and this.AppNamespace and this.ReportFolder are confirmed to be instantiated properly.
void AppClass_NewMailEx(string EntryIDCollection)
{
Outlook.MailItem Item = (Outlook.MailItem)this.AppNamespace.GetItemFromID(EntryIDCollection, this.ReportFolder.StoreID);
string FolderName = ""; //How do I get this?
}
The MSDN on MailItem is here. Am I missing something or approaching this the incorrect way?
I think there's a Parent that you can check - it should return a MAPIFolder that you can check the Name of.