I had a a c# script that connects to an OFFICE 365 mailbox and then take any emails with an xls file and puts it in a shared folder. Problem is now the OFFICE 365 mailbox has becomes an Outlook 2010 on premises mailbox, and the script has stopped working.
My questions is what Service URL and service credentials do I use, Is it the same syntax or do I need a new way of connecting in the script ?
OLD script
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Exchange.WebServices.Data;
namespace ST_0710846949654fbd84606ec3011bd081.csproj
{
[System.AddIn.AddIn("ScriptMain", Version = "1.0", Publisher = "", Description = "")]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
#region VSTA generated code
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
#endregion
/*
The execution engine calls this method when the task executes.
To access the object model, use the Dts property. Connections, variables, events,
and logging features are available as members of the Dts property as shown in the following examples.
To reference a variable, call Dts.Variables["MyCaseSensitiveVariableName"].Value;
To post a log entry, call Dts.Log("This is my log text", 999, null);
To fire an event, call Dts.Events.FireInformation(99, "test", "hit the help message", "", 0, true);
To use the connections collection use something like the following:
ConnectionManager cm = Dts.Connections.Add("OLEDB");
cm.ConnectionString = "Data Source=localhost;Initial Catalog=AdventureWorks;Provider=SQLNCLI10;Integrated Security=SSPI;Auto Translate=False;";
Before returning from this method, set the value of Dts.TaskResult to indicate success or failure.
To open Help, press F1.
*/
public void Main()
{
ExchangeService service = new ExchangeService();
service.TraceEnabled = true;
service.TraceFlags = TraceFlags.All;
service.Credentials = new WebCredentials("xxreturns#xxxxxxxxxxxx.co.uk", "PasswordXXXXXXXXX", "mail.xxxxxxxxxxxxxxx.co.uk");
service.Url = new Uri("https://mail.xxxxxxxxxxx.co.uk/owa");
// Variable population
string FileName1 = null;
string attSaveLocation = Dts.Variables["User::attSaveLocation"].Value.ToString();
string destfold = Dts.Variables["User::destFolder"].Value.ToString();
string emailFrom = Dts.Variables["User::emailFrom"].Value.ToString();
string filetype = Dts.Variables["User::filetype"].Value.ToString();
//find items in the email folder
FindItemsResults<Item> foundItems =
service.FindItems(WellKnownFolderName.Inbox, new ItemView(600)); //can limit how many results are pulled
foreach (Item item in foundItems)
{
string tmpitemid;
string processed = null;
tmpitemid = item.Id.ToString();
if (item is EmailMessage)
{
// Bind to an existing message item, requesting its Id property (using the tmpitemid) plus its attachments collection.
EmailMessage foundEmail = EmailMessage.Bind(service, new ItemId(tmpitemid), new PropertySet(BasePropertySet.IdOnly, ItemSchema.Attachments));
EmailMessage foundEmail2 = (EmailMessage)item;
FindFoldersResults findResults = service.FindFolders(WellKnownFolderName.Inbox, new FolderView(10));
//get the from e-mail address for exchange addresses
string fromaddress = null;
NameResolutionCollection nd = service.ResolveName(foundEmail2.From.Address);
foreach (NameResolution nm in nd)
{
if (nm.Mailbox.RoutingType == "SMTP")
{
fromaddress = nm.Mailbox.Address.ToLower();
}
else
{
fromaddress = foundEmail2.From.Address.ToString().ToLower();
}
}
//for other addresses
if (fromaddress == null)
{
fromaddress = foundEmail2.From.Address.ToString().ToLower();
}
//if the email address is like the parameter
if (fromaddress.Contains(emailFrom))
{
//process attachments
foreach (Attachment attachment in foundEmail.Attachments)
{
if (attachment is FileAttachment)
{
FileAttachment fileAttachment = attachment as FileAttachment;
FileName1 = attSaveLocation + fileAttachment.Name;
if (fileAttachment.Name.Contains(filetype))
{
fileAttachment.Load(FileName1);
processed = "Y";
}
}
}
if (processed == "Y")
{
// Get all the folders in the message's root folder.
Folder rootfolder = Folder.Bind(service, WellKnownFolderName.Inbox);
rootfolder.Load();
foreach (Folder folder in rootfolder.FindFolders(new FolderView(100)))
{
if (folder.DisplayName == destfold)
{
foundEmail2.Move(folder.Id);
}
}
}
}
}
}
Dts.TaskResult = (int)ScriptResults.Success;
}
}
}
Not sure if this works for Outlook 2010, but perhaps this link can help you:
https://msdn.microsoft.com/en-us/office/office365/api/mail-rest-operations
Related
We have an email coming at regular intervals (the request will be user driven), containing an Excel attachment. The goal is to extract the attachment from the email automatically, and pass it on to the method that will deal with the data in the file.
I'd like to stay away from 3rd party tools or libraries, and I'd like to keep this as simple as possible, minimal checks and features, literally just download the mail, save the attachment, if the email address matches the known source (to block spam).
From researching, there are 3 possible solutions. Which would be the most sensible route? And are there other options? Can anybody point me to relevant (and recent) tutorials?
Download using a 3rd party POP client
Write my own functionality, possibly using Exchange EWS (Preferred option) (using C#, VS2010)
Rather have Outlook download it, and then extract the attachment from Outlook
Here is an example of how I do it with our system. Let me know if you want me to explain anything as I did have to post this pretty quick.
namespace Namespace.Email
{
public class EmailLinker
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
public EmailLinker()
{
service.Credentials = new NetworkCredential("username", "password", "domain");
service.AutodiscoverUrl("email#email.com");
}
public void linkEmails()
{
FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.Inbox, new ItemView(128));
if (findResults.TotalCount > 0)
{
ServiceResponseCollection<GetItemResponse> items = service.BindToItems(findResults.Select(item => item.Id), new PropertySet(BasePropertySet.FirstClassProperties, EmailMessageSchema.From, EmailMessageSchema.ToRecipients));
foreach (GetItemResponse i in items)
{
MailItem m = new MailItem();
Item it = i.Item;
m.From = ((Microsoft.Exchange.WebServices.Data.EmailAddress)it[EmailMessageSchema.From]).Address;
m.Recipients = ((Microsoft.Exchange.WebServices.Data.EmailAddressCollection)it[EmailMessageSchema.ToRecipients]).Select(r => r.Address).ToArray();
m.Subject = it.Subject;
m.Body = it.Body.Text;
m.Recieved = it.DateTimeReceived;
m.attachments = it.Attachments;
foreach (Attachment a in m.attachments)
this.uploadAttachments(a);
i.Item.Delete(DeleteMode.HardDelete);
}
}
}
private void uploadAttachments(Attachment a)
{
ContentFile cf = new ContentFile();
cf.Name = a.Name;
cf.Size = a.Size;
cf.ContentType = MimeTypeMap.GetMimeType(Path.GetExtension(a.Name).Replace(".",""));
FileAttachment fa = (FileAttachment)a;
fa.Load();
cf.Data = fa.Content;
cf.DateAdded = DateTime.Now;
cf.save();
}
public class MailItem
{
public int id;
public string From;
public string[] Recipients;
public string Subject;
public string Body;
public DateTime Recieved;
public string RecievedString
{
get
{
return Recieved.ToShortDateString() + " " + Recieved.ToShortTimeString();
}
}
public AttachmentCollection attachments;
}
}
}
public class KCSExchangeLink : IKCSExchangeLink
{
private bool CertificateValidationCallBack(
object sender,
System.Security.Cryptography.X509Certificates.X509Certificate certificate,
System.Security.Cryptography.X509Certificates.X509Chain chain,
System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
// If the certificate is a valid, signed certificate, return true.
if (sslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
{
return true;
}
// If there are errors in the certificate chain, look at each error to determine the cause.
if ((sslPolicyErrors & System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors) != 0)
{
if (chain != null && chain.ChainStatus != null)
{
foreach (System.Security.Cryptography.X509Certificates.X509ChainStatus status in chain.ChainStatus)
{
if ((certificate.Subject == certificate.Issuer) &&
(status.Status == System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.UntrustedRoot))
{
// Self-signed certificates with an untrusted root are valid.
continue;
}
else
{
if (status.Status != System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.NoError)
{
// If there are any other errors in the certificate chain, the certificate is invalid,
// so the method returns false.
return false;
}
}
}
}
// When processing reaches this line, the only errors in the certificate chain are
// untrusted root errors for self-signed certificates. These certificates are valid
// for default Exchange server installations, so return true.
return true;
}
else
{
// In all other cases, return false.
return false;
}
}
private 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;
}
public void SaveAttachment(string email, string password, string downloadfolder, string fromaddress)
{
ServicePointManager.ServerCertificateValidationCallback = CertificateValidationCallBack;
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.Credentials = new WebCredentials(email, password);
service.TraceEnabled = true;
service.TraceFlags = TraceFlags.All;
service.AutodiscoverUrl(email, RedirectionUrlValidationCallback);
// Bind the Inbox folder to the service object.
Folder inbox = Folder.Bind(service, WellKnownFolderName.Inbox);
// The search filter to get unread email.
SearchFilter sf = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false));
ItemView view = new ItemView(1);
// Fire the query for the unread items.
// This method call results in a FindItem call to EWS.
FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.Inbox, sf, view);
foreach (EmailMessage item in findResults)
{
item.Load();
/* download attachment if any */
if (item.HasAttachments && item.Attachments[0] is FileAttachment && item.From.Address == fromaddress)
{
FileAttachment fileAttachment = item.Attachments[0] as FileAttachment;
/* download attachment to folder */
fileAttachment.Load(downloadfolder + fileAttachment.Name);
}
/* mark email as read */
item.IsRead = true;
item.Update(ConflictResolutionMode.AlwaysOverwrite);
}
}
}
I am using Outlook2013 which has a number of mailboxes from both exchange and pop servers.(Rob#mydomain.com[default exchange], rob#somethingdifferent.com[POP], support#mydomain.com[exchange])
I am trying to use Outlook automation to send an email using the support#mydomain.com account.
The problem I am having is the below code creates a mail item in the support outbox but the from field is rob#mydomain.com not support#mydomain.com. This stops it from being sent.
I would like to change the from address to support#mydomain.com. I thought that by setting the Sendusingaccount property did this.
Any help is greatly appreciated.
public static string Send_Email_Outlook(string _recipient, string _message, string _subject, string _cc, string _bcc, string accountname)
{
try
{
Microsoft.Office.Interop.Outlook.Application oApp = new Microsoft.Office.Interop.Outlook.Application();
// Get the NameSpace and Logon information.
Microsoft.Office.Interop.Outlook.NameSpace oNS = oApp.GetNamespace("mapi");
// Log on by using a dialog box to choose the profile.
oNS.Logon(Missing.Value, Missing.Value, true, true);
// Create a new mail item.
Microsoft.Office.Interop.Outlook.MailItem oMsg = (Microsoft.Office.Interop.Outlook.MailItem)oApp.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem);
// Set the subject.
oMsg.Subject = _subject;
// Set HTMLBody.
oMsg.HTMLBody = _message;
oMsg.To = _recipient;
oMsg.CC = _cc;
oMsg.BCC = _bcc;
#region Send via another account
if (accountname.Trim().Length != 0)
{
Microsoft.Office.Interop.Outlook.Accounts accounts = oMsg.Session.Accounts;
for (int i = 1; i <= accounts.Count; i++)
{
string accountfound = accounts[i].DisplayName.ToLower();
if (accountname.ToLower() == accountfound)
{
oMsg.SendUsingAccount = accounts[i]; // Send using support account
Microsoft.Office.Interop.Outlook.Recipient recipient = oMsg.Session.CreateRecipient(accountfound);
oMsg.Sender = recipient.AddressEntry;
break;
}
}
}
#endregion
// Send.
(oMsg as Microsoft.Office.Interop.Outlook._MailItem).Send();
// Log off.
oNS.Logoff();
// Clean up.
//oRecip = null;
//oRecips = null;
oMsg = null;
oNS = null;
oApp = null;
}
// Return Error Message
catch (Exception e)
{
return e.Message;
}
// Default return value.
return "";
}
Yes, you can use the SendUsingAccount property to set up the correct account you need to send items from.
public static Outlook.Account GetAccountForEmailAddress(Outlook.Application application, string smtpAddress)
{
// Loop over the Accounts collection of the current Outlook session.
Outlook.Accounts accounts = application.Session.Accounts;
foreach (Outlook.Account account in accounts)
{
// When the e-mail address matches, return the account.
if (account.SmtpAddress == smtpAddress)
{
return account;
}
}
throw new System.Exception(string.Format("No Account with SmtpAddress: {0} exists!", smtpAddress));
}
public static string Send_Email_Outlook(string _recipient, string _message, string _subject, string _cc, string _bcc, string accountname)
{
try
{
Microsoft.Office.Interop.Outlook.Application oApp = new Microsoft.Office.Interop.Outlook.Application();
// Get the NameSpace and Logon information.
Microsoft.Office.Interop.Outlook.NameSpace oNS = oApp.GetNamespace("mapi");
// Log on by using a dialog box to choose the profile.
oNS.Logon(Missing.Value, Missing.Value, true, true);
// Create a new mail item.
Microsoft.Office.Interop.Outlook.MailItem oMsg = (Microsoft.Office.Interop.Outlook.MailItem)oApp.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem);
// Set the subject.
oMsg.Subject = _subject;
// Set HTMLBody.
oMsg.HTMLBody = _message;
oMsg.To = _recipient;
oMsg.CC = _cc;
oMsg.BCC = _bcc;
#region Send via another account
// Retrieve the account that has the specific SMTP address.
Outlook.Account account = GetAccountForEmailAddress(oApp , "support#mydomain.com");
// Use this account to send the e-mail.
oMsg.SendUsingAccount = account;
// Send.
(oMsg as Microsoft.Office.Interop.Outlook._MailItem).Send();
// Log off.
oNS.Logoff();
// Clean up.
//oRecip = null;
//oRecips = null;
oMsg = null;
oNS = null;
oApp = null;
}
// Return Error Message
catch (Exception e)
{
return e.Message;
}
// Default return value.
return "";
}
I've looked around and haven't found a solution yet. I have picked up code snippets here and there to find a solution.
I have a Doc Library called "Document Collaboration" with the field "Assigned To". This is a People/Groups field. These people will be able to work on a specific document(list item permission). Now, at first, they will have hidden permissions(they cant see it), but when added to the doc, they will see it and be able to contribute it, also they will get an email notification. I have attached the full code below.
So, I don't get any errors, when I go through VS10 debug. But it doesn't send any email or doesn't set the permissions. What's wrong?
using System;
using System.IO;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
namespace ARDT.Notifications
{
/// <summary>
/// List Item Events
/// </summary>
public class Notifications : SPItemEventReceiver
{
/// <summary>
/// An item was checked in
/// </summary>
public override void ItemCheckedIn(SPItemEventProperties properties)
{
SPSite site = new SPSite("http://sp2010dev/ardt");
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists["Document Collaboration"];
SPListItem listItem = properties.ListItem;
SPUser userName = null;
String toAddress = null;
//EMail initializations
bool appendHtmlTag = false;
bool htmlEncode = false;
string subject = "Subject";
string message = "Message text";
//get usernames
string[] userNameArray = listItem.Fields["Assigned to"].ToString().Split(';');
for (int i = 0; i <= userNameArray.Length - 1; i++)
{
userName = web.AllUsers[userNameArray[i]];
toAddress = userName.Email;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
//EMAIL USER
bool result = SPUtility.SendEmail(web, appendHtmlTag, htmlEncode, toAddress, subject, message);
//PERMISSIONS
//remove permissions first
web.AllowUnsafeUpdates = true;
listItem.BreakRoleInheritance(false);
SPRoleAssignmentCollection raCollection = listItem.RoleAssignments;
//remove exisiting permissions one by one
for (int a = raCollection.Count - 1; i > -0; i--)
{
raCollection.Remove(a);
}
//grant permissions for specific list item
SPRoleDefinition roleDefintion = web.RoleDefinitions.GetByType(SPRoleType.Contributor);
SPRoleAssignment roleAssignment = new SPRoleAssignment(userName);
roleAssignment.RoleDefinitionBindings.Add(roleDefintion);
listItem.RoleAssignments.Add(roleAssignment);
listItem.Update();
});
}
}
base.ItemCheckedIn(properties);
}
}
}
nope, I made the simple mistake of putting it under checked in instead of updated, there's also a work around for the function being run multiple times when it updates, just make a column called "updateContributors" in your list and default value True/Yes
Here's the code/no time to explain, but pretty commented, good luck:
using System;
using System.IO;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
//Debugging includes
using System.Diagnostics;
namespace ARDT.Notifications
{
/// <summary>
/// List Item Events
/// </summary>
public class Notifications : SPItemEventReceiver
{
/// <summary>
/// An item was updated
/// </summary>
public override void ItemUpdated(SPItemEventProperties properties)
{
if (properties.ListItem["updateContributors"].ToString().Equals("True"))
{
//work around so it goes through it only once instead of everytime the item is updated
properties.ListItem["updateContributors"] = "False";
SPSite site = new SPSite("http://sp2010dev/ardt/");
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists["Document Collaboration"];
SPListItem listItem = properties.ListItem;
SPUser userName = null;
String toAddress = null;
//EMail initializations
bool appendHtmlTag = false;
bool htmlEncode = false;
string subject = "You have been assigned to a Document";
string message = "Test Message";
//get usernames
string tempFieldValue = listItem["Assigned To"].ToString();
string[] userNameArray = listItem["Assigned To"].ToString().Split(';');
//remove permissions first
web.AllowUnsafeUpdates = true;
listItem.BreakRoleInheritance(false);
SPRoleAssignmentCollection raCollection = listItem.RoleAssignments;
//remove exisiting permissions one by one
for (int a = raCollection.Count - 1; a >= 0; a--)
{
raCollection.Remove(a);
}
for (int i = 1; i < userNameArray.Length; i++)
{
tempFieldValue = userNameArray[i].Replace("#", "");
userName = web.AllUsers[tempFieldValue];
toAddress = userName.Email;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
//EMAIL USER
bool result = SPUtility.SendEmail(web, appendHtmlTag, htmlEncode, toAddress, subject, message);
//PERMISSIONS
//grant permissions for specific list item
SPRoleDefinition roleDefintion = web.RoleDefinitions.GetByType(SPRoleType.Contributor);
SPRoleAssignment roleAssignment = new SPRoleAssignment(userName);
roleAssignment.RoleDefinitionBindings.Add(roleDefintion);
listItem.RoleAssignments.Add(roleAssignment);
listItem.Update();
});
i++;
}
}
//base.ItemUpdated(properties);
//after final update has been done return true
properties.ListItem["updateContributors"] = "True";
}
}
}
}
One of the problems you have in your code - you create the SPWeb object in current execution context, but then try to send mail using SPSecurity.RunWithElevatedPrivileges. You should never open the web with one account and then use it in another. You have to re-create the context in RunWithElevatedPrivileges block as it can be seen in this example.
We have a public calendar for our company set up in an Exchange 2007 Public Folder. I am able to retrieve my personal calendar appointments for the current day using the code below. I have searched high and low online and I cannot find one example of someone retrieving calendar information from a Public Folder calendar.
It seems like it should be doable, but I cannot for the life of me get it working. How can I modify the code below to access the calendar? I am not interested in creating any appointments through asp.net, just retrieving a simple list. I am open to any other suggestions as well. Thanks.
ADDED BOUNTY
- I can't be the only person that ever needed to do this. Let's get this problem solved for future generations.
UPDATED AGAIN DUE TO IGNORANCE
- I failed to mention that the project I am working on is .NET 2.0 (very important don't you think?).
* ADDED MY CODE SOLUTION BELOW *
- I have replaced my original code example with the code that ended up working. Many thanks to Oleg for providing the code to find the public folder, which was the hardest part.. I have modified the code using the example from here http://msexchangeteam.com/archive/2009/04/21/451126.aspx to use the simpler FindAppointments method.
This simple example returns an html string with the appointments, but you can use it as a base to customize as needed. You can see our back and forth under his answer below.
using System;
using Microsoft.Exchange.WebServices.Data;
using System.Net;
namespace ExchangePublicFolders
{
public class Program
{
public static FolderId FindPublicFolder(ExchangeService myService, FolderId baseFolderId,
string folderName)
{
FolderView folderView = new FolderView(10, 0);
folderView.OffsetBasePoint = OffsetBasePoint.Beginning;
folderView.PropertySet = new PropertySet(FolderSchema.DisplayName, FolderSchema.Id);
FindFoldersResults folderResults;
do
{
folderResults = myService.FindFolders(baseFolderId, folderView);
foreach (Folder folder in folderResults)
if (String.Compare(folder.DisplayName, folderName, StringComparison.OrdinalIgnoreCase) == 0)
return folder.Id;
if (folderResults.NextPageOffset.HasValue)
folderView.Offset = folderResults.NextPageOffset.Value;
}
while (folderResults.MoreAvailable);
return null;
}
public static string MyTest()
{
ExchangeService myService = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
myService.Credentials = new NetworkCredential("USERNAME", "PASSWORD", "DOMAIN");
myService.Url = new Uri("https://MAILSERVER/ews/exchange.asmx");
Folder myPublicFoldersRoot = Folder.Bind(myService, WellKnownFolderName.PublicFoldersRoot);
string myPublicFolderPath = #"PUBLIC_FOLDER_CALENDAR_NAME";
string[] folderPath = myPublicFolderPath.Split('\\');
FolderId fId = myPublicFoldersRoot.Id;
foreach (string subFolderName in folderPath)
{
fId = Program.FindPublicFolder(myService, fId, subFolderName);
if (fId == null)
{
return string.Format("ERROR: Can't find public folder {0}", myPublicFolderPath);
}
}
Folder folderFound = Folder.Bind(myService, fId);
if (String.Compare(folderFound.FolderClass, "IPF.Appointment", StringComparison.Ordinal) != 0)
{
return string.Format("ERROR: Public folder {0} is not a Calendar", myPublicFolderPath);
}
CalendarFolder AK_Calendar = CalendarFolder.Bind(myService, fId, BasePropertySet.FirstClassProperties);
FindItemsResults<Appointment> AK_appointments = AK_Calendar.FindAppointments(new CalendarView(DateTime.Now,DateTime.Now.AddDays(1)));
string rString = string.Empty;
foreach (Appointment AK_appoint in AK_appointments)
{
rString += string.Format("Subject: {0}<br />Date: {1}<br /><br />", AK_appoint.Subject, AK_appoint.Start);
}
return rString;
}
}
}
Like promised here is a code example. I used the Microsoft Exchange Web Services (EWS) Managed API 1.0 and recommend you to do the same. The most comments I included in the code
using System;
using Microsoft.Exchange.WebServices.Data;
using System.Net;
namespace ExchangePublicFolders {
class Program {
static FolderId FindPublicFolder (ExchangeService myService, FolderId baseFolderId,
string folderName) {
// We will search using paging. We will use page size 10
FolderView folderView = new FolderView (10,0);
folderView.OffsetBasePoint = OffsetBasePoint.Beginning;
// we will need only DisplayName and Id of every folder
// se we'll reduce the property set to the properties
folderView.PropertySet = new PropertySet (FolderSchema.DisplayName,
FolderSchema.Id);
FindFoldersResults folderResults;
do {
folderResults = myService.FindFolders (baseFolderId, folderView);
foreach (Folder folder in folderResults)
if (String.Compare (folder.DisplayName, folderName, StringComparison.OrdinalIgnoreCase) == 0)
return folder.Id;
if (folderResults.NextPageOffset.HasValue)
// go to the next page
folderView.Offset = folderResults.NextPageOffset.Value;
}
while (folderResults.MoreAvailable);
return null;
}
static void MyTest () {
// IMPORTANT: ExchangeService is NOT thread safe, so one should create an instance of
// ExchangeService whenever one needs it.
ExchangeService myService = new ExchangeService (ExchangeVersion.Exchange2007_SP1);
myService.Credentials = new NetworkCredential ("MyUser#corp.local", "myPassword00");
myService.Url = new Uri ("http://mailwebsvc-t.services.local/ews/exchange.asmx");
// next line is very practical during development phase or for debugging
myService.TraceEnabled = true;
Folder myPublicFoldersRoot = Folder.Bind (myService, WellKnownFolderName.PublicFoldersRoot);
string myPublicFolderPath = #"OK soft GmbH (DE)\Gruppenpostfächer\_Template - Gruppenpostfach\_Template - Kalender";
string[] folderPath = myPublicFolderPath.Split('\\');
FolderId fId = myPublicFoldersRoot.Id;
foreach (string subFolderName in folderPath) {
fId = FindPublicFolder (myService, fId, subFolderName);
if (fId == null) {
Console.WriteLine ("ERROR: Can't find public folder {0}", myPublicFolderPath);
return;
}
}
// verify that we found
Folder folderFound = Folder.Bind (myService, fId);
if (String.Compare (folderFound.FolderClass, "IPF.Appointment", StringComparison.Ordinal) != 0) {
Console.WriteLine ("ERROR: Public folder {0} is not a Calendar", myPublicFolderPath);
return;
}
CalendarFolder myPublicFolder = CalendarFolder.Bind (myService,
//WellKnownFolderName.Calendar,
fId,
PropertySet.FirstClassProperties);
if (myPublicFolder.TotalCount == 0) {
Console.WriteLine ("Warning: Public folder {0} has no appointment. We try to create one.", myPublicFolderPath);
Appointment app = new Appointment (myService);
app.Subject = "Writing a code example";
app.Start = new DateTime (2010, 9, 9);
app.End = new DateTime (2010, 9, 10);
app.RequiredAttendees.Add ("oleg.kiriljuk#ok-soft-gmbh.com");
app.Culture = "de-DE";
app.Save (myPublicFolder.Id, SendInvitationsMode.SendToNone);
}
// We will search using paging. We will use page size 10
ItemView viewCalendar = new ItemView (10);
// we can include all properties which we need in the view
// If we comment the next line then ALL properties will be
// read from the server. We can see there in the debug output
viewCalendar.PropertySet = new PropertySet (ItemSchema.Subject);
viewCalendar.Offset = 0;
viewCalendar.OffsetBasePoint = OffsetBasePoint.Beginning;
viewCalendar.OrderBy.Add (ContactSchema.DateTimeCreated, SortDirection.Descending);
FindItemsResults<Item> findResultsCalendar;
do {
findResultsCalendar = myPublicFolder.FindItems (viewCalendar);
foreach (Item item in findResultsCalendar) {
if (item is Appointment) {
Appointment appoint = item as Appointment;
Console.WriteLine ("Subject: \"{0}\"", appoint.Subject);
}
}
if (findResultsCalendar.NextPageOffset.HasValue)
// go to the next page
viewCalendar.Offset = findResultsCalendar.NextPageOffset.Value;
}
while (findResultsCalendar.MoreAvailable);
}
static void Main (string[] args) {
MyTest();
}
}
}
You should update the string myPublicFolderPath to the value with your public calender folder. I set myService.TraceEnabled = true which produce long output with debug information. You should of cause remove the line for production.
UPDATED: Some additional links you could find in Create new calendar system support in Exchange OWA. If you not yet seen the videos and you want to use Exchange Web Services I would recommend you to watch there. It could save your time in the future.
I did similar thing for Exchange 2003, but using WebDAV Search method (http://msdn.microsoft.com/en-us/library/aa143053%28v=EXCHG.65%29.aspx).
http://geekswithblogs.net/cskardon/archive/2008/12/01/hunting-those-elusive-public-folders-using-exchange-web-services-part.aspx may help.
I need to extract/export the lotus notes email attachment into file system. for that I wrote following method but each time I am receiving an error at line foreach (NotesItem nItem in items).. Can anybody please tell me what I am doing wrong ..
Thanks
Jwalin
public void GetAttachments()
{
NotesSession session = new NotesSession();
//NotesDocument notesDoc = new NotesDocument();
session.Initialize("");
NotesDatabase NotesDb = session.GetDatabase("", "C:\\temps\\lotus\\sss11.nsf", false); //Open Notes Database
NotesView inbox = NotesDb.GetView("By _Author");
NotesDocument docInbox = inbox.GetFirstDocument();
object[] items = (object[])docInbox.Items;
**foreach (NotesItem nItem in items)**
{
//NotesItem nItem = (NotesItem)o1;
if (nItem.Name == "$FILE")
{
NotesItem file = docInbox.GetFirstItem("$File");
string fileName = ((object[])nItem.Values)[0].ToString();
NotesEmbeddedObject attachfile = (NotesEmbeddedObject)docInbox.GetAttachment(fileName);
if (attachfile != null)
{
attachfile.ExtractFile("C:\\temps\\export\\" + fileName);
}
}
}
You don't need to use the $File item to get the attachment name(s). Rather, you can use the HasEmbedded and EmbeddedObject properties of the NotesDocument class.
public void GetAttachments()
{
NotesSession session = new NotesSession();
//NotesDocument notesDoc = new NotesDocument();
session.Initialize("");
NotesDatabase NotesDb = session.GetDatabase("", "C:\\temps\\lotus\\sss11.nsf", false); //Open Notes Database
NotesView inbox = NotesDb.GetView("By _Author");
NotesDocument docInbox = inbox.GetFirstDocument();
// Check if any attachments
if (docInbox.hasEmbedded)
{
NotesEmbeddedObject attachfile = (NotesEmbeddedObject)docInbox.embeddedObjects[0];
if (attachfile != null)
{
attachfile.ExtractFile("C:\\temps\\export\\" + attachfile.name);
}
}
Ed's solution didn't work for me. Something about my Notes db design seems to have left the EmbeddedObjects property null even when the HasEmbedded flag is true. So I sort of combined the Ed's and Jwalin's solutions, modifying them to fetch all attachments from a Notes document.
NotesDocument doc = viewItems.GetNthEntry(rowCount).Document;
if (doc.HasEmbedded)
{
object[] items = (object[])doc.Items;
foreach (NotesItem item in items)
{
if(item.Name.Equals("$FILE"))
{
object[] values = (object[])item.Values;
doc.GetAttachment(values[0].ToString()).ExtractFile(fileSavePath + values[0].ToString());
}
}