c# 接发邮件

    技术2022-05-19  21

    本文涉及的内容:1:自己制作Pop3Helper   信件格式的处理有麻烦2:使用现成的pop3类   LumiSoft.Net.POP3.Client;      有两种处理方法3:使用IMAP收邮件      功能似乎更多,比起pop3来。4:SMTP发送邮件   关于 Mailbox unavailable. The server response was: 5.7.1 Unable to relay for xx 的错误处理

    自己写一个POP3的接收程序并不是很简单。主要问题就是如何处理信件的格式。其处理方法不是太复杂,用一个tcp联接就可以了。这是代码     public class Pop3Helper    {        string _pop3server;        string _user;        int _port;        string _pwd;

            public TcpClient _server;        public NetworkStream _netStream;        public StreamReader _reader;        public string _data;        public byte[] _charData;        public string _CRLF = "/r/n";

            private string _log;        public string LogMSG        {            get { return _log; }        }        /// <summary>        ///         /// </summary>        /// <param ></param>        /// <param ></param>        /// <param ></param>        /// <param ></param>        public Pop3Helper(string server, int port, string user, string pwd)        {            _pop3server = server;            _port = port;            _user = user;            _pwd = pwd;        }        /// <summary>        /// connect        /// </summary>        public void Connect()        {            //create a tcp connection            _server = new TcpClient(_pop3server, _port);

                //prepare             _netStream = _server.GetStream();            _reader = new StreamReader(_server.GetStream());            if (!CheckResult(_reader.ReadLine()))                throw new Exception("Connect Error");

                //login            _data = "USER " + this._user + _CRLF;            _charData = System.Text.Encoding.ASCII.GetBytes(_data.ToCharArray());            _netStream.Write(_charData, 0, _charData.Length);            if (!CheckResult(_reader.ReadLine()))                throw new Exception("User Error");

                _data = "PASS " + this._pwd + _CRLF;            _charData = System.Text.Encoding.ASCII.GetBytes(_data.ToCharArray());            _netStream.Write(_charData, 0, _charData.Length);            if (!CheckResult(_reader.ReadLine()))                throw new Exception("Pass Error");

            }        /// <summary>        /// get message Numbers        /// </summary>        /// <returns></returns>        public int GetMailCount()        {            try            {                _data = "STAT" + _CRLF;                _charData = System.Text.Encoding.ASCII.GetBytes(_data.ToCharArray());                _netStream.Write(_charData, 0, _charData.Length);                string resp = _reader.ReadLine();                string[] tokens = resp.Split(new char[] { ' ' });                return Convert.ToInt32(tokens[1]);            }            catch (Exception ex)            {                return 0;            }        }

            public string GetMail(int id)        {            string line;            string content = "";            try            {                //get by id                _data = "RETR " + id + _CRLF;                _charData = System.Text.Encoding.ASCII.GetBytes(_data.ToCharArray());                _netStream.Write(_charData, 0, _charData.Length);                line = _reader.ReadLine();

                    if (line[0] != '-')                {                    //end with '.'                    while (line != ".")                    {                        line = _reader.ReadLine();                        content += line + "/r/n";                    }                }

                    return content;

                }

                catch (Exception err)            {                Log(err.Message);                return "Error";            }        }        public void DeleteMail(int id)        {            _data = "DELE" + id + _CRLF;            _charData = System.Text.Encoding.ASCII.GetBytes(_data.ToCharArray());            _netStream.Write(_charData, 0, _charData.Length);            if (!CheckResult(_reader.ReadLine()))                throw new Exception("Delete Error");

            }        /// <summary>        /// close connection        /// </summary>        public void Close()        {

                _data = "QUIT" + _CRLF;            _charData = System.Text.Encoding.ASCII.GetBytes(_data.ToCharArray());            _netStream.Write(_charData, 0, _charData.Length);

                //close             _netStream.Close();            _reader.Close();        }

            private bool CheckResult(string reply)        {            Log(reply);            if (reply.IndexOf("+OK") > -1)                return true;            else                return false;        }        private void Log(string msg)        {            _log += msg + "/r/n";        }    }。。。。。但是这种方式的一个问题就是关于解析信件的格式。如果是附件的话,他也直接给出了二进制,不容易使用。所以,可以使用一个现成的工具:LumiSoft.Net.POP3.Client。这里面已经给写好了实现,用起来也很简单。这是一个简单的用法(这里使用了两种处理方式,前一种是不建议使用的)。。            using (POP3_Client pop3 = new POP3_Client())            {                //与Pop3服务器建立连接                pop3.Connect(_popServer, _pop3port,false);                //验证身份                pop3.Authenticate(_user, _pwd, false);

                    //get all messages                POP3_MessagesInfo infos = pop3.GetMessagesInfo();                 foreach (POP3_MessageInfo info in infos)                {                    byte[] bytes = pop3.GetMessage(info.MessageNumber);                    Mime mime = Mime.Parse(bytes);                    HandleMail(mime);                    //delete it at last                    //pop3.DeleteMessage(info.MessageNumber);                }                //the second way to do it//for (int i = 0; i < pop3.Messages.Count; i++)                //{                //    byte[] bytes = pop3.Messages[i].MessageToByte();                //    Mime mime = Mime.Parse(bytes);                //    HandleMail(mime);                //    //delete it at last                //    //pop3.DeleteMessage(pop3.Messages[i].SequenceNumber);                //}。。。。取得的邮件可以这要给获得。   #region pop3            //string customer = mime.MainEntity.To.ToAddressListString();//cargo company            //string sender = mime.MainEntity.From.ToAddressListString();//this is customer who send

                #endregion            string customer = MailboxesToString(envelope.To);//cargo company            string sender = MailboxesToString(envelope.From);//this is customer who send

    。。。除此之外,它提供的另外一个工具是IMAP,它操作起来更加方便。代码如下:。  IMAP_Client clnt = new IMAP_Client();            try            {                clnt.Connect("mail.xx.com", 143, false);                clnt.Authenticate("user", "password");                string[] folders = clnt.GetFolders();//get all types

                    string folder = "Inbox";                clnt.SelectFolder(folder);

                    IMAP_SequenceSet sequence_set = new IMAP_SequenceSet();                // All messages                sequence_set.Parse(string.Format("{0}:{1}", 1, clnt.MessagesCount));

                    IMAP_FetchItem[] fetchItems = clnt.FetchMessages(                        sequence_set,                        IMAP_FetchItem_Flags.UID | IMAP_FetchItem_Flags.MessageFlags | IMAP_FetchItem_Flags.Size | IMAP_FetchItem_Flags.Envelope,                        true, false                        );                //int count =0;                foreach (IMAP_FetchItem fetchItem in fetchItems)                {                    IMAP_Envelope envelope = fetchItem.Envelope;                    //hanldle it, means read and search and reply                    try                    {                        HandleMail(envelope);                        //count++;                    }                    catch (Exception ex)                    {                        Log("Sys", ex.Message);                    }                }                //delete it after hanlde                clnt.DeleteMessages(sequence_set, false);                //disconnect                clnt.Disconnect();

                    //MessageBox.Show(count.ToString() + " of " + fetchItems .Length+ " Success");            }            catch (Exception x)            {                Log("Sys", x.Message);                //MessageBox.Show(x.Message);            }。。上边都是如何收邮件。关于如何发送邮件是比较简单的。这里提供两种方式。第一种方式是使用网上的smtp。这种方式必须要提供用户名和密码。这个适合于web应用,使用的smtp也是网上的,我一般使用163的smtp,基本没有问题。第二种方式是使用本地的smtp。不需要提供密码,用户也可以是不存在的(垃圾邮件是不是就是这么产生的?),但是必要要提供smtp端口号。第二种方法测试的时候有时候会报错“Mailbox unavailable. The server response was: 5.7.1 Unable to relay for xxx”,查过资料之后(在baidu上没找到,还是google信息多一点),才发现问题原来是IIS里SMTP服务的配置有问题。这样修改可以解决:到开SMTP属性—>Access页面?Reply Restrictions/ Reply-?Only this Below选项,加上自己的ip:127.0.0.1(允许本机,使用loalhost,如果是允许其他机器,类似设置)代码如下public class EMail    {        static public string accountName;        static public string password;        static public string smtpServer;        static public int smtpPort;

            /// <summary>        /// need password,username, smtpserver        /// </summary>        /// <param ></param>        /// <param ></param>        /// <param ></param>        static public void SendMail(string sendTo, string subject, string body)        {            //.net smtp             System.Web.Mail.MailMessage mailmsg = new System.Web.Mail.MailMessage();            mailmsg.To = sendTo;            //mailmsg.Cc = cc;            mailmsg.Subject = subject;            mailmsg.Body = body;

                //sender here            mailmsg.From = EMail.accountName;             // certify needed              mailmsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", "1");//1 is to certify            //the user id               mailmsg.Fields.Add(                "http://schemas.microsoft.com/cdo/configuration/sendusername",                EMail.accountName);             //the password            mailmsg.Fields.Add(                "http://schemas.microsoft.com/cdo/configuration/sendpassword",                 EMail.password);

                System.Web.Mail.SmtpMail.SmtpServer = EMail.smtpServer;            System.Web.Mail.SmtpMail.Send(mailmsg);

            }

            #region send mail2        /// <summary>        /// need username,smtp,smtp port        /// </summary>        /// <param ></param>        /// <param ></param>        /// <param ></param>        static public void SendMail2(string sendTo, string subject, string body)        {            System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage();            msg.To.Add(sendTo);            msg.From = new System.Net.Mail.MailAddress(accountName );

                msg.Subject = subject;            msg.SubjectEncoding = System.Text.Encoding.UTF8;            msg.Body = body;//            msg.BodyEncoding = System.Text.Encoding.UTF8;            msg.IsBodyHtml = false;            //msg.Priority = MailPriority.High;//

                System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient();            client.Host = smtpServer;            client.Port = smtpPort;            //client.Credentials = new System.Net.NetworkCredential("user@xxx.com", "pass");             client.Send(msg);

            }        #endregion

        }

    Feedback

    @寒星星 这里提供的源程序已经够多了,剩下的就是你把他嵌入到自己的程序里. 其实,我也没有demo,都是从实际项目中摘出来的代码而已. 用c#发送邮件,用了很长时间了,也用了不少方法,遇到不少问题.这个随笔算是一个阶段性总结了. 想知道有没有方法处理群发问题? 用for 和用mail.bcc 都有问题,特别是超时问题 LumiSoft.Net.POP3.Client 这个在哪里可以得到?? 收邮件好像没这么简单,要把附件弄出来(好像要解码来的) MailMessage 竟然无法序列化。 这样发送失败的时候想使用MessageQueue 保存都不成。还要自己定义类去保存。 邮件发送失败的后续处理这里有么。 还有邮件的缓存,有时候考虑到服务器的能力可能会缓存一些邮件。空闲的时候再发送。 希望接着写哦。 @Faster LumiSoft.Net.POP3.Client里面是提供关于附件的解析的.如果自己作pop3,那就真得解码了. @snoopymin @暗香浮动 这个问题不属于纯粹的技术问题. 一般情况下,可以通过这样的方式来解决: 设置定时器,不要一次性发送过多邮件. 1:做一个ArrayList,存储发送列表. 2:然后再加一个定时器timer,5分钟执行一次. 3:在timer事件里面来发送邮件,每次发送10个,如果发送失败,就继续保留在list里面,成功则删除. 比较简单的逻辑. 这个随笔只是纯技术的. 剩下的逻辑都是额外的了,比如缓存,比如群发. 群发又有很多问题,比如定时发送,比如如何得知用户阅读情况等等. LumiSoft其实是一个邮件服务器程序,楼主用的只是最简单的页面POP功能,他还有一个C/S的邮件收发服务器软件,也是开源的,如果配合这个,简直是无敌,不过,国外好多论坛上说这个玩意CPU占用率比较高 @梦想依旧 必须指定.就像访问网页必须要指定哪一个域名(服务器)一样.^_^ @wkcode22 功能确实不错.我用的出了pop3还有imap,不错. 其他功能没有用过,暂时还不需要. @ithurricane 提供的代码片断已经足够多了。自己根据需要改编一下就行了。 IMAP 协议的接受邮件 你可以给我一份DEMO吗? 关键是 我看不太懂它的帮助,英文 接受后 怎么输出具体内容 例如 标题 我想知道这样用LumiSoft.Net.IMAP.Client的IMAP获取附件信息及邮件内容,希望给出代码,谢谢!!!

    最新回复(0)