Wednesday, May 27, 2009

RSS Aggregator Web Part

After a long search on internet, I finally thought I have to write this RSS Aggregator Web Part that works for both Atom and RSS Formats.

First, I would like to give credit to this post by Sahil Malik which gave me the kick start.

Next, read my previous blog to understand the differences between RSS and Atom XML structure as I will be using the base of them to retrieve both blogger posts.

Now that we have our basic understanding lets jump in to the code. I am using the same css class names here since I wanted to mimic the same way as the outbox RSS Webpart. You can have your own incase you need.

We will be using 3 classes here; 1. Webpart Class, 2. Class for RSSFeed 3. Class for RSSItem and 1 JS file. Ofcourse, this code is in working condition, however its not clean. You might want to look at the redundant variable declarations.

JS: _____________________________________________________________
 
<script type="text/javascript">
function switchMenu(obj) {
var el = document.getElementById(obj);
if (el.style.display != 'none') {
el.style.display = 'none';
}
else {
el.style.display = '';
}

CollapseAllDivs(el);
}

function CollapseAllDivs(sDiv) {
var rollUpContainer = document.getElementById('rollUpContainer');
var div = rollUpContainer.getElementsByTagName('div');
for(i = 0; i < div.length; i++) {
if (div[i].id.match("rssAgg") != null) {
var getDiv = document.getElementById(div[i].id);
if (sDiv.id != getDiv.id) {
getDiv.style.display = 'none';
}
}
}
}

</script>

Variable Declarations: _______________________________________________
 
private string rssUrl;
private string feedName;
private const string constDefFeedLimitValue = "5";
private string feedLimit = constDefFeedLimitValue;
private int feedLmt;

WebPart: ________________________________________________________
 
public class RssFeedAggregator : System.Web.UI.WebControls.WebParts.WebPart
{

private string rssUrl;
private string feedName;
private const string constDefFeedLimitValue = "5";
private string feedLimit = constDefFeedLimitValue;
private int feedLmt;

public RssFeedAggregator()
{
this.ExportMode = WebPartExportMode.All;
}

protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
{
try
{
feedLmt = Convert.ToInt32(feedLimit);
}
catch (Exception)
{
feedLmt = 0;
}
RssFeed feed = new RssFeed(rssUrl);
feed.Sort(delegate(RssItem r1, RssItem r2)
{
return r2.PubDate.CompareTo(r1.PubDate);
});

int i = 0;

string parameterToken;

writer.Write("<div id=\"rollUpContainer\">");
foreach (RssItem singleRssItem in feed)
{
if (i < feedLmt)
{
parameterToken = "rssAgg" + i;

writer.Write("<div id=\"rollUp\" class=\"slm-layout-main\">");
writer.Write("<table width=\"100%\">");
writer.Write("<tr>");
writer.Write("<td width=\"100%\" align=\"left\">");
writer.Write("<table width=\"100%\">");
writer.Write("<tr><td width='100%' class=\"groupheader item medium\">");
writer.Write("<a href='" + singleRssItem.BlogLink.ToString() + "' target='_blank'>" + singleRssItem.BlogTitle + "</a>");
writer.Write("</td>");
writer.Write("</tr>");
writer.Write("<tr><td width='100%' class=\"item link-item\">");
writer.Write("<a href=\"javascript:switchMenu('" + parameterToken + "');\">" + singleRssItem.Title + "</a>");
writer.Write("</td>");
writer.Write("</tr>");
writer.Write("</table>");
writer.Write("</td>");
writer.Write("</tr>");
writer.Write("</table>");
writer.Write("</div>");

if(i > 0)
writer.Write(string.Format(@"<div id='{0}' style='display:none'>", parameterToken));
else
writer.Write(string.Format(@"<div id='{0}'>", parameterToken));

writer.Write("<table><tr><td><div class=\"description\">");
writer.Write(singleRssItem.Body);
writer.Write("</div></td></tr>");

writer.Write("</table>");

writer.Write("</div>");

i++;
}
}
writer.Write("</div>");
}

public string FeedName
{
get
{
return feedName;
}
set
{
feedName = value;
}
}

[WebBrowsable(true),
Personalizable(true),
Category("RSS Properties"),
DisplayName("RSS Feed Url(s)"),
WebDisplayName("RSS Feed Url(s)"),
Description("Use ';' Character For Multiple Feed(s)")]
public string FeedURL
{
get
{
return rssUrl;
}
set
{
rssUrl = value;
}
}

[WebBrowsable(true)]
[Personalizable(true),
Category("RSS Properties"),
DisplayName("Feed Limit"),
WebDisplayName("Feed Limit"),
Description("Feed Limit"),
DefaultValue(constDefFeedLimitValue)]
public string FeedLimit
{
get
{
return feedLimit;
}
set
{
feedLimit = value;
}
}

}

RSSFeed Class: ___________________________________________________________
 
internal class RssFeed : List<RssItem>
{
private XmlDocument xDoc;

internal RssFeed(string RssURL)
{

if (RssURL == null)
{
this.Add(new RssItem());
}
else
{
string[] rssUrlsArray = RssURL.Split(new char[] { ';' });
foreach (string url in rssUrlsArray)
{

try
{
xDoc = new XmlDocument();
XmlTextReader xRead = new XmlTextReader(url);
xDoc.Load(xRead);

if (IsRss(xDoc))
ReadRssFeed(xDoc);
else
AtomFeed(xDoc);

}
catch (Exception)
{
this.Add(new RssItem());
}
}
}
}

internal bool IsRss(XmlDocument xDoc)
{
XmlNodeList xNodes = xDoc.GetElementsByTagName("rss");
if (xNodes.Count > 0)
return true;
else
return false;

}

internal void ReadRssFeed(XmlDocument rssDoc)
{

string blogTitle = string.Empty;
string blogLink = string.Empty;

XmlNodeList xNodesHeader = rssDoc.SelectNodes("./rss/channel");
foreach (XmlNode xNode in xNodesHeader)
{
blogTitle = HttpUtility.HtmlEncode(xNode.SelectSingleNode("./title").InnerText);
blogLink = xNode.SelectSingleNode("./link").InnerText;
}

XmlNodeList xNodes = rssDoc.SelectNodes("./rss/channel/item");
foreach (XmlNode xNode in xNodes)
{
this.Add(new RssItem(xNode, blogTitle, blogLink));
}
}

internal void AtomFeed(XmlDocument atomDoc)
{
string blogTitle = string.Empty;
string blogLink = string.Empty;

XmlNodeList xNodesHeader = atomDoc.GetElementsByTagName("feed");
foreach (XmlNode xNode in xNodesHeader)
{
if (xNode["title"] != null)
blogTitle = HttpUtility.HtmlEncode(xNode["title"].InnerText);

if (xNode["link"] != null)
blogLink = xNode["link"].InnerText;

}

XmlNodeList xNodes = atomDoc.GetElementsByTagName("entry");
foreach (XmlNode xNode in xNodes)
{
this.Add(new RssItem(xNode, true, GetHrefLink(xNode), blogTitle, blogLink));
}

}

internal string GetHrefLink(XmlNode xNode)
{
string ret = string.Empty;

for (int iCount = 0; iCount < xNode.ChildNodes.Count; iCount++)
{
if (xNode.ChildNodes[iCount].Name.ToLower() == "link")
{
if (xNode.ChildNodes[iCount].Attributes["rel"].Value.ToLower() == "alternate")
{
ret = xNode.ChildNodes[iCount].Attributes["href"].Value.ToString();
}
}
}

return ret;
}
}

RSS Item Class: ____________________________________________________________
 
internal class RssItem
{
private string title;
private string href;
private string body;
private string tags;
private DateTime pubDate;
private string blogTitle;
private string blogLink;

public string Href
{
get { return href; }
}

public string Title
{
get { return title; }
}

internal RssItem()
{
title = "No Data Available At This Time.";
href = "~";
}

public string Body
{
get { return body; }
set { body = value; }
}

public string Tags
{
get { return tags; }
set { tags = value; }
}

public DateTime PubDate
{
get { return pubDate; }
set { pubDate = value; }
}

public string BlogTitle
{
get { return blogTitle; }
set { blogTitle = value; }
}

public string BlogLink
{
get { return blogLink; }
set { blogLink = value; }
}

internal RssItem(XmlNode xNode, string sBlogTitle, string sBlogLink)
{
title = xNode.SelectSingleNode("./title").InnerText;
href = xNode.SelectSingleNode("./link").InnerText;
body = FixDesc(xNode.SelectSingleNode("./description").InnerText, href);
pubDate = Convert.ToDateTime(xNode.SelectSingleNode("./pubDate").InnerText);

XmlNodeList nodeList = xNode.SelectNodes("./category");
foreach (XmlNode node in nodeList)
{
tags = tags + " " + node.InnerText;
}

BlogTitle = sBlogTitle;
blogLink = sBlogLink;
}

internal RssItem(XmlNode xNode, bool isAtom, string hrefUrl, string sBlogTitle, string sBlogLink)
{
if (xNode["title"] != null)
title = xNode["title"].InnerText;

if(!string.IsNullOrEmpty(hrefUrl))
href = hrefUrl;
else
{
if (xNode["link"] != null)
{
href = xNode["link"].Attributes["href"].Value.ToString();
}
}

if (xNode["content"] != null)
body = FixDesc(xNode["content"].InnerText, href);

if (xNode["published"] != null)
pubDate = Convert.ToDateTime(xNode["published"].InnerText);

if (xNode["category"] != null)
{
tags = xNode["category"].Attributes["term"].Value.ToString();
}

BlogTitle = sBlogTitle;
BlogLink = sBlogLink;
}

public string FixDesc(object desc, object link)
{
if (link == null desc == null) return String.Empty;

string description = desc.ToString();
Regex reg = new Regex("<.*?>", RegexOptions.Compiled);
string stripDesc = reg.Replace(description, String.Empty);

if (stripDesc.Length > 250)
{
int startPos = 250;
char[] chars = stripDesc.ToCharArray();
char c = chars[startPos];
while (!Char.IsWhiteSpace(c) && startPos < chars.Length)
{
startPos++;
c = chars[startPos];
}
stripDesc = new String(chars, 0, startPos) + "<br><a href=" + link.ToString() + " target='_blank'>More...</a>";

}
return stripDesc;
}
}

Tuesday, May 26, 2009

Differences between Rss and Atom

Here are some of the important differences between RSS and Atom XML structure.
This would help you while programatically reading the RSS / Atom of a blog.

RSS Atom Remarks
rss - check for this to differentiate between RSS/Atom
channel feed  
title title  
link link if you are trying to read the link… check the rel attribute of the link value to alternate and corresponding href attribute value. This is very important.
description subtitle content  value to be read instead.
language - Atom uses standard xml:lang attribute
copyright rights  
webMaster -  
managingEditor author or contributor  
pubDate published (in entry) Atom has no feed-level equivalent
lastBuildDate (in channel) updated RSS has no item-level equivalent
category category Read term attribute value.
generator generator  
docs -  
cloud -  
ttl - <ttl> is problematic, prefer HTTP 1.1 cache control
image logo Atom recommends 2:1 aspect ratio
- icon As in favicon.ico
rating -  
textInput -  
skipHours -  
skipDays -  
item entry  
author author  
- contributor  
description summary and/or content depending on whether full content is provided
comments -  
enclosure - rel="enclosure" on <link> in Atom
guid id  
source - rel="via" on <link> in Atom
- source Container for feed-level metadata to support aggregation

Thursday, May 21, 2009

Unable to create list (custom or from template)

Yesterday one of my friends called up and he was getting the below issue and was unable to create a new custom list or a list from a list template.

Object reference not set to an instance of an object. at ASP._layouts_new_aspx.OnLoad(EventArgs e) in c:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\LAYOUTS\new.aspx:line 23

He was able to create it however on dev / test / stage boxes but not on production.
Guess what??? the only difference was, production is on https.

Fix: Create the list on extended web site (Intranet) instead of creating on the public facing domain on https.

New Look for SharePoint Home Page

SharePoint Team Blog announced the new look and feel using SilverLight. Looks pretty cool.

link is here.

Friday, May 15, 2009

Using AllowUnsafeUpdates

Syntax: bool SPSite.AllowUnsafeUpdates

Would essentially tell if you need to update on database when request is of type 'GET' - 'WITHOUT SECURITY' Validation. Well first of all why do you want to do it?

Usage:

web.AllowUnsafeUpdates = true;

Best Practices:

1. DONT USE IT - If you use it, you are exposing yourself to the Cross-Site Scripting.

2. If the request is 'POST' you can happily use SPUtility.ValidateFormDigest() to execute your needs.

3. By default the value is set to 'FALSE' for all Request types 'GET'. Meaning, if some one is trying to update any list - unless and until you specify the property value to 'TRUE', SharePoint will not allow one to update the item.

So, you have to set it to 'TRUE' and then after your meet your requirement... set it to 'FALSE'.

bool allowUpdates = web.AllowUnsafeUpdates;
web.AllowUnsafeUpdates = true;
// WHAT I WANT TO DO?
web.AllowUnsafeUpdates = allowUpdates;

Disadvantage(s) of RunWithElevatedPrivileges

With Great Power Comes Great Responsibility!

Which means > More Security and then finally the chances of getting breached are? Read on...

SPSecurity.RunWithElevatedPrivileges - A very powerful delegate method to get your self a magic wand with which you can 'almost' get to everything you want.

When you run the context under RunWithElevatedPrivileges - function allows access to secured SharePoint objects from the object model by changing the WSS user account context to SHAREPOINT\System. The current windows user context now changes to the current application pool user, configured in IIS. In typical SharePoint farm installations, the application pool user is an AD user with restricted permissions and limited access to external resources, although typically this user has more permissions than the local IUSR_MACHINENAME user.

and now 'YOU' become 'System User' and have access to 'EVERYTHING' - a security hole.

Apart from this, you got to code for this delegate my dear.

Use your better judgement.

Thursday, May 14, 2009

Restricting Users to see other's information

Scenario:

Any user (or role) with Read permissions can view other users details. Well, many organizations and their users need to protect their own identities and details and this is quite common.

Now, the requirements can varify. Some organizations can block every one and their own (User Information List) and that way no one can view their own details. To acheive this; please view the blog post here.

You can come up with the idea saying that why cant we alter the layout pages and security trim them. Well, 2 things to keep in mind.
1. What if you dont have access to layouts page.
2. When new service pack arrives, it would overwrite the layout pages and your changes are gone. Alternatively you can maintain the copies of the layout pages you modify but then replace them back etc etc... a big maintanance nightmare.

So, recently we had a similar situation... our hands are more tied up. The Site is hosted on a hosting server where we had no control except modifying the UI using SPD 2007 (as point 1 above). And the users need to see their own details but not others and this was mandate.

One of the solutions (I dont claim its very good but a temporary hack) is here below.

Step 1: As an Admin go to _layouts/people.aspx
Step 2: Click on Settings > List Settings
Step 3: Click on Default view (at the end of the settings)
Step 4: Go to Filter Section
Step 5: Filter column by ID 'is equal to' 0 (ZERO)
Step 6: Click OK

Repeat this for 'List View' also.

This would actually not display anything.

Now, go ahead and create another view but this time 'Personal View' instead of 'Public View' which would be available only to the person who created it.

Hope this helps for you.

Wednesday, May 13, 2009

WSS 3.0 Master Page Quick Reference

My friend shared this with me and I feel we all can take advantage of this quick reference image to understand better and easy.



Tuesday, May 12, 2009

Programmatically Upload documents to SharePoint Document Library

Scenario: Upload a document (any type) to SharePoint Document Library programmatically.

How? : Use the below code.

Parameters:
1. docName: Name of the document with which you want to upload to the library
2. content: byte[] content of the document you want to upload
3. siteName: Site where you want to upload the document
4. docLibName: Document Library Name to which you want to upload the document


///
///
///

/// Name of the document
/// byte format of the document
/// site name
/// sharepoint document library name
private void UploadDocumentToSharePointLibrary(string docName, byte[] content, string siteName, string docLibName)
{
using (SPSite site = new SPSite(siteName))
{
using (SPWeb web = site.RootWeb)
{
SPFolder docFolder = web.Folders[docLibName];
SPFile file = docFolder.Files.Add(docFolder.Url + "/" + docName, content, true);

file.Update();
docFolder.Update();
}
}

}

Customizing Search Box in SharePoint

Scenario:

Customize search box control on your site.

Implementation:

Step 1:
Add the below lines of code to the register control tag section

<%@ Register Tagprefix="SPSWC" Namespace="Microsoft.SharePoint.Portal.WebControls" Assembly="Microsoft.SharePoint.Portal, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

Step 2:
Search box control is found beteen the contentplaceholder

<asp:ContentPlaceHolder id="PlaceHolderSearchArea" runat="server">

and would be

<SharePoint:DelegateControl runat="server" ControlId="SmallSearchInputBox"/>

replace the above with the below code and add your fav images around to see a custom search box on your site.

<SPSWC:SearchBoxEx id="SearchButton" RegisterStyles="false" TextBeforeTextBox="" TextBoxWidth="88" GoImageUrl="/_layouts/images/GOSEARCH.GIF" GoImageActiveUrl="/_layouts/images/GOSEARCH.GIF" GoImageUrlRTL="" GoImageActiveUrlRTL="" UseSiteDefaults="true" DropDownMode="HideScopeDD" SuppressWebPartChrome="true" runat="server" WebPart="true" __WebPartId="{0043945F-2D2B-4A02-8510-CED13B6F04DF}"/>

the properties of this control are self explainatory and use them at your requirement.

Saturday, May 9, 2009

SharePoint Identity

Voila! This would be some thing I would have hard time to make one understand. This topic is simple until one keeps it flat, else a complete confusing serious session.

This post would be my attempt to make it very easy for beginners to understand it very easily to basic of Identity.

Well, lets understand the simple terms.

1. Authentication
a. FBA
b. Windows

2. Windows Account
a. IUSR_MachineName
b. App Pool User
c. Windows User

3. WSS Account
a. FBA User
b. Windows User
c. SHAREPOINT \ System

Now, I hope the following lines are not new for you...
<configuration>
<system.web>
<identity impersonate="true"/>
</system.web>
</configuration>

which means ASP.NET runtime impersonates the Windows Account passed by IIS. SharePoint keeps track of both Windows Account as well as WSS account. It uses the WSS Account to grant access to secure SPObjects (name it). However ASP.NET which is the base, impersonates the Windows Account when running Sharepoint Application and decides if the resources (webparts, custom etc) can access other resources (files, SQLServer etc).

During Windows Authentication, when user passes right credentials - IIS passes the windows user token to SharePoint. And SharePoint uses 'this context' and executes under this user context. Meaning at this point both WSS Account and Windows Account use same user.

On the other hand FBA is managed by ASP.NET rather than IIS. By default IIS passes the standard IUSER_MACHINENAME local user account token to ASP.NET. ASP.NET is configured to authenticate using forms by the following XML in the web.config file:

<configuration>
<system.web>
<authentication mode="Forms"/>
</system.web>
</configuration>

On successful authentication, SharePoint runs under the IUSER_MACHINENAME user context. The WSS account is depicted by the forms authentication identity, which is dependent on the membership provider configured in ASP.NET.

Now, when you run the context under RunWithElevatedPrivileges - function allows access to secured SharePoint objects from the object model by changing the WSS user account context to SHAREPOINT\System. The current windows user context now changes to the current application pool user, configured in IIS. In typical SharePoint farm installations, the application pool user is an AD user with restricted permissions and limited access to external resources, although typically this user has more permissions than the local IUSR_MACHINENAME user.

One problem with RunWithElevatedPrivileges is that, you now become System User and have access to 'EVERYTHING' - a security hole. So use caution while using it.

Friday, May 8, 2009

PDF Integration in SharePoint

1. Open DOCICON.XML file under C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\XML\ folder.

2. Add entry to the file as mentioned below (on all WFE's and Index servers)

<Mapping Key="pdf" Value="icpdf.gif" EditText="Adobe Acrobat" OpenControl="SharePoint.OpenDocuments" />

Note: EditText setting above will not work with Adobe Reader, it need to have professional version.

3. Get a 16x16 size pdf icon file from adobe (should be available on their site of just google it) and paste it to the below folder:

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\IMAGES\

Make sure the name of the icon is 'icpdf.gif' or if you have it as xyz.gif then change the Value in above mapping tag.

4. IISRESET

Thats it! Simple isn't it?

Rounded Corners with CSS

Alright, here we go. Couple of ways you can achieve this. But before that I have to give the credit to many of those who made it possible for the second method mentioned below so that I dont reinvent the wheel.
___________________________________________
FUTURE: CSS3:

An exciting wave is going to come to eliminate the present and past. CSS3 in beta stage is going to have a new class border-radius. Isnt it awesome?

Syntax: border-radius: <len><len>
the are the lengiths left->Right and right->left.

for individual corners:
border-top-right-radius
border-bottom-right-radius
border-bottom-left-radius
border-top-left-radius

Unfortunatly since it is in beta phase we cannot use it. however, mozilla has a work around.

use the below and you will see it flying

blockquote{
-moz-border-radius: 2em;
border-radius: 2em;
}

___________________________________________
PAST AND PRESENT
___________________________________________
Method I. (Globally followed) : WITH IMAGES
Create 4 curved images (for 4 corners of table / cell / div) and use the below CSS format code and use the classes to set it to your table / cell / div.

CSS:

.topright {background: url(top_right.gif) 100% 0 no-repeat; padding:10px;}
.bottomright {background: url(bottom_right.gif) 100% 100% no-repeat;}
.topleft {background: url(top_left.gif) 0 0 no-repeat;}
.bottomleft {background: url(bottom_left.gif) 0 100% no-repeat;}

and in your page:

<div class="bottomright">
<div class="topleft">
<div class="bottomleft">
<div class="topright">
// YOUR CODE GOES HERE
</div>
</div>
</div>
</div>

________________________________________________
Method II. (Browser dependancy) : WITHOUT IMAGES

CSS:

div.rounded {
width: 9em;
background-color: #E6E6E6;
margin: 3px;
}
div.top-left-corner, div.bottom-left-corner,
div.top-right-corner, div.bottom-right-corner
{position:absolute; width:20px; height:20px;
background-color:#FFF; overflow:hidden;}
div.top-left-inside, div.bottom-left-inside,
div.top-right-inside, div.bottom-right-inside
{position:relative; font-size:150px; font-family:arial;
color:#E6E6E6; line-height: 40px;}
div.top-left-corner { top:0px; left:0px; }
div.bottom-left-corner {bottom:0px; left:0px;}
div.top-right-corner {top:0px; right:0px;}
div.bottom-right-corner {bottom: 0px; right:0px;}
div.top-left-inside {left:-8px;}
div.bottom-left-inside {left:-8px; top:-17px;}
div.top-right-inside {left:-25px;}
div.bottom-right-inside {left:-25px; top:-17px;}
div.box-contents {
position: relative; padding: 8px; color:#000;
}

<div class="rounded">
<div class="top-left-corner">
<div class="top-left-inside">
</div>
</div>
<div class="bottom-left-corner">
<div class="bottom-left-inside">
</div>
</div>
<div class="top-right-corner">
<div class="top-right-inside">
</div>
</div>
<div class="bottom-right-corner">
<div class="bottom-right-inside">
</div>
</div>
<div class="box-contents">
// YOUR CONTENT GOES HERE
</div>
</div>

SharePoint List Type Id's

Have you come across any situation that you have to create your own custom list? Well if so, you must be aware of the below... otherwise browse through:

Create a module and decide what you need to deploy out of your module

<Module Name="Document library" Path="" List="101" Url="url">
<File Url="url" Type="GhostableInLibrary" />
</Module>

100 Generic list

101 Document library

102 Survey

103 Links list

104 Announcements list

105 Contacts list

106 Events list

107 Tasks list

108 Discussion board

109 Picture library

110 Data sources

111 Site template gallery

112 User Information list

113 Web Part gallery

114 List template gallery

115 XML Form library

116 Master pages gallery

117 No-Code Workflows

118 Custom Workflow Process

119 Wiki Page library

120 Custom grid for a list

130 Data Connection library

140 Workflow History

150 Gantt Tasks list

200 Meeting Series list

201 Meeting Agenda list

202 Meeting Attendees list

204 Meeting Decisions list

207 Meeting Objectives list

210 Meeting text box

211 Meeting Things To Bring list

212 Meeting Workspace Pages list

301 Blog Posts list

302 Blog Comments list

303 Blog Categories list

1100 Issue tracking

1200 Administrator tasks list

How to configure incoming email settings for document libraries

Scenario: Users send emails to a specific email id with attachements and need to save them in SharePoint list (document library)

One Line Answer: OOTB Feature Configuration
> applies to only document library
> doesnt work on FBA

How-To:

Open CA
1. Go to Operations > Topology and Services
2. Click on Incoming e-mail settings (4th link)
3. Set Enable sites on this server to receive e-mail? - Yes
4. Settings mode:
5. Directory Management Service - No
6. Incoming E-Mail Server Display Address - @mydomain.com
7. E-Mail Drop Folder -
8. Click OK

Open WebSite
1. Go to any document list
2. Click on Settings > Document Library Settings
3. Communications > Incoming e-mail settigns
4. Configure the settings what ever you need.
5. Click OK

And then if any one sends emails to the specified email; you shall see them in the document library / save in the root directory specified.

Regional SharePoint Users Conference 2009

Regional SharePoint Users Conference 2009
Friday, June 26, 2009 at 8:00 AM - Saturday, June 27, 2009 at 6:00 PM (ET)
Sterling, VA

Event details, fees etc are here.

Silverlight FireStarter DC

here is the event link.