Wednesday, July 18, 2012

Ways of sending mails in Sharepoint through code (for farm solutions only).

There are two ways of sending mail through code in sharepoint sites. One Through SPUtility Class of Microsoft.Sharepoint and another for SmtpClient Class of System.Net.Mail namespace. Both call its own function of Send mail and uses same parameters. But the main difference I found between them is if you want to send mail with attachments you don't have any parameter in SPUtility  class for the purpose however in SmtpClient you can. I am citing here an example of both.

Through SPUtility Class :

 public void SendMail(Guid objSPSiteId)      
{
 using (SPSite objSPSite = new SPSite(objSPSiteId))
            {
                using (objSPWeb = objSPSite.AllWebs[properties.OpenWeb().ID])
                {
                    SPUtility.SendEmail(objSPWeb, true, true, "abc@xyz.com", "Demo Mail for test.", "Abc");
                }
            }
}

You also need to configure Web Application Outgoing E-Mail Settings for that particular Web Application in which your site is hosted. Here fill all text boxes with details. This is needed in both the cases.

Through SmtpClient Class :


 public void SendMail(Guid objSPSiteId)      

 {
            using (SPSite objSPSite = new SPSite(objSPSiteId))
            {
                using (objSPWeb = objSPSite.AllWebs[properties.OpenWeb().ID])
                {
                    //SPUtility.SendEmail(objSPWeb, true, true, "abc@xyz.com", "Demo Mail for test through event receiver Adding event.", "Abc");
                    string smtpServer = objSPSite.WebApplication.OutboundMailServiceInstance.Server.Address;
                    string smtpFrom = objSPSite.WebApplication.OutboundMailSenderAddress;
                    MailMessage mailMessage = new MailMessage(smtpFrom, "def@mno.com");
                    mailMessage.Body = "Demo Body for the mail..";
                    mailMessage.Subject = "Demo Subject for the mail..";
                    SmtpClient objSmtpClient = new SmtpClient();
                    objSmtpClient.Send(mailMessage);
                }
           }
  }

We need to do these entry in web.config :

<system.net>
    <!--<defaultProxy />-->
    <mailSettings>
      <smtp from="def@mno.com">
        <network host="localhost"/>(I have put these).
      </smtp>
    </mailSettings>
  </system.net>

There are following steps need to follow when need to send with an list items attachments:

1.) First get all the attechments attached to particular list item :

 SPList mylist = SPContext.Current.List;
                    SPListItem myitem =  SPContext.Current.ListItem;
                    SPAttachmentCollection myattach = myitem.Attachments;
                    if (myattach.Count != 0)
                    {
                        objSPWeb.AllowUnsafeUpdates = false;
                        List<SPFile> lstSPFile = null;
                        SPSecurity.RunWithElevatedPrivileges(delegate
                        {
                            using (SPSite oSite = new SPSite(myitem.ParentList.ParentWeb.Site.ID))
                            {
                                using (SPWeb oWeb = oSite.OpenWeb(myitem.ParentList.ParentWeb.ID))
                                {
                                    SPFolder folder = myitem.ParentList.RootFolder.SubFolders["Attachments"].SubFolders                                               [myitem.ID.ToString()];
                                    lstSPFile = new List<SPFile>();
                                    foreach (SPFile file in folder.Files)
                                    {
                                        lstSPFile.Add(file);
                                    }
                                    _fileList = lstSPFile;
                                }
                            }
                        });

2.) Now get attachments in byte format and then add it into the MailMessage Class Object.

foreach (var file in _fileList)
                        {
                            WebClient webClient = new WebClient();//Supply the WebClient with the network credentials of our user
                            webClient.Credentials = CredentialCache.DefaultNetworkCredentials;
                            string mypath = objSPWeb.Url + "/Lists/" + mylist.Title + "/Attachments/"+ myitem.ID +"/"+ file.Name;                             //Download the byte array of the file
                            byte[] data = webClient.DownloadData(mypath);
                            MemoryStream memoryStreamOfFile = new MemoryStream(data);
                            mailMessage.Attachments.Add(new System.Net.Mail.Attachment(memoryStreamOfFile, file.Name.ToString()));
                        }

In this way you can send mail through Sharepoint site by calling these function on any particular event.

Tuesday, July 17, 2012

How to create custom search for seraching strings or set of strings a sharepoint list different columns through C# code.

I have created a console utility which can be very useful "To search a string or a set of string in different columns of sharepoint lists". It can be extended to so many level from search a string in a specific column of a specific list to search a string or set of strings in all columns of a all lists. But for that you need to do a lot of modifications. I have created a simple console which might be useful in extending it for practical use. Code for it as follows :

I have used  '-'  character as  separator for diving it into a sentence.

class Program
    {
        static void Main(string[] args)
        {
            using (SPSite objSPSite = new SPSite("http://serverName:portname/sites/TestPages"))
            {
                using (SPWeb objSPWeb = objSPSite.OpenWeb())
                {
                    SPList objSPListPoc1 = objSPWeb.Lists.TryGetList("listTitle");
                    if (objSPListPoc1 != null)
                    {
string toSearchEntered = "-This is a mandatory- training need to be -completed today- and as soon -as possible";
                        int countSeprator = CountChars('-', toSearchEntered);
                        if (isEven(countSeprator))
                        {
                            string toSearch = "-" + toSearchEntered + "-";
                            List<int> occurence = IndexOfNth(toSearch, '-');
                            /*foreach (int item in occurence)
                            {
                                Console.WriteLine(item + "\n");
                            }*/
                            List<string> stringsListToSearch = getSubStrings(toSearch, occurence);
                            /*foreach (string subString in stringsListToSearch)
                            {
                                Console.WriteLine(subString + "\n");
                            }*/
                            List<string> SearchStrings = getSearchStringsCollection(stringsListToSearch);
                            foreach (string splitedStrings in SearchStrings)
                            /*{
                                Console.WriteLine(splitedStrings + "\n");
                            }*/
                            StringBuilder stbQuery = GetQueryForAllDaysTCodes1(SearchStrings);
                            SPQuery objSPQuery = new SPQuery();
                            objSPQuery.Query = stbQuery.ToString();
                            SPListItemCollection objSPListItemCollection = objSPListPoc1.GetItems(objSPQuery);
                            if (objSPListItemCollection != null && objSPListItemCollection.Count > 0)
                            {
                                Console.WriteLine("Items found : " + objSPListItemCollection.Count);
                                foreach (SPListItem item in objSPListItemCollection)
                                {
                                    Console.WriteLine(item["ID"] + " " + item["Title"]);
                                }
                            }
                            else
                            {
                                Console.WriteLine("Item Not found");
                            }
                        }
                        else
                        {
                            Console.WriteLine("String contains odd number of -. Please remove or enclose it.");
                        }
                    }
                }
            }
            Console.WriteLine("Executed");
            Console.ReadLine();
        }

 public static List<int> IndexOfNth(string str, char c)
        {
            List<int> occuringAddress = new List<int>();
            for (int i = 0; i < str.Length; i++)
            {
                if (str[i] == c)
                {
                    occuringAddress.Add(i);
                }
            }
            occuringAddress.Add(str.Length);
            return occuringAddress;
        }

        public static List<string> getSubStrings(string toSearch, List<int> position)
        {
            List<string> stringsListToSearch = new List<string>();
            string substringSentenceSearch = string.Empty;
            if (position.Count() >= 0)
            {
                for (int i = 0; i <= position.Count - 2; i++)
                {
                    substringSentenceSearch = toSearch.Substring(position[i] + 1, (position[i + 1] - (position[i] + 1)));
                    stringsListToSearch.Add(substringSentenceSearch);
                }
            }
            return stringsListToSearch;
        }

        public static List<string> getSearchStringsCollection(List<string> splitedSerachString)
        {
            List<string> lstSearchStringsCollection = new List<string>();
            if (splitedSerachString.Count > 0)
            {
                for (int i = 0; i <= splitedSerachString.Count - 1; i++)
                {
                    if (i % 2 == 0)
                    {
                        List<string> temp = new List<string>();
                        temp = splitedSerachString[i].Split(' ').ToList();
                        if (temp != null && temp.Count > 0)
                        {
                            foreach (string item in temp)
                            {
                                lstSearchStringsCollection.Add(item);
                            }
                        }
                    }
                    else
                    {
                        lstSearchStringsCollection.Add(splitedSerachString[i]);
                    }
                }
            }
            return lstSearchStringsCollection;
        }

        public static int CountChars(char seprator, string value)
        {
            int result = 0;
            foreach (char c in value)
            {
                if (c == seprator)
                {
                    result++;
                }
            }
            return result;
        }

        public static bool isEven(int Count)
        {
            bool isEven = false;
            if (Count % 2 == 0)
            {
                isEven = true;
            }
            else
            {
                isEven = false;
            }
            return isEven;
        }

 public static StringBuilder GetQueryForAllDaysTCodes1(string[] Cities)
        {
            int loopCnt = 0, cityCnt = 0;
            StringBuilder stbQuery = new StringBuilder();
            stbQuery.Append("<Where>");
            bool first = true;
            foreach (string City in Cities)
            {
                if (Cities.Length > 0)
                {
                    for (int dataCnt = 0; dataCnt < (Cities.Length * 3) - 1; dataCnt++)
                        stbQuery.Append("<Or>");

                    for (int dataCnt = 0; dataCnt < Cities.Length; dataCnt++)
                    {
                        cityCnt++;
                        for (int fieldCnt = 0; fieldCnt <= 2; fieldCnt++)
                        {
                            loopCnt++;
                            switch (fieldCnt)
                            {
                                case 0:
                                    stbQuery.Append("<Contains><FieldRef Name='Column1' /><Value Type='Text'>" + Cities[dataCnt].TrimStart().TrimEnd() + "</Value></Contains>");
                                    break;
                                case 1:
                                    stbQuery.Append("<Contains><FieldRef Name='Column2' /><Value Type='Text'>" + Cities[dataCnt].TrimStart().TrimEnd() + "</Value></Contains>");
                                    break;
                                case 2:
                                    stbQuery.Append("<Contains><FieldRef Name='Column3' /><Value Type='Text'>" + Cities[dataCnt].TrimStart().TrimEnd() + "</Value></Contains>");
                                    break;
                            }
                            if (loopCnt >= 2 && cityCnt >= 1)
                                stbQuery.Append("</Or>");
                        }
                    }
                    stbQuery.Append("</Where>");
                }
            }
            return stbQuery;
        }

By increasing cases you can increase 'n' no. of columns. it will do an or query for all words splited by space. And string between -This is a mandatory- will be considered as a sentence and also searched as a sentence.

So result in the output screen will be like this.

You can modify received ListItemcollection as per your need and can use it in a Page or Webpart with Grid View or further processing. 

You can uncomment code to see all process step by step. Hope it helps you ...!!!