欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

深入Lumisoft.NET组件与.NET API实现邮件发送功能的对比分析

程序员文章站 2024-03-01 15:34:16
我在另一篇文章《深入lumisoft.net实现邮件发送功能的方法详解》有大致对这个lumisoft.net组件的使用进行了介绍,当然lumisoft.net组件除了提供邮...

我在另一篇文章《深入lumisoft.net实现邮件发送功能的方法详解》有大致对这个lumisoft.net组件的使用进行了介绍,当然lumisoft.net组件除了提供邮件发送功能外,还提供了邮件接收等功能的处理(包括基于pop3协议和imap协议),而.net则除了提供smtp协议功能外,则没有提供pop3协议处理的相关类库,因此收取邮件这需要自己进行封装(需要也可以参考codeproject.com上的相关文章)。

1、.net的邮件发送功能实现
.net本身封装了一个smtpclient类以及相关的邮件对象类,这样利用这些类库,也可以方便实现邮件的发送功能的了。

如添加发送人地址,抄送地址,以及暗送地址(多个地址用逗号分开)代码如下。

复制代码 代码如下:

string toemails = mailinfo.toemail;

            string bcc = "";
            mailinfo.recipientbcc.foreach(obj => bcc += string.format("{0},", obj));
            bcc = bcc.trim(',');

            string cc = "";
            mailinfo.recipientcc.foreach(obj => cc += string.format("{0},", obj));
            cc = cc.trim(',');

            mailmessage mail = new mailmessage(settinginfo.mailfrom, toemails);
            if (!string.isnullorempty(bcc))
            {
                mail.bcc.add(bcc);
            }
            if (!string.isnullorempty(cc))
            {
                mail.cc.add(cc);
            }


.net的附件和嵌入式资源由对象attachment和linkedresource进行管理,他们的利用代码如下所示:
复制代码 代码如下:

//附件
            foreach (string filename in mailinfo.attachments)
            {
                mail.attachments.add(new attachment(filename));
            }

            //嵌入资源
            alternateview view = alternateview.createalternateviewfromstring(mailinfo.body, encoding.utf8, mediatypenames.text.html);
            foreach (linkedattachementinfo link in mailinfo.embedobjects)
            {
                linkedresource resource = new linkedresource(link.stream, link.mimetype);
                resource.contentid = link.contentid;
                view.linkedresources.add(resource);
            }
            mail.alternateviews.add(view);


发送邮件的其他部分代码如下所示
复制代码 代码如下:

mail.isbodyhtml = mailinfo.isbodyhtml;
            mail.bodyencoding = encoding.utf8;
            mail.subject = mailinfo.subject;
            mail.subjectencoding = encoding.utf8;

            //发送账户设置信息
            smtpclient client = new smtpclient();
            client.host = settinginfo.smtpserver;
            client.port = settinginfo.smptport;
            client.usedefaultcredentials = false;
            client.deliverymethod = smtpdeliverymethod.network;
            client.credentials = new networkcredential(settinginfo.smtpuser, settinginfo.smtppass);

            bool success = false;
            try
            {
                client.send(mail);
                success = true;
            }
            catch (exception ex)
            {
                logtexthelper.error(ex);
                //throw;
            }


上面利用.net的smtpclient发送邮件操作的完整代码如下:
复制代码 代码如下:

/// <summary>
        /// 发送外部邮件(系统配置,系统邮件)
        /// </summary>
        /// <param name="mailinfo">发送邮件信息</param>
        /// <returns></returns>
        public commonresult send(mailinfo mailinfo)
        {
            commonresult result = new commonresult();
            try
            {
                appconfig config = new appconfig();
                string maildomain = config.appconfigget("maildomain");
                string mailusername = config.appconfigget("mailusername");
                string mailpassword = config.appconfigget("mailpassword");
                string mailport = config.appconfigget("mailport");
                string mailfrom = config.appconfigget("mailfrom");
                int port = 25;
                int.tryparse(mailport, out port);

                smtpsettinginfo settinginfo = new smtpsettinginfo(maildomain, port,
                    mailusername, mailpassword, mailfrom);

                result.success = privatesendemail(mailinfo, settinginfo);
            }
            catch (exception ex)
            {
                result.errormessage = ex.message;
                throw;
            }

            return result;
        }

        /// <summary>
        /// 通用发送邮件操作
        /// </summary>
        private static bool privatesendemail(mailinfo mailinfo, smtpsettinginfo settinginfo)
        {         
            string toemails = mailinfo.toemail;

            string bcc = "";
            mailinfo.recipientbcc.foreach(obj => bcc += string.format("{0},", obj));
            bcc = bcc.trim(',');

            string cc = "";
            mailinfo.recipientcc.foreach(obj => cc += string.format("{0},", obj));
            cc = cc.trim(',');

            mailmessage mail = new mailmessage(settinginfo.mailfrom, toemails);
            if (!string.isnullorempty(bcc))
            {
                mail.bcc.add(bcc);
            }
            if (!string.isnullorempty(cc))
            {
                mail.cc.add(cc);
            }

            //附件
            foreach (string filename in mailinfo.attachments)
            {
                mail.attachments.add(new attachment(filename));
            }

            //嵌入资源
            alternateview view = alternateview.createalternateviewfromstring(mailinfo.body, encoding.utf8, mediatypenames.text.html);
            foreach (linkedattachementinfo link in mailinfo.embedobjects)
            {
                linkedresource resource = new linkedresource(link.stream, link.mimetype);
                resource.contentid = link.contentid;
                view.linkedresources.add(resource);
            }
            mail.alternateviews.add(view);
            mail.isbodyhtml = mailinfo.isbodyhtml;
            mail.bodyencoding = encoding.utf8;
            mail.subject = mailinfo.subject;
            mail.subjectencoding = encoding.utf8;

            //发送账户设置信息
            smtpclient client = new smtpclient();
            client.host = settinginfo.smtpserver;
            client.port = settinginfo.smptport;
            client.usedefaultcredentials = false;
            client.deliverymethod = smtpdeliverymethod.network;
            client.credentials = new networkcredential(settinginfo.smtpuser, settinginfo.smtppass);

            bool success = false;
            try
            {
                client.send(mail);
                success = true;
            }
            catch (exception ex)
            {
                logtexthelper.error(ex);
                //throw;
            }

            string message = string.format("发送给【{0}】的邮件“{1}”,{2},时间:{3}",
                mailinfo.toemail[0], mailinfo.subject, success ? "发送成功" : "发送失败", datetime.now);
            logtexthelper.info(message);

            return success;
        }


2、基于lumisoft.net组件的邮件发送功能实现

基于lumisoft.net组件的邮件发送,也是一种很常用的,因为这个开源组件非常强大,经常可以在一些程序中被使用。

这个发送邮件的功能主要是利用smtp_client类来实现的,如下代码所示。注意其中的authenticate函数已经被舍弃,可以使用auth方法进行验证。但是函数参数有所不同,根据验证对象,使用不同的验证方式,一般选择auth_sasl_client_plain对象即可。

复制代码 代码如下:

public bool send()
        {
            bool sended = false;
            using (smtp_client client = new smtp_client())
            {
                client.connect(smtpserver, smtpport, smtpusessl);
                client.ehlohelo(smtpserver);
                var authhh = new auth_sasl_client_plain(username, password);
                client.auth(authhh);
                //client.authenticate(username, password);
                //string text = client.greetingtext;
                client.mailfrom(from, -1);
                foreach (string address in tolist.keys)
                {
                    client.rcptto(address);
                }

                //采用mail_message类型的stream
                mail_message m = create_plaintext_html_attachment_image(tolist, cclist, from, fromdisplay, subject, body, attachments);
                using (memorystream stream = new memorystream())
                {
                    m.tostream(stream, new mime_encoding_encodedword(mime_encodedwordencoding.q, encoding.utf8), encoding.utf8);
                    stream.position = 0;
                    client.sendmessage(stream);

                    sended = true;
                }
                if (m != null)
                {
                    m.dispose();
                }

                client.disconnect();
            }
            return sended;
        }


构造用于smtp发送的数据,可以使用mail_message 对象,也可以使用mime对象,虽然读都可以实现发送功能,不过mime对象是舍弃的对象了。

构造mail_message对象后,创建用于发送的格式要转换为stream对象。转换为发送的stream操作如下所示。

复制代码 代码如下:

using (memorystream stream = new memorystream())
{
        m.tostream(stream, new mime_encoding_encodedword(mime_encodedwordencoding.q, encoding.utf8), encoding.utf8);
        stream.position = 0;
        client.sendmessage(stream);

        sended = true;
 }


构造mail_message格式的邮件操作如下所示。
复制代码 代码如下:

private mail_message create_plaintext_html_attachment_image(dictionary<string,string> tomails, dictionary<string, string> ccmails, string mailfrom, string mailfromdisplay,
            string subject, string body, dictionary<string, string> attachments, string notifyemail = "", string plainttexttips = "")
        {
            mail_message msg = new mail_message();
            msg.mimeversion = "1.0";
            msg.messageid = mime_utils.createmessageid();
            msg.date = datetime.now;
            msg.subject = subject;
            msg.from = new mail_t_mailboxlist();
            msg.from.add(new mail_t_mailbox(mailfromdisplay, mailfrom));
            msg.to = new mail_t_addresslist();
            foreach (string address in tomails.keys)
            {
                string displayname = tomails[address];
                msg.to.add(new mail_t_mailbox(displayname, address));
            }
            msg.cc = new mail_t_addresslist();
            foreach (string address in ccmails.keys)
            {
                string displayname = ccmails[address];
                msg.cc.add(new mail_t_mailbox(displayname, address));
            }           

            //设置回执通知
            if (!string.isnullorempty(notifyemail) && validateutil.isemail(notifyemail))
            {
                msg.dispositionnotificationto.add(new mail_t_mailbox(notifyemail, notifyemail));
            }

            #region myregion

            //--- multipart/mixed -----------------------------------
            mime_h_contenttype contenttype_multipartmixed = new mime_h_contenttype(mime_mediatypes.multipart.mixed);
            contenttype_multipartmixed.param_boundary = guid.newguid().tostring().replace('-', '.');
            mime_b_multipartmixed multipartmixed = new mime_b_multipartmixed(contenttype_multipartmixed);
            msg.body = multipartmixed;

            //--- multipart/alternative -----------------------------
            mime_entity entity_multipartalternative = new mime_entity();
            mime_h_contenttype contenttype_multipartalternative = new mime_h_contenttype(mime_mediatypes.multipart.alternative);
            contenttype_multipartalternative.param_boundary = guid.newguid().tostring().replace('-', '.');
            mime_b_multipartalternative multipartalternative = new mime_b_multipartalternative(contenttype_multipartalternative);
            entity_multipartalternative.body = multipartalternative;
            multipartmixed.bodyparts.add(entity_multipartalternative);

            //--- text/plain ----------------------------------------
            mime_entity entity_text_plain = new mime_entity();
            mime_b_text text_plain = new mime_b_text(mime_mediatypes.text.plain);
            entity_text_plain.body = text_plain;

            //普通文本邮件内容,如果对方的收件客户端不支持html,这是必需的
            string plaintextbody = "如果你邮件客户端不支持html格式,或者你切换到“普通文本”视图,将看到此内容";
            if (!string.isnullorempty(plainttexttips))
            {
                plaintextbody = plainttexttips;
            }

            text_plain.settext(mime_transferencodings.quotedprintable, encoding.utf8, plaintextbody);
            multipartalternative.bodyparts.add(entity_text_plain);

            //--- text/html -----------------------------------------
            string htmltext = body;//"<html>这是一份测试邮件,<img src=\"cid:test.jpg\">来自<font color=red><b>lumisoft.net</b></font></html>";
            mime_entity entity_text_html = new mime_entity();
            mime_b_text text_html = new mime_b_text(mime_mediatypes.text.html);
            entity_text_html.body = text_html;
            text_html.settext(mime_transferencodings.quotedprintable, encoding.utf8, htmltext);
            multipartalternative.bodyparts.add(entity_text_html);

            //--- application/octet-stream -------------------------
            webclient client = new webclient();
            foreach (string attach in attachments.keys)
            {
                try
                {
                    byte[] bytes = client.downloaddata(attach);
                    using (memorystream stream = new memorystream(bytes))
                    {
                        multipartmixed.bodyparts.add(mail_message.createattachment(stream, attachments[attach]));
                    }
                }
                catch (exception ex)
                {
                    logtexthelper.error(ex);
                }
            }

            #endregion

            return msg;
        }


而构造mime格式的操作如下所示。
复制代码 代码如下:

private mime create_html_attachment_image(string mailto, string mailfrom, string mailfromdisplay,
            string subject, string body, list<string> attachments, dictionary<string, string> embedimages, string notifyemail = "", string plainttexttips = "",
            string replyemail = "")
        {
            mime m = new mime();
            mimeentity mainentity = m.mainentity;

            mainentity.from = new addresslist();
            mainentity.from.add(new mailboxaddress(mailfromdisplay, mailfrom));
            mainentity.to = new addresslist();
            mainentity.to.add(new mailboxaddress(mailto, mailto));
            mainentity.subject = subject;
            mainentity.contenttype = mediatype_enum.multipart_mixed;

            //设置回执通知
            if (!string.isnullorempty(notifyemail) && validateutil.isemail(notifyemail))
            {
                mainentity.dsn = notifyemail;
            }

            //设置统一回复地址
            if (!string.isnullorempty(replyemail) && validateutil.isemail(replyemail))
            {
                mainentity.replyto = new addresslist();
                mainentity.replyto.add(new mailboxaddress(replyemail, replyemail));
            }

            mimeentity textentity = mainentity.childentities.add();
            textentity.contenttype = mediatype_enum.text_html;
            textentity.contenttransferencoding = contenttransferencoding_enum.quotedprintable;
            textentity.datatext = body;

            //附件
            foreach (string attach in attachments)
            {
                mimeentity attachmententity = mainentity.childentities.add();
                attachmententity.contenttype = mediatype_enum.application_octet_stream;
                attachmententity.contentdisposition = contentdisposition_enum.attachment;
                attachmententity.contenttransferencoding = contenttransferencoding_enum.base64;
                fileinfo file = new fileinfo(attach);
                attachmententity.contentdisposition_filename = file.name;
                attachmententity.datafromfile(attach);
            }

            //嵌入图片
            foreach (string key in embedimages.keys)
            {
                mimeentity attachmententity = mainentity.childentities.add();
                attachmententity.contenttype = mediatype_enum.application_octet_stream;
                attachmententity.contentdisposition = contentdisposition_enum.inline;
                attachmententity.contenttransferencoding = contenttransferencoding_enum.base64;
                string imagefile = embedimages[key];
                fileinfo file = new fileinfo(imagefile);
                attachmententity.contentdisposition_filename = file.name;

                //string displayname = path.getfilenamewithoutextension(filename);
                attachmententity.contentid = key;//bytestools.bytestohex(encoding.default.getbytes(filename));

                attachmententity.datafromfile(imagefile);
            }

            return m;
        }


综合以上两者的发送功能,都可以实现邮件的发送操作,如下界面是发送邮件界面。

深入Lumisoft.NET组件与.NET API实现邮件发送功能的对比分析

3、lumisoft.net存储eml邮件文件以及发送eml文件操作

除了上面的发送普通邮件,lumisoft还支持吧邮件序列号存储到文件(.eml邮件文件)里面,然后也可以通过把文件读取到流里面,进行发送,对于某种场合,可以把邮件存储到eml文件是一个很好的操作。

存储eml文件的相关操作如下所示。

复制代码 代码如下:

private void btncreatefile_click(object sender, eventargs e)
        {
            string attachfile = path.combine(application.startuppath, "attachment/hotel2.png");
            list<string> attachments = new list<string>();
            attachments.add(attachfile);
            string subject = "测试邮件";
            string body = "<html>这是一份测试邮件,来自<font color=red><b>lumisoft.net</b></font></html>";
            string bodyembedy = "<html>这是一份测试邮件<img src=\"cid:test.jpg\">,来自<font color=red><b>lumisoft.net</b></font></html>";
            dictionary<string, string> embedlist = new dictionary<string, string>();
            embedlist.add("test.jpg", "c:\\test.jpg");

            //存储为eml文件
            string path = path.combine(application.startuppath, "eml");
            directoryutil.assertdirexist(path);
            string emlfile = string.format("{0}/{1}.eml", path, datetime.now.tofiletime());

            mime m = create_html_attachment_image(to, from, from, subject, bodyembedy, attachments, embedlist);
            m.tofile(emlfile);

            messageutil.showtips("ok");
        }


发送eml文件操作如下所示。
复制代码 代码如下:

private void btnsendfile_click(object sender, eventargs e)
        {
            using (smtp_client client = new smtp_client())
            {
                int smtpport = smtpusessl ? wellknownports.smtp_ssl : wellknownports.smtp;

                client.connect(smtpserver, smtpport, smtpusessl);
                client.ehlohelo(smtpserver);
                //var authhh = new auth_sasl_client_plain(username, password);
                //client.auth(authhh);
                client.authenticate(username, password);
                //string text = client.greetingtext;
                client.mailfrom(from, -1);
                client.rcptto(to);

                string path = path.combine(application.startuppath, "eml");
                string emlfile = directory.getfiles(path)[0];
                var msg = mail_message.parsefromfile(emlfile);

                memorystream stream = new memorystream();
                msg.tostream(stream, new mime_encoding_encodedword(mime_encodedwordencoding.q, encoding.utf8), encoding.utf8);
                stream.position = 0;
                client.sendmessage(stream);
                client.disconnect();
            }
            messageutil.showtips("ok");
        }