转自:http://www.zu14.cn/2009/05/20/read-analyze-send-eml-as-mail-by-csharp-cdosys/

最近,我发布了几篇关于 .NET 和 EML 文件的邮件相关 的博文,引来了一些网友的关注与讨论。尤其是对于“如何解析EML文件的内容”和 “发送现有的EML文件”。

目前,比较主流的解析EML文件的方式,基本是对MIME格式的分析,基于对 RFC822及其后续扩展的标准 的理解。但是,此种方法工作量太大,且过于繁琐。

我是个懒人,喜欢找捷径

大家都知道,微软的 outlook express 是可以保存和打开并发送EML文件的。那么很明显,outlook express 肯定是可以解析EML文件的。

问题就来了:我们可不可以利用微软现有的成果呢?

针对这个问题,我们再回到.NET中发送邮件的功能上,为了体现的明显,我们回到.NET 1.1上,.NET 1.1 发送邮件的是 System.Web.Mail ,这个System.Web.Mail 当时是比较弱的,原因就是它是基于 cdosys.dll 的基础上的且并未做富实现。

cdosys.dll是从windows 2000 开始被正式引入的,后续的操作系统都支持,关于cdosys.dll的细节,请看MSDN

经过一个晚上对cdosys的研究,终于得出了结果:CDOSYS是可以加载eml文件并进行解析和直接发送的

cdosys属于COM,在.NET使用,需要添加COM引用。

CDOSYS

添加引用,会在项目的引用里出现下面的2项:

image

下面我对发送EML文件,封装了一个类(只做了基本封装,大家可以自己扩展)

/// <summary>
/// 功能: 发送EML文件
/// 作者: 三角猫
/// 网址: http://www.zu14.cn
/// 声明: 转载务必保留此信息
/// </summary>
public class EmlSender
{
    private string emlFilePath;
    private string smtpServer;
    private string smtpServerPort = "25";
    private string smtpUserName;
    private string smtpPassword;
    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="EmlFilePath">EML文件的绝对路径</param>
    public EmlSender(string EmlFilePath)
    {
        emlFilePath = EmlFilePath;
    }

    /// <summary>
    /// SMTP服务器地址
    /// </summary>
    public string SmtpServer
    {
        set { smtpServer = value; }
    }

    /// <summary>
    /// SMTP服务器端口号
    /// </summary>
    public string SmtpServerPort
    {
        set { smtpServerPort = value; }
    }

    /// <summary>
    /// SMTP服务器认证帐号
    /// </summary>
    public string SmtpUserName
    {
        set { smtpUserName = value; }
    }

    /// <summary>
    /// SMTP服务器认证密码
    /// </summary>
    public string SmtpPassword
    {
        set { smtpPassword = value; }
    }

    /// <summary>
    /// 使用CDOSYS发送EML文件
    /// </summary>
    public void Send()
    {
        CDO.Message oMsg = new CDO.Message();
        CDO.IConfiguration iConfg = oMsg.Configuration;
        ADODB.Fields oFields = iConfg.Fields;

        //设置CDO相关的发送参数,主要是用于SMTP服务器的认证
         ADODB.Field oField = oFields["http://schemas.microsoft.com/cdo/configuration/sendusing"];
        oField.Value = "2";

        oField = oFields["http://schemas.microsoft.com/cdo/configuration/smtpserverport"];
        oField.Value = smtpServerPort;

        oField = oFields["http://schemas.microsoft.com/cdo/configuration/smtpserver"];
        oField.Value = smtpServer;

        oField = oFields["http://schemas.microsoft.com/cdo/configuration/languagecode"];
        oField.Value = "0x0804";

        //下面三项可以自己根据需要去填写,我比较懒
        oField = oFields["http://schemas.microsoft.com/cdo/configuration/sendemailaddress"];
        oField.Value = "";

        oField = oFields["http://schemas.microsoft.com/cdo/configuration/smtpuserreplyemailaddress"];
        oField.Value = "";

        oField = oFields["http://schemas.microsoft.com/cdo/configuration/smtpaccountname"];
        oField.Value = "";
        //------------------------

        oField = oFields["http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout"];
        oField.Value = "60";

        oField = oFields["http://schemas.microsoft.com/cdo/configuration/sendusername"];
        oField.Value = smtpUserName;

        oField = oFields["http://schemas.microsoft.com/cdo/configuration/sendpassword"];
        oField.Value = smtpPassword;

        oField = oFields["http://schemas.microsoft.com/cdo/configuration/smtpauthenticate"];
        oField.Value = "1";

        oFields.Update();

        try
        {
            //读取EML文件到CDO.MESSAGE,做分析的话,实际是用了下面的部分
            ADODB.Stream stm = new ADODB.Stream();
            stm.Open(System.Reflection.Missing.Value,
                     ADODB.ConnectModeEnum.adModeUnknown,
                     ADODB.StreamOpenOptionsEnum.adOpenStreamUnspecified,
                     "", "");
            stm.Type = ADODB.StreamTypeEnum.adTypeBinary;//二进制方式读入

            stm.LoadFromFile(emlFilePath); //将EML读入数据流

            oMsg.DataSource.OpenObject(stm, "_stream"); //将EML数据流载入到CDO.Message,要做解析的话,后面就可以了。

            stm.Close();

            oMsg.Send(); //发送
        }
        catch
        {
            throw;
        }
        finally
        {
            oField = null;
            oFields = null;
            oMsg = null;
        }
    }
}

使用方法:

EmlSender eml = new EmlSender(@"d:\a.eml");
eml.SmtpServer = "smtp.zu14.cn";
eml.SmtpServerPort = "25";
eml.SmtpUserName = "admin@zu14.cn";
eml.SmtpPassword = "*****";
eml.Send();

至此,.NET 关于MAIL 和 EML 相关的内容,算是告一段落了。

posted on 2011-09-16 22:13  混沌中  阅读(2773)  评论(0编辑  收藏  举报