Friday, December 17, 2010

Can't find all the attachments in .EML file?

Using CDOSYS.DLL is a very convenient way to parse and extract content and attachments from an EML file. However, embedded images in the HTML part of the email do not appear as attachments.

Solution: enumerate the BodyParts and look for BodyParts with a filename: this includes all the attachments and embedded images.  The syntax is a little tricky, but BodyParts work just the same as Attachments.


        Dim bodypart_count = Msg.BodyPart.BodyParts.Count
        Dim i As Integer = 0
        For i = 1 To bodypart_count
             If Msg.BodyPart.BodyParts(i).FileName <> "" Then
                attachment_count += 1
            End If
        Next

MySQL Restore fails with 'Server gone away'

Most probably due to the default value of 1M for max_allowed_packet.  Increase to 100M and problem will very likely go away.

Saturday, November 20, 2010

Reading EML files

You can do this 'properly' (certainly better than trying to parse it as a text file) by using the COM cdosys.dll ('Microsoft CDO for Windows 2000 Library').

You'll need to create a .Net wrapper for it by adding a reference: because it depends on ADODB.dll, you'll get Interop.CDO.dll and Interop.ADODB.dll created for you in your bin directory.

There's a lot of information around for sending emails using CDO but almost nothing about using it to read EML files, but I found this page that got me started with iterating through and reading all the eml files in a mailbox directory (like inetpub\mailroot\mailbox\xxx.domain.com\) http://support.microsoft.com/kb/310224

If what you want to do is just open a specific eml file (that you already know the filename of) then there's another way to do it: http://stackoverflow.com/questions/936422/recommendations-on-parsing-eml-files-in-c

 Public Shared Function getEmlFileAsMessage(ByVal path As String) As Object
        Dim msg As CDO.Message = New CDO.MessageClass()
        Dim stream As ADODB.Stream = New ADODB.StreamClass()
        Try
            stream.Open(Type.Missing, ADODB.ConnectModeEnum.adModeUnknown, ADODB.StreamOpenOptionsEnum.adOpenStreamUnspecified, String.Empty, String.Empty)
            stream.LoadFromFile(path)
            stream.Flush()
            msg.DataSource.OpenObject(stream, "_Stream")
            msg.DataSource.Save()
            Return msg
        Catch
            Return Nothing
        End Try

    End Function

Tuesday, August 31, 2010

Using MySql with WebMatrix

There's a small problem that affects any attempt to connect to a database through a connection string using WebMatrix : there's an error in the documentation that leads you to try to use Database.OpenConnectionString when you should be using the currently undocumented Database.Open (as shown below).
If you install the MySql.Data.MySqlClient dll to the GAC then you won't need the dbproviderfactories entry shown below. If you don't install it to the GAC, create a bin directory in your application and drop the dll in there.

See also: Useful information on WebMatrix from Rick Strahl


1. web.config:



<?xml version="1.0"?>


<configuration>
<connectionStrings>
<add name="myconnection" connectionString="server=localhost;user id=dimanuser; password=; database=diman; pooling=false; charset=utf8;" providerName="MySql.Data.MySqlClient"/>
</connectionStrings>
    <system.web>
        <compilation debug="false" targetFramework="4.0" />
    </system.web>
<system.data>
<DbProviderFactories>
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.2.2.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"/>
</DbProviderFactories>
</system.data>
</configuration>


2. Code:


<!DOCTYPE html>
<html>
    <head>
        <title></title>
    </head>
    <body>
@{   
    var db = Database.Open("myconnection");
    string sql = "select * from standard_text where rank <  @0 order by rank"; 
} 
    <ul> 
@foreach(var row in db.Query(sql,30)){ 
        <li> @row.rank - @row.title</li> 
} 
    </ul> 
    </body>
</html> 
  

Sunday, August 29, 2010

Export GridView to Excel

After researching this for some time I found an excellent article that provides a convenient solution from Matt Berseth: http://mattberseth.com/blog/2007/04/export_gridview_to_excel_1.html

Like most solutions to this problem, this article describes how to make ASP.NET re-render the GridView in a cleaned-up HTML format and then serve that rendering as a download. The downside to this is that it doesn't work with OpenOffice (this would require the Grid to be re-rendered as CSV rather than HTML).

The nice thing about this solution is that code can be easily customized. My GridViews contain images (as HTML images, not ImageButtons), so I added code to either eliminate them or render them in text.

Friday, August 27, 2010

ASP.NET and the annoying DropDownList problem...

'ddlxxxxx' has a SelectedValue which is invalid because it does not exist in the list of items.

Many people complain about this untrappable error, but if you search hard enough, you will eventually find the fix: http://forums.devx.com/showthread.php?t=155180


So, it turns out that it's very easy to create your own DropDownList control inheriting all the behaviour of the original except this error.  Now, if the value in your database doesn't match one of the values in the pull-down it will display the default value (1st in the list) - rather more friendly behaviour.  There's much more about this at http://aspddlsucks.spaces.live.com/ - I think it's annoying that a failure to enforce referential integrity in your database is punished in such a brutal way, so that you can't even catch the violation in a try/catch in your application code.  The official Microsoft response is certainly patronising: "just make sure your data is always correct".

1. Using Visual Basic 2008 Express (or similar, I'm sure C#-ers can work it out), compile the following code as a Class (be sure to add a reference to 'System.Web')

Imports Microsoft.VisualBasic
Imports System.Web

Namespace FixedDDL
    Public Class DropDownList
        Inherits System.Web.UI.WebControls.DropDownList

        Protected Overrides Sub PerformDataBinding(ByVal dataSource As System.Collections.IEnumerable)
            Try
                MyBase.PerformDataBinding(dataSource)
            Catch OutOfRangeEx As System.ArgumentOutOfRangeException
                ' Ignore exception
            End Try
        End Sub

    End Class
End Namespace

2. Grab the FixedDDL.dll and put it in the Bin directory of your web application

3. Add the following lines into your web.config:
<system.web>
<pages>
<tagMapping>
<add mappedTagType="FixedDDL.FixedDDL.DropDownList" tagType="System.Web.UI.WebControls.DropDownList">
</add>
</tagMapping>
</pages>

...
</system.web>





4. Job done

ASP.NET, databases, localization and the problem with Turkish...

This is one of the craziest problems ever:

1. You have a database field called 'CustomerId'
2. so you refer to this field as myrow("CustomerId")
3. this works for all users worldwide but fails for Turkish users
4. change the code to refer to myrow("Customerid") and it works

Reason:  Turkish has an i character without a dot.

So, in Turkish, 'i' and 'I' are not related in any way: they are not upper and lower case versions of the same character, but completely different characters.  There's a capital 'i' with a dot above it that is the upper case version of 'i' (with a dot).  Of course, 'I' without the dot is the upper case version of i without the dot. Clear?

When you switch on localization support in ASP.NET, this doesn't just affect the things that the user sees in their browser depending on the language settings, it also affects your programming!


Rick Strahl found this same issue back in 2005: http://www.west-wind.com/weblog/posts/2204.aspx