Dailycode.info

Short solution for short problems

How to read an email adress (mail box) from an Exchange 2007 or 2010 server and download email attachments?

For this I created a very simple WPF program (Source code attached at the bottom of this post) that will read a certain email address and process some items that have a certain subject. It will then download all the attachments of the items to the local disk. In the beginning I had some trouble finding the attachments of the items, but this was because I didn’t force a Load on the items. This will load all attachment information. (Lazy Loading I guess)

ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP1);

 

    //You can pass credentials of the creadetials running the program have no access to the mail box

    //service.Credentials = new NetworkCredential( "{Active Directory ID}", "{Password}", "{Domain Name}" );

 

    //Provide the mail box to read

    service.AutodiscoverUrl("mark@dailycode.info");

 

    //Create a filter for the mails returned, in this case only the mails with SendFilesID= in the subject will be returned

    SearchFilter searchFilter = new SearchFilter.ContainsSubstring(ItemSchema.Subject, "SendFilesID=");

 

    //Return the first 10 items

    FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.Inbox,searchFilter,new ItemView(10));

           

    try

    {

        //Loop over the items

        foreach (Item item in findResults.Items)

        {

            //Show result

            txtResult.Text += item.Subject +Environment.NewLine;

            //This load is needed to fill all the properties of the item, if you do not use this, attachment information will be empty

            item.Load();

            //Check if the item has attachments

            if (item.HasAttachments)

            {

                //Loop over the attachments

                foreach (Attachment attachment in item.Attachments)

                {

                    //Check if the attachemnts is a file

                    if (attachment is FileAttachment)

                    {

                        if (!Directory.Exists(("C:\\TEMP\\Attachments")))

                        {

                            Directory.CreateDirectory("C:\\TEMP\\Attachments");

                        }

                        FileAttachment fileAttachment = attachment as FileAttachment;

                        // Load the file attachment into memory

                        fileAttachment.Load();

                        Console.WriteLine("Attachment name: " + fileAttachment.Name);

                        // Stream attachment contents into a file.

                        Stream theStream = File.Create("C:\\TEMP\\Attachments\\" + fileAttachment.Name); //new FileStream("D:\\Downloads\\Attachments\\" + fileAttachment.Name, FileMode.OpenOrCreate, FileAccess.ReadWrite);

                        fileAttachment.Load(theStream);

                        theStream.Close();

                        theStream.Dispose();

                    }

                    else // Attachment is an item attachment.

                    {

                        // Load attachment into memory and write out the subject.

                        ItemAttachment itemAttachment = attachment as ItemAttachment;

                        itemAttachment.Load();

                        Console.WriteLine("Subject: " + itemAttachment.Item.Subject);

                    }

                }

            }

        }

    }

    catch (Exception er)

    {

        MessageBox.Show(er.Message);

    }

}

 

 

TestReadEmail.zip (17.67 kb)


Get email from SPUser field in SharePoint

Whe you are working with WSS workflows or webparts, you will come to the point you have to send emails to users.

If you are using a single user field (not allowed to enter multiple users) the value is returned as a string. So if you choose to show the users name and you want to email this users, you cannot get his email out of this field. So how can we get the users email? Here's some functions that might help:

First I get the authors name out of a field in a list:

searchPerson = _doc["Author"].ToString().Substring(_doc["Author"].ToString().IndexOf("#") + 1);
to =  GetEmail(searchPerson);

Sometimes Sharepoint stores #? characters after the names, so multiple values are allowed. The substring will get them out and return the users name correct. E.g. The value could be Mark, Deraeve#2 and after the substring it will be: Mark, Deraeve 

The GetEmail fuction will look for the user in the rootweb, if a user is present in the current web, he will be on the rootweb. Here the code that returns the users email:

        private string GetEmail(string username)
        {
            foreach (SPUser user in SPContext.Current.Site.RootWeb.AllUsers)
            {
                if (user.Name == username)
                {
                    return user.Email;
                }
            }
            return String.Empty;
        } 

So now you get the users email. You could prevent from looping through all users if you have the users login name, but in my case it the users full name, so I cannot use ...AllUsers[loginname] and I have to loop through the entire users collection.

If the user field allows multiple values, you can retrieve the email with the SPFieldUserValueCollection. Because it allows multiple users, it will not return a string, but a SPFieldUserValueCollection. We can use this to build up a list of email addresses:

SPFieldUserValueCollection col = (SPFieldUserValueCollection)_doc["Users"];
StringBuilder sb = new StringBuilder();
foreach (SPFieldUserValue user in col)
{
if (!IsGroup(user,ref sb))
      {
            sb.Append(user.User.Email + ";");
}
}

I will add some extra code that gets the emails of the users who are in a group:

private string GetEmails(string groupName)
        {
            foreach (SPGroup group in SPContext.Current.Site.RootWeb.Groups)
            {
                if (group.Name == groupName)
                {
                    StringBuilder ret = new StringBuilder();
                    foreach (SPUser user in SPContext.Current.Site.RootWeb.Groups[groupName].Users)
                    {
                        ret.Append(user.Email + ";");
                    }
                    return ret.ToString();
                }
            }
            return String.Empty;
        }

I used a function IsGroup, this function simply checks if it is a user or a group and adds all the users in the group to the email addresses (ref sb):

private bool IsGroup(SPFieldUserValue userOrGroup, ref StringBuilder sb)
        {
            SPGroup qsgroup = null;
            try
            {
                qsgroup = SPContext.Current.Site.AllWebs[_sopSiteName].Groups[userOrGroup.ToString()
	.Substring(userOrGroup.ToString().IndexOf("#") + 1)];
                //Page.Response.Write("group");
                foreach (SPUser user in qsgroup.Users)
                {
                    sb.Append(user.Email + ";");
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

Just for fun another function I used to check if a user is a member of a particular group:

        private bool UserInGroup(string group)
        {
            SPGroupCollection grps = CurrentUser().Groups;
            foreach (SPGroup grp in grps)
            {
                if (grp.Name.ToLower().TrimEnd() == group.ToLower().TrimEnd())
                { return true; }
            }
            return false;
        }

 


Send mail from WSS (using spcontext)

Don't start with the System.Net.Mail namespace, because Sharepoint has a better way to do this:

using Microsoft.SharePoint.Utilities;

SPUtility.SendEmail(SPContext.Current.Web, false, false, EmailTO, 
"Document review request", message.ToString());
 

If you like to address a person in CC or BCC, you will notice that you will have to use headers in your email. I tried this but it didn't send the mails. After a while a noticed that you are required to pass the from email adress to via the header.

When you do this, the mails are sent. The syntax looks like this:

 

 
StringDictionary headers = new StringDictionary();
headers.Add("to", "yourmail@dailycode.net");
headers.Add("bcc", "mymail@dailycode.net");
headers.Add("from","sharepoint@dailycode.net"); 
headers.Add("subject", "Instruction on Document: 120_01.doc");
headers.Add("content-type", "text/html");
////Then just use the SendEmail method:
bool test = SPUtility.SendEmail(SPContext.Current.Web, headers, message.ToString());