It appears that Yahoo Mail doesn't want you pulling in outside stylesheets. When our Trader Interviews email arrived in a Yahoo Mail account, the <link> tag to our CSS was replaced with an <xlink> tag, rendering it unusable. Googling around, it appears that xlink is a valid XHTML tag, but it appears that Yahoo is using it just to break links to outside stylesheets, since they also replace a <body> tag with <xbody>. Our workaround is to replace any <link> tags to outside stylesheets with the contents of that outside stylesheet, before an email is sent. Below is a test file with the function we use to do such a thing.

CODE:
  1. <?php
  2.  
  3. $text = '<LINK href="http://www.traderinterviews.com/main.css"type=text/css rel=stylesheet>Some more text';
  4.  
  5. echo StylesheetLink_Replace($text);
  6.  
  7. /*------------------------------------------------------------------------------
  8. Name:      StylesheetLink_Replace
  9. Arguments: html: The HTML to search for <link> tags in
  10. Returns:   The HTML passed in, with <link> tags to external stylesheets
  11.            replaced with the contents of that file
  12. Purpose:   Replaces links to external stylesheets with the actual contents of
  13.            the stylesheet. Yahoo changes the <link tag to <xlink, making the
  14.            CSS not work. Embedding it gets around the problem.
  15. Notes:     
  16. ------------------------------------------------------------------------------*/
  17. function StylesheetLink_Replace($html)
  18.    {
  19.    /* Find links to CSS files */
  20.    preg_match_all('/<LINK.*href="{0,1}.+\.css"{0,1}.*>/i',
  21.                   $html, $whole_links);
  22.  
  23.    /* Process each css link found */
  24.    foreach($whole_links[0] as $whole_link)
  25.       {
  26.       /* Find the css file path in the match */
  27.       preg_match('/href="{0,1}(.+\.css)"{0,1}/i', $whole_link, $paths);
  28.  
  29.       /* Open the file and read it into a variable */
  30.       $handle = fopen($paths[1], 'rb');
  31.  
  32.       /* If the remote file could be opened, do the replacement */
  33.       if($handle)
  34.          {
  35.          $contents = stream_get_contents($handle);
  36.          fclose($handle);
  37.  
  38.          /* Replace the found string with the contents */
  39.          $html = str_replace($whole_link,
  40.                              '<style type="text/css">'.$contents.'</style>',
  41.                              $html);
  42.          }
  43.       /* Otherwise, remove the CSS link, since it couldn't be opened anyway */
  44.       else
  45.          {
  46.          $html = str_replace($whole_link, '', $html);
  47.          }
  48.       }
  49.  
  50.    return $html;
  51.    }
  52.  
  53. ?>