Sending a web page by email programmatically. Image urls are not allowed
I am writing a SharePoint timer job that needs to pull the content of a web page and send that HTML address as an email.
I am using HttpWebRequest and HttpWebResponse objects to pull the content.
The email functionality works great except for one problem.
The web page that serves the content of my email contains images.
When the html of a page is sent as email, the image urls inside the HTML are relative urls, they are not resolved as an absolute url.
How do I resolve urls of images in their absolute paths within the content of a web page?
Is there any direct way to do this? I don't want to run Regex over html code to replace all relative urls with absolute urls.
source to share
Found this cool Codeplex tool called HtmlAgilityPack. http://www.codeplex.com/htmlagilitypack
Using this API, we can parse the Html so that we can parse XML documents. We can also query and search for nodes using XPath.
I used the following piece of code to fix image urls
HtmlDocument htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(htmlMessage);
//This selects all the Image Nodes
HtmlNodeCollection hrefNodes = htmlDoc.DocumentNode.SelectNodes("//img");
foreach (HtmlNode node in hrefNodes)
{
string imgUrl = node.Attributes["src"].Value;
node.Attributes["src"].Value = webAppUrl + imgUrl;
}
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
htmlDoc.OptionOutputAsXml = false;
htmlDoc.Save(sw);
htmlMessage = sb.ToString();
source to share
I ran into this problem several times and I don't think there is any magic wand method to do it all for you. HTMLAgilityPack does a good job of aggregating the content you want, but you'll have to decrypt it yourself. For instance; getting a list of HtmlNodes containing "// img" can return any of the following:
<img src="http://www.adg2435.com/pictures/pic.jpg"/> //absolute url
<img src="coolpicture.jpg"/> //relative to the page
<img src="pictures/pic.jpg"/>
<img src="./pictures/pic.jpg"/>
It is up to you to figure out what types of links will appear on a given web page. You also need to consider things like this: (Exaggerate the image url after the ".jpg" extension)
<img src="/pictures/pic.jpg?45823593&xyz=95325235r0634945823ot49140200"/>
So, it is convenient for me to keep a few things at hand at any given time:
- Source URL for the whole page
-
The domain for a given url (to do things like say "does the given src contain a domain?") Here's how you get the domain of the original link:
Uri domainUri = new Uri (fullUrl); domainUrl = domainUri.GetLeftPart (UriPartial.Authority);
-
Potentially you need a subdomain (ie "http://www.mysite.com/pictures/")
source to share